-
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> -
trigger_org_node_full(): guards (TASK_NOT_READY -- wrong task.status or required artifacts not validation_status=passed; CONCURRENCY_LIMIT_REACHED -- only on the planner/queued transition, per 04-P's guard column; USAGE_LIMIT_REACHED -- detected from the underlying claude error text, best-effort against REQ-14's cited "hit your session limit" phrasing) then calls U-005's trigger_org_node for the real subprocess call, then advances task.status: queued->planning_brd_prd_sdd (planner), planning_brd_prd_sdd ->coding (coder, gated on brd/prd/sdd/benchmark all passed), coding->validating (validator, gated on code_diff/test_report both passed). Verified for real: all three Org Agents actually triggered in sequence (chained claude --agent calls, ~15s/~$0.15 total) with task.status advancing correctly at each step -- not just planner like U-004/U-005's tests, all three personas confirmed invokable. Also corrects two more development-plan.md issues found while scoping this Unit, same class as U-002/U-009/U-036: - U-010's Done line cited '架构文档 §11"手工调用验证"里程碑' -- that phrase doesn't exist in architecture doc §11 at all. The real source is 05 §5.5's rollout step 2 ("手工调用验证...三个 Org Agent 分别可被触发"), whose "分别" (separately/respectively) is the load-bearing word: verify each CAN be triggered, not that a full artifact-validated chain runs end to end. That distinction is why this Unit's scope is exactly what got built -- not chasing planning_failed/coding_failed retries or validator PASS/FAIL routing, which need real Work Graph output (U-011+) or Org-level Loop routing (U-015/016, PH2) that don't exist yet. - Added an explicit scope note spelling out exactly which 3 transitions this Unit owns vs. which parts of p_org_task_lifecycle it deliberately doesn't touch, so nobody has to re-derive this from the code later. 11 new mocked stdlib unittest cases + 1 gated real chained-trigger test. 87 total mocked tests across U-001-010, all passing; the real test independently re-run and confirmed passing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> -
create_task(): validates goal_text/project_id/task_type (INVALID_PARAM per 03-C §3.1), inserts the task row (status=queued, assigned_org_node=planner, loop_round=0 -- 04-P p_org_task_lifecycle start_state) plus a task_status_changed execution_event, both in one transaction (explicit rollback on failure between the two inserts, tested by dropping execution_event mid-call). c_project_create isn't reimplemented -- it's already complete in U-002 (project_scaffold.create_project). Corrects another Done-line overreach found while scoping this Unit: development-plan.md claimed U-009 alone satisfies all three REQ-01 cases (happy/boundary/failure), but the happy case ("依次触发 planner/coder/ validator...task.status 按状态机正确流转") needs c_org_node_trigger's full implementation -- U-010's own Done criterion is almost that exact sentence, and U-009 doesn't depend on U-010 or even touch org-node triggering. Same class of issue as the U-002/U-036 corrections earlier this session (an SDD/plan line claiming more than the Unit's actual dependencies support), judged low-stakes enough (doesn't change what code to write, just when the REQ-01 happy case gets marked satisfied) to fix directly rather than stop and ask, per the graduated caution this session has been using. Boundary (concurrency limit doesn't block task *creation*, only later scheduling) and failure (INVALID_PARAM) are both fully real at U-009's scope and tested; happy completes cumulatively once U-010 lands. 12 new stdlib unittest cases. 75 total across U-001-009, all passing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> -
frontend/{index.html,app.js,style.css}: no build step, no npm, vanilla JS hash router (05 §5.7). Real page content is PH3 (U-022+, starting from docs/wireframes/); this is only the empty shell + working navigation the Done criterion asks for. backend_server.py serves the 3 files via an exact-path whitelist (not a generic static-file/directory server) -- no path-traversal surface to reason about for 3 fixed files. Verified in an actual browser this session (navigated to localhost, clicked all 3 nav links, screenshotted each) rather than only trusting stdlib tests -- a Python-only test can't exercise real hashchange/DOM behavior without a JS engine. Nav highlighting and content swap both confirmed working, no page reload, no build step. 7 new stdlib unittest cases covering what the server is actually responsible for (static files served with correct content-type, 404 on unknown GET path). 66 total across U-001-008, all passing. This closes out PH0 (U-001~U-008) -- all three Phase-acceptance criteria now hold for real: target-project directory scaffold, 15-table schema with constraint tests, and a real claude --agent round-trip. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> -
Pure stdlib http.server (ThreadingHTTPServer), zero third-party deps -- enforced by an AST-based test that parses backend_server.py's own imports and checks each against sys.stdlib_module_names, so this can't silently rot if someone adds a dependency later (05 §5.7). pick_folder(): macOS via `osascript 'choose folder'`; user-cancel maps to {"selected_path": null} (03-C §3.-1: not an error), non-macOS or any other osascript failure raises DialogUnavailableError -> HTTP 422 DIALOG_UNAVAILABLE. Windows/Linux native dialogs are PH3 (U-022). Known gap, noted rather than papered over: the Done criterion asks for a real popped dialog returning a real path, which needs an actual human click -- not something this agent can do non-interactively. Verified `osascript` itself is present and executes on this machine, and every code path is covered by mocked tests, but the literal "did a human click a real folder and get the right path back" check is still open for whoever runs this interactively next. 12 new stdlib unittest cases (server start/stop, pick_folder success/ cancel/non-macOS/other-failure, the same 4 cases through the HTTP route, zero-third-party-import check). 62 total across U-001-007 (60 real + 2 gated), all passing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> -
write_workflow_script(): writes an orchestration script to <target>/.claude/workflows/<name>.js -- versioned with the target project's own git history, not graphlemon's (03-C §3.5 step 1). execute_work_graph(): `claude -p 'Run /<name> with args {...}' --output-format json --json-schema <schema> --permission-mode auto`, no `--bare` (A-1 spike: skips credential discovery, breaks headless invocation), never bypassPermissions. Returns structured_output. No budget-usage bookkeeping or CLASSIFIER_BLOCKED handling yet -- U-012's job ("骨架" here). Real-call coverage reuses spikes/a1-dynamic-workflows/workflow-under-test.js verbatim (read from that file, not retyped) through the new wrapper -- "直接复用已验证的代码路径" per development-plan.md U-006, not just citing the old spike as prior art. Confirmed passing for real: same result as the original spike (sum=29 for [2,3,4]). 8 new mocked stdlib unittest cases + 1 gated real-agent test. 53 total mocked tests across U-001-006, all passing; both gated real-agent tests (U-004/U-005's planner call, U-006's reused spike workflow) re-verified manually this session. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> -
trigger_org_node(org_node, prompt, target_folder_path): shells out `claude --agent <org_node> -p ... --permission-mode auto` with cwd=target project, parses the JSON result, raises OrgNodeTriggerError on nonzero exit or is_error. Skeleton only, per development-plan.md ("不含完整状态机") -- TASK_NOT_READY/CONCURRENCY_LIMIT_REACHED/USAGE_LIMIT_REACHED handling is U-010's job. Also refactors test_agent_e2e.py (U-004) to call this real function instead of its own ad-hoc subprocess invocation, so the gated real-agent test now exercises U-005's actual production code path -- confirmed still passing against a real `claude --agent planner` call. 5 new mocked stdlib unittest cases (CLAUDE.md Testing constraint: mock the subprocess boundary in normal tests). 46 total across U-001-005, all passing; the 1 gated real-agent test re-verified manually. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> -
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>
-
U-003's coverage in unit_matrix.json is empty (no M/V/C/P/REQ) -- its Done criterion is a property, not a contract: platform dir and any target project dir stay physically separate, and the raw log directory never enters graphlemon's own git history. src/paths.py makes the `~/.graphlemon/ logs/...` example path from 01-M 1.13 / architecture doc §13.2 into the actual convention (GRAPHLEMON_HOME-overridable), defaulting to the user's home directory so it's outside this repo's checkout by construction rather than by a .gitignore rule. is_separate_from() is the property U-003 has to guarantee, tested from both directions (target nested in platform home, platform home nested in target). Also fixes a second stale reference to the pre-correction U-002 scope, found while scoping this Unit: U-036's "supervisor/ directory ownership" open question in development-plan.md still described U-002 as owning a `.claude/`/`skills/`/`src/` target-project tree (already corrected out of U-002 itself last commit). Notes that this makes the open question moot -- supervisor/ was never a real target-project candidate. 8 new stdlib unittest cases (src/test_paths.py); 31 total across U-001/U-002/U-003, all passing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
Implements c_project_create (03-C §3.0) as a plain function for U-007 to wire up later: idempotent by target_folder_path, creates .graphlemon/ + one init commit in an existing git repo, PATH_NOT_FOUND/PATH_NOT_WRITABLE/ GIT_INIT_DECLINED per contract, never silently `git init`s (02-V §2.1). Also corrects a real SDD-vs-plan conflict found while scoping this Unit: development-plan.md's U-002 line cited architecture doc §7.3's directory tree (.claude/agents/, skills/, top-level runs/) as what to create inside a target project. But §13.1 (a later, confirmed decision) states those are graphlemon's own platform-repo assets (U-003 scope), and 01-M's own graphlemon_subdir_initialized field already points at §13.2, whose target- project tree is only .git/ + .graphlemon/ + the target's pre-existing src/. §7.3 predates the "target project is an independent code space" pivot and was superseded by it. Corrected development-plan.md, unit_matrix.json, CLAUDE.md, and 05-实施约束与依赖.md accordingly (user confirmed, 2026-07-31). 23 stdlib unittest cases (src/test_schema.py + new src/test_project_scaffold.py), all passing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
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>