Repository navigation
refactor(*): the dag card hands its graph to the desk task pane - #611
Conversation
The orchestration card in the transcript drew its own graph and, under it, a node panel whose "open the run" link raised the old agents-panel record window. The desk's task pane already draws the same graph and reads the same dag.node record, node by node, so the card was a second renderer for work the desk owns. The prototype's card is the grid alone, with the task cell as the door to the run. - The card keeps its grid and nothing else. The task cell is a door (role=button, title, a standing arrow) whenever the run has an id, and opens the run's task pane on the desk; a playbook load has it as soon as dag.run_started names the run, before dag.get supplies a title. - openDagRun goes through the tasks seam: openRun when the store holds the row, one tasks.list read when it does not, the tasks tab when neither answers. The delivered row already went through openDagRun and follows. - The node panel, its inputs and template rows, the openDagNode seam and features/dag/open.ts go; so do the 21 catalogue keys only the panel read, the dag-renderer gate whose CSS is gone, and the four import-direction rows those imports held. - The desk's node panel carries the node id on its title, which the deleted panel used to spell out; the first failed node is no longer opened unasked -- the desk pane's banner names it. - Five binding tests for dagFeed read the node states through a test seam now that the card draws none. Co-authored-by: Claude (claude-sonnet-5) <noreply@anthropic.com> Co-authored-by: Claude (claude-fable-5-1) <noreply@anthropic.com>
With the transcript card gone, the desk's task board is DagGraph's only caller and it hands the renderer its own node card. The default SVG box -- rect, status mark, two-line label, tooltip -- its card surface and five-layer cap, the shared-prefix label trimming and the per-node clock had no reader left. - DagGraph draws layout, edges, selection and the node's click and keyboard handling; renderNode is required and surface is gone. - graph.ts keeps depths, layout (dims required), layers and shape; the sheet and card dims, the mark table and took go. - labels.ts, the dag-label-css gate, the box's rules in page.css and the board's override of the group dimming those rules did go with it, as do the one catalogue key the layer cap read, nodes.ts's settled (the clock was its last reader) and the composer's svg work glyph, whose only reader was the box. Co-authored-by: Claude (claude-sonnet-5) <noreply@anthropic.com> Co-authored-by: Claude (claude-fable-5-1) <noreply@anthropic.com>
gloryfromca
left a comment
There was a problem hiding this comment.
No blockers; suggestions only, and they are marked inline.
The refactor has one task renderer after the transcript card hands off through the tasks seam, and the removed DAG renderer surface, CSS, catalogue keys, and tests have no remaining callers. The new summary/door behavior and the narrowed caller-supplied DagGraph contract are covered well.
I checked AGENTS.md/CLAUDE.md and the Web UI context, the full diff, surrounding callers, commit history, compatibility of the removed exports and i18n keys, and that the tests were replaced with state/door assertions rather than merely weakened. I found one nonblocking stale-response race in the fallback opener, marked inline.
Verification: npm test (188 files, 2,464 tests passed); npm run type-check (passed); npm run lint (passed with four existing hook warnings in untouched files). git diff --check passed.
## Summary The orchestration card in the transcript (a `run_subagent_dag` or `load_playbook` row, expanded) drew a graph of its own and, under it, a node panel whose "open the run" link raised the old agents-panel record window. The desk's task pane already draws the same graph and reads the same `dag.node` record, node by node, so the card was a second renderer for work the desk owns. The prototype's card is the grid alone, with the task cell as the door to the run. This PR makes the card that. Two commits, the second deleting only what the first killed: 1. **The card hands its graph to the desk.** The card keeps its grid (task, scale, playbook, state, cost, run id, replanned-into) and nothing else. The task cell is a door -- `role=button`, a title, a standing arrow -- whenever the run has an id, and opens the run's task pane on the desk. `openDagRun` goes through the tasks seam: `openRun` when the tasks store holds the row, one `tasks.list` read when it does not, the tasks tab when neither answers (a branched conversation replaying its parent's delivered row lands there). The delivered row already went through `openDagRun` and follows. The node panel, the `openDagNode` seam, `features/dag/open.ts`, the 21 catalogue keys only the panel read and the `dag-renderer` gate go. 2. **The renderer's default box goes.** The desk's board is `DagGraph`'s only caller and hands it its own node card, so the default SVG box, the card surface, the label trimming, the mark table and the per-node clock had no reader left. User-visible changes besides the door: the first failed node is no longer opened unasked inside the card (the desk pane's failure banner names it, one click away); a node's internal dependencies are read off the board's edges rather than a list; the node id, which the deleted panel spelled out, rides on the desk node panel's title. Left for a follow-up, deliberately: `features/dag/mount.ts` and `store.ts` (the run state `state/session/resume.ts` still writes and nothing reads) -- deleting them means either a new row on `domain-shape`'s shrink-only exceptions or dissolving `features/dag/` into its two remaining consumers, which is a decision of its own. ## Type - [ ] Fix - [ ] Feature - [ ] Docs - [ ] CI / tooling - [x] Refactor - [ ] Other ## Verification - `npm test --prefix ui-web` -- 188 files, 2464 tests, all pass (three suites fewer than the base: the two deleted gates and the deleted label suite) - `npm run type-check --prefix ui-web` -- clean - `npm run lint --prefix ui-web` -- 0 errors (4 pre-existing warnings in CronPage/SubagentsPage, untouched here) - `node ui-web/scripts/check-class-namespace.mjs` -- OK; the transcript and dag pins lowered to what the tool prints - `npm run --prefix ui-tui lint:i18n` -- generated catalogue up to date - `npm run --prefix ui-web build && python3 ui-web/build.py` -- boot-snapshot OK (235 nodes match golden) Driven on a real host (`raven serve` from this branch on an isolated `RAVEN_HOME` built from a real config, deepseek as the default model, every channel off), with a playwright driver against the served page: | Step | Result | | --- | --- | | Expand the card of a running three-node graph | grid only, no graph, no node panel; task cell is `role=button` with a title and the arrow; a long title is cut and the arrow stays in view | | Click the task cell | exactly one desk pane, `task:dag:<run_id>`, headed by the run's summary, showing the board | | Click a node on the board | the desk's node panel with the node's record | | Click the task cell again | no second pane | | Click the delivered row after the run settles | the same pane | | Reload, expand the restored card, click | the same pane | | A graph with one node on a lane that cannot reach its model | the card's state row counts `1 failed`; the desk pane shows the failure banner before any node is picked; the banner opens the failed node | | The board before and after commit 2 | screenshots identical (node cards, edges, lane frames) | - [x] Relevant tests pass locally - [x] Relevant lint / type checks pass locally - [ ] User-facing docs or screenshots are updated when needed ## Risk Web UI only; no server or wire change. The transcript card loses its graph and node panel on purpose; every fact they showed is on the desk's task pane, reached from the card's task cell and from the delivered row. `features/dag/mount.ts` keeps running unchanged. Rollback is reverting the squash commit. - [x] Security impact considered - [x] Backward compatibility considered - [x] Rollback path is clear for risky changes ## Related Issues N/A --------- Co-authored-by: Claude (claude-sonnet-5) <noreply@anthropic.com>
## Summary The orchestration card in the transcript (a `run_subagent_dag` or `load_playbook` row, expanded) drew a graph of its own and, under it, a node panel whose "open the run" link raised the old agents-panel record window. The desk's task pane already draws the same graph and reads the same `dag.node` record, node by node, so the card was a second renderer for work the desk owns. The prototype's card is the grid alone, with the task cell as the door to the run. This PR makes the card that. Two commits, the second deleting only what the first killed: 1. **The card hands its graph to the desk.** The card keeps its grid (task, scale, playbook, state, cost, run id, replanned-into) and nothing else. The task cell is a door -- `role=button`, a title, a standing arrow -- whenever the run has an id, and opens the run's task pane on the desk. `openDagRun` goes through the tasks seam: `openRun` when the tasks store holds the row, one `tasks.list` read when it does not, the tasks tab when neither answers (a branched conversation replaying its parent's delivered row lands there). The delivered row already went through `openDagRun` and follows. The node panel, the `openDagNode` seam, `features/dag/open.ts`, the 21 catalogue keys only the panel read and the `dag-renderer` gate go. 2. **The renderer's default box goes.** The desk's board is `DagGraph`'s only caller and hands it its own node card, so the default SVG box, the card surface, the label trimming, the mark table and the per-node clock had no reader left. User-visible changes besides the door: the first failed node is no longer opened unasked inside the card (the desk pane's failure banner names it, one click away); a node's internal dependencies are read off the board's edges rather than a list; the node id, which the deleted panel spelled out, rides on the desk node panel's title. Left for a follow-up, deliberately: `features/dag/mount.ts` and `store.ts` (the run state `state/session/resume.ts` still writes and nothing reads) -- deleting them means either a new row on `domain-shape`'s shrink-only exceptions or dissolving `features/dag/` into its two remaining consumers, which is a decision of its own. ## Type - [ ] Fix - [ ] Feature - [ ] Docs - [ ] CI / tooling - [x] Refactor - [ ] Other ## Verification - `npm test --prefix ui-web` -- 188 files, 2464 tests, all pass (three suites fewer than the base: the two deleted gates and the deleted label suite) - `npm run type-check --prefix ui-web` -- clean - `npm run lint --prefix ui-web` -- 0 errors (4 pre-existing warnings in CronPage/SubagentsPage, untouched here) - `node ui-web/scripts/check-class-namespace.mjs` -- OK; the transcript and dag pins lowered to what the tool prints - `npm run --prefix ui-tui lint:i18n` -- generated catalogue up to date - `npm run --prefix ui-web build && python3 ui-web/build.py` -- boot-snapshot OK (235 nodes match golden) Driven on a real host (`raven serve` from this branch on an isolated `RAVEN_HOME` built from a real config, deepseek as the default model, every channel off), with a playwright driver against the served page: | Step | Result | | --- | --- | | Expand the card of a running three-node graph | grid only, no graph, no node panel; task cell is `role=button` with a title and the arrow; a long title is cut and the arrow stays in view | | Click the task cell | exactly one desk pane, `task:dag:<run_id>`, headed by the run's summary, showing the board | | Click a node on the board | the desk's node panel with the node's record | | Click the task cell again | no second pane | | Click the delivered row after the run settles | the same pane | | Reload, expand the restored card, click | the same pane | | A graph with one node on a lane that cannot reach its model | the card's state row counts `1 failed`; the desk pane shows the failure banner before any node is picked; the banner opens the failed node | | The board before and after commit 2 | screenshots identical (node cards, edges, lane frames) | - [x] Relevant tests pass locally - [x] Relevant lint / type checks pass locally - [ ] User-facing docs or screenshots are updated when needed ## Risk Web UI only; no server or wire change. The transcript card loses its graph and node panel on purpose; every fact they showed is on the desk's task pane, reached from the card's task cell and from the delivered row. `features/dag/mount.ts` keeps running unchanged. Rollback is reverting the squash commit. - [x] Security impact considered - [x] Backward compatibility considered - [x] Rollback path is clear for risky changes ## Related Issues N/A --------- Co-authored-by: Claude (claude-sonnet-5) <noreply@anthropic.com>
Summary
The orchestration card in the transcript (a
run_subagent_dagorload_playbookrow, expanded) drew a graph of its own and, under it, a node panel whose "open the
run" link raised the old agents-panel record window. The desk's task pane already
draws the same graph and reads the same
dag.noderecord, node by node, so thecard was a second renderer for work the desk owns. The prototype's card is the grid
alone, with the task cell as the door to the run. This PR makes the card that.
Two commits, the second deleting only what the first killed:
playbook, state, cost, run id, replanned-into) and nothing else. The task cell is
a door --
role=button, a title, a standing arrow -- whenever the run has anid, and opens the run's task pane on the desk.
openDagRungoes through thetasks seam:
openRunwhen the tasks store holds the row, onetasks.listreadwhen it does not, the tasks tab when neither answers (a branched conversation
replaying its parent's delivered row lands there). The delivered row already
went through
openDagRunand follows. The node panel, theopenDagNodeseam,features/dag/open.ts, the 21 catalogue keys only the panel read and thedag-renderergate go.DagGraph's onlycaller and hands it its own node card, so the default SVG box, the card
surface, the label trimming, the mark table and the per-node clock had no
reader left.
User-visible changes besides the door: the first failed node is no longer opened
unasked inside the card (the desk pane's failure banner names it, one click away);
a node's internal dependencies are read off the board's edges rather than a list;
the node id, which the deleted panel spelled out, rides on the desk node panel's
title.
Left for a follow-up, deliberately:
features/dag/mount.tsandstore.ts(the runstate
state/session/resume.tsstill writes and nothing reads) -- deleting themmeans either a new row on
domain-shape's shrink-only exceptions or dissolvingfeatures/dag/into its two remaining consumers, which is a decision of its own.Type
Verification
npm test --prefix ui-web-- 188 files, 2464 tests, all pass (three suitesfewer than the base: the two deleted gates and the deleted label suite)
npm run type-check --prefix ui-web-- cleannpm run lint --prefix ui-web-- 0 errors (4 pre-existing warnings inCronPage/SubagentsPage, untouched here)
node ui-web/scripts/check-class-namespace.mjs-- OK; the transcript and dagpins lowered to what the tool prints
npm run --prefix ui-tui lint:i18n-- generated catalogue up to datenpm run --prefix ui-web build && python3 ui-web/build.py-- boot-snapshot OK(235 nodes match golden)
Driven on a real host (
raven servefrom this branch on an isolatedRAVEN_HOMEbuilt from a real config, deepseek as the default model, every channel off), with
a playwright driver against the served page:
role=buttonwith a title and the arrow; a long title is cut and the arrow stays in viewtask:dag:<run_id>, headed by the run's summary, showing the board1 failed; the desk pane shows the failure banner before any node is picked; the banner opens the failed nodeRisk
Web UI only; no server or wire change. The transcript card loses its graph and
node panel on purpose; every fact they showed is on the desk's task pane, reached
from the card's task cell and from the delivered row.
features/dag/mount.tskeepsrunning unchanged. Rollback is reverting the squash commit.
Related Issues
N/A