feat(desktop): the Call tab and a planning worker's tab read the plan's conversation on the agent tab's held read (one runtime §3.7 C)
Merged
DA
6d ago+513+513+012345678901234567890123456789-350-350-012345678901234567890123456789
One-agent-runtime §3.7, PR C of the one-held-read plan: the renderer switch. It builds on A (#2436) and B (#2437), both merged, and keeps #2433's Call tab behaviour and tests.
Compatibility (expand/contract)
- The service: still sends
plan.workand still serves/api/plans/{id}/workfor v0.12.0 desktops. - The host: still holds
planning.work; this renderer stops reading it. - Removal: dropping both, along with
planWorkOfandPlanWorkTurn, is the contract PR (D), once the release carrying this PR is the floor. - Service version: this PR needs a service with A's routes, which production has since #2436 merged.
What
work-model.ts:workRowsOfbuilds the Call tab's rows fromplanning.conversation, the plan's planning conversation as the agent tab reads a coding agent's.- Turns: each turn is its journal message. It moves while the call stands and the journal is open, and reads as ended without answering where its record names an ending, so a stopped turn still says "Stopped".
- Workers: a worker is a delegation part of the journal, standing where the page's standings (its own session) say. Its call part answers the pair its session ran on, as before.
- Stop naming and starts:
workerJobsreads eve's receipts off the journals, so a stop names its worker's job.startedAgentCallIdsreads the journals too.
plan-call.tsx: takesconversationin place ofturns/earlier. Turns are placed under their asking lines by the message's ownasked/askedAt. "Show earlier work" reads the conversation's earlier page (PLANNING_CONVERSATION_EARLIER).- A planning worker's tab is now the agent tab's own
AgentSubagentTab:- It reads its session through
/api/plans/{id}/subagents/{call}/messages(PLANNING_MESSAGES), with the plan in the agent's place, as an agent's worker tab does. - Its hover card and copy read what the tab held, or the whole session, as a delegated worker's do.
plan-work.tsx'sSubagentTabandtranscript-copy'sworkerTranscriptare deleted.
- It reads its session through
- Other consumers (
use-plans-tab.ts,side-panel.tsx,command-palette.tsx,plan-summary.tsx): worker tab holding, the agent-list re-read on Luke's starts, the Call tab's "holds something", the palette, the plan's summary and the side panel's workers all read the conversation. - Two review fixes: a worker whose session failed carries a failed ending, so its tab and cards say "Failed", not "Stopped". The transcript message gains an optional
earlierOmitted, which the planner page sets and the row reads, so a cut turn keeps its "Earlier steps are not shown." notice. Goldens are re-recorded withLUKE_UPDATE_FIXTURES=1; the only change is the new optional key. It's additive, and the service may send it before or after this desktop. agent-tab.tsx:WORKER_LEADandAgentTranscriptVieware internal again; nothing outside uses them now.
Tests
apps/desktop/src/testing/plan-work.ts: a newconversationOf(turns)builds the conversation a planner page carries from the existing turn builders, so every Call tab and work-model test reads the new path.- Fixtures moved, assertions unchanged:
plan-call.test.ts(including #2433's: a brain turn under its ask, a steered first ask, brain words and Worked-for inside the fold) passesconversation: conversationOf([...])where it passedturns;work-model.test.tsbuilds rows withworkRowsOf(conversationOf(...)).
- Changed, because a worker's session is no longer on the Call tab's wire (its own tab reads it, through the agent tab's tested
useAgentTranscript):work-model.test.ts's "a worker's session is read into parts the way a turn is… and its tab finds it among the turns" keeps its tab-finding half (workerOf) and drops the session-parts half;- the background-worker test drops its session-journal assertion.
- New in
use-plans-tab.test.ts: a planning worker's tab reads its session throughPLANNING_MESSAGESwith the plan in the agent's place and the call that started it. The test mount now hands an answered act its payload. ./scripts/check.shexits 0.
Mac UI
CI could not verify the Mac UI, and ./scripts/verify.sh was not run (no Mac here; LUKE-159 is the manual pass). The screenshots are the real components (PlanCall over conversationOf, and AgentSubagentTab over a fake planner worker reader) rendered in jsdom over the built styles.css and captured in headless Chrome. They are not the Electron window.
| Light | Dark | |
|---|---|---|
| Call tab | ![]() | ![]() |
| Planning worker tab | ![]() | ![]() |
The running turn shows its words above Luke's spoken line. That is #2433's behaviour; the same turn renders the same way on main through the old path.
🤖 Generated with Claude Code



