Repository navigation
feat(web): a Done section that keeps the last 7 days - #65
Merged
Merged
Conversation
The overview's Done today becomes Done: the last seven days of finished work, latest first under Today, Yesterday and dated day headings, ten rows and then Show all in Workers, which opens ⌘J on its Done. ⌘J merges Done today and Earlier into one Done section with the same day headings and all the history Earlier had. Workers archived after their PR merged stay in Done and read merged.
ANT1OFF
added a commit
that referenced
this pull request
Nov 2, 2026
The user asked for Done to show every past chat, not the last 7 days.
Done now lists **every finished chat**: workers and the solo threads
marked done, all the way back. It also gets a **group-by choice in its
header: Date (the default) or Orchestrator**. The choice is remembered,
and ⌘J's Done has the same choice.
**What Done holds**
- Every finished worker in every workspace, as ⌘J lists them: merged,
delivered, done, archived, and closed with their worktree (from the
reopen list, then the transcript archive, back to the oldest transcript
the archive keeps, up to 500 per workspace).
- Solo threads marked done, mixed in with the workers by when they
finished. "Finished" means what the old Solo threads → Done line used
(`doneSoloThreads`: `completedAt` set, settled, not parked). That line
is gone, so finished chats are in one place. A solo row keeps its
right-click menu (Reopen etc.) and can still be dragged into a pane.
- Times: workers use the same time ⌘J already used (thread
`completedAt`, else last report, else last activity; closed workers use
`closedAt`). Solo threads use `completedAt`, which `doneSoloThreads`
guarantees. The code falls back to `lastActivityAt` only in case it's
ever missing.
**Grouping** (one icon in the Done header. Its hover says "Group by
date" or "Group by orchestrator", and a click opens a menu with both)
- **Date** (default): Today, Yesterday, then weekday and date ("Fri 30
Oct") for the last 7 days, then by month ("October 2026"). Rows show
24-hour times within the week and the date ("6 Oct", or "31 Dec 2025" in
another year) under month headings.
- **Orchestrator**: one group per workspace, named as the overview names
it, plus **Solo threads**. The group with the latest finished item comes
first, and rows are latest first within each group. Each row shows its
time today, else its date.
- The choice is saved in the layout store (`doneGrouping`, persisted
with the window's layout like `reviewRequestsGrouped`). The overview and
⌘J share it.
**Paging: paginated, not virtualized**
- Done still starts folded. Opened, it shows 30 rows. A quiet **Show
more** adds 30 more each time.
- Paging runs **across the whole list**, not per group (the simpler
option): the page cuts wherever row 30 falls, even inside a group.
- The data: the web already gets every live thread in the snapshot, with
no time cut, so ledger workers and solo threads were all there. But
`orchestrator.finishedWorkers` only returned the reopen list plus the
newest **50** archive-only workers per workspace, while the archive
keeps up to 500. New additive RPC: **`orchestrator.finishedWorkersPage {
workspaceId, after? } → { workers, next? }`**. Its first page is exactly
what `finishedWorkers` returns. Later pages are the next 50 archive
transcripts past an exact `(archivedAt, threadId)` cursor, so nothing
repeats or gets skipped, even when timestamps tie. The old RPC is
unchanged.
- The web reads only a workspace's first page up front. It asks for the
next page only when "Show more" reaches rows a later page could come
before (`doneWindow`). Until that page arrives, those rows are held
back, so loading never puts a row above ones already shown.
- **"Show all in Workers (⌘J)" is removed.** Done now has everything,
across all workspaces, while ⌘J shows only one workspace, so the link no
longer added anything.
- The count in the header is everything loaded so far. When older
archive pages haven't been read yet, it grows as you page.
**⌘J**
- Done has the same grouping control and groups as the overview, solo
threads included (shown as a "Solo threads" feature by date, or their
own group by orchestrator). Workers stay sub-grouped by feature inside
each group. Same 30-row pages with Show more. Search filters all loaded
rows. An archived worker's line now carries its date ("archived 3 Oct").
**Not included / known limits**
- When Done is turned off in Settings → General, solo threads marked
done aren't listed anywhere in the overview, because the separate solo
Done line is gone. They can still be found through search and ⌘K.
- The persisted section id stays `doneToday`, as in #65, so users keep
their fold and hide settings.
- The cursor struct is written inline in the RPC payload. Using the
named `FinishedWorkersCursor` schema there made every RPC client type
collapse (TS2722 across the web). The response type uses the named
schema. There's a comment at the spot.
### Checks (all synthetic, against the mock API; no live provider)
- `bun run typecheck`: pass
- `bun run lint`, `bun run fmt:check`, `bun run check:scaffold`: pass
- vitest, web `src/orchestration src/views src/stores src/settings
src/settings-sync src/api`: 118 files, 1030 tests, pass. New
`done-model.test.ts` covers date grouping (days, months, other years,
undated last), orchestrator grouping and its ordering, solo and worker
interleaving, paging across the list, holding rows back for an unread
page in both groupings, choosing which workspace to load, and a
workspace with nothing loaded yet. `overview-extras-model.test.ts` and
`workers-model.test.ts` were updated (no time window, solo rows, month
headings, `soloWorkerRow`, `doneFeatures`, `searchRows`).
- vitest, server `finished-workers.test.ts` (new test: 120 transcripts
with non-worker ones and same-millisecond ties, paged in 3 pages, no
repeats or skips, with live and reopen-list workers excluded) plus
`service-wakes.test.ts`: pass. Contracts: 48 files, 551 tests, pass.
- Playwright `orchestration, overview-sidebar, sidebar-virtual, grid,
grid-ergonomics, drag-to-workspace, thread-actions, overview-extras,
workers-list, reaching-workers`: all pass. New cases: Show more paging
through 120 archived workers from a new mock scenario
(`simulateLongHistory`), Orchestrator grouping in the overview and in
⌘J, and the choice persisting.
- `smoke.spec.ts` "streams a scripted thread…" **fails, and fails the
same way on main (8c7bd49)** in a separate checkout. That's unrelated to
this change. Its other test passes.
- I didn't run the full `bun run check`; the merge gate runs it.
`perf-views.spec.ts` was not run (it needs `GRAM_PERF_VIEWS=1`).
### Screenshots
The pr-shots clock is fixed to mid-June, so the headings read June
dates.
**The overview at 1440 px with Pull requests and Done opened** (dark)
| Before | After |
| --- | --- |
|

|

|
**The overview at 1440 px with Pull requests and Done opened** (light)
| Before | After |
| --- | --- |
|

|

|
**Done opened on a busy week: 10 rows and Show all before; days, a page
of 30 and Show more after** (dark)
| Before | After |
| --- | --- |
|

|

|
**The same** (light)
| Before | After |
| --- | --- |
|

|

|
**Solo threads: a Done line under it before; only Parked after (the done
ones are in Done)** (dark)
| Before | After |
| --- | --- |
|

|

|
**The same** (light)
| Before | After |
| --- | --- |
|

|

|
**Done on a long history (120 archived workers), Show more pressed
twice: month groups** (after only)
| Dark | Light |
| --- | --- |
|

|

|
**Done grouped by orchestrator, with the group-by menu open** (after
only)
| Dark | Light |
| --- | --- |
|

|

|
**⌘J scrolled to Done's oldest group, with its search** (dark)
| Before | After |
| --- | --- |
|

|

|
**⌘J's Done, with a worker whose worktree was cleaned up** (dark)
| Before | After |
| --- | --- |
|

|

|
**⌘J's Done grouped by orchestrator: the workspace, then the solo
threads** (dark, after only)

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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The overview's Done today only showed what finished since local midnight, so finished work vanished overnight. It is now Done, and keeps the last 7 days.
Overview → Done
dayLabel, as Outputs uses: "Fri 30 Oct"). Row times are 24-hour.⌘J Workers
Archived and merged workers
archive_threadparks the thread) never removed a worker from the done lists. The ledger the web reads keeps parked workers as statearchived, and the model already counted them as done. Workers closed with their worktree come fromorchestrator.finishedWorkersand show as before. Both are in Done for their 7 days, and the tests now cover it.merged api#412) instead of a bare "archived", using the ledger'sstateBase.Not included
doneToday. It is stored in the layout store and synced asSettings.layout.overviewSections.doneTodayin the contracts schema, and renaming it would reset users' fold and hide choices. Only the label, component and model names changed (OverviewDone,doneRows,DoneRow,WorkersTab "done").merged 12 Octbefore today) because the worker header and the finished-worker view show it outside any day heading. Under ⌘J's day headings the date repeats the heading.Checks run (all synthetic, against the mock API; no live provider):
bun run typecheck: passbunx vitest run src/orchestration src/stores/side-panels.test.ts src/views src/settings src/settings-sync: 85 files, 765 tests, pass. New model tests cover the midnight boundary, Yesterday, the 7-day cutoff (in and out by one minute), DST-safedaysBefore, an archived-after-merge worker still in Done and reading merged, closed workers on their days, and undated rows last.bunx playwright test e2e/orchestration.spec.ts e2e/overview-sidebar.spec.ts e2e/overview-extras.spec.ts e2e/workers-list.spec.ts: 73 pass, including a new "Done shows its first ten rows, and Show all opens ⌘J on its Done".bun run lint,bun run fmt:check,bun run check:scaffold: passbun run check; the merge gate runs it.Known limits and anything left untested: no live-provider run.
perf-views.spec.tsonly had its profiler name renamed (OverviewDone) and was not run, since it needsGRAM_PERF_VIEWS=1.Screenshots
The overview at 1440 px with Pull requests and Done opened (dark)
The overview at 1440 px with Pull requests and Done opened (light)
The overview's Done opened on a busy week: its days, ten rows and Show all (dark)
The overview's Done opened on a busy week: its days, ten rows and Show all (light)
⌘J scrolled to its earlier days (Earlier before Done took it in), with its search (dark)
⌘J's Done (Done today before), with a worker whose worktree was cleaned up (dark)