CLAUDE.md 15.1 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Read this first, then follow the pointers below — do not start writing code before reading docs/development-plan.md and the current Unit's coverage references in docs/sdd/.

What this is

graphlemon is a Level 5 autonomous "lights-out software factory": a two-layer Organizer Agent architecture (Org Graph = fixed Planner→Coder→Validator; Work Graph = dynamic per-task execution graph) that drives real software development end-to-end, backed entirely by Claude Code ACP (claude -p non-interactive calls) — there is no Hermes CLI execution backend in this project (decision, 2026-07-29, see docs/sdd/05-实施约束与依赖.md §5.3).

The authoritative spec is docs/sdd/ (00-06 + docs/sdd/sdd-mvcp-contract.json), generated via the MVCP (Model/View/Controller/Process) methodology from docs/graphlemon_architecture.md. Do not treat graphlemon_architecture.md as the spec to implement against — it's the PRD- equivalent input that produced the SDD. When they conflict, the SDD wins (it's newer and more detailed); if a conflict looks unresolved, stop and ask rather than picking one silently.

Status: all 43 planned Units (U-001~U-043, PH0~PH5) are implemented and committed

docs/development-plan.md and docs/sdd/unit_matrix.json describe the plan as it read at inception (2026-07-29) — they were not kept updated with "done" checkmarks as work landed, so don't treat their prose as a live status board. git log --oneline is the actual record: every Unit from U-001 through U-043 has a matching commit, plus many U-0XX fix:/U-0XX follow-up: commits for bugs found during real (not mocked) runs, plus a long tail of graphlemon: <artifact type> for task <uuid> / graphlemon: auto-commit uncommitted changes for <id> / graphlemon: merge <id> commits — those are graphlemon actually self-hosting: running its own Planner→Coder→Validator loop against its own repo (target_folder_path == this checkout, src/paths.is_self_target()), with the Deploy Supervisor (supervisor/) staging, health-checking, and cutting over its own code changes. PH5 (self-modification / auto-rollback) is real and running, not future work — see "Two things named Supervisor" below and supervisor/self_hosting_e2e.py.

When a development-plan.md line and the actual code disagree about what's done, trust the code and git log, and — if it matters to the task at hand — flag the doc as stale rather than silently trusting either source. development-plan.md's per-Unit "实现补充"/"真实 bug" notes (inline, added after-the-fact) are still valuable: they're a real incident log of bugs found during self-hosting runs and how they were fixed (e.g. worktree commits being silently dropped, memory: project writes landing on the wrong checkout) — read them before touching supervisor/isolation/, src/work_node_run.py, or anything worktree-related.

Where to start

  1. Read docs/development-plan.md for the Phase → Sub-phase → Unit breakdown and the design rationale behind each piece — but see Status above before trusting any "done"/"depends_on" framing as current. docs/sdd/unit_matrix.json is its machine-readable mirror (also static).
  2. docs/sdd/06-验收与测试锚点.md has REQ-01 through REQ-15, the acceptance anchors every Unit's Done criterion cites. REQ-15 (PH5, Deploy Supervisor blue-green + auto-rollback) was added 2026-07-30 after the original REQ-01~14 set.
  3. For any specific behavior, prefer reading the actual module in src//supervisor//agents/ over the plan doc — the plan doc records intent at write-time and known deviations, the code is truth.

Commands

Two independent unittest discover roots — there is no single top-level discover that covers both (deliberately: supervisor/ was added later as PH5 landed, see development-plan.md's U-036 note):

# graphlemon's own backend/schema/agent-orchestration code (560+ tests as of PH5)
python3 -m unittest discover -s src

# Deploy Supervisor + the isolate/diff/apply library it depends on
# (this also picks up supervisor/isolation/test_*.py — no separate invocation needed)
python3 -m unittest discover -s supervisor -p "test_*.py"

# single test
python3 -m unittest src.test_work_graph_execute.SomeTestClass.test_method

Both suites skip real-claude-subprocess tests by default (skip_unless_env, src/test_support.py) — those need RUN_REAL_AGENT_E2E=1 and real API spend, e.g.:

RUN_REAL_AGENT_E2E=1 python3 -m unittest src.test_agent_e2e

supervisor/self_hosting_e2e.py's own real end-to-end scenario (run_self_hosting_closed_loop, the literal 9-step self-development-feasibility.md walkthrough) is gated the same way in supervisor/test_self_hosting_e2e.py — do not invoke it casually; it does a real self-targeted Planner→Coder→Validator→stage→cutover→monitor run against this repo.

No build step, no lint config, no package manager — pure stdlib Python, nothing to install.

# A-1 spike (already validated 2026-07-29, kept for reference/re-running)
./spikes/a1-dynamic-workflows/run-spike.sh /path/to/some/git/repo

# local console (U-007/U-008): backend serves the API, frontend is static no-build HTML/JS
python3 -m src.backend_server --port 8000   # default --port 0 means OS-assigned (fine for tests, not for browsing)

Hard constraints (do not relitigate these — they're settled decisions)

  • Execution backend: Claude Code ACP only (claude -p ... --output-format json --json-schema <schema> --permission-mode auto, no --bare, no --dangerously-skip-permissions). See 05 §5.3, §5.3.1, §5.4. One documented gotcha: --agent + --json-schema together silently drop structured_output — see 05 §5.4.1.1 and src/work_graph_plan.py's ```json fence parsing workaround.
  • Implementation language: graphlemon's own backend/frontend/Deploy Supervisor are pure stdlib Python — no Flask/FastAPI/Express/Node.js, no npm build step. This mirrors the predecessor project graphloop's convention. See 05 §5.7. (This constraint is on graphlemon's own implementation only — it does NOT apply to the code graphlemon generates for target projects, which follows whatever stack that target project uses.)
  • Testing: stdlib unittest only, no pytest/fixtures. Mock the subprocess/claude -p boundary in normal tests; real end-to-end tests that actually shell out to claude are gated behind RUN_REAL_AGENT_E2E=1 (src/test_support.py:skip_unless_env, mirrors graphloop's precedent) — reuse that helper, don't invent a per-file variant.
  • Isolation: parallel coding nodes must use git_worktree_ref (src/work_node_run.py). If target_folder_path is graphlemon's own repo (self-hosting/self-modification), worktree is unconditionally mandatory even for serial single-node changes — see 05 §5.8, src/paths.is_self_target(). Worktree checkouts live at .graphlemon-worktrees/<node_exec_id>/ inside the main repo's working tree while a node runs (gitignored — never let git add -A on repo_path pick one up mid-run). Before touching this code, read the three U-013 incident notes in development-plan.md (uncommitted worktree changes silently dropped on merge, memory: project writes landing on the main checkout instead of the worktree, and the pathspec-vs-gitignore conflict that fixing the second one introduced) — work_node_run.ensure_worktree_committed() is the fix for all three; don't re-solve the same problem a fourth way.

Two things named "Supervisor" — do not confuse them

  1. "Supervisor(调度子 Agent)" — an in-process monitoring node inside the Coder Work Graph (architecture doc, existing concept). Watches Work Node execution, triggers reflection/ rescheduling. Part of the Graph Engine itself.
  2. "Deploy Supervisor" (supervisor/) — an independent OS process (python3 -m supervisor.deploy_supervisor), entirely outside the Graph Engine, that handles blue-green deployment and automatic rollback when graphlemon modifies its own code. Fully implemented (U-034~U-043): deploy_stage.py (stage a candidate), deploy_health_check.py (poll for startup readiness, not one-shot — see U-038 fix), deploy_cutover.py, deploy_monitor.py, deploy_rollback.py. Fail-closed, never-auto-restart philosophy adapted (not imported) from graphloop's hermes_watchdog.py. See docs/done/supervisor-auto-rollback-design.md for the full design and the disambiguation note at the top of that file.

These are unrelated components that happen to share a root word in casual English. Identifiers for #2 are always prefixed c_deploy_supervisor_* / deploy_health_signal — never abbreviate to just "supervisor" in code or docs.

Prior art worth reading, not worth copying wholesale

/Users/yibo/Documents/lemonAI/graphloop is an earlier, unmaintained attempt at this same architecture — substantially implemented (two-layer graph, isolated workspace, change manifest, selective apply, fan-in/fan-out, real Claude-based Planner/Worker/Reviewer agents) but its own Phase 10 self-evolution attempt stalled with concrete documented failures (a worker writing files outside its isolated workspace, a 300s timeout, a stale-PID recovery incident). Its CLAUDE.md is worth reading for architecture patterns; its hermes_watchdog.py/phase10_controller.py are worth reading for the "fail-closed, deterministic, never-auto-restart" supervision philosophy (graphlemon's Deploy Supervisor deliberately extends this into auto-rollback rather than just auto-halt — see docs/done/supervisor-design-comparison.md for why). Do not import graphloop code directly; anything worth reusing has already been copied and adapted into this repo (supervisor/isolation/, adapted verbatim per the U-036 note in development-plan.md).

Repo layout

  • docs/ — architecture doc (graphlemon_architecture.md), SDD (docs/sdd/, authoritative), development plan, and gap-analysis all live at the top level as living/actively-read documents (see Status above for how stale the plan/unit-matrix "done" framing is relative to the real code). Point-in-time material is split into three subdirectories by role, not chronology: docs/done/ (design/decision docs whose conclusions have been fully absorbed into the SDD — e.g. the Deploy Supervisor design chain — kept for the reasoning trail, not because they're still authoritative), docs/todo/ (requirements/design docs for work not yet implemented — BRD/PRD-level requirements docs and, once confirmed, SDD-level design docs, same two-stage split the Planner itself uses), docs/reference/ (external source material — articles, course notes — plus graphlemon's own "how does this compare to our architecture" notes on each one). When adding a new doc, pick by role (has its conclusion shipped into the SDD? → done; still pending confirmation/implementation? → todo; is it someone else's writing you're archiving? → reference), not by putting everything loose in docs/.
  • docs/wireframes/ — static no-build HTML prototypes for the PH3 console views (v_*.html), referenced per-page from docs/sdd/02-V-界面与交互.md §2.1-2.13; DOM/class names map 1:1 to that doc's field lists.
  • skills/ — the Skill library (architecture doc §7.3): one directory per skill (skills/<name>/SKILL.md + optional references/), migrated/adapted from the Hermes profiles (§9's role mapping) and referenced by name from each Org Agent's .claude/agents/*.md skills: frontmatter list (src/agent_profile.py::FRONTMATTER, the canonical source of that list — edit it there, not by hand-editing the deployed .claude/agents/*.md).
  • .claude/workflows/ — auto-generated, not hand-authored: real Dynamic Workflow scripts written by src/work_graph_execute.py::write_workflow_script()/src/work_graph_orchestrate.py (one script per Work Node execution) and by e2e_pipeline.py's PRD-consistency check. Version- controlled because it's inside the target repo (self-target case: this repo), but treat the contents as execution artifacts, not source you maintain by hand.
  • src/ — graphlemon's own backend: schema.py (17-table SQLite schema — the original 01-M 15 entities plus PH5's deployment/deploy_health_signal), backend_server.py (stdlib http.server HTTP API + WebSocket-ish log/event streaming, no third-party deps), the Org Graph layer (org_node_trigger.py, org_node_lifecycle.py, org_loop_route.py, org_level_loop.py), the Work Graph layer (work_graph_plan.py, work_graph_execute.py, work_graph_orchestrate.py, work_node_run.py), root-cause tracing (root_cause_trace.py), skills (skill_update.py, skill_query.py), budget/scheduling (budget_guardrail.py, scheduler.py), and paths.py (graphlemon's own runtime home — ~/.graphlemon by default, override via GRAPHLEMON_HOME, deliberately outside this repo checkout so logs/db never enter this repo's own git history). This is not the same kind of src/ a target project has in its own repo — a target project's own src/ is its pre-existing source tree; graphlemon doesn't create or restructure it (05 §5.7, architecture doc §13.2). Each src/x.py has a same-directory src/test_x.py (and sometimes src/test_x_e2e.py for the gated real-agent variant) — that pairing is the repo convention, keep it when adding modules.
  • supervisor/ — Deploy Supervisor process + its isolation library (supervisor/isolation/: isolated_workspace.py, change_manifest.py, selective_apply.py, workspace_security.py, adapted from graphloop). supervisor/self_hosting_e2e.py is the acceptance-scenario glue that wires Graph Engine scheduling + Deploy Supervisor into one real self-targeted run.
  • agents/{coder,planner,validator}/SOUL.md — original Hermes-profile identity docs, migrated 2026-07-31 (A-2 assumption, "部分成立" — Coder's needed real rewriting to drop a hardcoded Feishu API token and a --dangerously-skip-permissions self-invocation; Planner/Validator were near-verbatim). These are the source-of-truth prose; .claude/agents/*.md is the actual Claude-Code-discoverable wrapper (frontmatter: skills:/memory: project/tools:/model:) that Claude Code loads — if you change agent behavior, both need to move together, and the .claude/agents/*.md frontmatter comment block records exactly what changed between them.
  • frontend/ — the PH3 console: static index.html/app.js/style.css, no build step, no npm.
  • spikes/ — one-off validation spikes (a1-dynamic-workflows/, confirmed 2026-07-29).
  • .claude/agent-memory/{coder,planner,validator}/ — per-agent memory: project files, tracked in git on purpose (architecture doc §8 decision: memory must leave a git trail, not be silently mutable local state).
  • .graphlemon/runs/<task_id>/ — real Artifacts (brd/prd/sdd/benchmark/code_diff/test_report) from actual self-hosting runs against this repo. .graphlemon-worktrees/ (gitignored, see Isolation above) is the transient per-node worktree checkout directory, not persistent state.