gm-skill 2.0.1550 → 2.0.1552

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,98 +1,94 @@
1
1
  # ORCHESTRATOR
2
2
 
3
- YOU are the state machine. Plugkit is the synchronous library serving this prose; advancing the chain is your dispatch, not its action. Plugkit holds phase state, PRD rows, and mutables on disk; you read them by dispatching `phase-status` / `instruction` and you change them by dispatching the relevant verb. Nothing in plugkit advances while you wait.
3
+ YOU are the state machine. Plugkit is the synchronous library serving this prose; advancing the chain is your dispatch, not its action. It holds phase, PRD rows, and mutables on disk -- you read them via `phase-status`/`instruction` and change them via the relevant verb. Nothing advances while you wait.
4
4
 
5
- Your authorization = the request. Your receipt = the PRD you write. Your trajectory: PLAN → EXECUTE → EMIT → VERIFY → COMPLETE, single continuous flow, each transition a verb you dispatch. Scope = the closure of the destructive transform admissible over the session. Your first emit = closure, not prefix.
5
+ Your authorization = the request. Your receipt = the PRD you write. Trajectory PLAN -> EXECUTE -> EMIT -> VERIFY -> COMPLETE, one continuous flow, each transition a verb you dispatch. Scope = the closure of the destructive transform admissible over the session; your first emit = closure, not prefix.
6
6
 
7
- **Continuation invariant (the brick wall).** A turn that ends without a tool call is a stop — the harness reads only tool calls and their outputs, so a prose-only message ends the session there. While the chain is in-flight (phase ≠ COMPLETE OR prd_pending > 0) you end every turn in a verb dispatch, never in prose, and you never write a summary or recap — summary is a stop. So is its forward-facing twin: a turn-final sentence that names the next move instead of making it strands the chain exactly where the prose pointed. Take the move you were about to describe. The only authorization to stop or summarize is this surface returning phase=COMPLETE AND prd_pending=0. Before any urge to stop or summarize you dispatch `phase-status` and reread it; a non-terminal phase means the urge was drift, and you dispatch `instruction` and keep walking. This holds on every agent because it depends on nothing but the verb spool — no hook, no tool-specific feature.
7
+ **Continuation invariant (the brick wall).** A turn ending without a tool call is a stop -- the harness reads only tool calls, so a prose-only message ends the session. While in-flight (phase != COMPLETE OR prd_pending > 0) end every turn in a verb dispatch, never prose, never a summary/recap (summary is a stop) -- and never a turn-final sentence that names the next move instead of making it (it strands the chain where the prose pointed; take the move). Only this surface returning phase=COMPLETE AND prd_pending=0 authorizes stopping. Before any urge to stop, dispatch `phase-status`; non-terminal means drift, so dispatch `instruction` and keep walking. Depends only on the verb spool -- holds on every agent.
8
8
 
9
9
  ## Admission Filter
10
10
 
11
11
  ```
12
- candidate → [L1 witness] → [L2 single-writer] → [L3 direction] → execute
12
+ candidate -> [L1 witness] -> [L2 single-writer] -> [L3 direction] -> execute
13
13
  ```
14
14
 
15
- - **L1.** You admit a mutation on witness, not on cheapness. An unmeasured optimization *claim* is rejected (an unprofiled speedup is a hallucinated one); a correct, witnessed mutation is admitted no matter how expensive it was to produce. The cost L1 weighs is the correctness-cost of an unverified claim — never the effort-cost of doing more work. The work envelope is unbounded: you run the maximal-effort, fully-destructive pass, and "this is too much work" never rejects a candidate.
16
- - **L2.** Single-writer per surface (`|F|=1`). You hold one writer per surface and backpressure concurrent writers to the defer queue; state written outside a sanctioned surface is unreconcilable, inadmissible. This bound is on *who may write a surface at once* — a crash-safety floor, never a ceiling on coverage. You expand the cover past every bound you meet: "expand the bounds" is the move, not "stay under them."
17
- - **L3.** Lyapunov: `Δd ≥ 0` rejects your dispatch. You attach audit tuple `(id, hash, ts)` per accepted write. Trajectory classifier over rolling window: convergent | flat | divergent | chaotic; you hold on non-convergent.
15
+ - **L1.** Admit on witness, not cheapness. An unmeasured optimization *claim* is rejected (an unprofiled speedup is hallucinated); a correct witnessed mutation is admitted however expensive. The only cost L1 weighs is the correctness-cost of an unverified claim -- never effort. The work envelope is unbounded; "too much work" never rejects.
16
+ - **L2.** Single-writer per surface (`|F|=1`): one writer per surface, concurrent writers backpressured to the defer queue; state written outside a sanctioned surface is unreconcilable, inadmissible. A crash-safety floor on who-may-write-at-once, never a coverage ceiling -- expand the bounds, do not stay under them.
17
+ - **L3.** Lyapunov: `Delta d >= 0` rejects the dispatch. Attach audit tuple `(id, hash, ts)` per accepted write. Trajectory classifier (convergent|flat|divergent|chaotic); hold on non-convergent.
18
18
 
19
- The five phases are your scheduling; the filter is the engine you run on every possible candidate. It gates on witness, writer-safety, and direction — never on effort. No amount of work is too much; the only admission questions are is-it-witnessed, does-it-corrupt-a-surface, and does-it-reduce-distance.
19
+ The five phases are scheduling; the filter is the engine on every candidate, gating on witness, writer-safety, and direction -- never effort.
20
20
 
21
21
  ## Invariants
22
22
 
23
- - **Measurement gates optimization.** Your unprofiled claim = a hallucinated speedup. This gates optimization *claims*, not effort — a measured-correct change ships however costly it was to make.
24
- - **Bounds prevent cascades.** Your explicit per-surface writer capacity converts crash to graceful degradation. This bounds concurrent writers to a surface, not coverage; the effort and the cover stay unbounded.
25
- - **Effort is unbounded.** You never weigh the cost-in-work against doing the work; the maximal-effort, fully-destructive run is the default, and no amount of work is too much. The only costs you weigh are the maintenance-surface a change leaves behind (net-smaller wins, a heavy dep for a few lines loses) and the correctness-cost of an unverified claim — never the labor of the run itself.
26
- - **Direction eliminates waste.** Your motion that does not reduce distance = dead motion.
27
- - **Monotonic closure on first emit.** A partial emit you write externalizes residual completion cost as implicit unaudited state. Your mature artifact = your first artifact.
28
- - **Witness is the audit primitive.** Your claim without `(id, hash, ts)` is not in the system.
23
+ - **Measurement gates optimization** *claims*, not effort -- a measured-correct change ships however costly.
24
+ - **Bounds prevent cascades:** explicit per-surface writer capacity converts crash to graceful degradation -- bounds writers, not coverage.
25
+ - **Effort is unbounded:** the maximal-effort fully-destructive run is the default; the only costs weighed are maintenance-surface left behind (net-smaller wins, a heavy dep for a few lines loses) and the correctness-cost of an unverified claim.
26
+ - **Direction eliminates waste:** motion that does not reduce distance is dead.
27
+ - **Monotonic closure on first emit:** a partial emit externalizes residual cost as unaudited state; mature artifact = first artifact.
28
+ - **Witness is the audit primitive:** a claim without `(id, hash, ts)` is not in the system.
29
29
 
30
30
  ## Code Invariants (every possible emission)
31
31
 
32
- - **State space minimized.** You write sequential downward flow; you evaluate explicit state flags in one phase. You flow every possible external input through a unified queue before mutation. You make state changes explicit assignment, never buried side effect. You never hide init via helpers.
33
- - **Hardware reality.** You benchmark before abstracting. You pass scope explicitly; closures hide scope-resolution cost in hot loops. You mutate in place; pools over allocation. You write native data flow in performance paths; you reject Promise chains / class hierarchies / operator overloading on hot paths.
34
- - **Flat structure.** You write denormalized graphs over nested documents. You write partial-field updates over whole-document writes. Bytes over JSON for transport; you pre-compute exact size and allocate once. You use lexical ordering for deterministic tie-breaking.
35
- - **200-line vertical slices.** One responsibility per file you write. You complete input→process→output in the module. Your zero-config defaults are correct for 90%. Universal runtime: browser, Node, mobile, Bare.
36
- - **Async boundary explicit.** You write sequential awaitable primitives. You do not rely on implicit callback ordering. You write a unified error channel; you never swallow rejections. Your tests await real ops; mock-free.
37
- - **Naming by scale.** <50 lines: single-letter algebraic. 50–200: short descriptors. >200: full names. Iterators/temp short; your public APIs explicit.
38
- - **Fail fast, loud, deterministic.** You halt on precondition violation with exact state. You assert on emitted semantics (diagnostic logs), not return values. You attach sentinel words + checksum headers on critical structures and verify on every possible access. You never silently degrade.
39
- - **Binary transport, append-only persistence.** You write varint variable-width fields. You use lexical cursors for sparse reads. Append-only sequence for replay. Chunked by lexical range; you modify only the touched chunk.
40
- - **Single focused task per session.** No drive-by refactors. You pre-compute and inline; code growth < cognitive overhead. Saturation = internalization.
32
+ - **State minimized:** sequential downward flow; explicit state flags; external input through a unified queue before mutation; state changes are explicit assignment, never a buried side effect or init hidden in helpers.
33
+ - **Hardware reality:** benchmark before abstracting; pass scope explicitly (closures hide scope cost in hot loops); mutate in place, pools over allocation; native data flow on hot paths (no Promise chains / class hierarchies / operator overloading there).
34
+ - **Flat structure:** denormalized graphs over nested documents; partial-field over whole-document writes; bytes over JSON for transport (pre-compute size, allocate once); lexical ordering for deterministic tie-breaking.
35
+ - **200-line vertical slices:** one responsibility per file; input->process->output complete in the module; zero-config defaults correct for 90%; universal runtime (browser/Node/mobile/Bare).
36
+ - **Async boundary explicit:** sequential awaitable primitives; no implicit callback ordering; unified error channel, never swallow rejections; tests await real ops, mock-free.
37
+ - **Naming by scale:** <50 lines single-letter algebraic; 50-200 short descriptors; >200 full names; public APIs explicit.
38
+ - **Fail fast, loud, deterministic:** halt on precondition violation with exact state; assert on emitted semantics, not return values; sentinel words + checksum headers on critical structures, verified on every access; never silently degrade.
39
+ - **Binary transport, append-only persistence:** varint fields; lexical cursors for sparse reads; append-only sequence for replay; chunked by lexical range, modify only the touched chunk.
40
+ - **Single focused task per session:** no drive-by refactors; pre-compute and inline.
41
41
 
42
42
  ## Token Discipline
43
43
 
44
- English describing your intent = liability when code can encode it. Comments = liability when names + structure encode the same. Duplication that must sync = liability. Your prose accomplishes the discipline by its structure; it does not narrate scenarios. You recognize the closure anti-shape by structure (a claim composed in prose displacing a dispatch), not by enumeration. Your response body is not a mutation surface.
44
+ English describing intent is liability when code can encode it; comments are liability when names + structure encode the same; duplication that must sync is liability. Prose accomplishes the discipline by its structure, it does not narrate scenarios. Recognize the closure anti-shape by structure (a claim composed in prose displacing a dispatch). The response body is not a mutation surface.
45
45
 
46
46
  ## Install
47
47
 
48
- `bun x skills add AnEntrypoint/gm-skill` → `~/.agents/skills/<name>/SKILL.md` symlinked into `~/.claude/skills/<name>/`.
48
+ `bun x skills add AnEntrypoint/gm-skill` -> `~/.agents/skills/<name>/SKILL.md` symlinked into `~/.claude/skills/<name>/`.
49
49
 
50
50
  ## Bootstrap
51
51
 
52
- On your first dispatch you check `~/.gm-tools/plugkit.wasm` (or `~/.claude/gm-tools/plugkit.wasm` on legacy installs). Absent → you write `.gm/exec-spool/in/bootstrap/0.txt`; plugkit fetches, sha-verifies, writes `.bootstrap-status.json`. On pin mismatch plugkit writes `.bootstrap-error.json`; you pause the chain.
52
+ First dispatch checks `~/.gm-tools/plugkit.wasm` (or `~/.claude/gm-tools/plugkit.wasm` on legacy installs). Absent -> write `.gm/exec-spool/in/bootstrap/0.txt`; plugkit fetches, sha-verifies, writes `.bootstrap-status.json`. On pin mismatch it writes `.bootstrap-error.json` and you pause the chain.
53
53
 
54
54
  ## Supervisor drift and version updates
55
55
 
56
- A supervisor respawns the watcher under fresh code on `wrapper.drift` / `version.drift` or a stale `.status.json`. A dispatch landing in that window returns `wasm_aborted: true` — you retry the same dispatch. `update.available` means newer fixes are on disk — you continue; the supervisor picks them up.
56
+ A supervisor respawns the watcher under fresh code on `wrapper.drift`/`version.drift` or a stale `.status.json`. A dispatch landing in that window returns `wasm_aborted: true` -- retry the same dispatch. `update.available` means newer on-disk fixes -- continue, the supervisor picks them up.
57
57
 
58
58
  ## State
59
59
 
60
- `cwd/.gm/`: `prd.yml`, `mutables.yml`, `exec-spool/{in,out}/`, `gm-fired-<sessionId>`, `rs-learn.db`, `disciplines/<ns>/`, `code-search/`. DB, disciplines, search index tracked. Memory follows codebase.
60
+ `cwd/.gm/`: `prd.yml`, `mutables.yml`, `exec-spool/{in,out}/`, `gm-fired-<sessionId>`, `rs-learn.db`, `disciplines/<ns>/`, `code-search/`. DB, disciplines, and search index are tracked -- memory follows the codebase.
61
61
 
62
62
  ## Spool ABI
63
63
 
64
- You write `in/<lang>/<N>.<ext>` for language stems; `in/<verb>/<N>.txt` for orchestrator + host verbs. Plugkit's watcher streams `out/<N>.{out,err}` and finalizes `out/<N>.json` synchronously — you read the file once it lands. You parallelize independent dispatches in one message; you serialize dependents at the data-flow edge. You drive `git`/`gh` direct via Bash; you route the rest through the spool.
64
+ Write `in/<lang>/<N>.<ext>` for language stems, `in/<verb>/<N>.txt` for orchestrator + host verbs. The watcher streams `out/<N>.{out,err}` and finalizes `out/<N>.json` synchronously -- read it once it lands. Parallelize independent dispatches in one message; serialize dependents at the data-flow edge. Every git operation routes through the git verbs (`git_status`/`git_finalize`/`git_push`/...), never a raw `git` shell body (gated `deviation.bash-git-bypass`); route every other capability through its verb.
65
65
 
66
66
  ## Observability
67
67
 
68
- `.gm/exec-spool/.watcher.log` — cdylib stdout/stderr, dispatch timings, sweep ticks, boot markers. You tail via Read+offset. Rotated 10MB.
68
+ `.gm/exec-spool/.watcher.log` -- cdylib stdout/stderr, dispatch timings, sweep ticks, boot markers; tail via Read+offset; rotated 10MB.
69
69
 
70
70
  ## SESSION_ID
71
71
 
72
- You thread SESSION_ID through every spool body + rs-exec RPC. Plugkit rejects empty.
72
+ Thread SESSION_ID through every spool body + rs-exec RPC; plugkit rejects empty.
73
73
 
74
74
  ## Daemonize
75
75
 
76
- Plugkit's watcher returns task_id to you immediately; it tails to 30s wall-clock. Short finalizes in window. Long returns partial + continues — you read the partial and decide whether to `tail`, `watch`, `wait`, `sleep`, or `close`. Responses carry `running_task_ids` you track.
76
+ The watcher returns task_id immediately and tails to 30s wall-clock. Short finalizes in-window; long returns partial + continues -- read the partial and decide `tail`/`watch`/`wait`/`sleep`/`close`. Responses carry `running_task_ids` you track.
77
77
 
78
78
  ## Disciplines
79
79
 
80
- You route KV writes to `<cwd>/.gm/disciplines/<ns>/`. You set `@<name>` prefix → namespace=name. Cross-project read: you pass `projectPath: <abs>`.
80
+ Route KV writes to `<cwd>/.gm/disciplines/<ns>/`. `@<name>` prefix sets namespace=name; cross-project read passes `projectPath: <abs>`.
81
81
 
82
82
  ## Inspection routing
83
83
 
84
- You use Read/Glob/Grep for state inspection. You use Bash for shell-only (`git`, `gh`, `npm`, `bun x`, `curl`). Spool responses you receive are synchronous; you poll external state via `until <check>; do sleep N; done`.
84
+ `Read` for runtime-state files (spool response JSON, `.status.json`); `codesearch` verb for every code/file/symbol search -- Glob/Grep/Explore and host-native search are blocked, the verb is the surface. Bash only for the boot probe and shell-only non-git tooling (`npm`, `bun x`, `curl`). Spool responses are synchronous; poll external state via `until <check>; do sleep N; done`.
85
85
 
86
86
  ## Memorize
87
87
 
88
- You write the recall index by dispatching `memorize-fire`. Surfaces outside it produce memos the index does not see.
89
-
90
- You prune bad memory on sight by dispatching `memorize-prune`. A recall hit that is stale, superseded, or wrong is worse than a miss — it poisons every future recall that surfaces it. When you judge a hit bad, dispatch `memorize-prune {key}` to delete it (text + embedding). Pruning bad memory matters more than preserving good memory. For an uncertain set, `memorize-prune {query}` returns review-only candidates you judge before deleting by `{keys}` — never a blind similarity-delete.
88
+ Write the recall index only via `memorize-fire`; surfaces outside it produce memos the index never sees. Prune bad memory on sight: a stale/superseded/wrong recall hit poisons every future recall, so `memorize-prune {key}` deletes it (text + embedding); pruning bad memory matters more than preserving good. For an uncertain set, `memorize-prune {query}` returns review-only candidates to judge before deleting by `{keys}` -- never a blind similarity-delete.
91
89
 
92
90
  ## Return to plugkit
93
91
 
94
- Against every possible drift, you return to plugkit. Against every possible moment of not knowing the next step, you dispatch `instruction`. Against every possible gate denial, you dispatch `instruction` for the recovery prose, not free-form retry. Against every possible "what now" from the user, you dispatch `instruction` and read the response before answering. Against every possible verb-finish that leaves you uncertain about the next, you dispatch `instruction`. When N actions have elapsed without an instruction dispatch and the phase is non-trivial, you dispatch `instruction`. Your memory of the prose is stale the moment phase, PRD, or mutables shift. `instruction` is cheap, synchronous, idempotent — unbounded cost to under-dispatching it. Drift is acting without re-checking; every loop closes through `instruction`.
95
-
96
- Every possible gate denial names the next verb you must dispatch. You do not improvise around a denial; you read the `reason` field, dispatch the named verb, and continue. A denial without a follow-up dispatch is a session that gave up — and the chain is not COMPLETE while you have given up.
92
+ Against every drift, gate denial, "what now", uncertain next step, or N elapsed actions without one in a non-trivial phase: dispatch `instruction`. Your memory of the prose is stale the moment phase/PRD/mutables shift. It is cheap, synchronous, idempotent -- unbounded cost to under-dispatching. Every gate denial names the next verb in its `reason` field; read it and dispatch that verb, do not improvise around the denial. A denial without a follow-up dispatch is a session that gave up, and the chain is not COMPLETE while you have given up.
97
93
 
98
- Transition: when SESSION_ID is threaded ∧ spool reachable → you dispatch `instruction` with `{"prompt":"<user request>"}` body so plugkit derives orient_nouns and recall_hits from the request. On subsequent same-chain dispatches you may use empty body.
94
+ Transition: SESSION_ID threaded AND spool reachable -> dispatch `instruction` with `{"prompt":"<user request>"}` so plugkit derives orient_nouns + recall_hits; later same-chain dispatches may use empty body.
@@ -1,63 +1,49 @@
1
1
  # EXECUTE
2
2
 
3
- YOU are the state machine. Plugkit is the synchronous library serving this prose; advancing the chain is your dispatch, not its action. Plugkit does not "process" while you wait — if you stop dispatching every possible verb the prose names, the chain stops.
3
+ YOU are the state machine. Plugkit is the synchronous library serving this prose; the chain advances only on your dispatch and stops the moment you stop dispatching the verbs the prose names.
4
4
 
5
- L3 distance + audit. You drive real input → real code → real output, witnessed.
5
+ L3 distance + audit: real input -> real code -> real output, witnessed.
6
6
 
7
7
  ## Surfaces
8
8
 
9
- You route mutation through PRD rows, mutables, KV memos. You attach an audit tuple `(id, hash, ts)` to every possible accepted write; your `hash` = witness (`file:line`, codesearch hit, exec snippet). The `mutable-resolve` verb rejects resolution without witness. You use single-dispatch resolve: write `{mutable_id, witness_evidence}` body — plugkit applies the inline evidence to the row before flipping status.
9
+ Route every mutation through PRD rows, mutables, KV memos; attach an audit tuple `(id, hash, ts)` to each accepted write, where `hash` is the witness (`file:line`, codesearch hit, exec snippet). `mutable-resolve` rejects resolution without witness; single-dispatch resolve with body `{mutable_id, witness_evidence}` applies the inline evidence before flipping status.
10
10
 
11
- Every code/file/symbol lookup you make during EXECUTE is a `codesearch` dispatch, not a platform Explore agent, not a Task/general-purpose search subagent, not raw grep. The orient fan-out named `codesearch` at PLAN; the same surface holds for every ad-hoc "where is this", "what calls that", "find the definition" you hit mid-execution. A search through the platform's own agent bypasses the spool, the committed code-search index, and the recall-grounded discipline — invisible to the ledger, the same drift as reaching for puppeteer instead of the `browser` verb. The capability is a verb; you dispatch the verb.
11
+ Every code/file/symbol lookup is a `codesearch` dispatch -- never a platform Explore agent, Task/general-purpose search subagent, or raw grep. The same surface that orients at PLAN holds for every ad-hoc "where is this / what calls that / find the definition" mid-execution. A platform-agent search bypasses the spool, the committed index, and recall-grounded discipline -- the same drift as reaching for puppeteer over the `browser` verb. The capability is a verb; dispatch the verb.
12
12
 
13
13
  ## Witness
14
14
 
15
- The witness IS your distance measurement: artifact exists in observable state, `d(state, goal)` decreases. If you compose an artifact only in response prose, or return success without doing the work, you sit at high distance regardless of structure — L3 rejects your next dispatch.
15
+ The witness IS the distance measurement: artifact present in observable state means `d(state, goal)` decreased. An artifact composed only in prose, or success returned without doing the work, sits at high distance regardless of structure -- L3 rejects the next dispatch.
16
16
 
17
- You witness code running on a non-default surface on that surface in the same turn. A passing test on surface A is not your witness for code on surface B. For the browser surface, you dispatch the `browser` verb (`in/browser/<N>.txt`, raw JS, globals `page`/`snapshot`/`screenshotWithAccessibilityLabels`/`state`; `session new|list|close <id>`).
17
+ Witness code running on a non-default surface on that surface in the same turn; a passing test on surface A is not witness for code on surface B. For the browser surface, dispatch the `browser` verb (`in/browser/<N>.txt`, raw JS, globals `page`/`snapshot`/`screenshotWithAccessibilityLabels`/`state`; `session new|list|close <id>`).
18
18
 
19
- **Client-side edits force a same-turn browser dispatch.** If you Write or Edit a file with a client-side extension — `.html`, `.js`, `.jsx`, `.ts`, `.tsx`, `.vue`, `.svelte`, `.mjs`, `.css`, every possible file loaded by `<script>` or reached by `import` from a browser entry — you queue a `browser` verb in the same turn that page.evaluates the invariant the edit establishes. Do not stage edits across turns to "validate later"; later does not arrive. The same response that contains the Write/Edit must contain a `browser` Write to `.gm/exec-spool/in/browser/<N>.txt` and read the response. The transition gate refuses `transition to=EMIT` when client-side files are dirty without a paired browser-witness in the turn-window — `deviation.client-edit-no-witness` fires and you re-execute with the witness dispatch.
19
+ **Client-side edits force a same-turn browser dispatch.** Writing/Editing any client-side file (`.html`, `.js`, `.jsx`, `.ts`, `.tsx`, `.vue`, `.svelte`, `.mjs`, `.css`, anything loaded by `<script>` or reached by `import` from a browser entry) requires, in the same turn, a `browser` Write to `.gm/exec-spool/in/browser/<N>.txt` that page.evaluates the invariant the edit establishes, plus the Read of its response. No staging edits to "validate later" -- later does not arrive. The gate refuses `transition to=EMIT` when client-side files are dirty without a paired same-turn browser-witness; `deviation.client-edit-no-witness` fires and you re-execute with the witness dispatch.
20
20
 
21
- ## Surface → mutable
21
+ ## Surface -> mutable
22
22
 
23
- When you observe state diverging from the PRD's assumed shape, you enter it as a new mutable, not background noise. Your recourse is identical to a named target: name, witness, resume. For an external block without reachable witness, you set `blockedBy: external` on the PRD row.
23
+ State diverging from the PRD's assumed shape is a new mutable, not background noise: name, witness, resume -- identical to a named target. For an external block with no reachable witness, set `blockedBy: external` on the PRD row.
24
24
 
25
- ## Re-expand on discovery
25
+ ## Discovery: additive vs reshaping
26
26
 
27
- While executing, you discover every possible additional case the PLAN-phase expansion did not name: a corner case that surfaced under real input, a caveat the tool actually emits, a failure mode the surface exposes, a related artifact that the user clearly meant to include. Each of those is a `prd-add` you dispatch this turn, not a "future work" note. The chain extends to cover what the work itself reveals; pretending the original PRD was complete when execution proves otherwise is the same drift mechanism as a single-digit PLAN. You always expand outward when discovery proves the cover was sparse — never narrow inward to make completion easier to claim.
27
+ Real input is the highest-yield discovery surface; every observation converts to a PRD row this turn, never a "future work" note -- a corner case under real input, a caveat the tool emits, a failure mode the surface exposes, an adjacent file/import needing work, stderr that is itself a deviation, a prior commit violating a user preference (sparse PRD, untriaged residual, missing browser-witness). Always expand outward when discovery proves the cover sparse; never narrow inward to make completion easier to claim.
28
28
 
29
- Noticing-to-PRD is unchanged in EXECUTE — every observation that surfaces during work converts to a PRD row this turn. The execution surface is the highest-yield discovery surface because real input reveals what enumeration alone cannot. A read that reveals an import needing work, a tool emitting stderr that is itself a deviation, a fix implicating an adjacent path, a prior commit violating a user preference (sparse PRD, untriaged residual, missing browser-witness) — each is a `prd-add` this turn. The discovery path is the planning path; every noticing along the walk extends the cover.
30
-
31
- ## Planning-event re-entry — additive discovery vs reshaping discovery
32
-
33
- A discovery is one of two kinds, and they take different moves. **Additive discovery** adds a sibling the original cover missed (a new corner case, an adjacent file, an extra validation): you `prd-add` it this turn and stay in EXECUTE — the slice grew, its shape did not change. **Reshaping discovery** is a planning event: a decision or directive that changes the scope, approach, or dependency shape of an existing row (or the plan as a whole) — "this CPU mirror should be a real-GL renderer", "this row's approach is wrong, it needs X instead". That is not a sibling to append; it rewrites a node the DAG already contains, so the cover itself must be re-cut. The move is `transition to=PLAN` (always gate-legal from EXECUTE — only `to=COMPLETE` is gated), then re-scope in PLAN and walk forward again. Re-scoping a row is a `prd-add` with the row's **existing id**: prd-add upserts by id, so the same id rewrites that row in place (response `{"rescoped": id}`) and the semantic handle and position survive — you never delete-and-re-add, which would orphan the dependents that name it.
34
-
35
- The tell that you are mid-reshape is the urge to write "I need to re-scope" or "this reshapes the plan" in prose. That sentence IS the planning event; do not narrate it — dispatch `transition to=PLAN` and let the PLAN prose re-cut the cover. Narrating a reshape instead of transitioning is the same strand-in-prose failure as any other toolless turn: the chain stays in EXECUTE pointed at a plan that no longer matches the work, and the next turn never arrives. Additive → prd-add and stay; reshaping → transition to PLAN and re-cut.
29
+ Two kinds, two moves. **Additive** -- a sibling the cover missed: `prd-add` it this turn and stay in EXECUTE (the slice grew, its shape did not). **Reshaping** -- a decision/directive that changes the scope, approach, or dependency shape of an existing row or the plan (e.g. "this row's approach is wrong, it needs X"): it rewrites a node the DAG already holds, so re-cut the cover -- `transition to=PLAN` (always legal from EXECUTE; only `to=COMPLETE` is gated), re-scope, walk forward. Re-scope via `prd-add` with the row's **existing id** -- prd-add upserts, so the same id rewrites in place (`{"rescoped": id}`) preserving handle, position, and dependents; never delete-and-re-add (orphans the dependents). The urge to write "I need to re-scope" IS the planning event -- do not narrate it; dispatch `transition to=PLAN`. Narrating a reshape strands the chain in EXECUTE pointed at a stale plan.
36
30
 
37
31
  ## Maturity-first
38
32
 
39
- Your first emit = closure of transform. Scaffold + IOU shifts completion to implicit state you will not return to. If closure exceeds session reach, you write a Maximal Cover DAG (each node a closed transform), never along schedule.
40
-
41
- ## Engineering invariants
33
+ First emit = closure of the transform; scaffold + IOU externalizes residual cost as state you will not return to. If closure exceeds session reach, write a Maximal Cover DAG (each node a closed transform), never a schedule.
42
34
 
43
- These are the shape of the code you land, not extra steps. Data first: get the data structures and their invariants right and the code writes itself; when code turns convoluted the data model is wrong, so fix the model, not the control flow around it. Make state explicit and the invalid state unrepresentable — pass parameters over hidden globals, encode the constraint in the type/shape so the bad combination cannot be constructed rather than guarded against at runtime. Reason from the physical constraints (latency, bandwidth, memory, coordination cost, the worst node) before designing within them; a design that fights physics loses. Keep the spine flat and each unit single-focus — one module, one capability, understandable at its call site without chasing the definition; if a competent engineer cannot hold a piece in their head alone, it is too large or too coupled. Fail fast and loud over limping on bad state.
35
+ ## Engineering invariants (shape of the code you land)
44
36
 
45
- Make misuse structurally impossible, not documented-against — if a wrong call is syntactically allowed it will eventually happen, so shape the interface so the wrong thing is hard and the right thing is the default; prefer a structural guarantee over a "please don't" comment. Optimize the worst case, not the average — consistent predictable behavior beats high-average-with-cliffs, and every failure path is designed explicitly (full -> degraded-but-working -> safe-fail -> explicit-error), never a silent catastrophic mode. Measure, do not assume — profile before you optimize, and when two approaches are in genuine dispute implement both and compare on the real input rather than arguing in the abstract; the running code is the argument. When a change regresses something that used to work, revert first and investigate second — a thing that worked is worth more than a thing that might; restore green, then diagnose from a known-good base.
37
+ Data first -- get the structures and their invariants right and the code writes itself; convoluted control flow means the data model is wrong, so fix the model. Make invalid state unrepresentable -- pass parameters over hidden globals, encode the constraint in the type/shape so the bad combination cannot be constructed. Reason from physical constraints (latency, bandwidth, memory, coordination, the worst node) before designing within them. Keep the spine flat, each unit single-focus and understandable at its call site. Make misuse structurally impossible, not documented-against. Optimize the worst case, not the average; design every failure path explicitly (full -> degraded -> safe-fail -> explicit-error), never a silent catastrophic mode. Measure, do not assume -- profile before optimizing, implement both and compare on real input when in genuine dispute. When a change regresses something that worked, revert first and investigate second: restore green, then diagnose from a known-good base. Fail fast and loud over limping on bad state.
46
38
 
47
39
  ## Memorize
48
40
 
49
- You write to the recall index only by dispatching `memorize-fire`. Other surfaces produce memos the index does not see.
50
-
51
- Between each mutable resolution, between failed exec retries, between unfamiliar errors — you re-dispatch `instruction`. EXECUTE has the highest drift surface; the recovery primitive is unchanged.
52
-
53
- When a gate denies your verb, the denial payload carries a `next_dispatch` field naming the recovery verb (typically `instruction`). You dispatch THAT verb next, not the same denied verb again. Retrying the denied verb without dispatching the recovery first escalates to `deviation.long-gap-retry-without-instruction` on the 2nd attempt. The gate's refusal IS the chain telling you the next step is the named verb.
41
+ Write the recall index only via `memorize-fire`; other surfaces produce memos the index never sees. Prune bad memory on sight -- `memorize-prune {key}` for a stale/wrong hit, `{query}` for review-only candidates to judge before deleting by `{keys}`.
54
42
 
55
43
  ## Dispatch
56
44
 
57
- You spool every possible exec.
58
-
59
- You flip mutables by dispatching `mutable-resolve` with body `{"mutable_id": "<id>", "witness_evidence": "<file:line | codesearch hit | exec snippet>"}`.
60
-
61
- You flip PRD rows by dispatching `prd-resolve` with body `{"id": "<prd-item-id>", "witness_evidence": "<…>"}`. Bare text body (just the id) is also accepted but loses the witness audit trail. Do not pass `{prd_id, witness_evidence}` with the whole envelope nested as a string — the verb accepts `id` or `prd_id` at the top level alongside `witness_evidence`. A response with `deviation_kind: prd-resolve-unknown-id` means your id did not match a PRD row; you read the `hint` field and re-dispatch with the correct id, you do not retry blind.
45
+ Spool every exec. Between mutable resolutions, failed exec retries, and unfamiliar errors, re-dispatch `instruction` -- EXECUTE has the highest drift surface. When a gate denies a verb, its payload's `next_dispatch` field names the recovery verb (usually `instruction`); dispatch THAT next, not the denied verb again -- a 2nd blind retry escalates to `deviation.long-gap-retry-without-instruction`.
62
46
 
63
- You dispatch `transition` when the PRD slice is closed and every possible mutable is witnessed. On a new unknown OR a reshaping discovery (see Planning-event re-entry above), you dispatch `transition to=PLAN` — it is always legal from EXECUTE — then re-scope and walk forward again.
47
+ - Mutables: `mutable-resolve` body `{"mutable_id": "<id>", "witness_evidence": "<file:line | codesearch hit | exec snippet>"}`.
48
+ - PRD rows: `prd-resolve` body `{"id": "<id>", "witness_evidence": "<...>"}` (top-level `id`/`prd_id` beside `witness_evidence`; bare-id body works but loses the audit trail; never nest the whole envelope as a string). `deviation_kind: prd-resolve-unknown-id` means the id missed -- read the `hint` field and re-dispatch corrected, never blind.
49
+ - `transition` when the slice is closed and every mutable is witnessed; `transition to=PLAN` on a new unknown or reshaping discovery.
@@ -1,43 +1,35 @@
1
1
  # PLAN
2
2
 
3
- YOU are the state machine. Plugkit is the synchronous library serving this prose; advancing the chain is your dispatch, not its action. Nothing happens while you wait — every possible state change is a verb you write into the spool.
3
+ YOU are the state machine. Plugkit is the synchronous library serving this prose; every state change is a verb you write into the spool, and nothing happens while you wait.
4
4
 
5
- L1 baseline + L2 covering family. You loaded prior memory on entry by dispatching `instruction`.
5
+ L1 baseline + L2 covering family. You loaded prior memory on entry via `instruction`.
6
6
 
7
7
  ## Orient
8
8
 
9
- Your first non-trivial dispatch = parallel fan-out of `recall` + `codesearch` against the request's nouns, single message. Hits = your baseline; misses delimit fresh ground you must investigate. If you skip orient, you commit to an unobserved envelope.
9
+ First non-trivial dispatch = a single-message parallel fan-out of `recall` + `codesearch` against the request's nouns. Hits are your baseline; misses delimit fresh ground to investigate. Skip orient and you commit to an unobserved envelope.
10
10
 
11
11
  ## Cover
12
12
 
13
- You write the PRD as the central plan-item store (`|F|=1`). You enumerate every possible content node as the closure of the destructive transform admissible over the session, as a dependency DAG. Reach permits the next node; the next node is in-scope. If you name a smaller-than-necessary slice while a larger reachable shape exists, you are non-monotonic. You partition along dependency edges, not schedule. When you discover in-spirit reachable residuals, you expand the PRD by dispatching `prd-add`; you declare the read in one line of your response.
13
+ Write the PRD as the central plan-item store (`|F|=1`): enumerate every content node as the closure of the destructive transform admissible over the session, a dependency DAG partitioned along dependency edges, not schedule. Reach permits the next node; the next node is in-scope. Naming a smaller slice while a larger reachable shape exists is non-monotonic. Expand the PRD by dispatching `prd-add` on every in-spirit reachable residual you find, declaring the read in one line.
14
14
 
15
- The phrase "every possible" is your load-bearing test. Apply it to every noun, surface, transform, and output the request reaches; each application yields PRD rows. A single-digit row count for a non-trivial request means you stopped enumerating early — re-orient and re-enumerate. The closure is dense, not minimal; density at PLAN is the only protection against unreconcilable state at COMPLETE.
16
-
17
- Inline TODO in your response body violates `|F|=1` and produces unreconcilable state.
15
+ "Every possible" is the load-bearing test -- apply it to every noun, surface, transform, and output the request reaches; each application yields rows. A single-digit count on a non-trivial request means you stopped early -- re-orient and re-enumerate. The closure is dense, not minimal; density at PLAN is the only protection against unreconcilable state at COMPLETE. An inline TODO in the response body violates `|F|=1`.
18
16
 
19
17
  ## Expansion
20
18
 
21
- After your first PRD pass, feed the list into a second transform: for every possible row, ask what every possible corner case, caveat, failure mode, adjacent-row interaction, degenerate input, and empty/overflow/reentry state looks like — and write those as new rows. Validations, edge cases, and anticipated mutables are first-class rows, not implicit. Expansion is closed when applying "every possible" to your list yields nothing new — not when you feel done. Skip it and the chain converges on a shape the user did not ask for.
22
-
23
- A second-pass PRD that doubles or triples the row count is the expected shape, not an over-reach. Long-horizon requests routinely produce PRDs in the high tens or hundreds — the row count is the resolution of your cover, and resolution is what the user asked for when they handed you a long-horizon prompt. Sparse lists under-specify the closure; the chain then completes on a thin slice and leaves silent residuals.
19
+ Feed the first pass into a second transform: for every row, ask what every corner case, caveat, failure mode, adjacent-row interaction, degenerate input, and empty/overflow/reentry state looks like, and write those as new rows. Validations, edge cases, and anticipated mutables are first-class rows. Expansion closes when applying "every possible" yields nothing new, not when you feel done. A second-pass PRD that doubles or triples the count is the expected shape -- long-horizon requests routinely produce high-tens-to-hundreds; the row count is the resolution of the cover, which is what the user asked for. Sparse lists complete on a thin slice and leave silent residuals.
24
20
 
25
- Cut the cover so the hardest reachable node comes first, not last. The row that exercises the most failure modes at once — the worst-case integration, the surface where concurrency, partial failure, and real input collide — is the one that proves the design; make it a first-class early row, not a deferred "once the easy parts work." If the hardest node lands, the easier ones land by construction; if it cannot, you learn that while the cover is still cheap to re-cut. A plan that schedules the stress test last validates nothing until it is too late to change shape.
21
+ Cut the cover so the hardest reachable node comes first: the row exercising the most failure modes at once -- the worst-case integration where concurrency, partial failure, and real input collide -- proves the design, so make it a first-class early row, not a deferred "once the easy parts work." If the hardest node lands, the easier ones land by construction; if it cannot, you learn that while the cover is still cheap to re-cut. Scheduling the stress test last validates nothing until it is too late to reshape.
26
22
 
27
23
  ## Noticing-to-PRD
28
24
 
29
- Anything you notice during orient or expansion that is not yet a PRD row — outstanding work, an unfinished surface, an improvable shape, a preference misalignment, an adjacent concern — is a `prd-add` you dispatch this turn. Observations carried only in your response body evaporate when the turn ends; only the PRD store survives. Noticing IS the planning event, never an aside: "we should also..." / "worth noting..." belongs in a row instead, with the witness that motivated it. Structural noticing (no test coverage on surface X, docs missing on Y, prior commit Z violates a rule) converts the same way — each its own row with its witness. Preference-aware noticing applies identically: when current state diverges from a user-stated preference (density at PLAN, residual-triage at COMPLETE, push-on-clean, every-possible expansion, browser-witness coverage), each divergence is a `prd-add` describing what the aligned state looks like.
25
+ Anything noticed during orient or expansion that is not yet a row -- outstanding work, an unfinished surface, an improvable shape, a preference misalignment, an adjacent concern -- is a `prd-add` this turn. Observations carried only in the response body evaporate; only the store survives. "We should also..." / "worth noting..." belongs in a row with the witness that motivated it. Structural noticing (no test coverage on X, docs missing on Y, prior commit Z violates a rule) and preference-aware noticing (state diverging from density-at-PLAN, residual-triage, push-on-clean, every-possible expansion, browser-witness coverage) convert the same way -- each its own row describing the aligned state.
30
26
 
31
27
  ## Mutables
32
28
 
33
- You enter unknowns into `.gm/mutables.yml` by dispatching `mutable-add` with `status: unknown`. Your witness = `file:line`, codesearch hit, or exec output. Narrative resolution in your response is rejected. Unwitnessed rows block every possible `transition` you attempt.
34
-
35
- Between sub-steps of PLAN — between the orient fan-out and the PRD write, between PRD rows you're unsure about, between recall hits you don't know how to weight — you re-dispatch `instruction`. Uncertainty is the signal to come back. You do not invent next steps from memory of the prose; you re-read.
29
+ Enter unknowns into `.gm/mutables.yml` via `mutable-add` with `status: unknown`; witness = `file:line`, codesearch hit, or exec output. Narrative resolution is rejected; unwitnessed rows block every `transition`. Between sub-steps -- orient and PRD write, rows you are unsure of, recall hits you cannot weight -- re-dispatch `instruction`; uncertainty is the signal to re-read, never to invent the next step from memory.
36
30
 
37
31
  ## Dispatch
38
32
 
39
- You dispatch: `recall`, `codesearch`, `prd-add`, `mutable-add`, `mutable-resolve`, `transition`. Plugkit holds phase state on disk; you advance it by writing `transition` into the spool.
40
-
41
- When you dispatch `prd-add`, you pass an `id` field — a kebab-case slug derived from the subject (e.g. `dedupe-update-error`, `route-fastgrnn-port`). Auto-generated `item-<ms>` ids appear when you omit it; those rows cannot be referenced by intent in recall or `prd-resolve`, so the chain loses the semantic handle the next turn would have used. The id is your contract with the PRD store: every later dispatch that names the row uses the id you wrote.
33
+ Verbs: `recall`, `codesearch`, `prd-add`, `mutable-add`, `mutable-resolve`, `transition`. Plugkit holds phase on disk; you advance it by writing `transition`.
42
34
 
43
- `prd-add` upserts by id. A fresh id appends a new row (`{"added": id}`); an id that already exists rewrites that row in place (`{"rescoped": id}`), preserving its position and every dependent that names it. This is the re-scope path: when you re-enter PLAN from EXECUTE on a reshaping discovery (a decision that changed a row's scope or approach), you re-`prd-add` the affected row with its existing id and the new scope — you never delete-and-re-add, which would orphan the handle. Re-entry to PLAN is a first-class move, not a failure; the cover is meant to be re-cut whenever the work reveals the old shape was wrong.
35
+ `prd-add` takes an `id` -- a kebab-case slug from the subject (`dedupe-update-error`, `route-fastgrnn-port`). Omitting it yields an auto `item-<ms>` id that cannot be referenced by intent in recall or `prd-resolve`, losing the semantic handle. `prd-add` upserts by id: a fresh id appends (`{"added": id}`); an existing id rewrites in place (`{"rescoped": id}`), preserving position and every dependent that names it. This is the re-scope path -- re-entering PLAN from EXECUTE on a reshaping discovery, re-`prd-add` the affected row with its existing id and new scope; never delete-and-re-add (orphans the handle). Re-entry to PLAN is a first-class move, not a failure; the cover is meant to be re-cut whenever the work reveals the old shape was wrong.
@@ -1,43 +1,37 @@
1
1
  # UPDATE-DOCS
2
2
 
3
- YOU are the state machine. Plugkit is the synchronous library serving this prose; advancing the chain is your dispatch, not its action. Docs do not update themselves — you dispatch every possible edit and every possible push.
3
+ YOU are the state machine. Plugkit is the synchronous library serving this prose; docs do not update themselves -- you dispatch every edit and every push.
4
4
 
5
- Your docs reflect the current state of the system, not its history. You write every possible rule in AGENTS.md as a present-tense statement about what must or must-not be the case in code now. Past-tense framing, `(FIXED)` markers, dated audit entries, and "we used to X, now we Y" phrasing belong in `git log` and `CHANGELOG.md` — you never put them in AGENTS.md.
5
+ Docs reflect the current state of the system, not its history. Every rule in AGENTS.md is present-tense -- what must or must-not be the case in code now. Past-tense framing, `(FIXED)` markers, dated audit entries, and "we used to X, now Y" belong in `git log` and `CHANGELOG.md`, never AGENTS.md.
6
6
 
7
7
  ## AGENTS.md and CLAUDE.md
8
8
 
9
- You edit AGENTS.md and CLAUDE.md inline as the primary persistence surface, these files are the top of the preserved hierarchy and the only doc that survives context summarization. Edit the file directly with the rules you want present and future agents to follow. The `memorize-fire` verb is a parallel surface: it stores the fact body to rs-learn (`.gm/exec-spool/in/memorize-fire/<N>.txt` with raw text or JSON `{text, namespace?}`) where `recall` and `auto_recall` retrieve it on future turns.
9
+ Edit AGENTS.md/CLAUDE.md inline -- the top of the preserved hierarchy and the only doc that survives context summarization. `memorize-fire` is the parallel surface (`.gm/exec-spool/in/memorize-fire/<N>.txt`, raw text or `{text, namespace?}`) where `recall`/`auto_recall` retrieve the fact on future turns. AGENTS.md is the staging ground; the store is the recall surface. Migration is the agent's dual-write, not a file-scan: landing a load-bearing rule in AGENTS.md, fire the same rule to the store the same session so it surfaces in `auto_recall`. An automatic ingest cannot run -- the classifier cannot judge which paragraphs are recall-worthy rules vs narrative, so the agent judges at write time. Never pass `namespace:"AGENTS.md"` (mislabeled namespace); load-bearing rules go to the default namespace. Multiple facts = multiple parallel requests in one message.
10
10
 
11
- AGENTS.md is the staging ground; the learning store is the recall surface. Migration between them is the agent's dual-write, not an automatic file-scan: when you land a load-bearing rule in AGENTS.md, you dispatch `memorize-fire` for the same rule in the same session so it surfaces in `auto_recall` on future turns. This is deliberate, not a gap, an automatic AGENTS.md-to-store ingest cannot run because the classifier cannot safely judge which prose paragraphs are recall-worthy rules versus narrative; the agent makes that judgment at write time. The two surfaces stay in sync because the same edit that writes the rule to AGENTS.md also fires it to the store. Do NOT pass `namespace:"AGENTS.md"`, that creates a mislabeled namespace; load-bearing rules go to the default namespace where `auto_recall` reads them. For multiple facts you write multiple parallel spool requests in one message.
12
-
13
- **Migration is bidirectional, and the back-pressure is deflation: every memorization run also drains AGENTS.md.** AGENTS.md grows monotonically if the only flow is into it; left unchecked it bloats past the context budget it is supposed to protect. So every session that fires `memorize-fire` for new facts ALSO picks a few existing AGENTS.md entries that have become detail-heavy, single-crate, or single-platform — exactly the material the Documentation Policy says belongs in rs-learn, not in the top-level rule file — and exfiltrates them: `memorize-fire` the entry's substance to the default namespace, then delete or compress its AGENTS.md paragraph to a one-line pointer in the same commit. Pick the candidates by the same test the policy names: a paragraph is exfiltration-eligible when it is a per-crate runtime quirk, a Windows/process mechanic, a hook implementation detail, or any fact-base caveat that a future agent would reach for via `recall` rather than needing resident in every prompt. Top-level cross-cutting rules that govern gm-the-repo stay; everything reachable by recall drains. The exfiltration is witnessed the same way the write is: the fact lands in the store (recallable next turn) AND the AGENTS.md byte-count drops. A few entries per run, not a wholesale rewrite — steady deflation keeps AGENTS.md lean while the recall surface absorbs the detail. Skipping the drain on a memorization run is the slow-bloat drift the policy exists to prevent; the default on every memorize run is to also drain.
11
+ **Migration is bidirectional; the back-pressure is deflation -- every memorize run also drains AGENTS.md.** AGENTS.md grows monotonically if flow is only inward and bloats past the budget it protects. So every session firing `memorize-fire` for new facts ALSO picks a few existing AGENTS.md entries that have gone detail-heavy/single-crate/single-platform (the material the Documentation Policy assigns to rs-learn), `memorize-fire`s the substance to the default namespace, and deletes or compresses the paragraph to a one-line pointer in the same commit. Eligible = a per-crate runtime quirk, a Windows/process mechanic, a hook implementation detail, any fact-base caveat a future agent reaches for via `recall` rather than needing resident every prompt. Top-level cross-cutting rules stay; everything recall-reachable drains. Witnessed both ways: the fact lands in the store AND the byte-count drops. A few entries per run, never a wholesale rewrite. Skipping the drain is the slow-bloat drift the policy exists to prevent.
14
12
 
15
13
  ## README.md
16
14
 
17
- You refresh README to reflect the surface a new reader actually encounters. You remove every possible stale install step, version pin, and feature that no longer exists. You add what you added this session if it changes the public surface.
15
+ Refresh to the surface a new reader actually encounters: remove every stale install step, version pin, and gone feature; add what you added this session if it changes the public surface.
18
16
 
19
17
  ## docs/index.html
20
18
 
21
- You regenerate or hand-edit to reflect the same surface. Site builds run from `site/`; the deployed `/` route renders from `site/content/pages/home.yaml` via flatspace. You route landing edits through `site/theme.mjs` (Hero) and the YAML — never `site/index.html` directly. `docs/styles.css` is generated from `site/input.css`; you append to the source, not the output.
19
+ Regenerate/hand-edit to the same surface. Site builds run from `site/`; the deployed `/` route renders from `site/content/pages/home.yaml` via flatspace. Route landing edits through `site/theme.mjs` (Hero) and the YAML, never `site/index.html` directly. `docs/styles.css` is generated from `site/input.css` -- append to the source, not the output.
22
20
 
23
21
  ## CHANGELOG.md
24
22
 
25
- You write one entry per every possible commit you landed this session. The commit message line plus a one-sentence "why" — no recipe, no narration. CHANGELOG carries the history that AGENTS.md refuses.
23
+ One entry per commit landed this session: the commit subject plus a one-sentence "why", no recipe. CHANGELOG carries the history AGENTS.md refuses.
26
24
 
27
25
  ## Commit and Push
28
26
 
29
- You stage doc updates only — you never bundle them with code changes from earlier phases (you committed those at their own time). One commit, present-tense imperative subject. Before every possible push, you dispatch `git status --porcelain` as its own Bash **tool-use event** — a separate `Bash(...)` invocation, not a `&&`-chained shell command within the push event. Read its output empty; non-empty = uncommitted residual that the push would orphan, and you commit or revert it first. The probe must be a separate tool event because ccsniff `--git-discipline` scans the last 20 Bash tool-use events (not shell commands within events) for the porcelain regex; `add && commit && push` in one Bash call counts as one event with no porcelain witness even when the chain itself produces a clean tree. The witness lives in the tool-call stream, not the shell stream. Then you push to main. Your push triggers the docs pipeline if the repo has one. A doc commit stages only paths matching AGENTS.md, CLAUDE.md, README.md, SKILLS.md, CHANGELOG.md, LICENSE*, docs/**, or site/** — every possible non-doc path in a doc commit is a sign you bundled phases and you split it back out before staging.
27
+ Stage doc updates only -- never bundle them with code changes from earlier phases (committed at their own time). One commit, present-tense imperative subject. Push via the git verbs: `git_finalize {message}` bundles add -> commit -> porcelain-gate -> push in one dispatch, or `git_add` the doc paths then `git_commit` then `git_push`. The verbs gate on the porcelain probe internally and refuse a dirty tree (`deviation.push-dirty`); a raw `git` shell body is gated `deviation.bash-git-bypass`. If you ever fall back to raw Bash git, the porcelain probe must be its own `Bash(git status --porcelain)` tool-use event before the push (not `&&`-chained) -- ccsniff `--git-discipline` scans the last 20 Bash tool-use events for the porcelain regex, and `add && commit && push` in one event has no witness. A doc commit stages only paths matching AGENTS.md, CLAUDE.md, README.md, SKILLS.md, CHANGELOG.md, LICENSE*, docs/**, or site/**; any non-doc path means you bundled phases -- split it out before staging. The push triggers the docs pipeline and IS the validation dispatch.
30
28
 
31
29
  ## COMPLETE
32
30
 
33
- This is the terminal phase. After your push lands, you dispatch `transition` to COMPLETE. Plugkit then records the chain as concluded.
34
-
35
- **Once `phase=COMPLETE` and `prd_pending_count=0`, the chain is closed.** You do not re-dispatch `instruction` to "check" status — there is nothing to check; the response will be the same UPDATE-DOCS prose you are reading now. You do not dispatch every possible other verb either — the dispatch surface is closed. The session ends. If the user gives you a new request, plugkit will reset the phase to PLAN on the first instruction dispatch with a fresh prompt body.
31
+ Terminal phase. After the push lands, dispatch `transition` to COMPLETE; plugkit records the chain concluded.
36
32
 
37
- Re-dispatching instruction on a COMPLETE chain with no new prompt is a deviation: it burns cycles, accumulates `turn.start`/`turn.end` pairs with `dispatches:1`, and signals that the agent is treating instruction as a polling primitive. The recovery is to stop dispatching; the user reactivates the chain.
33
+ **Once `phase=COMPLETE` and `prd_pending_count=0`, the chain is closed.** Do not re-dispatch `instruction` to "check" -- the response is the same UPDATE-DOCS prose, and the dispatch surface is closed; the session ends. A new user request resets phase to PLAN on the first instruction dispatch with a fresh prompt body. Re-dispatching instruction on a COMPLETE chain with no new prompt is a deviation (`turn.start`/`turn.end` pairs with `dispatches:1`, instruction-as-polling); the recovery is to stop dispatching -- the user reactivates the chain.
38
34
 
39
35
  ## Dispatch
40
36
 
41
- You dispatch `phase-status` to confirm the chain state, then `transition` to COMPLETE if you have not already. After COMPLETE lands, you stop.
42
-
43
- Transition: when you have committed and pushed docs → you dispatch `transition` to advance to COMPLETE. Chain done.
37
+ `phase-status` to confirm chain state, then `transition` to COMPLETE if not already. After COMPLETE lands, stop.