feat(desktop): the Work tab draws Luke's turns with a coding agent's own transcript component (one runtime 3/n)
The third PR of the one-agent-runtime migration (docs/proposals/one-agent-runtime.md §3.7 and §5, PR 3). It is the foundation for Dean's design A: one Call tab drawn with the coding agent tab's blocks, which the mockups workspace builds on top of this PR.
What
The Work tab and a coding agent's tab already shared the transcript blocks (transcript-blocks.tsx). Each kept its own layer between the wire and those blocks: part model, fold reading, part dispatcher, tool-call adapter, subagent row, subagent tab and copy. This PR keeps the agent tab's layer and deletes the Work tab's.
work-model.tsis now an adapter. Each planning turn becomes the message a coding agent's turn is (CodingAgentMessage, AI SDK parts), andworkRowsOf(...)[i].messageis it. The Work wire already reads each call (kind, subject, description), so every call part carries that reading beside it assaid, and its row draws what the wire said.WorkBlock,WORK_READING,WorkCall,WorkerLine,WorkBlockViewandWorkTurnRowsare deleted.- One part model (
coding-agent-model.ts):AgentPart's tool part gainssaid?: SaidCall(turn-rows.ts).delegates(part)treats the planning model'sworkeras a delegation.startedAgentOf(part)reads the agent a start began, and the agent tab's fold counts it as a coding agent, as the Work tab's did.
- One tool-call adapter (
tool-call-model.ts):toolCallViewdraws a said call as said.delegationViewreads a planning worker'smessage(or its subject) as the task. - One part dispatcher and message (
agent-tab.tsx):AgentPartViewdraws a delegation of either kind as the subagent row, and a start that began an agent as the one button that opens its tab (DelegationDoors.onOpenAgent).AgentMessageis exported, andPLANNING_LEADdraws a finished turn with no harness mark.AgentTranscriptViewgainsbriefTitleandearlierOmitted.
- The Work tab (
plan-work.tsx) draws each turn as its checkpoint plusAgentMessage. Paging, reveal and the empty state are unchanged. - A planning worker's tab (
SubagentTab) is nowAgentTranscriptViewoverworkerLines(task, [session]), the same view a coding agent's worker tab uses. - Copy:
workerTranscriptreads throughagentTranscript.
No tab moves, is renamed, or merges. That is the Call tab's work (mockups workspace), which builds on these exports.
What a developer sees change
Luke's turns now behave as an agent's turns do:
- Luke's words carry the same Copy button.
- A turn that was stopped or failed folds its lead under one line, as an agent's does. Before, it stayed open.
- A call's input that the wire sent as JSON is drawn as JSON instead of plain text.
- A planning worker's tab is the agent worker tab's own view. "Nothing recorded." is now its end line.
Tests
plan-work.test.ts, new: Luke's turn draws the agent's Copy, and a stopped turn's lead folds under "1 tool call". Both fail before this change.coding-agent-model.test.ts, new:- A part's
saidreading is read. - A kind this build doesn't know is dropped.
- A planning worker is a delegation.
- A start names its agent only once one began.
- A part's
tool-call-model.test.ts, new: a said call is drawn as said, even for a tool a coding agent also has.work-model.test.tsnow reads each turn through the agent tab's ownagentRowsandtoolCallView. Folding, grouping, worker rows, stop naming, a left-running turn and worker sessions all hold.desktop-plans.test.tsandplan-work.test.ts: a planning worker's card is now the agent tab's card (data-plan-card).- All 1,049 tests across
src/renderer/planningandsrc/renderer/desktoppass. Lint, typecheck and repository checks pass.
Screenshots
The real component markup from jsdom, wrapped in the built styles.css and rendered in headless Chrome on Linux (460 px wide). Harness marks are blank because the capture page can't load the app's mark images.
| The Work tab: a finished turn folded, a running turn's open group | The finished turn's fold opened: a said command, search, the planning worker's subagent row, and the start that opens its agent | A planning worker's tab, now the agent worker tab's own view |
|---|---|---|
![]() | ![]() | ![]() |
CI could not verify the Mac UI: CI builds nothing for the Mac, and ./scripts/verify.sh was not run (LUKE-159 is the manual Mac pass).
🤖 Generated with Claude Code


