Commit a5f1618eb6c9d5faa4227234afe4e7338f686a38

Authored by bboonnee
1 parent 5098fbe4

Rewrite CLAUDE.md to reflect current repo state, not PH0-era scaffolding

The original CLAUDE.md described a pre-scaffolding repo with no commits and
open questions about A-2/critical path -- stale since PH0. Updates it to
point at git log as the actual status record, document the two independent
unittest discover roots (src/ and supervisor/), the real backend_server.py
CLI, the .graphlemon-worktrees/ isolation mechanism and its three real
incident notes, and a full repo layout reflecting what's actually there.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Showing 1 changed file with 134 additions and 63 deletions
CLAUDE.md
1 1 # CLAUDE.md
2 2  
3   -This file orients Claude Code when working in this repository. Read this first, then follow the
4   -pointers below — do not start writing code before reading `docs/development-plan.md` and the
5   -current Unit's coverage references in `docs/sdd/`.
  3 +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
  4 +
  5 +Read this first, then follow the pointers below — do not start writing code before reading
  6 +`docs/development-plan.md` and the current Unit's coverage references in `docs/sdd/`.
6 7  
7 8 ## What this is
8 9  
... ... @@ -18,80 +19,125 @@ the MVCP (Model/View/Controller/Process) methodology from `docs/graphlemon_archi
18 19 equivalent input that produced the SDD. When they conflict, the SDD wins (it's newer and more
19 20 detailed); if a conflict looks unresolved, stop and ask rather than picking one silently.
20 21  
  22 +## Status: all 43 planned Units (U-001~U-043, PH0~PH5) are implemented and committed
  23 +
  24 +`docs/development-plan.md` and `docs/sdd/unit_matrix.json` describe the plan as it read at
  25 +inception (2026-07-29) — they were **not** kept updated with "done" checkmarks as work landed, so
  26 +don't treat their prose as a live status board. `git log --oneline` is the actual record: every
  27 +Unit from U-001 through U-043 has a matching commit, plus many `U-0XX fix:`/`U-0XX follow-up:`
  28 +commits for bugs found during real (not mocked) runs, plus a long tail of `graphlemon: <artifact
  29 +type> for task <uuid>` / `graphlemon: auto-commit uncommitted changes for <id>` / `graphlemon:
  30 +merge <id>` commits — those are graphlemon **actually self-hosting**: running its own
  31 +Planner→Coder→Validator loop against its own repo (`target_folder_path` == this checkout,
  32 +`src/paths.is_self_target()`), with the Deploy Supervisor (`supervisor/`) staging, health-checking,
  33 +and cutting over its own code changes. PH5 (self-modification / auto-rollback) is real and running,
  34 +not future work — see "Two things named Supervisor" below and `supervisor/self_hosting_e2e.py`.
  35 +
  36 +When a `development-plan.md` line and the actual code disagree about what's done, trust the code
  37 +and `git log`, and — if it matters to the task at hand — flag the doc as stale rather than
  38 +silently trusting either source. `development-plan.md`'s per-Unit "实现补充"/"真实 bug" notes
  39 +(inline, added after-the-fact) are still valuable: they're a real incident log of bugs found
  40 +during self-hosting runs and how they were fixed (e.g. worktree commits being silently dropped,
  41 +`memory: project` writes landing on the wrong checkout) — read them before touching
  42 +`supervisor/isolation/`, `src/work_node_run.py`, or anything worktree-related.
  43 +
21 44 ## Where to start
22 45  
23   -1. Read `docs/development-plan.md` — Phase → Sub-phase → Unit breakdown (`docs/sdd/unit_matrix.json`
24   - is the machine-readable mirror). Work is organized as Development Units, each classified
25   - Value Path / Risk Gate / Enabler, each with explicit `depends_on` and a `done` criterion that
26   - references a specific REQ in `docs/sdd/06-验收与测试锚点.md`.
27   -2. The critical path starts at **U-001** (01-M schema) → U-002 → U-004 → ... Follow
28   - `development-plan.md` §3 "关键路径" — do not skip ahead to later Units even if they look more
29   - interesting; most have real `depends_on` edges.
30   -3. **U-004 (A-2 assumption) is the next unvalidated risk on the critical path.** A-1 (dynamic
31   - workflow programmatic invocation) was already spike-validated (`spikes/a1-dynamic-workflows/`,
32   - confirmed 2026-07-29). A-2 (Hermes profile SOUL.md/AGENTS.md migrating cleanly into
33   - `.claude/agents/*.md` without major rewrites) is not yet tested. Validate it early with a
34   - minimal spike (per `development-plan.md`'s explicit recommendation) rather than discovering
35   - problems after U-010/U-011 are fully built on top of it.
  46 +1. Read `docs/development-plan.md` for the Phase → Sub-phase → Unit breakdown and the *design*
  47 + rationale behind each piece — but see Status above before trusting any "done"/"depends_on"
  48 + framing as current. `docs/sdd/unit_matrix.json` is its machine-readable mirror (also static).
  49 +2. `docs/sdd/06-验收与测试锚点.md` has REQ-01 through REQ-15, the acceptance anchors every Unit's
  50 + Done criterion cites. REQ-15 (PH5, Deploy Supervisor blue-green + auto-rollback) was added
  51 + 2026-07-30 after the original REQ-01~14 set.
  52 +3. For any specific behavior, prefer reading the actual module in `src/`/`supervisor/`/`agents/`
  53 + over the plan doc — the plan doc records intent at write-time and known deviations, the code is
  54 + truth.
36 55  
37 56 ## Commands
38 57  
39   -No build, lint, or test tooling exists yet — the repo is pre-scaffolding (PH0, no commits made
40   -yet). `supervisor/isolation/` has no test suite of its own (that's U-036); `docs/` and `spikes/`
41   -aren't packages. The one real executable entry point today:
  58 +Two independent `unittest discover` roots — there is no single top-level `discover` that covers
  59 +both (deliberately: `supervisor/` was added later as PH5 landed, see
  60 +`development-plan.md`'s U-036 note):
42 61  
43 62 ```bash
44   -# A-1 spike: verify Claude Code dynamic workflows can be invoked headlessly (already validated,
45   -# kept here for re-running / reference — see spikes/a1-dynamic-workflows/RESULTS.md)
46   -./spikes/a1-dynamic-workflows/run-spike.sh /path/to/some/git/repo
  63 +# graphlemon's own backend/schema/agent-orchestration code (441 tests as of U-043)
  64 +python3 -m unittest discover -s src
  65 +
  66 +# Deploy Supervisor + the isolate/diff/apply library it depends on
  67 +# (this also picks up supervisor/isolation/test_*.py — no separate invocation needed)
  68 +python3 -m unittest discover -s supervisor -p "test_*.py"
  69 +
  70 +# single test
  71 +python3 -m unittest src.test_work_graph_execute.SomeTestClass.test_method
  72 +```
  73 +
  74 +Both suites skip real-`claude`-subprocess tests by default (`skip_unless_env`, `src/test_support.py`)
  75 +— those need `RUN_REAL_AGENT_E2E=1` and real API spend, e.g.:
  76 +
  77 +```bash
  78 +RUN_REAL_AGENT_E2E=1 python3 -m unittest src.test_agent_e2e
47 79 ```
48 80  
49   -Once U-002/U-003 scaffold `src/`, tests run via stdlib `unittest` only (see Testing below) — there
50   -is no repo convention yet for a single-test invocation beyond the standard
51   -`python3 -m unittest path.to.test_module.TestClass.test_method`; don't invent a different pattern.
  81 +`supervisor/self_hosting_e2e.py`'s own real end-to-end scenario (`run_self_hosting_closed_loop`,
  82 +the literal 9-step self-development-feasibility.md walkthrough) is gated the same way in
  83 +`supervisor/test_self_hosting_e2e.py` — do not invoke it casually; it does a real self-targeted
  84 +Planner→Coder→Validator→stage→cutover→monitor run against **this repo**.
  85 +
  86 +No build step, no lint config, no package manager — pure stdlib Python, nothing to install.
  87 +
  88 +```bash
  89 +# A-1 spike (already validated 2026-07-29, kept for reference/re-running)
  90 +./spikes/a1-dynamic-workflows/run-spike.sh /path/to/some/git/repo
  91 +
  92 +# local console (U-007/U-008): backend serves the API, frontend is static no-build HTML/JS
  93 +python3 -m src.backend_server --port 8000 # default --port 0 means OS-assigned (fine for tests, not for browsing)
  94 +```
52 95  
53 96 ## Hard constraints (do not relitigate these — they're settled decisions)
54 97  
55 98 - **Execution backend**: Claude Code ACP only (`claude -p ... --output-format json --json-schema
56 99 <schema> --permission-mode auto`, no `--bare`, no `--dangerously-skip-permissions`). See
57   - 05 §5.3, §5.3.1, §5.4.
  100 + 05 §5.3, §5.3.1, §5.4. One documented gotcha: `--agent` + `--json-schema` together silently drop
  101 + `structured_output` — see 05 §5.4.1.1 and `src/work_graph_plan.py`'s ```` ```json ```` fence
  102 + parsing workaround.
58 103 - **Implementation language**: graphlemon's own backend/frontend/Deploy Supervisor are **pure
59 104 stdlib Python** — no Flask/FastAPI/Express/Node.js, no npm build step. This mirrors the
60 105 predecessor project graphloop's convention. See 05 §5.7. (This constraint is on graphlemon's
61 106 own implementation only — it does NOT apply to the code graphlemon generates for target
62 107 projects, which follows whatever stack that target project uses.)
63 108 - **Testing**: stdlib `unittest` only, no pytest/fixtures. Mock the `subprocess`/`claude -p`
64   - boundary in normal tests; real end-to-end tests that actually shell out to `claude` should be
65   - gated behind an explicit env var and skipped by default (mirror graphloop's
66   - `RUN_REAL_AGENT_E2E=1` pattern) — this project doesn't have that harness yet, build it as part
67   - of the relevant Unit rather than improvising a different pattern per test file.
68   -- **Isolation**: parallel coding nodes must use `git_worktree_ref`. If `target_folder_path` is
69   - graphlemon's own repo (self-hosting/self-modification, PH5 only), worktree is **unconditionally
70   - mandatory** even for serial single-node changes — see 05 §5.8.
  109 + boundary in normal tests; real end-to-end tests that actually shell out to `claude` are gated
  110 + behind `RUN_REAL_AGENT_E2E=1` (`src/test_support.py:skip_unless_env`, mirrors graphloop's
  111 + precedent) — reuse that helper, don't invent a per-file variant.
  112 +- **Isolation**: parallel coding nodes must use `git_worktree_ref` (`src/work_node_run.py`). If
  113 + `target_folder_path` is graphlemon's own repo (self-hosting/self-modification), worktree is
  114 + **unconditionally mandatory** even for serial single-node changes — see 05 §5.8,
  115 + `src/paths.is_self_target()`. Worktree checkouts live at `.graphlemon-worktrees/<node_exec_id>/`
  116 + **inside** the main repo's working tree while a node runs (gitignored — never let `git add -A`
  117 + on `repo_path` pick one up mid-run). Before touching this code, read the three `U-013` incident
  118 + notes in `development-plan.md` (uncommitted worktree changes silently dropped on merge, `memory:
  119 + project` writes landing on the main checkout instead of the worktree, and the pathspec-vs-gitignore
  120 + conflict that fixing the second one introduced) — `work_node_run.ensure_worktree_committed()` is
  121 + the fix for all three; don't re-solve the same problem a fourth way.
71 122  
72 123 ## Two things named "Supervisor" — do not confuse them
73 124  
74 125 1. **"Supervisor(调度子 Agent)"** — an in-process monitoring node inside the Coder Work Graph
75 126 (architecture doc, existing concept). Watches Work Node execution, triggers reflection/
76 127 rescheduling. Part of the Graph Engine itself.
77   -2. **"Deploy Supervisor"** — an independent OS process, entirely outside the Graph Engine, that
78   - handles blue-green deployment and automatic rollback when graphlemon modifies its own code
79   - (PH5 only). See `docs/supervisor-auto-rollback-design.md` for the full design and the
80   - disambiguation note at the top of that file.
  128 +2. **"Deploy Supervisor"** (`supervisor/`) — an independent OS process (`python3 -m
  129 + supervisor.deploy_supervisor`), entirely outside the Graph Engine, that handles blue-green
  130 + deployment and automatic rollback when graphlemon modifies its own code. Fully implemented
  131 + (U-034~U-043): `deploy_stage.py` (stage a candidate), `deploy_health_check.py` (poll for
  132 + startup readiness, not one-shot — see U-038 fix), `deploy_cutover.py`, `deploy_monitor.py`,
  133 + `deploy_rollback.py`. Fail-closed, never-auto-restart philosophy adapted (not imported) from
  134 + graphloop's `hermes_watchdog.py`. See `docs/supervisor-auto-rollback-design.md` for the full
  135 + design and the disambiguation note at the top of that file.
81 136  
82 137 These are unrelated components that happen to share a root word in casual English. Identifiers
83 138 for #2 are always prefixed `c_deploy_supervisor_*` / `deploy_health_signal` — never abbreviate to
84 139 just "supervisor" in code or docs.
85 140  
86   -## PH5 (Deploy Supervisor / self-hosting) is not in scope yet
87   -
88   -`docs/development-plan.md` PH5 (Units U-034~U-043) depends on PH4 closing first — self-modification
89   -safety only makes sense once the base system has passed full regression. Don't build any of
90   -U-034~U-043 before PH0-PH4 are done, even though the design (`docs/supervisor-auto-rollback-design.md`)
91   -and its four reusable isolation modules (`supervisor/isolation/`) are already staged. Those modules
92   -were adapted from graphloop and have had exactly one manual smoke test — they still need a real
93   -`unittest` suite (U-036) before anyone should trust them in a real rollback path.
94   -
95 141 ## Prior art worth reading, not worth copying wholesale
96 142  
97 143 `/Users/yibo/Documents/lemonAI/graphloop` is an earlier, unmaintained attempt at this same
... ... @@ -104,20 +150,45 @@ worth reading for the &quot;fail-closed, deterministic, never-auto-restart&quot; supervisi
104 150 (graphlemon's Deploy Supervisor deliberately extends this into auto-rollback rather than just
105 151 auto-halt — see `docs/supervisor-design-comparison.md` for why). Do not import graphloop code
106 152 directly; anything worth reusing has already been copied and adapted into this repo
107   -(`supervisor/isolation/`).
108   -
109   -## Repo layout (as of PH0, before scaffolding exists)
110   -
111   -- `docs/` — architecture, SDD, development plan (see above)
112   -- `docs/wireframes/` — static no-build HTML prototypes for the PH3 console views (`v_*.html`), referenced
113   - per-page from `docs/sdd/02-V-界面与交互.md` §2.1-2.13 — implementation starting point once PH3 begins,
114   - DOM/class names map 1:1 to that doc's field lists.
115   -- `supervisor/isolation/` — staged utility library (isolate/diff/apply), not yet wired to anything
116   -- `spikes/` — one-off validation spikes (currently just A-1)
117   -- `src/` (created by U-001) — graphlemon's own backend source (schema, then U-007+ HTTP/WebSocket server).
118   - **Not the same `src/` a target project already has in its own repo** — a target project's `src/` is
119   - its own pre-existing source tree; graphlemon does not create or restructure it (see 05-实施约束与依赖.md
120   - §5.7 and architecture doc §13.2 — U-002 only creates `.graphlemon/` inside a target project, corrected
121   - 2026-07-31 after finding development-plan.md's U-002 line had cited the wrong architecture section).
122   -- Everything else (`.claude/agents/`, `skills/`, `runs/`, per-target-project scaffolding) gets created by
123   - U-002/U-003 — it doesn't exist yet, and that's expected at this stage.
  153 +(`supervisor/isolation/`, adapted verbatim per the U-036 note in `development-plan.md`).
  154 +
  155 +## Repo layout
  156 +
  157 +- `docs/` — architecture doc, SDD (`docs/sdd/`), development plan, self-hosting design docs. See
  158 + Status above for how stale the plan/unit-matrix "done" framing is relative to the real code.
  159 +- `docs/wireframes/` — static no-build HTML prototypes for the PH3 console views (`v_*.html`),
  160 + referenced per-page from `docs/sdd/02-V-界面与交互.md` §2.1-2.13; DOM/class names map 1:1 to
  161 + that doc's field lists.
  162 +- `src/` — graphlemon's own backend: `schema.py` (17-table SQLite schema — the original 01-M 15
  163 + entities plus PH5's `deployment`/`deploy_health_signal`), `backend_server.py` (stdlib
  164 + `http.server` HTTP API + WebSocket-ish log/event streaming, no third-party deps), the Org Graph
  165 + layer (`org_node_trigger.py`, `org_node_lifecycle.py`, `org_loop_route.py`, `org_level_loop.py`),
  166 + the Work Graph layer (`work_graph_plan.py`, `work_graph_execute.py`, `work_graph_orchestrate.py`,
  167 + `work_node_run.py`), root-cause tracing (`root_cause_trace.py`), skills (`skill_update.py`,
  168 + `skill_query.py`), budget/scheduling (`budget_guardrail.py`, `scheduler.py`), and `paths.py`
  169 + (graphlemon's own runtime home — `~/.graphlemon` by default, override via `GRAPHLEMON_HOME`,
  170 + deliberately outside this repo checkout so logs/db never enter this repo's own git history).
  171 + **This is not the same kind of `src/` a target project has in its own repo** — a target
  172 + project's own `src/` is its pre-existing source tree; graphlemon doesn't create or restructure
  173 + it (05 §5.7, architecture doc §13.2). Each `src/x.py` has a same-directory `src/test_x.py` (and
  174 + sometimes `src/test_x_e2e.py` for the gated real-agent variant) — that pairing is the repo
  175 + convention, keep it when adding modules.
  176 +- `supervisor/` — Deploy Supervisor process + its isolation library (`supervisor/isolation/`:
  177 + `isolated_workspace.py`, `change_manifest.py`, `selective_apply.py`, `workspace_security.py`,
  178 + adapted from graphloop). `supervisor/self_hosting_e2e.py` is the acceptance-scenario glue that
  179 + wires Graph Engine scheduling + Deploy Supervisor into one real self-targeted run.
  180 +- `agents/{coder,planner,validator}/SOUL.md` — original Hermes-profile identity docs, migrated
  181 + 2026-07-31 (A-2 assumption, "部分成立" — Coder's needed real rewriting to drop a hardcoded
  182 + Feishu API token and a `--dangerously-skip-permissions` self-invocation; Planner/Validator were
  183 + near-verbatim). These are the source-of-truth prose; `.claude/agents/*.md` is the actual
  184 + Claude-Code-discoverable wrapper (frontmatter: `skills:`/`memory: project`/`tools:`/`model:`)
  185 + that Claude Code loads — if you change agent behavior, both need to move together, and the
  186 + `.claude/agents/*.md` frontmatter comment block records exactly what changed between them.
  187 +- `frontend/` — the PH3 console: static `index.html`/`app.js`/`style.css`, no build step, no npm.
  188 +- `spikes/` — one-off validation spikes (`a1-dynamic-workflows/`, confirmed 2026-07-29).
  189 +- `.claude/agent-memory/{coder,planner,validator}/` — per-agent `memory: project` files, tracked
  190 + in git on purpose (architecture doc §8 decision: memory must leave a git trail, not be silently
  191 + mutable local state).
  192 +- `.graphlemon/runs/<task_id>/` — real Artifacts (brd/prd/sdd/benchmark/code_diff/test_report)
  193 + from actual self-hosting runs against this repo. `.graphlemon-worktrees/` (gitignored, see
  194 + Isolation above) is the transient per-node worktree checkout directory, not persistent state.
... ...