-
A merged graph's one run genuinely spans several org_nodes now (Planner/ Coder/Validator all append their own nodes into the SAME run) -- a single run-level org_node column was never accurate once Phase 2b/2c landed, and real per-node ownership already lives in work_node_execution.subagent_type. Schema: work_graph_run.org_node column removed; ux_work_graph_run_active narrowed from UNIQUE(task_id, org_node) to UNIQUE(task_id) WHERE status NOT IN ('done', 'failed') -- 'blocked' now counts as active on purpose, since resuming a blocked run always appends into the same row rather than inserting a fresh one. New migrate_drop_work_graph_run_org_node() handles already-populated databases, wired into backend_server.py's startup path. Call sites updated: work_graph_plan.py/work_graph_fork.py/ root_cause_trace.py's INSERTs; work_graph_run_query.py/task_query.py now return "org_nodes_involved" (derived from work_node_execution.subagent_type) instead of the removed single-value "org_node"; frontend/app.js's org-strip and run-list rendering updated to the list-based shape. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
Implements org-graph-unification-phase2-universal-self-planning-design.md §2.3, §3, §6 -- Coder's implement_code() no longer runs one hardcoded synthetic "implement" node; it self-plans via plan_work_graph(conn, "coder", ..., append_to_run_id=run_id), appending its own nodes onto Planner's existing work_graph_run instead of creating a separate one. - work_graph_plan.py: per-org_node suggested node-type catalogs (_CODER_NODE_CATALOG/_VALIDATOR_NODE_CATALOG, "starting points, not requirements" same as _PLANNER_NODE_CATALOG), new judgment/on_fail/ promotes_to_artifact fields in the generic planning prompt. New plan_work_graph(..., append_to_run_id=...) parameter: merges newly planned nodes into an existing run (node_id collision -> raise, never silent overwrite), returns new_node_ids so callers can avoid reprocessing nodes an earlier stage already promoted to artifacts. New shared dispatch_build_prompt() for graphs mixing Planner-shaped (artifact_type) and Coder-shaped (task_prompt) nodes side by side. - e2e_pipeline.py: _write_completed_node_artifacts() now also promotes nodes declaring promotes_to_artifact (not just Planner's artifact_type nodes), with an only_node_ids scope so a merged-graph caller doesn't re-touch artifacts an earlier stage already wrote. implement_code() reworked around self-planning; code_diff stays Python-computed (a real git diff, not any node's own content -- no node can know the diff ahead of running it), test_report is promoted from whatever the self-planned graph declares, falling back to a synthesized concatenation if it declares none. needs_worktree=True now passed to run_graph() for Coder (found missing entirely during this rework -- harmless with the old single-node manifest, a real 03-C §3.6 gap once concurrent code-writing nodes are possible). Also fixed a real bug found while wiring this up: _review_planner_output_with_retries()'s "reuse existing artifacts" branch hardcoded run_id=None, even though every real artifact row already has a valid produced_by_run_id -- Coder had nothing to append into on that resume path. - work_graph_fork.py: _reconstruct_build_prompt now dispatches per-node (via the new shared dispatch_build_prompt) instead of requiring the whole graph to be one uniform shape -- a real regression Phase 2b would otherwise have introduced silently, since a forked merged graph can now genuinely mix both node shapes. Sequencing note (unchanged from Phase 2a's own finding): work_graph_run's org_node column removal and the ux_work_graph_run_active index narrowing (design doc §2.1/§2.2) stay deferred to Phase 2c -- Validator still creates its own separate run until Validator also appends into the shared one, so narrowing the index to task_id-only now would collide with it. python3 -m unittest discover -s src (752 tests) + discover -s supervisor -p "test_*.py" (126 tests) both green, zero regressions. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
Per CLAUDE.md's docs/ role split (todo = pending, done = shipped into the SDD/code): all seven Graph Engineering series items with a real implementation (B, D, E, F, G, H -- A had no separate doc, resolved directly in graphlemon_architecture.md; C is explicitly won't-do) now have their requirements+design docs moved from docs/todo/ to docs/done/, git mv'd to preserve history. Every cross-reference to the 12 moved files -- across the other moved docs themselves, graph-engineering-open-items.md, 2 Skill files, and 9 src/*.py docstrings/comments -- updated from docs/todo/<file> to docs/done/<file>. Verified no stale docs/todo/ references to any of the 12 filenames remain anywhere in the repo. graph-engineering-open-items.md itself stays in docs/todo/ (not moved) -- it's a living index that keeps gaining new entries from later comparison-note/gap-analysis passes (H itself was added this way, and a new item already appeared while this cleanup was in progress), not a single finished conclusion. Its own header now reflects that all of A/B/D/E/F/G/H are done and explains why it wasn't moved. Also fixed two pre-existing stray path references (missing todo/done/ prefix entirely, predating this cleanup) in its G section. Full src suite (625 tests) passes -- this is a pure documentation/comment change, no behavior touched. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
Implements docs/todo/work-graph-time-travel-debugging-design.md, backend and console together (user confirmed 2026-08-06). Key finding that shrank the v1 scope: ux_work_graph_run_active is a PARTIAL unique index (only covers non-terminal statuses), not a blanket one -- forking from a parent run that's already reached a terminal status never collides with it at all. v1 restricts forking to exactly that case, so no index/constraint change is needed, only two new nullable columns (parent_run_id, fork_of_node_exec_id). Resolved the requirements doc's FR-1 ambiguity ("override input_payload, re-trigger execution") as OUTPUT SUBSTITUTION instead: the fork point's own output_payload is replaced with the human-supplied content directly, it is never re-executed via a new claude -p call -- only the strict downstream subgraph actually re-runs. This sidesteps reconciling the different build_prompt/input_payload conventions each caller uses (Planner's artifact_type lookup, E's generic task_prompt field, F's jury) -- work_graph_fork.py only needs the persisted graph_manifest and each node's output_payload. Implementation needs ZERO changes to the execution engine: pre-seeding every non-downstream node as a 'done' work_node_execution row before calling the unmodified run_graph() on the unmodified graph_manifest is enough -- run_work_node()'s existing REQ-06 breakpoint-recovery short-circuit (already-'done' nodes return their persisted output without calling run_fn) does all the "reuse without re-executing" work for free. _reconstruct_build_prompt supports two graph shapes generically from persisted state alone (Planner's canonical doc chain via e2e_pipeline._planner_prompt_builder, and E's generic task_prompt field); anything else raises ForkGraphShapeUnsupportedError rather than producing broken prompts. New: src/work_graph_fork.py (create_fork/execute_fork/fork_work_graph_run/ start_fork_in_background, the last splitting fast DB-only setup from slow real execution so an HTTP caller gets run_id back immediately, same pattern task_execution.start_task_execution_in_background already uses). work_graph_run gets parent_run_id/fork_of_node_exec_id (SCHEMA_SQL + migrate_add_work_graph_fork_columns for existing databases). work_graph_run_query.py/task_query.py surface both fields. New endpoint POST /api/work-nodes/:node_exec_id/fork. Console: a "从这里分叉" form on each 'done' node in v_run_detail, a fork badge linking back to the parent run, and a 🔀 marker on v_graph_console's run list -- no diff/merge UI (non-goal #3), read-only branch visibility only. Verified end-to-end for real: started the actual backend, sent a real HTTP fork request, confirmed the new run persisted with correct parent_run_id/fork_of_node_exec_id lineage. Tests cover requirements doc acceptance standards 1-3 (PRD swapped -> SDD/Benchmark genuinely re-execute, BRD untouched; original run completely unaffected; the same node forked twice produces independent branches) plus schema migration idempotency, query-layer field surfacing, the HTTP route, and 3 frontend smoke-test assertions. Full src suite (608 tests) + all 3 frontend smoke tests pass. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>