githubnext/chopinPublic

Let's compose rich plans together

Show unanswered decision counts on Projects sidebar rows

Document, child, and project rows in the Projects sidebar now show their
unanswered decision counts with the quiet Count the Decisions tab uses (#345).

- channel_state gains a generated unanswered_decisions column computed from
  the sidecar question records, so counts come from authoritative records and
  listing the sidebar never opens a room.
- Channel listings carry a per-document count, and the unfiltered active
  listing adds a repository total that includes documents on unloaded pages.
- A new session:decisions frame carries the committed count, repository total,
  and storage revision whenever a commit changes an open document's count and
  when a socket opens it. The client ignores counts older than what it holds.
- Each row has one trailing slot. Hover or keyboard focus swaps the count for
  the row action, and the project row's New document action now collapses like
  document actions so every count lines up at the same trailing edge.
- Touch pointers keep the count visible beside the always-shown action.
  Archived catalogue views show no counts.

Closes #345

Assistant-model: Claude Opus 5.5 (fast)
Assistant-workflow: issue-to-pr
Assistant-duration: 31m converged, estimated 3h
Assistant-verification: bun run fix passed: dprint fmt and oxlint --fix, no new warnings
Assistant-verification: bun test failed: 4039 pass, 29 fail, all in scripts/pr-maintenance because git commit signing is required in this environment; they also fail on unmodified main and pass with commit.gpgsign=false
Assistant-verification: bun run types passed: every workspace package and e2e
Assistant-verification: bun run ci passed: dprint, oxlint, tokens, design contract after renewing two reviewed owner hashes, design record, impeccable
Assistant-verification: test:postgres passed: 74 pass against a disposable postgres:17 on port 56433 (TEST_DATABASE_URL override), including SQL/TypeScript count parity
Assistant-verification: playwright e2e passed: e2e/sidebar-decision-counts.e2e.ts (hover and focus swap, alignment, touch, live ask and answer)
Assistant-verification: playwright e2e failed: 85 of 86 sidebar-adjacent specs passed; "a long description card stays inside the window" fails identically on unmodified main
Assistant-verification: agent-browser screenshot passed: running app at 1160x760 showing project total 7 and document and child counts at rest and on hover
Co-authored-by: Alex Lavaee <lavaman131@github.com>
ALAlex Lavaee authored
98a8bffPatch
Parentdc25a85
36 files changed+1494-52
StackedSplit
apps/server/src/channels/routes.test.ts+58 โˆ’0
apps/server/src/channels/routes.ts+13 โˆ’7
apps/server/src/main.ts+3 โˆ’0
apps/server/src/plan/decision-counts.test.ts+155 โˆ’0
apps/server/src/plan/service.ts+51 โˆ’1
apps/server/src/questions-service-durability-1.test.ts+4 โˆ’1
apps/server/src/questions/unanswered.test-fixtures.ts+76 โˆ’0
apps/server/src/questions/unanswered.test.ts+20 โˆ’0
apps/server/src/questions/unanswered.ts+39 โˆ’0
apps/server/src/storage/contract.ts+113 โˆ’0
apps/server/src/storage/memory/adapter.ts+25 โˆ’9
apps/server/src/storage/model.ts+8 โˆ’1
apps/server/src/storage/port.ts+2 โˆ’0
apps/server/src/storage/postgres/adapter.test.ts+24 โˆ’0
apps/server/src/storage/postgres/adapter.ts+38 โˆ’2
apps/server/src/storage/postgres/migrations.ts+3 โˆ’0
apps/server/src/storage/postgres/migrations/017_unanswered_decisions.sql+46 โˆ’0
apps/server/src/storage/postgres/research.ts+8 โˆ’1
apps/web/src/api.ts+3 โˆ’0
apps/web/src/decision-view-control.tsx+20 โˆ’0
apps/web/src/document-actions.tsx+79 โˆ’4
apps/web/src/navigation-shell.tsx+6 โˆ’1
apps/web/src/navigation.css+38 โˆ’2
apps/web/src/project-sidebar.tsx+35 โˆ’1
apps/web/src/room-workspace.tsx+7 โˆ’12
apps/web/src/sidebar-decision-counts.test.ts+280 โˆ’0
apps/web/src/use-project-documents.ts+43 โˆ’3
docs/channels.md+11 โˆ’0
docs/storage.md+1 โˆ’1
e2e/document-creation.e2e.ts+6 โˆ’1
e2e/document-navigation.e2e.ts+1 โˆ’1
e2e/hosted.e2e.ts+5 โˆ’2
e2e/playwright.config.ts+2 โˆ’0
e2e/shell.e2e.ts+3 โˆ’1
e2e/sidebar-decision-counts.e2e.ts+243 โˆ’0
packages/protocol/index.d.ts+25 โˆ’1