Two new decisions captured, one page corrected:
terminal.md — the terminal-capability decision. Why colibri-tui and the agents
it supervises need modified-key reporting (Tab vs Shift-Tab, n vs N, Enter),
why the choice fell on Kitty, the tmux extended-keys + csi-u passthrough for
the in-tmux workflow, raw-vs-tmux distinction, the SSH xterm-kitty terminfo
gotcha, and pi's identical requirement. The decision is about capability;
Kitty is the instance.
operator-attention.md — the shipped attention system as one decision. Attention
as a derived view over the state machine (not a sixth variant), the TUI
bar/jump/filter/row-highlight, and the #193 terminal-capture + signature-triage
+ edge-triggered alerts. Records the has_attention session-filter bug and fix.
Lists what is still open (outbound push, answer-from-dashboard).
glasspane.md — corrected drift. The real AgentState enum is {Idle, Working,
Blocked, Done, Error}; Stalled is a derived flag, not a variant (the page's
diagram omitted Blocked and listed Stalled as a variant). The "Usability
roadmap (TODO)" listed the attention half as not-yet-built; it shipped via
#191/#193, so those items move to operator-attention.md and the roadmap keeps
only the genuinely-unbuilt direction.
index.md — two table rows (also satisfies the orphan-page check).
Verified: prettier-clean on all 4 files; wiki-lint --strict clean (144 pass /
0 fail, up from 137); no dangling refs, no orphans, no resurrected names.
(Sam & Claude)
scripts/ci-checks.sh runs five gates; .forgejo/workflows/ci.yml ran only four
— wiki-lint --strict was missing. quality-gates.md states "ci.yml encodes the
same checks" as local, which was not quite true. Add the wiki-lint step to the
markdown job so CI matches local the day a runner is registered.
wiki-lint is pure POSIX sh (grep/awk/sed/find), so it runs in the existing
node:20 container — no new image or job.
This does not by itself stop drift reaching main: as quality-gates.md notes,
no Forgejo Actions runner is registered, so nothing enforces CI server-side
today. The local pre-push hook remains the active enforcement layer; this
change ensures CI is ready to take over once a runner exists. Verified
wiki-lint passes clean on main (137 pass / 0 fail).
(Sam & Claude)
Once any pane carried a session_id, rebuild_session_list() forced
session_filter = Some(first), so the operator could never get back to the
aggregated "All sessions" view — Tab only cycled individual sessions.
Documented as a known bug in GLASSPANE-TUI-ENHANCEMENTS.md.
Model the session cycle as [All, s1, s2, ...]: index 0 is a synthetic "All
sessions" entry (filter = None), any other index scopes to sessions[i-1].
Two helpers encode the mapping:
- session_count() = sessions.len() + 1 (All is always present)
- apply_session_filter() maps session_idx -> filter (0 => None)
Behavior changes:
- On connect, the operator now lands on "All sessions" (was: the
alphabetically-first session). The aggregated view is the more useful
default and is always reachable via Tab/BackTab.
- The position indicator now shows for any cycle > 1 item, so the
"All (1 of 2)" hint appears even with a single session.
self.sessions still holds real session ids only (no sentinel string), so the
sorted/deduped invariant is unchanged.
Tests:
- rebuild_session_list_dedupes_and_sorts: updated for the new default +
offset mapping (index 1 => s1, index 2 => s2).
- all_sessions_view_is_reachable_with_sessions_present: new regression test
covering connect-defaults-to-All and the Tab cycle All -> s1 -> s2 -> All.
- attention_bar_ignores_other_session_panes: comment corrected (rebuild no
longer selects the first session).
19/19 TUI tests pass; fmt + clippy (-D warnings) clean.
(Sam & Claude)