Skip to content

feat(web): orchestrator → workers in the sidebar, a board that matches - #80

Merged
ANT1OFF merged 2 commits into
mainfrom
feat/simplify-sidebar-board
Nov 2, 2026
Merged

ANT1OFF merged 2 commits into
mainfrom
feat/simplify-sidebar-board

Conversation

@ANT1OFF

@ANT1OFF ANT1OFF commented Nov 2, 2026 •

Copy link
Copy Markdown
Owner

Simplifies how orchestrator work shows in the sidebar and on the Board, and makes the two agree. Presentation only: features and groups stay in the server and the ledger, and nothing in packages/ changes.

Sidebar

  • Orchestrator → workers. The feature headings are gone, in the open sidebar and the compact rail's flyout. A worker's feature stays on its hover card.
  • Order was spawn order; it is now needs you, working, waiting on CI or a review, then the rest, stable within each, with held briefs last.
  • Plain status lines. The sidebar showed the raw activity (Running grep -n …, Reading …/scratch/…, Running: a background shell • ssh …). It now goes through activityGist, the Board's own words, so a command or path can't reach a row. Waiting on CI · #69 and other headlines are unchanged.

Board

  • Ungrouped lines get an Other heading under the bands, so they no longer read as the last group's. No heading when no band is above them.
  • Line name is the worker's title, with +N for more workers. The slug moves to the hover. A line's only worker no longer repeats that title on its chip.
  • Finished work leaves for Done. A line goes when its workers are merged, delivered or archived, or when the ledger no longer has them and nothing runs, the rule the sidebar already used. The second part is what clears the stale "reported done" lines: a closed worker's card stays as it last was. A held brief, a worker still running or asking, and a merged worker that still has work going all keep a line on the Board.
  • Show archived became Show finished, and brings all of it back. It keeps the existing boardArchivedShown setting.

Decision: one-feature groups stay as bands

Stages and the plan editor live on the band. Now that finished lines leave, a group shrinks to one line mid-effort, so flattening it would make its stage disappear and reappear as work moved. Bands also stay stable when a second feature joins.

Known limits

  • A worker that only reported done, and is still in the ledger, stays on the Board because the orchestrator may act on its report. The sidebar already hides those, so the two differ there.
  • Reading is worded "Reading code" rather than "Reading a file", because this reuses the Board's words so both surfaces agree.
  • Sidebar order follows tone, so a row can move when its state changes.
  • Not run against a live provider or real workspace data: screenshots and e2e use the synthetic mock.

Verification

On this head, rebased onto main:

  • bun run typecheck, bun run fmt:check, bun run check:scaffold: pass
  • vitest run src/orchestration src/views src/thread src/sidebar src/shell: 1082 passed
  • bun run --filter @gram/web e2e overview-sidebar board-parity board-rail board-virtual feature-sheet orchestration workers-list held-briefs worker-questions getting-around --workers=1: 105 passed, 1 failed
    • The failure is orchestration.spec.ts:1870, the digest's report evidence, which this change doesn't touch. It passed in the earlier run and 3/3 with --repeat-each=3 alone, so I read it as a flake under load on a shared machine.
  • Not run: the full bun run check, left to the merge gate.

The e2e caught one real bug on the way: an Other heading as its own list entry had no tab stop, so Tab died there. The heading now belongs to the first ungrouped line's entry, and board-virtual's Tab test covers it. Specs that pinned the old headings and Show archived are updated, not deleted.

Screenshots

The sidebar's workers under their orchestrator, plain status lines, and the Board beside (dark)

Before After
overview-board-dark before overview-board-dark after

Board: finished work gone to Done, Show finished in the bar brings it back (dark)

Before After
board-finished-dark before board-finished-dark after

The sidebar lists an orchestrator's workers straight under it, most urgent
first, with status lines in plain words. The Board names lines by their
worker, keeps ungrouped lines out of the group above them, and leaves
finished work to Done. Presentation only: features and groups stay in the
server and the ledger.
@ANT1OFF
ANT1OFF force-pushed the feat/simplify-sidebar-board branch from 6cca457 to ce84660 Compare November 2, 2026 04:49
@ANT1OFF
ANT1OFF merged commit 686e737 into main Nov 2, 2026
22 checks passed
@ANT1OFF
ANT1OFF deleted the feat/simplify-sidebar-board branch November 2, 2026 05:06
ANT1OFF added a commit that referenced this pull request Nov 2, 2026
Calmer, believable README screenshots, on top of #80's orchestrator →
workers sidebar and Board, plus a new Quiet screenshot and a short
section explaining it.

### What changed
- **Hero** (`docs/assets/gram-orchestrator.png`, 1600×1250, 87 KB): an
ordinary morning in one workspace, `storefront`. You can follow the flow
top to bottom: your task, the orchestrator's reply that it started six
workers, a card per feature with each worker's state and PR, then the
one question waiting on you. Two workers are running, one is on CI, one
is in review and two have merged. Nothing else asks, there's no usage
warning, and the right panel is closed. The sidebar reads "1 needs you".
- **Board** (`docs/assets/gram-board.png`, 1600×943, 59 KB): the same
scene with the sidebar hidden, at 1120 px wide, so rows read at README
width. At 980 px the cards truncated ("checks ru…"), so I kept 1120.
- **Quiet** (`docs/assets/gram-quiet.png`, new, 1600×1000, 39 KB): the
same one ask as Quiet's card over an empty window, with the workspace's
dots along the bottom.
- **README**: new alt text for the hero and Board, and a `## Quiet`
section after How it works.
- **Reusable scene**: `simulateReadme` in
`apps/web/src/api/mock-readme.ts` (synthetic `storefront` across the
mock's `api`/`web` repos), wired through the mock like
`simulateQuietBusy`. Three pr-shots entries (`readme-hero`,
`readme-board`, `readme-quiet`, dark, default look) capture the images.
The README images are those captures resized to 1600 px wide and
palette-quantised.

The Quiet text describes only what the code does. You open Quiet with
the moon button (`QuietToggle`) or `mod+alt+4` (`view.quiet`), and leave
with Esc (`quiet.leave`). The deck shows one card at a time, the strip
shows a dot per worker, and "Quiet when idle" lives under Settings →
General → Interruptions, after five idle minutes with nothing asked.

### Rendered README (dark, 880 px wide, GitHub's own Markdown renderer)

**Top**

| Before | After |
| --- | --- |
| ![top
before](https://github.com/user-attachments/assets/6467a49a-ff65-4eca-9034-8dd1996e47ed)
| ![top
after](https://github.com/user-attachments/assets/bba7ad05-e7e7-4992-b81c-00b65f607f86)
|

**How it works through Quiet**

| Before | After |
| --- | --- |
| ![lower
before](https://github.com/user-attachments/assets/19b53678-9d2c-4075-9666-3b9bcf19f386)
| ![lower
after](https://github.com/user-attachments/assets/66e427f0-7021-402a-8e06-8d2e141bb1bd)
|

### Verification
- `bun run check:docs`, `bun run check:scaffold`, `bun run fmt:check`,
`bun run typecheck`: pass
- `vitest run src/api` (web): 17 files, 107 tests passed
- `bun run --filter @gram/web pr:shots --shot
readme-hero,readme-board,readme-quiet --after-only`: 3 passed; every
image inspected
- Not run: the full `bun run check`; that's left to the merge gate.

### Known limits
- All data is synthetic mock data. Seeded solo threads that ask
(`t-flaky`, `t-question`, `t-plan`) and two that read oddly out of
context are parked for these shots.
- The existing `quiet-busy` pr-shot already fails on `main`: the seeded
solo threads ask, so Quiet shows a card instead of `quiet-empty`. I
didn't touch it here.
- Light mode isn't captured; the README uses the default Dark look.
ANT1OFF added a commit that referenced this pull request Nov 2, 2026
…t agree (#92)

Three simplifications to the sidebar and Board that follow #80.
Presentation only: nothing in `packages/` or the server ledger changes.
The PR chips and the Pull requests section are unchanged.

### 1. One attention count
Before this change, the needs-you pill counted the Needs you list, while
each workspace badge, the switcher row, the ask stack ("5 asks") and the
Board's chip ("2 waiting on you") each counted something different. A
badge counted only asks, so it could disagree with the list it sat
beside.

- A new selector, `needsYouCounts(groups)` (in `needs-you-items.ts`),
derives every count from the one Needs you list: the total plus each
workspace's share. `useNeedsYouCounts` exposes it, and the pill, the
window title and dock badge (`needsYouCount`), the open sidebar's
workspace badge, the compact rail's tile badge and the workspace
switcher all read it.
- A workspace badge now equals its section of Needs you, failures and
waits included. The badges plus the solo threads' section add up to the
pill.
- Two counts are removed because they only repeated a neighbour:
- The ask stack's "N asks" header becomes "Asks". Its 1/N stepper
already says how many.
  - "2 in billing" becomes "Also in billing".
- The Board's waiting chip keeps its icon and label but drops its
number.
- The tests read `data-count` instead of the removed text.

### 2. The sidebar and the Board agree on which workers show
**The rule** (`workerShown`, in `orchestration/worker-shown.ts`) is the
one ⌘J already uses to put a worker in Done (`workerWait` → the Done
bucket):
- A worker that is at work now, or asking you, always shows.
- An archived worker never shows.
- Otherwise a worker shows while the ledger has it and its work isn't
over. A worker that reported done, merged or delivered still shows while
it has an **open PR or something pending**: a request, a standing
blocked/question report, a wake, a monitored run, or you holding it.
- Done with nothing left, or gone from the ledger: it leaves both the
sidebar and the Board and lives in Done. Show finished brings it back on
the Board.
- Before the ledger is read, the card's state decides.

`ledgerWorkersOver` (in `workers-model.ts`) computes "over" once from
the ledger. Four places now use the rule: the sidebar's rows
(`overviewFeatures`), the orchestrator line's "N workers"
(`workerTones`), the compact rail, and the Board's lines (`railRows`). A
Board line draws only the workers that show and leaves for Done when
none do and it has no held brief. The feature sheet still lists all of a
feature's non-archived workers.

- **Line names.** A line with several workers is named by its feature
(`mail-trigger`), not "first worker +N". Its hover says how many workers
it has.
- **Empty Board.** A Board whose work is all finished says "Nothing
going now / Finished work is in Done" instead of "No features yet".

### 3. Quieter rows
- Sidebar rows drop "Step N of M ·" (`steplessLine`). The full line is
in the row's tooltip and on its hover card.
- A Board line shows its repo names only when the workspace has more
than one repo. These lines were the only rows that named a repo.

### Behaviour changes worth knowing
- On the Board, a merged worker on a line that is still going used to
sit in the Merged column. It is now in Done until Show finished, as in
the sidebar, so the Merged column is mostly empty except while something
is pending, such as a monitored release run.
- A line whose plan still has steps, but whose workers are all done with
nothing left, leaves the Board. The next worker the orchestrator spawns
brings it back.

### Known limits
- The menu bar's tray and Quiet still count the asks they list and
answer. They aren't Needs you surfaces, so I left them alone.
- An archived worker with failing CI nobody fixes: ⌘J lists it under
Now, but the sidebar and the Board hide it (archived never shows). Its
failure is still in Needs you.
- Not run against a live provider or real workspace data. Tests and
screenshots use the synthetic mock.

### Verification
- `bun run typecheck`, `bun run lint`, `bun run fmt:check`, `bun run
check:scaffold`: pass
- `vitest run src/orchestration src/views src/shell src/sidebar
src/desktop src/thread`: 1148 passed. New tests:
- `worker-shown.test.ts`: the rule, plus the sidebar, the Board and the
worker tally showing the same workers from one mixed ledger.
- `needs-you-source.test.tsx`: in a mixed scenario (asks, failures, a
wait, a solo error, an ask put away for Later), the pill, every badge,
the title count and the list sections are equal.
  - `steplessLine` and line-naming cases.
- `bun run --filter @gram/web e2e overview-sidebar board-parity
board-rail board-virtual feature-sheet orchestration ask-stack
waiting-on-you worker-questions views-and-layout one-bar
orchestration-memory workspace-density workers-list held-briefs
--workers=1`: 127 passed, 4 failed.
- All 4 failures pinned the old behaviour: merged or reported-done
workers on the Board, and the chip's number. I updated them, not
deleted, and they pass (4/4).
- `ask-stack.spec`'s count test now checks, in the app, that the pill
equals the panel's item count and that each badge equals its panel
section and the switcher's row.
- Not run: the full `bun run check`, left to the merge gate.

### Screenshots

**Board: the ask stack's scenario as feature lines, the stack docked
below** (dark)

| Before | After |
| --- | --- |
| ![board-view-dark
before](https://github.com/user-attachments/assets/66997ffd-947f-421d-9c79-52badd08ade2)
| ![board-view-dark
after](https://github.com/user-attachments/assets/cfc2a20f-fd11-47bb-9481-abd54b65504e)
|

**Board: the header's controls, and its waiting chip unfolding Waiting
on you** (dark)

| Before | After |
| --- | --- |
| ![board-waiting-dark
before](https://github.com/user-attachments/assets/6268b289-af10-4f48-bb3d-1add5128212b)
| ![board-waiting-dark
after](https://github.com/user-attachments/assets/30152c36-f35a-4442-a263-d13fe1e281d3)
|

**The sidebar's workers under their orchestrator, plain status lines,
and the Board beside** (dark)

| Before | After |
| --- | --- |
| ![overview-board-dark
before](https://github.com/user-attachments/assets/72e20e0d-04e5-4253-bd02-8d1cc7d41429)
| ![overview-board-dark
after](https://github.com/user-attachments/assets/5bb6779b-5e14-4215-bbc5-c8b6f2f7844c)
|

**Board: finished work gone to Done, Show finished in the bar brings it
back** (dark)

| Before | After |
| --- | --- |
| ![board-finished-dark
before](https://github.com/user-attachments/assets/97fa05b8-bb9e-4d66-9c4a-53dd4f10fdee)
| ![board-finished-dark
after](https://github.com/user-attachments/assets/fffd38b3-8fc4-4fd2-a458-08a761125f24)
|
ANT1OFF added a commit that referenced this pull request Nov 2, 2026
Desktop release metadata proposal only. Merging this PR does not publish
or tag Gram; follow docs/RELEASING.md to release.
---


## [1.4.0](v1.3.1...v1.4.0)
(2026-11-02)


### Features

* **agents:** identify Gram's Claude processes as the gram entrypoint
([#91](#91))
([f7dd703](f7dd703))
* **desktop:** run on Linux
([#82](#82))
([1d37deb](1d37deb))
* **desktop:** turn voice input off on Linux with one check
([#79](#79))
([470ff8b](470ff8b))
* **orchestration:** a person's PR comment wakes the worker that owns it
([#86](#86))
([19bdc1c](19bdc1c))
* **orchestration:** a wrap-up turn when a worker stops without
reporting ([#88](#88))
([36a07fb](36a07fb))
* **orchestration:** workers say what they ruled out and check before
repeating ([#90](#90))
([8bdce01](8bdce01))
* **release:** publish and update Linux AppImage and .deb
([#95](#95))
([c33c464](c33c464))
* **voice:** an accurate mode with a Parakeet pass on each pause
([#83](#83))
([2b04a52](2b04a52))
* **voice:** hold one key to talk, with a tone at each end
([#87](#87))
([1a9b3ef](1a9b3ef))
* **voice:** start capture at the press, and an opt-in ready microphone
([#81](#81))
([505d240](505d240))
* **web:** a Done section that keeps the last 7 days
([#65](#65))
([8c7bd49](8c7bd49))
* **web:** Done lists every finished chat
([#67](#67))
([c91d9ac](c91d9ac))
* **web:** one attention count, quieter rows, a sidebar and board that
agree ([#92](#92))
([f193da4](f193da4))
* **web:** orchestrator → workers in the sidebar, a board that matches
([#80](#80))
([686e737](686e737))


### Bug Fixes

* **desktop:** harden the Linux key vault and autostart entry
([#85](#85))
([4b35eac](4b35eac))
* **e2e:** hold the t-flaky turn while the smoke test reads its opening
line ([#93](#93))
([2edc4ac](2edc4ac))
* **e2e:** release the dictation tap as soon as a word is heard
([#94](#94))
([7781194](7781194))
* prepare only approved local-check sources
([#32](#32))
([af3fab7](af3fab7))
* repair main after [#32](#32)
([#68](#68))
([ce352e6](ce352e6))
* **voice:** keep the last word after release
([#78](#78))
([cc40a47](cc40a47))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Co-authored-by: gram-release-please[bot] <351321620+gram-release-please[bot]@users.noreply.github.com>
Co-authored-by: Johan <32440065+ANT1OFF@users.noreply.github.com>
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