-
U-031: closes a structural integration gap found during the REQ-01~14 regression audit -- plan_work_graph/execute_work_graph/run_work_node were each individually tested but never actually called together in production code (e2e_pipeline.py's only validated closed loop bypassed all three via flat org_node_trigger calls). Adds work_graph_orchestrate.py (topological sort over graph_manifest + one one-node dynamic-workflow agent() call per Work Node, needed for REQ-06's per-node breakpoint recovery), rewires e2e_pipeline.py's plan_documents/ implement_code onto the real chain, and fixes two bugs a real API run surfaced: graph_manifest's id/node_id/depends_on normalization (work_graph_plan._normalize_graph_manifest) and a missing repo_path in run_work_node's cwd resolution. work_node_run.py also now marks a node 'blocked' instead of leaving it stuck 'running' on any unretryable run_fn exception. U-024.5: the regression audit also found REQ-12's reconnect boundary case (refetch a snapshot after a dropped WS reconnects) was never implemented -- only the dashboard reacted to onStatusChange, and even it never refetched. Fixes mountDashboard/mountTaskBoard/mountTaskDetail (which embeds v_graph_visualizer) to refetch their current snapshot on reconnect. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
now 默认值从 time.monotonic 改成 time.time(墙钟),使 quota 等待的 已耗时计算能在进程重启后正确续算;run_work_node 对已 done 的节点直接 返回存量结果不重跑,对 retrying/waiting_for_quota 节点从持久化的 retry_count/quota_wait_started_at 续算而非清零;needs_worktree=True 时复用已存在的 worktree 而不是重新 create。新增 resume_work_graph_run() 返回一次 run 里尚未完成的 node_exec_id 列表, 并对内部不一致的持久化状态统一抛 CorruptPersistedStateError。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
Re-checking REQ-14's boundary case against the letter of its text found a real functional gap, not just a testing gap: U-013's opus handling only did "skip backoff" -- it never actually retried on a downgraded model, just failed immediately. REQ-14 boundary says "不走退避轮询,直接降级到非 Opus 模型重试" (skip backoff, retry immediately on a non-opus model) -- the retry was the part that was missing. Fixed: run_fn's signature is now run_fn(cwd, model=None); an opus quota signal retries immediately (no backoff) with opus_downgrade_model (default "claude-sonnet-5"). If the downgraded model somehow also reports an opus signal (shouldn't happen -- it's not using Opus), this doesn't loop forever chasing it, raises UsageLimitWaitTimeoutError instead. work_graph_execute.py's own opus handling (U-012) deliberately NOT changed to match: REQ-14's coverage only names c_work_node_run/c_org_node_trigger, and that mechanism (a multi-agent dynamic workflow, no single top-level --agent identity) has no one "the model" to downgrade -- a deeper A-1 question, documented as out of scope rather than silently left inconsistent without explanation. Also filled in a real test gap: quota_limit_type=weekly (detection + recovery, and the 9-day timeout) was never tested despite the mechanism already supporting it since U-013. 11 new/changed stdlib unittest cases across work_node_run.py's test suite (all existing run_fn lambdas updated for the new signature). 178 total across U-001-020, all passing. This closes PH2-S3 alongside U-019. REQ-14 is now genuinely complete, not just "mostly right." Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
run_work_node(): the per-node contract -- input schema check (rejects outright, never starts, vs. output schema failure which retries), status machine (pending->running->(reflecting/retrying up to caller-specified max_retries)->done|blocked), execution_log_file lifecycle (active on start, closed in a finally so it closes even when run_fn raises), and USAGE_LIMIT_REACHED handling using 03-C §3.6's *exact* detection regex (`hit your (session|weekly|opus) limit`, case-insensitive) -- more precise than the phrase-matching approximations U-010/U-012 used before this Unit existed to give quota_wait_started_at/quota_limit_type a real owner. git worktree isolation (create_worktree/merge_worktree/remove_worktree) tested for real, no LLM call needed: two independent nodes each get their own worktree + branch, each run_fn writes and commits a different file, both merge back into the main checkout with --no-ff, git log confirms both commits landed, git_worktree_ref differs per node. This is REQ-03's boundary case, verified end to end with real git. "actual work" is an explicit required run_fn(cwd) dependency, not a hidden default calling `claude` -- what a node does is inherently node-specific (the whole point of "give each node a contract"); production callers wire in a real subprocess call, tests inject fakes. Corrects the same Done-line overreach as U-009/010/011/012 (5th occurrence): REQ-03's happy case needs c_artifact_write (still unowned, per U-011's flagged gap) and a real Coder session, neither of which U-013 has access to via its own dependencies (U-012 only). Boundary is what's real here. 10 new stdlib unittest cases, all real (no mocking needed -- git and the DB are both fast/free/local). 117 total across U-001-013, all passing. This closes PH1-S2, the sub-phase development-plan.md's own text flagged as "本项目风险最高的 Sub-phase" (highest-risk in the project). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>