• 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/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>
    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 »

  • Adds the two Deploy Supervisor entities from 01-M §1.15/§1.16 (17 tables
    total): deployment (full 15-value blue-green state machine, per 01-M's own
    text rather than supervisor-auto-rollback-design.md §3's abbreviated
    summary table) and deploy_health_signal (append-only health/monitoring
    samples). ux_deployment_active enforces 01-M's "only one non-terminal
    deployment at a time" constraint via an expression-based unique index
    (CREATE UNIQUE INDEX ... ON deployment((1)) WHERE status NOT IN (...)) --
    the same partial-unique-index idiom work_graph_run already uses, just with
    a constant instead of a real grouping column since there's exactly one
    graphlemon self-target.
    
    bug_record.root_cause_category's schema-level CHECK now accepts
    core_engine, but bug_record.py's own application-layer whitelist
    deliberately does not follow yet -- classifying a bug as core_engine is a
    file-path-based rule (05 §5.8), not something the Validator's existing
    3-perspective judge_root_cause can produce, and wiring that classification
    + c_org_loop_route's routing is U-035's job.
    
    392 tests green.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    bboonnee authored
     
    Browse File »

  • Implements docs/sdd/01-M-模型设计.md §1.0-1.14 as stdlib sqlite3 DDL in src/
    (deployment/deploy_health_signal §1.15-1.16 are PH5/U-034, deliberately
    excluded). Covers all entities' fields, enum CHECK constraints, FKs, and
    the two non-trivial unique indexes (work_graph_run's per-(task_id,org_node)
    active-run partial index, artifact's (task_id,artifact_type,git_commit_sha)
    composite key).
    
    Per user decision (2026-07-30): bug_record.root_cause_category excludes
    'core_engine' for now -- that value is PH5-scoped and development-plan.md
    assigns adding it to U-034, not U-001; a test locks this in.
    
    14 stdlib unittest cases in src/test_schema.py cover table creation and the
    Done criterion's named constraint classes (unique/FK/enum), all passing.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    bboonnee authored
     
    Browse File »