gm-skill 2.0.1549 → 2.0.1551
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.
- package/AGENTS.md +62 -70
- package/gm-plugkit/instructions/browser.md +14 -21
- package/gm-plugkit/instructions/emit.md +8 -12
- package/gm-plugkit/instructions/entry.md +37 -41
- package/gm-plugkit/instructions/execute.md +20 -34
- package/gm-plugkit/instructions/plan.md +11 -19
- package/gm-plugkit/instructions/update_docs.md +11 -17
- package/gm-plugkit/instructions/verify.md +21 -31
- package/gm-plugkit/package.json +1 -1
- package/gm-plugkit/scripts/sync-instruction-consts.mjs +36 -0
- package/gm.json +1 -1
- package/package.json +1 -1
- package/prompts/bash-deny.txt +2 -2
- package/prompts/pre-compact.txt +1 -1
- package/prompts/prompt-submit.txt +24 -64
- package/scripts/check-prose-bundle.mjs +28 -0
- package/skills/gm-skill/SKILL.md +32 -42
|
@@ -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.
|
|
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.
|
|
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
|
|
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
|
|
12
|
+
candidate -> [L1 witness] -> [L2 single-writer] -> [L3 direction] -> execute
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
- **L1.**
|
|
16
|
-
- **L2.** Single-writer per surface (`|F|=1`)
|
|
17
|
-
- **L3.** Lyapunov:
|
|
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
|
|
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
|
|
24
|
-
- **Bounds prevent cascades
|
|
25
|
-
- **Effort is unbounded
|
|
26
|
-
- **Direction eliminates waste
|
|
27
|
-
- **Monotonic closure on first emit
|
|
28
|
-
- **Witness is the audit primitive
|
|
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
|
|
33
|
-
- **Hardware reality
|
|
34
|
-
- **Flat structure
|
|
35
|
-
- **200-line vertical slices
|
|
36
|
-
- **Async boundary explicit
|
|
37
|
-
- **Naming by scale
|
|
38
|
-
- **Fail fast, loud, deterministic
|
|
39
|
-
- **Binary transport, append-only persistence
|
|
40
|
-
- **Single focused task per session
|
|
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
|
|
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`
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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`
|
|
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
|
-
|
|
72
|
+
Thread SESSION_ID through every spool body + rs-exec RPC; plugkit rejects empty.
|
|
73
73
|
|
|
74
74
|
## Daemonize
|
|
75
75
|
|
|
76
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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:
|
|
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;
|
|
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
|
|
5
|
+
L3 distance + audit: real input -> real code -> real output, witnessed.
|
|
6
6
|
|
|
7
7
|
## Surfaces
|
|
8
8
|
|
|
9
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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.**
|
|
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
|
|
21
|
+
## Surface -> mutable
|
|
22
22
|
|
|
23
|
-
|
|
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
|
-
##
|
|
25
|
+
## Discovery: additive vs reshaping
|
|
26
26
|
|
|
27
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
35
|
+
## Engineering invariants (shape of the code you land)
|
|
44
36
|
|
|
45
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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;
|
|
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
|
|
5
|
+
L1 baseline + L2 covering family. You loaded prior memory on entry via `instruction`.
|
|
6
6
|
|
|
7
7
|
## Orient
|
|
8
8
|
|
|
9
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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`
|
|
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;
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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.
|