diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e529d6..09742fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 (`taste = 2`, or `terrain = 2` with any `ambiguity`). `md.aperture()` renders **`Pre-build map: required`** so `/ratchet:ignite` routes high-uncertainty work through the fog gate instead of relying on the operator to remember. A4 still builds nothing. +- **The map lives through the build.** New `templates/unknowns-map.md` (the four-quadrant + map's file shape, with a *Deviations during build* section) and `templates/deviation-note.md` + (map said X → code revealed Y → call made). `/ratchet:build` now builds *against* an existing + `unknown-map` artifact and records deviations as decisions/open-loops/defects instead of + silently absorbing them; `/ratchet:handoff` surfaces those deviations so the receiver never + re-litigates what the build already discovered. ## [0.5.0] - 2026-07-04 — Receipt diff --git a/skills/build/SKILL.md b/skills/build/SKILL.md index 57ce36e..248f4a3 100644 --- a/skills/build/SKILL.md +++ b/skills/build/SKILL.md @@ -40,6 +40,12 @@ Templates for records live in the plugin's `templates/` directory — mirror the 4. **Write a 5-point working test.** Concrete pass/fail checks a stranger could run. If you cannot write the test, you do not yet understand the artifact — say so and narrow scope. +**Build against the map.** If `/ratchet:map` left an `unknown-map` artifact +(`.ratchet/unknowns-map.md`), build against it — and when the code contradicts what the map +assumed, do not silently absorb it. Record a deviation (`templates/deviation-note.md`) as a +`decision`, `openLoop`, or `defect`, and add it to the map's *Deviations during build* +section. The map is a living record through the build, not a pre-build formality. + For large or code-heavy artifacts, delegate to the `ratchet-builder` subagent. ## Output contract @@ -61,6 +67,7 @@ EXPLICIT HOLES: ``` ratchet artifact add '{"title":"","kind":"<kind>","status":"v0","path":"<path or empty>","holes":["...","..."]}' +ratchet state append openLoops '{"text":"deviation: map said X, code revealed Y — needs user judgment","status":"open"}' # only if the build diverged from the map ratchet state set phase build ``` diff --git a/skills/handoff/SKILL.md b/skills/handoff/SKILL.md index 34acf4f..03a52e6 100644 --- a/skills/handoff/SKILL.md +++ b/skills/handoff/SKILL.md @@ -37,6 +37,9 @@ to skim past: 7. **Context to act** — the minimum files, commands, or facts the receiver needs. Point to locations; don't paste the world. 8. **Watch-outs** — the traps you already hit or foresee. +9. **Deviations from the map** — if `/ratchet:map` ran, where the build diverged from its + plan (map said X → code revealed Y → call made) and which calls still need the user's + judgment. This is what stops the receiver from re-litigating what you already discovered. ## Rules @@ -57,6 +60,7 @@ OPEN RISKS: <[severity] summary> (each) NEXT ACTION: <the single concrete first move> CONTEXT TO ACT: <files / commands / facts, by location> WATCH-OUTS: <traps> +DEVIATIONS: <map said X → code revealed Y → call made> (each, if a map ran) NEXT COMMAND: /ratchet:<command> ``` diff --git a/skills/map/SKILL.md b/skills/map/SKILL.md index 82b5c22..26806ff 100644 --- a/skills/map/SKILL.md +++ b/skills/map/SKILL.md @@ -68,10 +68,12 @@ the moment you hit them; never close a quadrant off-screen. status: decided | OPEN | sharp-edge ``` -5. **Hand over the map.** One page, all four quadrants. OPEN items live **on the map**, not - buried in chat. Add a tweakable build plan ordered by *what might change* (judgment calls - first, routine work compressed at the bottom) and a copy-paste implementation prompt. - Then stop — implementation is a separate engagement. +5. **Hand over the map.** One page, all four quadrants — shape it like + `templates/unknowns-map.md` and write it to `.ratchet/unknowns-map.md`. OPEN items live + **on the map**, not buried in chat. Add a tweakable build plan ordered by *what might + change* (judgment calls first, routine work compressed at the bottom) and a copy-paste + implementation prompt. Then stop — implementation is a separate engagement. The map stays + live through the build: `/ratchet:build` records deviations back onto it. ## Output contract diff --git a/templates/deviation-note.md b/templates/deviation-note.md new file mode 100644 index 0000000..3608bb3 --- /dev/null +++ b/templates/deviation-note.md @@ -0,0 +1,20 @@ +# Deviation: <one line — what the map did not predict> + +- **Date:** <ISO date> +- **Against map:** .ratchet/unknowns-map.md +- **Needs user judgment?** yes | no + +## Map said +<What the map assumed or planned for this part.> + +## Code revealed +<What the terrain actually showed once you built it — evidence: file:line.> + +## Call made +<The conservative call you took to keep moving without silently absorbing the surprise.> + +## Record as +<Pick one and write it to state: +- committed a path → `ratchet state append decisions '{"choice":"...","rejected":"...","tripwire":"..."}'` +- needs the user → `ratchet state append openLoops '{"text":"deviation: ...","status":"open"}'` +- a real failure → `ratchet defect add '{"severity":"...","summary":"..."}'`> diff --git a/templates/unknowns-map.md b/templates/unknowns-map.md new file mode 100644 index 0000000..5b9fdfd --- /dev/null +++ b/templates/unknowns-map.md @@ -0,0 +1,34 @@ +# Unknowns Map: <target> + +- **Date:** <ISO date> +- **Aperture:** <A0–A4, score/10> +- **Status:** handoff | building | closed +- **Path:** .ratchet/unknowns-map.md + +## Known knowns — settled ground +- <fact> — evidence: <file:line> +- <assumption> — treated as true until challenged + +## Known unknowns — decision ledger +| Question | Recommended | Closed by | Unblocks | +| --- | --- | --- | --- | +| <question> | <lettered answer> | user \| territory \| OPEN | <what it unblocks> | + +## Unknown knowns — extracted tacit context +- <constraint surfaced by the user's reaction> — reshaped the target: <how> + +## Unknown unknowns — landmines +| Landmine | Evidence | Why it bites | What it changes | Status | +| --- | --- | --- | --- | --- | +| <name> | <file:line> | <mechanism> | <task impact> | decided \| OPEN \| sharp-edge | + +## Build plan (tweakable — judgment calls first) +1. <judgment call the user might change> +2. <routine work, compressed at the bottom> + +## Implementation prompt +<copy-paste line that launches the build with this map's context> + +## Deviations during build +<Grows as you build — one entry per surprise, shaped like templates/deviation-note.md. +OPEN items stay here on the map, not buried in chat. Empty until the build reveals one.> diff --git a/test/plugin-shape.test.js b/test/plugin-shape.test.js index c774ede..d357f8b 100644 --- a/test/plugin-shape.test.js +++ b/test/plugin-shape.test.js @@ -146,4 +146,13 @@ ok('the /ratchet:map fog gate is wired into the prompt catalog', () => { assert.ok(prompts.includes('/ratchet:map'), 'PROMPTS.md references /ratchet:map'); }); +ok('the living unknowns-map ships as templates and threads through build → handoff', () => { + // The map is not a pre-build formality: it has a file shape, and it stays alive + // through the build as deviation notes that surface again at handoff. + assert.ok(exists('templates/unknowns-map.md'), 'templates/unknowns-map.md exists'); + assert.ok(exists('templates/deviation-note.md'), 'templates/deviation-note.md exists'); + assert.ok(/deviation/i.test(read('skills/build/SKILL.md')), 'build records map deviations'); + assert.ok(/deviation/i.test(read('skills/handoff/SKILL.md')), 'handoff surfaces map deviations'); +}); + process.stdout.write(`\n${passed} passed\n`);