From 2728750b1c9ec511d2878ab381786fec260293a5 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 27 Jul 2026 20:58:10 +0000 Subject: [PATCH 1/2] Apply HTDAG disciplines to the loop meta-layer (plan DAG, re-plan node, no-action-without-node) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the three HTDAG disciplines to the autonomous loop, built on the existing loop + run-log + memory wiki (no new runtime). Additive only — no existing gate is weakened; no workflow .js engine touched. - Persistent plan: new .claude/memory/loop-plan.md — a durable, mutable DAG of typed nodes (id, description, after: deps, status, origin, notes) with a documented ready-node rule. Pointer added to the memory index. Distinct from the append-only loop-run-log.md history. - Re-plan as a first-class node: loop.md step 9 "Re-evaluate & re-plan" runs BEFORE dispatch so the loop consults the fresh DAG every iteration — marks nodes done, adds nodes from confirmed findings, drops obsolete, recomputes ready. Run-log format gains node: and re-plan: lines. - No action without a node: L2/L3 dispatch (loop-iteration args.items) must be ready plan nodes; node creation is the only exempt action (the sanctioned bootstrap), so an empty/first-iteration plan populates rather than deadlocks. Readiness never bypasses the denylist or trust level. - Consistency: loop-checklist.md §5, topics/workflow.md, and the loop-iteration diagram label updated to match. Verification in progress: /improve-skills gate running over the changed files as the independent checker (maker/checker split). Follow-up commits will apply any confirmed real-and-safe findings. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_014xUCrJdREvUMjoVzSX5T8G --- .claude/loop-checklist.md | 4 ++ .claude/loop.md | 70 ++++++++++++++++++++++--------- .claude/memory/index.md | 5 ++- .claude/memory/loop-plan.md | 64 ++++++++++++++++++++++++++++ .claude/memory/loop-run-log.md | 6 ++- .claude/memory/topics/workflow.md | 10 +++++ docs/workflow-graphs.md | 2 +- 7 files changed, 138 insertions(+), 23 deletions(-) create mode 100644 .claude/memory/loop-plan.md diff --git a/.claude/loop-checklist.md b/.claude/loop-checklist.md index 1341629..b9fa0ba 100644 --- a/.claude/loop-checklist.md +++ b/.claude/loop-checklist.md @@ -36,6 +36,10 @@ this repo from the "loop engineering" loop-design checklist - [ ] Run state documented (`.claude/memory/loop-run-log.md`) - [ ] Prior state read at every iteration start - [ ] Outcomes + timestamps written; resolved items pruned; human overrides recorded +- [ ] Durable **plan/DAG** (`.claude/memory/loop-plan.md`) read at iteration start; every + L2/L3 action traces to a **ready node** (no action without a node) +- [ ] **Re-plan is an explicit step run before dispatch**; the empty/first-iteration plan + bootstraps a node rather than deadlocking **6. Human handoff** - [ ] Escalation triggers explicit (max attempts, risk paths, ambiguity) diff --git a/.claude/loop.md b/.claude/loop.md index 989a95e..e39febf 100644 --- a/.claude/loop.md +++ b/.claude/loop.md @@ -12,15 +12,30 @@ budget, denylist, escalation, stop conditions). Before running, fix the loop's - **L3 — Unattended.** May act without a human watching; requires every section of `.claude/loop-checklist.md` to be satisfied first. +## The plan (`.claude/memory/loop-plan.md`) — the DAG every action traces to +The loop's watchlist is a **durable, mutable plan** of typed work nodes with `after:` +dependency edges, kept in `.claude/memory/loop-plan.md` (schema + ready-node rule are +documented there). Two disciplines follow from it: +- **No action without a node.** Every L2/L3 fix the loop dispatches MUST be a **ready + node** in the plan (its `args.items` `id` = the node `id`). An action with no backing + node is not taken — the re-plan step creates the node first. Readiness does **not** + bypass the denylist or trust level; those gates still apply on top. +- **Re-plan is a first-class step** that runs *before* dispatch (step 9 below), not an + afterthought — the loop consults the fresh DAG before every action. +The plan is the concrete realization of "the watchlist" referenced throughout this file; +`loop-run-log.md` remains the separate, append-only *history*. + ## Per-iteration process (act as Lead Agent) -1. **Read state first:** open `.claude/memory/loop-run-log.md` (prior iterations, - outcomes, human overrides) and check **remaining budget** against the per-run cap - (turns or tokens — see *Budget & limits*) before doing anything; stop and - escalate if it is already exhausted. **If no per-run cap was declared, default to - 25 turns and record that you used the default** in the run-log entry. -2. Identify the current active task from the conversation or run-log. **If no active - task is identifiable, treat the watchlist as empty and self-stop (per *Stop when*) - rather than inventing a task.** +1. **Read state first:** open **`.claude/memory/loop-plan.md`** (the current plan/DAG) + and `.claude/memory/loop-run-log.md` (prior iterations, outcomes, human overrides), + and check **remaining budget** against the per-run cap (turns or tokens — see + *Budget & limits*) before doing anything; stop and escalate if it is already + exhausted. **If no per-run cap was declared, default to 25 turns and record that you + used the default** in the run-log entry. +2. **Orient on the plan:** note its current ready nodes (ready = all `after:` deps + `done`; see the plan's ready-node rule). Node *selection* is deferred to step 10 + (after re-plan) so dispatch always consults the freshest DAG — never act on a raw + finding here. 3. Check git status and changed files. 4. Start or reuse the dev server. 5. Open the relevant localhost page in Chrome or Playwright MCP. @@ -31,18 +46,31 @@ budget, denylist, escalation, stop conditions). Before running, fix the loop's Render the returned `confirmed` matrix. 8. **Maker/checker:** the pass that verifies a fix must be *separate* from the one that made it — the implementer never marks its own work "done". -9. Act **only within the trust level** (**if no level was explicitly declared for - this run, treat it as L1 — never infer L2/L3 from context**): - - L1: record findings only. - - L2/L3: fix the confirmed blockers + directly-related important findings via the - **loop-iteration Workflow** (`.claude/workflows/loop-iteration.js`, - `args.items` = the triaged, denylist-cleared items): an implementer subagent - fixes each in an isolated worktree and a *separate* verifier reviews the real - diff and approves/rejects (a hard denylist gate also forces escalation). For - each **approved** item, apply its returned `diff` patch and re-run the smallest - relevant check before committing; escalate `rejected`/`escalate` items. Never - fix nice-to-haves automatically; never start unrelated refactors. -10. **Append a run entry** to `.claude/memory/loop-run-log.md` (see format below). +9. **Re-evaluate & re-plan** (a first-class step, not an afterthought) — run this + **before** any dispatch so the DAG is fresh when you act. Rewrite + `.claude/memory/loop-plan.md`: mark nodes verified done in a prior iteration as + `done` (unblocking their dependents), **add new nodes** for this run's confirmed + findings (with `after:` deps + `origin`), re-order by priority, `drop` obsolete + nodes, and recompute which nodes are `ready`. New evidence may re-shape the DAG here + — that is the point. Node creation is the *only* loop action exempt from "no action + without a node"; it is the sanctioned bootstrap, so an empty/first-iteration plan is + populated here rather than deadlocking. Record the re-plan delta in the run-log entry. +10. **Select & act — only within the trust level** (**if no level was explicitly + declared for this run, treat it as L1 — never infer L2/L3 from context**). Pick the + highest-priority **ready node(s)** from the just-updated plan: + - L1: record findings only (no dispatch). + - L2/L3: fix the selected nodes via the **loop-iteration Workflow** + (`.claude/workflows/loop-iteration.js`, `args.items` = those **ready plan nodes**, + each `id` = the node `id`; **no action without a node**): an implementer subagent + fixes each in an isolated worktree and a *separate* verifier reviews the real diff + and approves/rejects (a hard denylist gate also forces escalation — readiness does + not bypass it). For each **approved** item, apply its returned `diff` patch, re-run + the smallest relevant check, then mark that node `done` in the plan; escalate + `rejected`/`escalate` items (set the node `escalated`). Never fix nice-to-haves + automatically; never start unrelated refactors. + - **If no node is ready** after re-plan, do not invent work — **self-stop** (per + *Stop when*). +11. **Append a run entry** to `.claude/memory/loop-run-log.md` (see format below). ## Denylist — never touch autonomously (escalate instead) Auth, payments, secrets/`.env`, infrastructure/deploy, CI workflow config, and @@ -82,8 +110,10 @@ Notify only when action is needed — do not ping on a no-op run. ## Run-log entry (append to `.claude/memory/loop-run-log.md`) ``` ## [YYYY-MM-DD HH:MM] L | +- node: - found: - actions: +- re-plan: - budget: / (turns or tokens) - escalations: - evidence: diff --git a/.claude/memory/index.md b/.claude/memory/index.md index dbd1310..7d7f275 100644 --- a/.claude/memory/index.md +++ b/.claude/memory/index.md @@ -4,7 +4,10 @@ The **always-loaded catalog** of the project knowledge wiki (Andrej Karpathy's "LLM wiki" pattern). `CLAUDE.md` imports **only this file**, so it loads every session and must stay small. Detailed knowledge lives in topic pages under `.claude/memory/topics/` and is read **on demand** — never all at once. History -lives in `.claude/memory/log.md`. +lives in `.claude/memory/log.md`. Loop **state** (not knowledge) lives beside it: +`loop-plan.md` is the loop's current plan/DAG (the mutable watchlist every loop action +traces to) and `loop-run-log.md` is the append-only run history — neither is a topic +page; both are read only by a running `/loop`. > Links below are plain markdown (not `@imports`), so topic pages are NOT > auto-loaded. Open the ones relevant to the current task. diff --git a/.claude/memory/loop-plan.md b/.claude/memory/loop-plan.md new file mode 100644 index 0000000..e305836 --- /dev/null +++ b/.claude/memory/loop-plan.md @@ -0,0 +1,64 @@ +# Loop Plan — the DAG every loop action traces to + +The loop's **durable, mutable plan**: an ordered set of typed work nodes with explicit +`after:` dependency edges. This is the HTDAG "no action without a plan node" surface — +every L2/L3 fix the loop dispatches must correspond to a **ready node** here. + +This is **distinct from `loop-run-log.md`**: +- `loop-plan.md` (this file) = the *current* plan — what remains, mutable, re-planned each iteration. +- `loop-run-log.md` = append-only *history* — what happened, never rewritten. + +> Not `@imported`, so it costs nothing until a loop opens it. The loop reads it at +> iteration start (step 1) and rewrites it in the re-plan step (see `.claude/loop.md`). + +## Node schema +One row per node in the table below: + +| Field | Meaning | +|---|---| +| `id` | Stable node id, `LP-NNN` (never reused after `done`/`dropped`). | +| `description` | One line — the bounded unit of work. | +| `after` | Comma-separated `id`s this node depends on; empty = no deps. | +| `status` | `ready` · `blocked` · `in-progress` · `done` · `escalated` · `dropped`. | +| `origin` | Where it came from: a confirmed critic finding, a re-plan, or a human. | +| `notes` | Evidence / decision trail (attempt count, escalation reason). | + +**Status meaning** +- `ready` — all `after:` deps are `done`; eligible for dispatch this iteration. +- `blocked` — has an unmet `after:` dep (compute, don't hand-set, when deps are open). +- `in-progress` — dispatched to the loop-iteration Workflow this iteration. +- `done` — implemented **and** verified by the separate checker; deps unblock. +- `escalated` — handed to a human (denylist hit, max attempts, ambiguity). +- `dropped` — obsoleted by re-plan; kept as a row for the decision trail. + +## Ready-node rule (what the loop dispatches next) +A node is **ready** iff `status ∉ {done, dropped, escalated}` **and** every `id` in its +`after:` is `done`. The loop picks the highest-priority ready node (topmost first). +Denylist and trust-level gates still apply **on top** of readiness — a ready node whose +fix would touch a denylist path is escalated, never auto-applied. + +## No action without a node +Every L2/L3 dispatch (`loop-iteration.js` `args.items`) MUST be ready nodes from this +table — each item's `id` is its node `id`. An action with no backing node is **not +taken**; instead the re-plan step creates the node first (see below). Node creation is +the *only* loop action not itself gated by an existing node — it is the sanctioned way +to bootstrap, so an empty plan never deadlocks: + +- **Empty / first-iteration plan:** after triage, the re-plan step creates nodes from + this run's *confirmed* findings, then dispatch acts on the now-ready nodes. If triage + + re-plan yield zero ready nodes, the loop **self-stops** (empty-watchlist rule in + `loop.md`) — it does not invent work. + +## Example (illustrative — not a live row) +``` +| LP-001 | Fix hydration warning on / | — | done | critic:frontend | verified 2026-… | +| LP-002 | Add E2E for the cleared-name path | LP-001 | ready | critic:qa | | +| LP-003 | Rework auth token refresh | — | escalated | critic:security | denylist: auth | +``` + +## Plan +_No nodes yet. The first L2/L3 loop run bootstraps nodes here from its confirmed +findings during the re-plan step._ + +| id | description | after | status | origin | notes | +|---|---|---|---|---|---| diff --git a/.claude/memory/loop-run-log.md b/.claude/memory/loop-run-log.md index db06164..c42459d 100644 --- a/.claude/memory/loop-run-log.md +++ b/.claude/memory/loop-run-log.md @@ -8,8 +8,10 @@ Entry format (see `.claude/loop.md`): ``` ## [YYYY-MM-DD HH:MM] L | +- node: - found: - actions: +- re-plan: - budget: / (turns or tokens) - escalations: - evidence: @@ -18,7 +20,9 @@ Entry format (see `.claude/loop.md`): Rules: - One entry per loop iteration; record outcomes, timestamps, and any human override. -- Prune resolved watchlist items; keep the decision trail. +- The **plan** (`.claude/memory/loop-plan.md`) holds the *current* watchlist/DAG (mutable, + re-planned each iteration); this run-log is the *append-only history*. Prune resolved + nodes in the plan, not here; keep the decision trail in both. - **Rotation:** when this file passes **500 lines**, roll older entries into `.claude/memory/loop-run-log/.md` — **create that directory/file on demand** if absent (same rule as `log.md`); the file is not `@imported`, so this is about diff --git a/.claude/memory/topics/workflow.md b/.claude/memory/topics/workflow.md index a8d5c06..52ee2ad 100644 --- a/.claude/memory/topics/workflow.md +++ b/.claude/memory/topics/workflow.md @@ -15,6 +15,16 @@ `.claude/memory/loop-run-log.md`, and obeys the denylist + red-flag stop conditions in `.claude/loop.md`. Raise a level only after `.claude/loop-checklist.md` passes. The verifier pass is always separate from the implementer (no self-approve). +- **The loop is HTDAG-disciplined:** it traces every action to a durable plan/DAG in + `.claude/memory/loop-plan.md` — typed nodes with `after:` dependency edges and a + `ready` rule (deps `done`). Three disciplines: (1) **persistent plan** the loop reads + at iteration start (step 1) and rewrites in the re-plan step; (2) **re-plan is a + first-class node** that runs *before* dispatch (step 9) so the loop consults the fresh + DAG every iteration; (3) **no action without a node** — every L2/L3 dispatch is a ready + plan node, and node creation is the *only* action exempt (the sanctioned bootstrap, so + an empty plan populates rather than deadlocks). Readiness never bypasses the denylist + or trust level — those gates stay on top. `loop-plan.md` = current mutable plan; + `loop-run-log.md` = append-only history — keep them distinct. - Custom commands live in `.claude/commands/` (each with a `description` for routing); the grouped "when to use" catalog is `.claude/skills-index.md`. A catalog file must NOT live in `.claude/commands/` — anything there auto-registers diff --git a/docs/workflow-graphs.md b/docs/workflow-graphs.md index ae677e4..daeecaa 100644 --- a/docs/workflow-graphs.md +++ b/docs/workflow-graphs.md @@ -121,7 +121,7 @@ flowchart LR ```mermaid flowchart LR - items([triaged, denylist-cleared items]) --> budget{budget floor?} + items([ready plan nodes — triaged, denylist-cleared]) --> budget{budget floor?} budget -- "under floor" --> esc0[▫️ escalate all] budget -- ok --> P subgraph P["pipeline — per item, independent"] From fea771d3999a8200c42b8c73ab49bd1bcfd97174 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 27 Jul 2026 21:20:13 +0000 Subject: [PATCH 2/2] Apply /improve-skills checker findings on the HTDAG loop discipline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The independent checker (24 agents) confirmed 0 blockers — no safety gate was weakened (criterion 4 holds) — and 14 important real+safe findings, all additive DAG-contract tightenings. Deduped to six fixes + two consistency touches: - Ready formula now excludes `in-progress` too, so a node orphaned by a crash/ timeout mid-dispatch isn't re-read as freshly ready (duplicate-dispatch risk); added a stale-in-progress recovery rule to the re-plan step. - Cascade rule: a node whose `after:` dep becomes `dropped`/`escalated` (never `done`) is resolved in re-plan (drop/re-point for dropped; escalate-with-note for escalated) instead of sitting silently `blocked` forever. - Terminology: re-plan is a "step", not a "node" (node is reserved for LP-NNN plan rows) — fixed in topics/workflow.md. - loop-checklist.md §5: disambiguated "resolved items pruned" — the run-log is append-only; prune resolved nodes only in loop-plan.md. - Stale pointers updated: CLAUDE.md and skills-index.md now name loop-plan.md as loop state alongside the run-log. - Consistency: step-2 ready shorthand marked illustrative + defers to the plan; empty-watchlist self-stop hardened "should"->"MUST". No .js engine touched; safety gates (denylist, L1/L2/L3 defaults, maker/checker) verified intact. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_014xUCrJdREvUMjoVzSX5T8G --- .claude/loop-checklist.md | 3 ++- .claude/loop.md | 18 ++++++++++++------ .claude/memory/loop-plan.md | 23 +++++++++++++++++++---- .claude/memory/topics/workflow.md | 2 +- .claude/skills-index.md | 5 +++-- CLAUDE.md | 2 ++ 6 files changed, 39 insertions(+), 14 deletions(-) diff --git a/.claude/loop-checklist.md b/.claude/loop-checklist.md index b9fa0ba..5dcffcb 100644 --- a/.claude/loop-checklist.md +++ b/.claude/loop-checklist.md @@ -35,7 +35,8 @@ this repo from the "loop engineering" loop-design checklist **5. State / memory** - [ ] Run state documented (`.claude/memory/loop-run-log.md`) - [ ] Prior state read at every iteration start -- [ ] Outcomes + timestamps written; resolved items pruned; human overrides recorded +- [ ] Outcomes + timestamps appended to the run-log (append-only — never pruned there); + resolved *plan nodes* pruned only in `loop-plan.md`; human overrides recorded - [ ] Durable **plan/DAG** (`.claude/memory/loop-plan.md`) read at iteration start; every L2/L3 action traces to a **ready node** (no action without a node) - [ ] **Re-plan is an explicit step run before dispatch**; the empty/first-iteration plan diff --git a/.claude/loop.md b/.claude/loop.md index e39febf..4656925 100644 --- a/.claude/loop.md +++ b/.claude/loop.md @@ -32,8 +32,10 @@ The plan is the concrete realization of "the watchlist" referenced throughout th *Budget & limits*) before doing anything; stop and escalate if it is already exhausted. **If no per-run cap was declared, default to 25 turns and record that you used the default** in the run-log entry. -2. **Orient on the plan:** note its current ready nodes (ready = all `after:` deps - `done`; see the plan's ready-node rule). Node *selection* is deferred to step 10 +2. **Orient on the plan:** note its current ready nodes (shorthand: `status` not + done/dropped/escalated/in-progress AND all `after:` deps `done` — illustrative only; + always defer to the plan's ready-node rule for the exact formula). Node *selection* + is deferred to step 10 (after re-plan) so dispatch always consults the freshest DAG — never act on a raw finding here. 3. Check git status and changed files. @@ -52,9 +54,13 @@ The plan is the concrete realization of "the watchlist" referenced throughout th `done` (unblocking their dependents), **add new nodes** for this run's confirmed findings (with `after:` deps + `origin`), re-order by priority, `drop` obsolete nodes, and recompute which nodes are `ready`. New evidence may re-shape the DAG here - — that is the point. Node creation is the *only* loop action exempt from "no action - without a node"; it is the sanctioned bootstrap, so an empty/first-iteration plan is - populated here rather than deadlocking. Record the re-plan delta in the run-log entry. + — that is the point. Also **repair broken states** (see the plan's rules): reset any + stale `in-progress` node left by an interrupted prior run, and **cascade-resolve** any + node whose `after:` dep became `dropped`/`escalated` (drop, re-point, or escalate it) + so nothing is left silently `blocked`. Node creation is the *only* loop action exempt + from "no action without a node"; it is the sanctioned bootstrap, so an + empty/first-iteration plan is populated here rather than deadlocking. Record the + re-plan delta in the run-log entry. 10. **Select & act — only within the trust level** (**if no level was explicitly declared for this run, treat it as L1 — never infer L2/L3 from context**). Pick the highest-priority **ready node(s)** from the just-updated plan: @@ -101,7 +107,7 @@ Notify only when action is needed — do not ping on a no-op run. a token ceiling — and record remaining budget in every run-log entry; stop and escalate when reached. - Max iterations per item per run: small (e.g. 3). Max auto-PRs per day: small. -- A loop with an empty watchlist should self-stop, not spin. +- A loop with an empty watchlist **MUST** self-stop, not spin. ## Stop when - No blockers remain, browser verification passes, relevant tests pass, and the diff --git a/.claude/memory/loop-plan.md b/.claude/memory/loop-plan.md index e305836..0ce78ac 100644 --- a/.claude/memory/loop-plan.md +++ b/.claude/memory/loop-plan.md @@ -32,10 +32,17 @@ One row per node in the table below: - `dropped` — obsoleted by re-plan; kept as a row for the decision trail. ## Ready-node rule (what the loop dispatches next) -A node is **ready** iff `status ∉ {done, dropped, escalated}` **and** every `id` in its -`after:` is `done`. The loop picks the highest-priority ready node (topmost first). -Denylist and trust-level gates still apply **on top** of readiness — a ready node whose -fix would touch a denylist path is escalated, never auto-applied. +A node is **ready** iff `status ∉ {done, dropped, escalated, in-progress}` **and** every +`id` in its `after:` is `done`. The loop picks the highest-priority ready node (topmost +first). Denylist and trust-level gates still apply **on top** of readiness — a ready node +whose fix would touch a denylist path is escalated, never auto-applied. + +**Stale `in-progress` recovery:** `in-progress` means "dispatched this iteration" and +normally resolves to `done`/`escalated` in the same iteration. A node still `in-progress` +at the *start* of a later iteration means the prior run was interrupted (crash / timeout / +budget exhaustion) — it is stale. The re-plan step MUST resolve it (reset it to `ready` +or `blocked` per its current `after:` deps, with a note) before it can be selected again; +never dispatch a leftover `in-progress` node as-is (it may be mid-flight or orphaned). ## No action without a node Every L2/L3 dispatch (`loop-iteration.js` `args.items`) MUST be ready nodes from this @@ -48,6 +55,14 @@ to bootstrap, so an empty plan never deadlocks: this run's *confirmed* findings, then dispatch acts on the now-ready nodes. If triage + re-plan yield zero ready nodes, the loop **self-stops** (empty-watchlist rule in `loop.md`) — it does not invent work. +- **Cascading drop / escalation** (a dependency never reaching `done`): since readiness + requires every `after:` id to be `done`, a node whose dependency becomes `dropped` or + `escalated` can never become ready and would sit `blocked` forever. The re-plan step + MUST resolve such a node the same iteration — never leave it silently stuck: + - dependency **`dropped`** → drop the dependent too (`origin: cascade from `) if now + obsolete, or re-point its `after:` to a live node; + - dependency **`escalated`** → do **not** re-wire to un-block it (its prerequisite work + is unresolved) — set the dependent `escalated` too, with a note. ## Example (illustrative — not a live row) ``` diff --git a/.claude/memory/topics/workflow.md b/.claude/memory/topics/workflow.md index 52ee2ad..411377c 100644 --- a/.claude/memory/topics/workflow.md +++ b/.claude/memory/topics/workflow.md @@ -19,7 +19,7 @@ `.claude/memory/loop-plan.md` — typed nodes with `after:` dependency edges and a `ready` rule (deps `done`). Three disciplines: (1) **persistent plan** the loop reads at iteration start (step 1) and rewrites in the re-plan step; (2) **re-plan is a - first-class node** that runs *before* dispatch (step 9) so the loop consults the fresh + first-class step** that runs *before* dispatch (step 9) so the loop consults the fresh DAG every iteration; (3) **no action without a node** — every L2/L3 dispatch is a ready plan node, and node creation is the *only* action exempt (the sanctioned bootstrap, so an empty plan populates rather than deadlocks). Readiness never bypasses the denylist diff --git a/.claude/skills-index.md b/.claude/skills-index.md index 339c755..9fa5f5d 100644 --- a/.claude/skills-index.md +++ b/.claude/skills-index.md @@ -24,8 +24,9 @@ catalog so both you and Claude can route to the right command. - **Capture/curate what was learned** → `/dream`, `/memory-audit` - **Improve the system's own prompts/skills/workflows** → `/improve-skills` - **Keep watching localhost on an interval** → `/loop` (uses `.claude/loop.md`; - gate trust level with `.claude/loop-checklist.md`, state in - `.claude/memory/loop-run-log.md`) + gate trust level with `.claude/loop-checklist.md`; state in + `.claude/memory/loop-plan.md` (current plan/DAG — every L2/L3 action traces to a ready + node here) and `.claude/memory/loop-run-log.md` (append-only history)) ## Development loop diff --git a/CLAUDE.md b/CLAUDE.md index 70b0d94..89a5836 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -62,6 +62,8 @@ building. Triggers: "write me the `/goal` for this", "turn this into a `/loop`", For recurring/watchdog work, the standing loop prompt is `.claude/loop.md` (used by `/loop`). Loops are **hardened** ("loop engineering"): declare a trust level — **L1 report-only → L2 assisted → L3 unattended** — and stay within it; read +`.claude/memory/loop-plan.md` (the durable plan/DAG — every L2/L3 action must trace to a +ready node, and re-plan runs as a first-class step before each dispatch) and `.claude/memory/loop-run-log.md` at the start of each iteration and append an entry per iteration; respect the denylist (auth, payments, secrets, infra, CI config, migrations), the escalation triggers, and the red-flag stop conditions. Before raising a loop's