feat(web,hosted): a planning turn names the spoken lines it took as its ask, and a transcript line names its row (call tab 1/3)
First of the Call tab rollout (Dean picked design A: one Call tab that reads like a coding agent's tab, the brain's work under the line that asked for it; mockups at https://stage-w2034.conductor.show/). This PR carries the link from a line to its work to the desktop. It draws nothing.
The link already exists in the store. A spoken ask's rows take the delegation (attachSpokenAsk), and the turn takes those rows (turn_id, via attachAskLines). The desktop gets that link through the one id both sides know: the client id the voice's ledger mints for a line. The live call already names its lines by it (VoiceView.callTranscript.lines[].rowId).
planWorkTurnSchema.asked(optional): the client ids of the developer's spoken rows the turn holds, in conversation order.- On the read path, one statement per page (
spokenAskRowsOf,plan-work-store.ts). - On the live follow (
live-brain.ts), read until a look finds them and kept after, so the 250 ms poll does no extra read once they're found.
- On the read path, one statement per page (
transcriptMessageSchema.metadata.rowId(optional): the row the voice wrote for a stored line, matched by its call, speaker, and where its words began (transcript-store.ts). Caption lines and rows come from the same ledger grouping.
Both fields are optional: an older desktop ignores them and an older service answers without them.
Coordinated with the one-agent-runtime rollout (#2361, PR 3 = #2365). That rollout owns the transcript part view and the later one-wire switch. This rollout owns the Call tab, and its thread model takes turns in any shape, so the one-wire PR only swaps where turns come from.
Tests (real Postgres via PGlite):
plans-app.test.ts: a stored line names its row, and a line with no row names none.plan-work.test.ts: a page of work names each spoken turn's lines in order, a typed turn names none, and another account reads none.voice-live-brain.test.ts: the live work frame names the line from the first look. This one fails without the live-brain change.
Goldens (re-recorded with LUKE_UPDATE_FIXTURES=1): live-contract-planWorkFrameSchema gains asked (array of strings, max 128 chars each, max 20 items). The four transcript-wire goldens (transcriptMessageSchema and the call, transcript, and answer schemas that hold a message) gain the optional metadata: { rowId } object. Nothing else moved.
Server and wire only, so there is no Mac UI in this PR. ./scripts/verify.sh was not run (Linux VM). CI cannot verify the Mac; LUKE-159 is the manual Mac pass.
š¤ Generated with Claude Code