Skip to content

feat(sidebar): a status section above Projects, in the board's columns - #357

Open
nvkvin wants to merge 7 commits into
simion:mainfrom
nvkvin:feature/sidebar-status-section
Open

nvkvin wants to merge 7 commits into
simion:mainfrom
nvkvin:feature/sidebar-status-section

Conversation

@nvkvin

@nvkvin nvkvin commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Adds an opt-in STATUS section above PROJECTS that lists tasks by the Kanban board's columns, so the board's "what needs me" half stays on screen while you work.
The board is an overlay that deselects the open task, so it is never visible mid-task.
Off by default; a check row in the Project list options menu and Settings > Appearance > Sidebar turn it on.

Buckets come only from the board's own precedence.
taskBoardColumn now delegates to boardColumnFromFacts over three raw facts, and the section calls the same function.
Nothing is stored on Task.
Needs attention, Working and In review list their tasks; Settled and Not started show a count until opened.
Rows follow the tree: they expand to their agent tabs, and task groups draw in their own colour, fold like the tree's, and sit in the bucket of their most urgent member.
The project tree itself is unchanged.
Status rows carry their own attributes and testids, so nothing that assumes one row per task sees a second.

One behaviour change outside the section, in its own commit (7c5e123): a question no longer loses its bell when you look at its tab.
It clears when you answer (a key in that terminal, Esc, Ctrl-C, or the agent's done hook), as docs/agent-states.md already said.
Without it, a question you glanced at read as Settled on the board and in the section.

Perf: the section reads its own facts record, so an agent starting a turn does not re-render the Sidebar body, and a collapsed row selects values only.
Pinned in selectorFanout.test.ts, each pin checked by injecting the regression.

Tests: npm test, tsc -b, typecheck:e2e, and a new sidebar-status.e2e.ts with 10 cases.
On the branch rebased onto main, the three specs it touches pass: sidebar-status (10), projects (84) and agent (80).
The full make e2e run on this Mac has late-run failures in projects, settings and terminal-find while the machine is in use; run alone they pass, and projects' fail the same way on main.

Manually tested in tauri:dev: the section and its buckets, a Claude question keeping its bell until answered, a Claude + Codex task expanding to both tabs, and a task group moving and folding as one unit.

Supersedes #349.
Refs #298 (batches across projects and the compact-rail count are not in this PR).

nvkvin added 7 commits October 1, 2026 19:20
Lists the tasks that need you, are working or are in review above the
project tree, grouped by the Kanban board's columns, so the board's
attention half stays on screen while you work (the board itself is an
overlay that deselects the open task). Settled and Not started show a
count until opened. Off by default; a check row in the Project list
options menu and Settings > Appearance > Sidebar write the one pref.
Once on, the section starts open, and its fold and each bucket's
persist in scoped localStorage.

Buckets come only from the board's precedence: taskBoardColumn now
delegates to boardColumnFromFacts over three raw facts, and the section
calls the same function. Nothing is stored, and there is no sidebar-only
rule. The project tree does not change.

The facts live in a record of their own (useStatusTabFacts), not on
SidebarTaskFacts, so an agent starting a turn never re-renders the
Sidebar body, and the section costs nothing while it is off. Rows select
their badge as a value, carry data-status-task-id and none of the tree's
data-sidebar-* attributes, and render their badges under their own
testids, so every one-row-per-task assumption still holds.

Tests: the facts path agrees with taskBoardColumn over the whole matrix,
bucket order and filtering, the prefs' bail on unchanged values, fan-out
pins (each verified by injecting the regression), and an e2e spec of
eight cases. Docs: ui.md, performance.md, profiles.md, e2e-coverage.md.

Refs simion#298
A chevron on the section header made it the odd one out next to
PROJECTS, and the on/off switch already decides whether the section is
there. The header no longer folds, and its pref (statusSectionCollapsed)
is gone. Each bucket still folds and remembers it.

Refs simion#298
An agent blocked on the user (a permission prompt, a question) lost its
bell the moment its tab was on screen in a focused window, on opening
the task, or on switching to the tab. Nothing then said the agent was
still waiting, so a question glanced at and left unanswered read as a
finished turn: no bell, and Settled on the board and in the sidebar's
status section. docs/agent-states.md already said attention ends on
"answering it"; the code did not.

The three "seen" paths now leave an attention mark alone
(unreadClearsOnSight); every other mark still clears on sight. The bell
ends on an answer instead: any key typed in that terminal (claude's
permission prompt takes a bare digit, no Enter), a bare Escape or
Ctrl-C, or the agent's own done hook (answered through remote control,
or given up). xterm's automated replies and arrow keys begin with ESC
and do not count. Nor does a working heartbeat, since parallel
subagents fire tool hooks while one of them waits on a prompt.

Tests: the rule itself, the store's activation and tab-switch paths
with a control for the other marks, watchedBadgedTab, an e2e case that
pins dot-clears-on-sight against bell-waits-for-a-key, and the status
section's click case. Docs: agent-states.md, ui.md, e2e-coverage.md
(including the CSS-transition stall found while measuring the row).

Refs simion#298
A task group draws in the status section the way the tree draws it: a
caption in the group's colour and its members behind a rail of the same
colour. The group stays one unit, in the bucket of its most urgent
member, so a settled lead sits under Needs attention while one of its
workers asks something. Every member keeps its own badge, which is what
says why the group is there.

A layout rule over the board's buckets, not a state: each task's own
bucket is still boardColumnFromFacts. A bucket's count is task rows,
members included. The caption does not fold, rename or open a menu, and
carries data-status-group-id, never the tree's data-task-group-id, which
the task drag hit-tests. Cross-project batches (spawn trees) are the
same rule one level up and are still to come.

Refs simion#298
The case asserted that opening a task clears its attention notification,
which is the behaviour d281ef1b removed on purpose: opening is not
answering. It now pins both halves: the count holds while the task is
open and watched, and a keystroke in the terminal (a bare digit) clears
it, with the active task still listed until another is selected.

Refs simion#298
A status row showed one agent glyph, from task.cli (the agent the task
was created with), so a task running claude and codex read as claude
alone. The board answers this with extra icons on the card and the tree
with child rows; the section now follows the tree.

A row has the tree's chevron and its (n) from two terminals up, and
expands to one child per main-pane terminal tab, each with its own
agent, title and badge. A click on a child opens that tab, and the
child then carries the selection and the badges, as in the tree. The
expansion is its own pref (statusTaskExpanded, pruned of dead ids on
write), not the tree's task collapse, so opening a row here never opens
the tree's.

A collapsed row still selects values only (badge, tab count, whether a
child holds the selection); only an expanded row's children hold tabs,
through useRowTabs, since they draw the titles. The fan-out pins and the
source check cover both.

Refs simion#298
A group caption in the status section did not fold, while the tree's
does. It now folds the same way: a chevron, the member count, the
members' marks on the caption while folded (groupBadgeKinds, the tree's
own helper), and the active task's row kept in view.

It stays its own component with its own fold state
(statusGroupCollapsed, pruned of dissolved groups on write). The tree's
TaskGroupBlock carries the tree's drag, rename and menu, and its
data-task-group-id is what the task drag hit-tests, so reusing it would
put a second drop target per group under the tree's drag. Folding here
never folds the tree, and nothing in the tree changes.

The section's own fold maps (rows expanded, groups folded) now share
one pair of helpers, parseIdFlags and nextIdFlags.

Refs simion#298
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant