• Validator's terminal verdict is now a real self-planned node (node_type=
    'final_verdict', judgment.kind='mechanical', on_fail.action=
    'dynamic_loop_back') appended into the SAME shared work_graph_run Planner
    and Coder already contribute to (plan_work_graph(..., append_to_run_id=
    run_id)), instead of a flat post-graph org_node_trigger call against a
    separate hardcoded Validator manifest. This is what lets a failing verdict
    genuinely trigger Reflection-review + Fix-Skill + a precise loop back to
    whichever real ancestor node is at fault, reusing the existing
    dynamic_loop_back machinery instead of a parallel retry loop.
    
    The 2026-08-06 hard gate (a real non-zero exit from Validator's own test
    script force-overrides the verdict to FAIL, Python-enforced not just
    prompted) is preserved via a build_prompt wrapper + mechanical check
    closure sharing mutable state. INCONCLUSIVE is now treated the same as
    FAIL (triggers a bounded retry via dynamic_loop_back) rather than accepted
    as a terminal result.
    
    _VALIDATOR_MANIFEST/_VALIDATOR_DOC_PROMPTS/_VALIDATOR_VERDICT_PROMPT/
    _validator_prompt_builder are kept unused (same precedent as _CODER_PROMPT).
    org_node column removal (§2.1), index narrowing (§2.2), and the new
    work-graph-node-review skill (§7.1) remain for a later sub-phase.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    bboonnee authored
     
    Browse File »
  • 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>
    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/dynamic-work-graph-design-skill-design.md. G already
    answered FR-2 (how to mark a parallel-eligible node group): no new field
    needed -- topological_layers() infers independence purely from
    depends_on/edges, so the new Skill's job is just "express real
    dependencies honestly, don't add fake ones."
    
    New Skill skills/design-dynamic-work-graph/SKILL.md: the node-boundary /
    zero_token-vs-needs_judgment / per-node self-contained task_prompt
    methodology, wired into agent_profile.py's FRONTMATTER for coder and
    validator (Planner's own doc-chain path is untouched -- FR-4 only names
    Coder/Validator).
    
    work_graph_plan.py: new _GENERIC_PROMPT_TEMPLATE + generic_node_prompt_builder(),
    used whenever org_node != 'planner'. Planner keeps its existing fixed
    brd/prd/sdd/benchmark/... chain (_PROMPT_TEMPLATE) completely unchanged --
    zero regression risk to the one real production planning path.
    
    Scoped per the requirements doc's non-goal #1 ("prove the mechanism works,
    don't cover every real scenario yet"): does NOT wire into
    e2e_pipeline.py::implement_code()'s existing single-node production path.
    New tests prove the mechanism itself: a Coder scenario that naturally
    splits into 3 independent modules produces a correctly-shaped
    graph_manifest, topological_layers() puts all three in one concurrent
    layer (ties E directly to G), and generic_node_prompt_builder drives it
    through run_graph() to completion.
    
    Full src suite (580 tests) passes with zero regressions.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    bboonnee authored
     
    Browse File »
  • Root cause traced (docs/implementation-gap-analysis.md): the Benchmark
    document Validator relies on for its verdict was frequently a narrative
    about the work session ("The planner workflow completed and produced a
    Benchmark defining 18 scenarios...") instead of the actual scenarios --
    found via a real skill-detail-page task's benchmark.md, then confirmed
    present since the earliest real self-hosting runs. Validator's own
    judgment was, in practice, resting on thin, sometimes-vacuous prose.
    
    Planner's work graph (brd->prd->sdd->benchmark) extends to
    benchmark->test_dataset->test_script: test_dataset/test_script are always
    present as nodes, but the generating subagent judges per-goal whether a
    real dataset/script applies (many goals, e.g. UI wiring, legitimately
    don't have one -- replying 'N/A: <reason>' is a real, expected answer, not
    a failure). test_script gets a genuinely mechanical verify_fn (real
    py_compile/node --check, not LLM judgment) -- the one node type where an
    objective check is actually possible. All four document prompts also gained
    an explicit anti-narration instruction (only 'brd' had a weaker version of
    this before).
    
    Coder's implementation prompt now receives the real benchmark/dataset/
    script and must make the Planner's real script pass for real, not just
    whatever tests it invents on its own.
    
    Validator gets its own 3-node Work Graph (validator_benchmark ->
    validator_test_dataset -> validator_test_script), generated independently
    from SDD/PRD -- deliberately NOT reusing Coder's or Planner's own copies,
    same reasoning as a held-out eval set vs. the dev set a model was tuned
    against. The resulting script, if real, is actually executed against the
    current repository state; a non-zero real exit code force-overrides the
    verdict to FAIL in code (user-confirmed hard gate: the script is not up
    for LLM debate on a failure, only on a pass can subjective judgment add
    INCONCLUSIVE/risk notes).
    
    schema.py: artifact.artifact_type's CHECK constraint gains the 5 new
    types, plus migrate_expand_artifact_types() -- SQLite has no ALTER-based
    constraint migration, so this is the standard rebuild-copy-swap dance,
    applied for real to the live ~/.graphlemon/graphlemon.db (42 rows,
    verified byte-identical count before/after, integrity_check clean).
    
    skills/qa-task-validation.md and skills/project-sdd-planning.md already
    gained a standing principle from this same incident: verify cross-task
    data dependencies against real system state, not seeded fixtures alone
    (see prior commit d7035fc) -- this commit is the mechanism-level half of
    the same fix, not just the prose-guidance half.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    bboonnee authored
     
    Browse File »

  • The 6th real self-hosting attempt (first to reach the full 4-node doc-writing
    graph after the previous five bugs) hit a genuinely new failure: this real
    graph_manifest had no edges at all, not just wrong field names -- worse than
    the case _normalize_graph_manifest already handled. With zero dependency
    info to normalize from, topological_order() scheduled 'benchmark' before
    'sdd' (alphabetically first among zero-in-degree nodes), and build_prompt()
    crashed with KeyError: 'sdd_content' trying to format a template needing
    sdd's not-yet-produced output.
    
    _PROMPT_TEMPLATE always asks for exactly the same fixed 4-node linear chain
    -- that's a constant architectural fact, not something that should be
    re-inferred from the LLM's output every call. _normalize_graph_manifest now
    deterministically enforces brd->prd->sdd->benchmark whenever all four
    canonical artifact_types are present, regardless of what depends_on/edges
    the LLM did or didn't provide. Same "机制用代码" principle as
    ensure_worktree_committed and the earlier normalize logic.
    
    Three new regression tests: zero dependency info still gets the chain
    enforced, node_id != artifact_type still resolves to the real node_id (not
    a guessed string), and a partial set (missing one of the four types) is
    correctly left alone rather than guessed at.
    
    560 tests green (440 src + 120 supervisor).
    
    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 »

  • judge_root_cause(): runs 3 perspective_fns (correctness/requirement-
    completeness/skill-defect, 04-P §4.3), requires >=2/3 agreement on a
    category or raises InconclusiveEscalateError with all raw judgments
    attached (REQ-04's failure case). trace_root_cause_test_failed() creates a
    brand-new bug_record on agreement; trace_root_cause_human_reported()
    field-completes an existing one instead (04-P's explicit distinction
    between the two origins, not a new record either way).
    
    c_bug_record_create (bug_record.py): validates root_cause_category against
    {planning, coder, skill_defect} -- core_engine deliberately excluded,
    matching U-001's schema CHECK constraint (PH5/U-034 scope). Known,
    deliberately-unenforced gap noted rather than guessed at: 03-C §3.10's
    "skill_defect requires creating a skill_iteration_suggestion" constraint
    can't be satisfied yet (skill_iteration.before/after_git_commit_sha are
    NOT NULL but don't exist until a real skill rewrite happens in U-018) --
    REQ-04's three cases never exercise skill_defect, so nothing here needs it
    resolved yet.
    
    real_validator_perspective() builds a real claude --agent validator call
    framed from one of the three perspectives, parsing a CATEGORY:/DETAIL:
    response format.
    
    Also fixes a real diagnostic bug found investigating an unrelated failure:
    org_node_trigger.py/work_graph_plan.py/work_graph_execute.py's nonzero-exit
    error paths only included stderr in the raised exception, silently
    dropping stdout -- which is where a real `claude` failure's actual detail
    often lives. A real Coder call failed with exit 1 and empty stderr,
    giving zero diagnostic signal; fixed to include both streams (truncated).
    
    18 new mocked stdlib unittest cases + 1 gated real test (3 real Validator
    perspective calls judging a deliberately-injected wall-collision bug,
    expecting agreement on root_cause_category=coder). 146 total mocked tests
    across U-001-015, all passing.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    bboonnee authored
     
    Browse File »
  • plan_work_graph(): real `claude --agent <org_node> -p` call, produces a
    graph_manifest (4 nodes for brd/prd/sdd/benchmark, dependency-chained
    sdd->prd->brd, each edge tagged zero_token/needs_judgment per 03-C §3.4),
    recorded as a work_graph_run row (status='planning' -- 04-P
    p_work_graph_execution start_state). Does not execute the plan or produce
    real artifacts -- 03-C §3.4 says so explicitly ("不执行,只规划").
    
    Real call surfaced a genuine, undocumented constraint: --json-schema is
    silently ignored when combined with --agent (structured_output never
    appears; the identity itself works fine -- the response referenced the
    migrated SOUL.md's own principle numbering). First attempt at this Unit
    failed against the real API for exactly this reason. Fixed by asking the
    model to fence its JSON and parsing it out of `result` instead
    (_extract_graph_manifest, tolerant of bare JSON / fenced blocks / an extra
    wrapper key). Documented centrally in 05-实施约束与依赖.md §5.4.1.1 since
    this will matter for any future Unit needing agent-identity + structured
    output together, not just this one.
    
    Also corrects the same class of Done-line overreach as U-009/U-010
    (development-plan.md claimed U-011 alone satisfies REQ-02's happy case,
    but c_work_graph_plan's own contract explicitly excludes execution) and
    flags a real, previously-invisible gap found while tracing REQ-02's actual
    dependencies: no Unit in development-plan.md's 43-unit breakdown owns
    c_artifact_write (03-C §3.7), despite REQ-02's happy AND failure cases both
    requiring it directly. Not fixed here -- noted for whichever Unit (U-012/
    U-013, most likely) needs it first.
    
    15 new mocked stdlib unittest cases + 1 gated real test (re-run and passing
    after the --json-schema fix). 98 total mocked tests across U-001-011, all
    passing.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    bboonnee authored
     
    Browse File »