B — PROJECT LEDGER

Each project owns a dedicated Tasks surface: a dense, stable ledger — a flat list, no board — that sits beside the thread list and can grow to hundreds of rows without noise. The project, not a global inbox, is the unit of focus. Rows never reorder on status change; signals appear as inline chips only when true; done work settles into a collapsed tail. Detail opens in a right panel so the list never leaves the screen.

TESTED AGAINST: busy ledger (9+ tasks) · empty state · task detail w/ provenance + attempts · conversation capture · start attempt (provider choice) · blocked · done w/ evidence + reopen · mobile list · mobile capture

B1 · PROJECT LEDGER — BUSY (t3code / Tasks)
1 2 3 4 5 6
t3code/Tasks
Open 11· Blocked 2· Snoozed 3· Done 41 Group: none ▾
Pinned
📌#245 Focus ring lost after closing command palette with Esc attempt · working 6w
Open · 11
#249 Crash: renaming a thread while its agent is settling suggested by agent Accept · Dismiss 2d
#244 Purge job for settled threads past retention window blocked · waiting on #231 1w
#241 Add test for snooze across DST boundary 3w
#238 Thread list flickers on reconnect when >200 threads ↗ GH-1204 4w
#231 Decide retention policy for settled threads blocked · needs decision 5w
#229 Composer stash lost when switching projects 6w
#198 Focus outline invisible on amber buttons dup? #245 9w
Done · 41
#212 Migrate diff renderer to @pierre/diffs v3 5w
#207 Empty-state copy for archived threads 7w
1Project header carries a small mono # 14 count chip (hover / always) — 11 open + 3 snoozed, never counting done. Clicking it, or the pinned "Tasks" row beneath, opens this surface. The chip mirrors the ledger exactly; the honesty contract that keeps the surface alive.
2One thin filter row is the entire chrome: segmented text counts, right-aligned search, a "Group: none ▾" ghost. No toolbar, no view switcher, no board.
3Pinned tasks float to a top group with a pin glyph; everything below sorts stable by id desc. Rows never reorder on status change — a stable list is what makes a 300-row ledger trustworthy.
4Signal chips render only when true: amber blocked (with the dependency named), sky pulsing live attempt, ↗ when promoted to GitHub, faint "dup?" hint. A quiet row is a quiet row.
5#249 was suggested by an agent mid-thread — it sits in the ledger as a proposal with inline Accept · Dismiss; nothing enters the count until a human accepts.
6Done collapses into a "Done · 41" tail section, same gesture as the sidebar's Settled tail — finished work settles downward instead of cluttering the working set.
B3 · TASK DETAIL — #245 IN THE RIGHT PANEL (LIST STAYS PUT)
1 2 3 4
t3code/Tasks
Open 11· Blocked 2· Snoozed 3· Done 41
Pinned
📌#245 Focus ring lost after closing command palette… working 6w
Open · 11
#249Crash: renaming a thread while its agent is settling2d
#244Purge job for settled threads past retention…blocked1w
#241Add test for snooze across DST boundary3w
#238Thread list flickers on reconnect when >200…4w
#231Decide retention policy for settled threadsblocked5w
#229Composer stash lost when switching projects6w
#198Focus outline invisible on amber buttons9w
Done · 41
#245 Open 📌 pinned opened 6w ago
Focus ring lost after closing command palette with Esc
▸ Start Snooze Done •••
Esc closes the palette but focus returns to <body>, so the ring disappears until the user tabs. Repro on Safari + Chrome. Likely the restoreFocus path in usePalette.
Provenance
Logged from Focus ring bug — #245 · 6w ago
"after I hit Esc the focus ring is just gone — tab does nothing visible until I click somewhere. log that as a task"
Files
apps/web/src/hooks/usePalette.ts apps/web/src/components/CommandPalette.tsx
Attempts
Focus ring bug — #245 Working now
Focus ring repro spike Failed 3w
▸ History · 7 events
1Selecting a row opens detail beside the list — the T3 diff-panel pattern. Selection ≠ navigation: the ledger never leaves the screen, so triage keeps its rhythm.
2Panel header = identity, status, flags, age, then Start (primary) · Snooze · Done · ••• (Drop, Promote to GitHub, Copy id). Everything destructive or rare hides behind •••.
3Provenance is first-class: origin thread, age, and the exact quoted excerpt that spawned the task, with "Open origin thread →" jumping to the anchored chip in the timeline.
4Attempts are threads, each wearing its own thread-status pill. A failed attempt does not touch the task: it stays Open until a human marks it Done.
B4 · CAPTURE MID-CONVERSATION — LOG MODE + CONFIRMATION CHIP
1 2 3 4 5
t3code/Reconnect flicker fix Working
the flicker is back when the socket drops on a big workspace — can you chase it down?
Reproduced with 240 threads. The reconnect handler re-mounts the whole virtual list; I'll debounce the reconnect events and diff the thread snapshot instead.
Debounce reconnect events in ThreadListStore 4/7
#246 Composer loses draft when the socket reconnects Logged
Logging a task — won't interrupt the agent
# reconnect also wipes whatever I had typed in the composer claude · opus
1The agent's Working pill stays sky and pulsing the entire time — capture never interrupts a run.
2Plan chip = the agent's execution checklist: chevron, pip segment bar, current step, 4/7. Deliberately distinct from tasks — pips mean "the run's steps", never "your ledger".
3Confirmation is this inline chip and nothing else — no toast. The chip IS the provenance anchor: #245-style detail links back to this exact spot in the timeline, so confirmation and provenance are one object.
4Typing # first flips the composer to log mode: thin indigo top border + hint line. Enter logs to this project's ledger and quietly returns the composer to normal.
5Chip anatomy: #246 mono id, inferred title, small "Logged" affirmation. One line, subtle border — never a card, no pips.
B5 · STARTING #245 — ATTEMPT ≠ STATUS
1 2
#245 Open Focus ring lost after closing command palette…
▸ Start Snooze •••
Start attempt on #245
New focused thread
Opens "Focus ring — #245" seeded with description, quote & files
codex · gpt-5.3
Continue here
Hand #245 to the current thread's agent
Cancel Start
Resulting focused thread
t3code/ Focus ring — #245 Working
…and the ledger row, meanwhile
📌#245 Focus ring lost after closing command palette… attempt · working Open 6w
1Start defaults to a new focused thread, seeded from the task; the provider + model chip (codex · gpt-5.3) is selectable — tasks are provider-neutral by design. "Continue here" reuses the current thread instead.
2Task status ≠ run status. The row wears a sky pulsing "attempt · working" chip while the status pill stays Open — "in progress" is a property of the attempt thread, never of the task.
B2 · EMPTY LEDGER — A NEW PROJECT
xenforo-cloud/Tasks
#
Nothing logged yet. While an agent works, type # in the composer — or just say "log that as a task."
·No count chip on the project header while the ledger is empty — the chip only exists when it has something honest to say. Empty state teaches the capture gesture, not the surface.
B6 · DONE TASK DETAIL — EVIDENCE + REOPEN (INSET)
#212 ✓ Done closed 5w ago · open for 3w
Migrate diff renderer to @pierre/diffs v3
↩ Reopen •••
Verification
Swapped the legacy renderer for @pierre/diffs v3 behind a flag, soaked for a week, removed the flag. Word-level highlights now match upstream; no perf regression at 4k-line diffs.
pnpm test — 214 passed ▣ screenshot diff +38 −6
▸ History · 11 events
·Done is a claim with receipts: agent summary + evidence chips (tests, screenshot, diff stat) and a ghost Reopen. Reopening restores the row to its stable id-desc slot — no reshuffle.
B7 · MOBILE — PROJECT SCREEN, TASKS SEGMENT (+ MENU OPEN)
9:41▂▄▆ ▮
Threads 8
Tasks 14
📌 Pinned
#245 Focus ring lost after closing palette… working 6w
Open · 11
#249Crash: renaming a settling threadsuggested2d
#244Purge job for settled threadsblocked1w
#241Snooze test across DST boundary3w
#238Thread list flickers on reconnect4w
#231Retention policy for settled threadsblocked5w
#229Composer stash lost switching projects6w
▸ Done · 41
💬New thread
#Log task
Rename project
·Project screen gains a segmented control — Threads | Tasks — same ledger rows adapted to 320px; task detail is a pushed screen. The "+" menu carries a "Log task" row with the # sigil for capture outside any thread.
B8 · MOBILE — QUICK CAPTURE IN A THREAD (# ABOVE THE KEYBOARD)
9:41▂▄▆ ▮
the flicker is back on big workspaces — chase it down?
Reproduced with 240 threads. Debouncing the reconnect events and diffing the snapshot instead of re-mounting the list.
#246 Composer loses draft on reconnect Logged
Logging a task — won't interrupt the agent
# reconnect also wipes my draft
# Log task @ File / Command
·The # chip lives in the accessory bar above the keyboard; tapping it (or typing #) flips the composer to log mode — same indigo top border, same hint, same inline chip confirmation as web. One gesture, both platforms.