feat(web,desktop): a turn's "Worked for" line hangs a card saying what it ran on, when, how it ended, and its tokens
What
Dean asked for useful details when hovering "Worked for X" on every tab. Hovering anywhere on the footer line under a finished turn ("Worked for 34s · Today, 2:32 PM"), whether on the duration or the timestamp, now opens a hover card. The hover target is only as wide as the text, so the empty space beside it does not open the card. It uses the shared Tooltip card mode (#2088), so it stays open while the pointer is on it and its text can be selected. The footer is still selectable text. The footer appears in three places, all through WorkedFor: Work tab turns (Luke's brain), a planning worker's subagent tab, and coding agent and coding-agent subagent tabs.
The card shows only what the turn's row actually recorded, with no placeholders:
| Section | Shows |
|---|---|
| Head | Model + effort via the shared ModelLabel ("Opus 5.5 High", "GPT-6.1 Sol Medium"). The harness mark appears where the catalog lists the model, same as subagent rows. Luke's own Work tab turns get no mark because they don't run in a harness. On the right, Stopped / Failed / Abandoned when the turn did not finish normally. |
| When | Start → end in full, in the app's moment format ("Oct 12, 2026, 2:31 PM → 2:32 PM"). A same-day end shows only the time. |
| Tokens (under the card hairline) | Input (input not served from cache) · Output · Cache read: muted labels on the left, values right-aligned in tabular figures. No dollar cost. Hidden when the row recorded no usage (older turns). |
Left out on purpose:
- Work done counts: the finished turn's fold header already counts its calls and subagents.
- BYOK: nothing on a turn row records whose key it ran on.
- Cache write: eve's
step.completedreports it, butBrainRunUsagedrops it before the turn row is written. Recording it is a separate small follow-up PR: an optional field summed into the existingusagejsonb, plus one more card row.
Data / wire
The turns row already records model, reasoning_effort, usage (input / output / cached / reasoning), status, and failure for brain turns and coder turns alike, so nothing new is recorded. Each new wire field is optional:
coding-agent-wire.ts:turnRecordFields=model,effort,tokens{input, output, cachedInput}, andending(stopped|failed|abandoned). They are spread ontocodingAgentMessageSchema,planWorkTurnSchema, andplanWorkSessionSchema. The session'smodelkey is unchanged.hosted/turn-record.ts(new):turnRecordOf(row).catalogIdOfmoved here fromchild-models.ts.- The server fills these fields from rows its reads already fetch:
planWorkOf's turn,subagentRecordsByCall(wassubagentModelsByCall), and the coder transcript'sturnsNamedread. No new queries. - Goldens were regenerated with
LUKE_UPDATE_FIXTURES=1. The only diff is the new optional keys in the four message and plan-work schemas. - A service older than this sends none of the new fields, so the card shows only the times.
- Settled-turn refresh (Devin review): a turn that answers closes its journal before its row settles. That means a coding agent's page could read the journal without tokens or ending, and nothing would ever send it again.
turnEndednow bumps the revision of an already-closed journal in place (reviseJournal; nothing else on the row changes), so a reader past that cursor gets it again with the settled record. The Work tab does not need this: its live follow recomputes the turn on every look.
Tests
working-time.test.ts(desktop, real components): hovering an agent turn's footer shows "Opus 5.5 High" with the Claude Code mark, the start → end span, and the three token rows; a turn with no usage shows no token section; stopped, failed, and abandoned turns say so; a Work tab turn shows "GPT-6.1 Sol" with no harness mark and "Stopped". Hovering the duration part and the timestamp part of the line opens the same card. The existing footer test now hovers to reach the card where it used to readtitle.plan-work.test.ts(web, PGlite through the real relay): a finished planning turn carries its model, effort, and tokens, with no ending; cancelled and failed turns say stopped and failed; a running turn has a model but no tokens or ending yet; the stored plan work for a worker's session carries its effort, tokens, and ending.coding-agents-app.test.ts: an agent's journal message carries model and effort while it is written, then tokens andstoppedonce the turn is cancelled. A journal read between MESSAGE_COMPLETED and TURN_ENDED is read again past that cursor, this time with its tokens.hosted-store-writer.test.ts: the revision test now asserts that settling bumps the closed journal's revision (3 → 4).turn-record.test.ts:abandonedversusfailed; unreadable or missing usage gives no tokens; an empty effort gives none.
Screenshots (Chrome render of the real AgentTranscriptView / PlanWork, footer hovered)
| Light | Dark | |
|---|---|---|
| Agent tab | ![]() | ![]() |
| Work tab (stopped) | ![]() | ![]() |
Mac validation
CI could not verify the Mac UI: CI builds nothing for the Mac, and ./scripts/verify.sh was not run because this is a Linux cloud VM. LUKE-159 is the manual Mac pass. ./scripts/check.sh exits 0.
🤖 Generated with Claude Code



