-
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>
-
Establishes the first commit for graphlemon before U-001 work begins: architecture/SDD docs (including the PH5 self-hosting design already folded into 01-M/03-C/04-P/mvcp-contract v1.7.0), the A-1 spike results, the graphloop-adapted supervisor/isolation utilities, PH3 wireframe prototypes (now cross-referenced from 02-V), and this session's development-plan review (U-024 dependency split, U-035 regression requirement, new U-004.5 e2e-harness unit, src/ directory convention). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>