• Real incident (2026-08-13, task b243dfe8), diagnosed live with the user after
    they asked "what's the actual bug behind this block": the task's benchmark
    regression-check node kept looping back to itself, then hit
    "exceeded max_attempts=3" -- but the DB had no record of WHY the final
    (3rd) attempt was rejected, only attempts 1 and 2's feedback. This made the
    block impossible to properly diagnose: reading attempt 3's actual content
    (now possible thanks to the artifact-promotion fix) showed it had correctly
    grounded itself in the task's own approved SDD, unlike attempts 1/2 -- but
    whether the judge agreed was unknowable from the DB alone.
    
    Root cause: _run_layers()'s exceeded-limit branch raised
    ConsistencyCheckFailedError immediately, skipping the
    _record_loop_back_event() call a few lines below entirely -- sig.feedback
    (the judge's real, specific reason for rejecting THIS FINAL attempt, the one
    that actually exhausted the budget) was silently discarded. Every other
    rejected attempt's feedback gets persisted via that same call; only the
    budget-exhausting one didn't.
    
    Fixed by recording it before raising, same as every other rejection. New
    test drives a real 3-attempt exhaustion (max_attempts=2 -> attempts 1, 2, 3)
    and asserts all three loop_back_triggered events exist with attempt 3's own
    distinct feedback text -- confirmed it reproduces the exact real gap (2
    events, not 3) on the pre-fix code.
    
    823/823 tests.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    bboonnee authored
     
    Browse File »

  • …3d96-main-checkout-drift
    graphlemon authored
     
    Browse File »
  • Implements docs/done/work-graph-node-execution-deblackbox-requirements.md
    end to end. The three documented call sites (e2e_pipeline.py::
    _check_prd_consistency, work_graph_orchestrate.py::_llm_judgment_verify_fn,
    work_graph_orchestrate.py::_make_run_fn) all used to render a one-off
    Dynamic Workflow .js script and run it via `claude -p 'Run /<name>...'`
    purely to get "agent identity + schema-shaped output" -- a workaround for
    --json-schema silently conflicting with --agent (05 §5.4.1.1). That
    workaround was never actually necessary: work_graph_plan.py::
    plan_work_graph() solved the identical problem from day one with a flat
    `claude --agent ... -p ...` call + ```json-fence extraction from free text,
    already validated in production.
    
    New org_node_trigger.trigger_org_node_structured() unifies all three call
    sites onto that same flat-call approach. extract_json_payload() generalizes
    work_graph_plan.py's fence-extraction algorithm; _extract_graph_manifest is
    now a thin wrapper over it. Two more call sites not in the original design
    doc (written before they existed) were found and migrated too:
    _run_reflection_perspective and _fix_skill_for_node (Phase 2a's
    Reflection-review/Fix-Skill). work_graph_fork.py needed no changes -- it
    only reaches _make_run_fn indirectly via run_graph(), so it benefits
    automatically.
    
    FR-4's real-agent verification (RUN_REAL_AGENT_E2E=1, mandatory, not
    optional -- src/test_org_node_trigger_e2e.py) confirmed persona loading,
    --model override, and JSON-fence extraction all work against a real model.
    
    write_workflow_script/execute_work_graph/execute_work_graph_with_usage_
    limit_retry are confirmed to have no remaining production callers;
    docstrings mark them historical, the file is kept (not deleted).
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    bboonnee authored
     
    Browse File »

  • Implements org-graph-unification-phase2-universal-self-planning-design.md
    §4 + §5, the engine-extension sub-phase (Phase 2a) -- no org-flow callers
    changed yet, this is the underlying capability.
    
    - _run_one_node() now resolves subagent_type/skill_ref per-node (node.get
      with the run-level org_node/skill_id as fallback), threaded through
      _ensure_node_row/_make_run_fn/_resolve_node_verify_fn -- a node's own
      judgment.kind="llm" call runs under its own declared identity, not
      always the graph-level default. Found and fixed a real gap surfaced by
      writing this: run_graph() only ensures the run-level default skill_id
      exists as a placeholder skill (work_node_execution.skill_ref's FK
      target) -- a node declaring its own skill_ref needs the same guarantee
      or the first INSERT for that skill_id fails FOREIGN KEY constraint.
    
    - New on_fail.action="dynamic_loop_back": Reflection-review
      (_judge_root_cause_node) runs three real parallel perspectives (content/
      connectivity/history) under the Validator identity, each picking a
      target_node_id from the failing node's real ancestors plus a defect_kind
      (content_error vs skill_defect), majority-voted by _tally_reflection
      (own small Counter-based implementation, not imported from
      root_cause_trace.py -- that module already imports this one). A runtime
      ancestor check in _run_one_node backs up _tally_reflection's own
      degradation guarantee.
    
    - skill_defect triggers Fix-Skill (_fix_skill_for_node) before the loop
      back fires: reads the target node's declared skill_ref, builds a
      rewrite prompt from what was asked/produced/why it failed/prior loop
      history, runs it under the Validator identity (user-confirmed via
      AskUserQuestion), then calls the existing but -- until now -- never
      actually invoked by any production path bug_record.create_bug_record()
      + skill_update.update_skill(), against skill_query._REPO_ROOT (never
      target_folder_path). Logs a real 'skill_iterated' execution_event (a
      CHECK-enum value that has existed since the original U-001 schema but
      was never written before). Rate-limited to
      _MAX_SKILL_FIXES_PER_RUN_PER_SKILL rewrites of the same Skill per run.
    
    - New total-attempts-per-source-node loop_limit guard alongside the
      existing per-(target,source) one -- dynamic_loop_back can pick a
      different target each round, which would otherwise dodge the per-pair
      cap indefinitely. New settings_config key shape
      "{org_node}:{source_node_id}:total", no interface change needed there.
    
    - New skills/skill-defect-remediation/SKILL.md (Validator-only), wired
      into roles/validator/role.json.
    
    python3 -m unittest discover -s src (741 tests) + discover -s supervisor
    -p "test_*.py" (126 tests) both green, zero regressions.
    
    Deferred to Phase 2b (per design doc's own sequencing note): §2.1/§2.2
    (work_graph_run.org_node removal + ux_work_graph_run_active index
    narrowing) -- narrowing that index now, before the append-to-existing-run
    mechanism lands, would break the current production flow, since Planner's
    and Coder's work_graph_run rows both stay non-terminal indefinitely on
    the happy path today (only Validator's own graph ever reaches 'done').
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    bboonnee authored
     
    Browse File »



  • 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>
    bboonnee authored
     
    Browse File »
  • Implements docs/todo/work-graph-parallel-execution-design.md: run_graph()
    now schedules graph_manifest nodes layer-by-layer (topological_layers(),
    Kahn's algorithm grouped by round instead of flattened), running a
    multi-node layer's nodes concurrently via ThreadPoolExecutor (default 4
    workers) with a barrier between layers; a single-node layer stays
    synchronous, matching every real graph_manifest observed so far.
    topological_order() is now a thin flattening wrapper, unchanged behavior
    (regression-tested).
    
    _LockedConn/_FetchedRows makes the existing scattered conn.execute() call
    sites in work_node_run.py/work_graph_orchestrate.py/execution_log.py safe
    to call from multiple threads without touching those call sites -- note
    the lock must cover the full execute()-through-fetchone()/fetchall()
    cycle, not just execute() itself, or two threads can still collide on the
    shared sqlite3 connection handle. That gap was caught for real (not
    theoretically) by RunGraphRealSqliteConcurrencyTest during development --
    committing the fixed version, not the first draft.
    
    create_worktree() (work_node_run.py) gets a module-level lock around the
    `git worktree add` call for concurrent layers touching the same repo.
    
    New tests: layer grouping, same-layer concurrency + inter-layer barrier,
    one node's failure not cancelling a concurrent sibling (WorkGraphLayerError
    aggregates), breakpoint-recovery resume of a concurrent layer, a quota-wait
    timeout coexisting with a sibling's real persisted output, real (non-mocked)
    sqlite under concurrent writes across several rounds, and real concurrent
    `git worktree add` calls. Full src (575 tests) + supervisor (125 tests)
    suites pass with zero regressions.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    bboonnee authored
     
    Browse File »
  • …de13-main-checkout-drift
    graphlemon authored
     
    Browse File »


  • Adds paths.repo_root()/is_self_target() and forces needs_worktree=True in
    work_graph_orchestrate.run_graph() whenever target_folder_path is graphlemon's
    own checkout, regardless of caller intent -- 05 §5.8's unconditional rule,
    since a self-target in-place edit risks corrupting the currently-running
    process's own source out from under it.
    
    Adds src/core_engine_classify.py (path-based rule: .claude/agents/*.md,
    src/*, supervisor/* = core_engine; frontend/, docs/ = not) and
    bug_record.record_core_engine_change() (a PASS-path audit record, distinct
    from create_bug_record's FAIL-path root-cause attribution -- no route
    decision, status='resolved' from creation). scheduler.finish_task_lifecycle()
    records this audit trail as an additive side effect after close_task_done()
    on self-target PASS closures.
    
    Found and resolved a real SDD-internal conflict (confirmed with the user via
    AskUserQuestion) before wiring this up: supervisor-auto-rollback-design.md §1
    triggers Deploy Supervisor on self-target+Validator-PASS alone, but 03-C
    §3.11/04-P §4.6 literally gate it on an existing core_engine bug_record --
    and task_create.py confirms goal-type self-improvement tasks (the exact
    self-development-feasibility.md walkthrough scenario) never produce a
    bug_record on their happy path, which would silently defeat that whole task
    class under the literal reading. Resolved per user decision: trigger on
    self-target+PASS alone; the bug_record is a byproduct, not a gate.
    p_deploy_supervisor_blue_green (04-P §4.6) never touches task.status, so
    close_task_done() still runs unconditionally -- Deploy Supervisor is a fully
    decoupled state machine, matching §2's "no shared failure domain" principle.
    
    org_loop_route.py is intentionally untouched -- fast_lane/full_replan is
    FAIL-path retry routing, orthogonal to this PASS-path trigger; deployment
    row creation stays U-037's job per its own Done criterion.
    
    417 tests green; RealGitWorktreeIsolationTest (U-013/REQ-03's real git
    worktree regression) re-verified passing per this Unit's own Done criterion.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    bboonnee authored
     
    Browse File »
  • CLAUDE.md is explicit that PH5 (self-modification/auto-rollback) must not
    start until PH4 has genuinely closed -- not just "all unit tests green,"
    but 06-验收与测试锚点.md's REQ-01~14 happy/boundary/failure cases actually
    covered. A REQ-by-REQ audit (the same discipline that caught U-031's
    integration gap) found 5 real gaps:
    
    - REQ-03 failure: work_node_execution.status jumped straight
      running->retrying, skipping 'reflecting' (declared in the schema enum,
      never once written by any code).
    - REQ-05 failure / REQ-09 boundary: the "scheduler keeps serving other
      queued tasks past one blocked_pending_human" scenario was never tested
      against a real scheduler -- the old test literally said "no scheduler
      exists yet to test against directly" (stale since U-032).
    - REQ-06 / REQ-07 / REQ-14 failure (the biggest gap, shared root cause):
      CorruptPersistedStateError, ClassifierBlockedError, and
      UsageLimitWaitTimeoutError were each correctly raised and each correctly
      marked their own work_node_execution 'blocked', but nothing ever routed
      that to task.status='blocked_pending_human' with the blocked_reason each
      REQ's acceptance text names. e2e_pipeline.run_end_to_end is split into
      run_task_lifecycle() so scheduler.py's run_goal_to_completion can create
      the task itself and catch these three specific exceptions, following the
      same UPDATE+execution_event pattern budget_guardrail.check_budget()
      already established for REQ-10.
    - REQ-02 boundary: PRD internal-contradiction check (verifying->reflecting)
      had no implementation anywhere -- artifact_write always marked
      validation_status='passed' unconditionally. Added an optional verify_fn
      hook to work_graph_orchestrate.run_graph() (one regeneration attempt,
      then ConsistencyCheckFailedError) and a real consistency-check agent()
      call scoped to the PRD node only. The first real run of this new call
      caught a genuine bug: the model returned "consistent": "false" as a JSON
      string, not a boolean, which `if ok:` silently treated as truthy -- fixed
      with explicit _coerce_bool().
    - REQ-13 failure: minor test-assertion weakness (WS 404 rejection test
      didn't check the JSON error body).
    
    384 tests green. REQ-01~14 now have real, exercised coverage rather than a
    "tests are green" assumption -- PH4 can be treated as genuinely closed.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    bboonnee authored
     
    Browse File »

  • 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>
    bboonnee authored
     
    Browse File »