• 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/role-package-abstraction-design.md. Requirements
    review (docs/todo/graph-engineering-open-items.md's H section) had already
    corrected the requirements doc's own dependency analysis before this;
    scope confirmed with user 2026-08-06: relax all 4 org_node CHECK
    constraints in one pass, not staged.
    
    Format is JSON, not YAML: 05 §5.7's pure-stdlib constraint rules out
    PyYAML, and unlike Skill files (whose YAML frontmatter only Claude Code
    itself ever parses, never this codebase's own Python), role.json genuinely
    needs to be read by agent_profile.py -- json.load is the zero-risk choice
    over a hand-rolled parser.
    
    role.json is a REFERENCE manifest, not a content copy: identity.soul_md_path/
    agents_md_path still point at the untouched agents/<role>/SOUL.md/AGENTS.md
    files. This is what makes "deployed output must stay identical" close to
    automatic -- render_agent_definition()'s body-assembly logic doesn't
    change at all, only the frontmatter's data source does (hardcoded
    FRONTMATTER dict -> parsed role.json). Verified byte-for-byte: diffed the
    old (git HEAD) render_agent_definition() output against the new one for
    all three roles, zero differences.
    
    agent_profile.py: ORG_NODES is now discovered by scanning roles/ for
    role.json files (_discover_role_ids()) instead of a hardcoded 3-tuple;
    FRONTMATTER/_DESCRIPTIONS/_MIGRATED_FROM_PROFILE dicts are gone. Every
    public function takes an optional roles_dir override specifically so a
    test can prove "a new role needs zero code changes" against a throwaway
    fixture directory (NewRoleWithoutCodeChangeTest) rather than asserting it
    by inspection.
    
    schema.py: skill.owner_org_node/task.assigned_org_node/work_graph_run.org_node/
    agent_profile.org_node relaxed from CHECK(x IN ('planner','coder','validator'))
    to CHECK(x != ''). Real blast radius found during design (bigger than the
    requirements doc's own risk note): task/work_graph_run/skill are
    referenced by several other tables' foreign keys, but since only the
    parent tables' own CHECK text changes (child FK definitions are untouched),
    only these 4 parent tables need rebuilding -- followed SQLite's documented
    procedure for schema changes under active foreign keys (foreign_keys=OFF
    for the duration, rebuild, foreign_key_check to confirm nothing went
    dangling, foreign_keys=ON). migrate_relax_org_node_constraints() depends
    on D's migrate_add_work_graph_fork_columns() having run (called
    unconditionally, idempotent) so work_graph_run's rebuild has the right
    column set either way. ux_work_graph_run_active and task's 3 indexes
    verified to survive the rebuild.
    
    work_graph_run_query.py's own separately-hardcoded _VALID_ORG_NODES
    (a real dependency the requirements doc's risk section missed) now reuses
    agent_profile.ORG_NODES instead of maintaining a second copy.
    
    Explicitly NOT done (scoped out during requirements review, not an
    oversight): frontend/app.js's 4 hardcoded 3-role spots (route regex, sort
    order, dropdown, lookup object) -- a new role still won't be recognized by
    the PH3 console. A `role` table with real FK referential integrity was
    also not built; this uses the simpler "just relax the enum" approach.
    
    Full src suite (623 tests) + supervisor suite (125 tests) pass with zero
    regressions.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    bboonnee authored
     
    Browse File »
  • Implements docs/todo/validator-loop-until-dry-skill-design.md. Pure Skill +
    Agent-definition wiring, no execution-engine changes -- the convergence
    loop runs inside a single Work Node's one claude -p session (multi-turn
    tool use), not a graph_manifest-level cycle, so topological_layers()/
    run_graph() are untouched.
    
    New Skill skills/unknown-scope-defect-sweep/SKILL.md: K=2 consecutive
    no-new-finding rounds to stop, 20-round hard cap, dedup key must be a
    structural identifier (file path + line, route path, package name) not a
    natural-language description (the same finding gets reworded call to
    call, so text-keyed dedup never converges), dedup set is "everything ever
    seen" not "everything confirmed" (the common bug the 14-step reference
    names: a rejected candidate reappearing as a false "new finding" every
    round). Each candidate is verified via qa-task-validation's existing
    PASS/FAIL/INCONCLUSIVE framework -- deliberately NOT root_cause_trace's
    three-perspective jury (F), since that answers a different question
    (root cause AFTER a failure) from this one (is this candidate real at
    all) -- documented in the design doc's own tradeoff note.
    
    Wired into agent_profile.py's FRONTMATTER["validator"]["skills"] and
    agents/validator/AGENTS.md's "必须加载" section with a concrete trigger
    signal (task description can't state an exact expected count/boundary
    up front).
    
    Only FR-4 (Skill wired into the rendered .claude/agents/validator.md) has
    deterministic, mockable behavior -- new test
    test_validator_references_unknown_scope_defect_sweep_skill. Acceptance
    criteria 1-3 (actually finds everything, actually dedups correctly,
    actually stops at the hard cap) need real multi-turn claude -p behavior,
    out of scope for mocked tests (RUN_REAL_AGENT_E2E=1 territory), same
    category of limitation as F's own real-concurrency-timing note.
    
    Full src suite (587 tests) passes with zero regressions.
    
    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 »

  • Found running U-014's full real closed loop: the Validator gave an
    INCONCLUSIVE verdict and explicitly said it had no Bash tool, despite its
    frontmatter granting one. Isolated with a minimal test subagent: any
    "Bash(...)" scoped pattern (e.g. "Bash(git commit:*)") in a subagent's
    disallowedTools frontmatter field disables Bash *entirely*, not just that
    subcommand -- confirmed by comparing a disallowedTools=[Edit,Write] agent
    (Bash works) against one adding a single Bash(git commit:*) entry (Bash
    breaks completely). The CLI's own --disallowedTools flag documents this
    exact scoped syntax as supported; subagent frontmatter just doesn't honor
    it the same way, and nothing in the docs says so.
    
    Fixed agent_profile.py's validator FRONTMATTER to disallowedTools=
    [Edit, Write] only -- dropping the four Bash(git *) entries that were
    silently breaking test execution. The "don't commit/push/reset/clean"
    constraint now relies on the prose instruction already in the migrated
    AGENTS.md instead of a tool-level block that never actually worked; fixed
    that file's own (now-false) claim that it was enforced at the tool level,
    and documented the finding centrally in 05-实施约束与依赖.md §5.4.1.2 since
    it'll matter for any future agent definition, not just this one.
    
    Verified for real, redeployed: Bash now works for the actual Validator
    identity, Edit/Write remain correctly blocked.
    
    1 test fixed (was asserting the now-removed scoped pattern) + 1 new test
    (disallowedTools frontmatter must never contain "Bash(" again). 174 total
    across U-001-019, all passing.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    bboonnee authored
     
    Browse File »
  • Resolves the A-2 assumption with a real `claude --agent planner -p` call
    (--permission-mode auto, $0.05) against a deployed target project: the
    migrated identity comes through correctly, not the default assistant
    persona. Verdict is "部分成立" (partially confirmed), per the criterion
    development-plan.md's U-004 line pre-registered for exactly this outcome --
    Planner/Validator's SOUL.md migrated almost verbatim, but Coder's SOUL.md
    needed real rewriting: the original hardcoded a live Feishu Base API token
    (redacted, never committed), strongly bound its task-claiming to
    `lark-cli`/Base status vocabulary, and told itself to shell out
    `claude --dangerously-skip-permissions` (conflicts directly with 05
    §5.3.1's `auto`-mode decision). All three replaced with graphlemon's own
    task table / c_org_node_trigger / task.status vocabulary.
    
    Also resolves a second, higher-stakes conflict found while scoping this
    Unit: where does `.claude/agents/<org_node>.md` actually live? Architecture
    doc §13.1 says graphlemon's own platform repo; 03-C §3.3 and 05 §5.1 (both
    core SDD, not the architecture PRD) explicitly say the target project --
    matching how Claude Code's --agent flag actually discovers subagents
    (relative to invocation cwd). User confirmed 03-C/05 win. Resolved as two
    different files, not a contradiction: agents/<org_node>/SOUL.md (+
    validator/AGENTS.md) here is the canonical migrated source (01-M 1.9
    agent_profile.soul_file_path, a singleton with no target-project
    reference); src/agent_profile.py compiles that into the deployable
    .claude/agents/<org_node>.md and writes it into a target project via
    deploy_agent_definitions(). Does not reopen the U-002 correction from the
    previous commit -- .graphlemon/ scaffolding and agent deployment are
    different, non-conflicting concerns.
    
    validator's tools/disallowedTools frontmatter encodes qa/AGENTS.md's
    original workspace-permission contract (read-only on source, no git
    mutation commands) as actual Claude Code permissions instead of prose.
    
    14 new stdlib unittest cases (test_agent_profile.py, all real) + 1 gated
    real-agent test (test_agent_e2e.py, RUN_REAL_AGENT_E2E=1, mirrors
    graphloop's pattern per CLAUDE.md's Testing constraint -- this is the first
    Unit that actually shells out to `claude`, so this is also where that
    harness gets built, per the harness-ownership decision from the earlier
    "什么还需要" review). 41 total tests across U-001-004, all passing.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    bboonnee authored
     
    Browse File »