Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- **`/ratchet:map` — the pre-build fog gate.** The loop had no pre-build ambiguity pass:
`/ratchet:cut` attacks assumptions, but nothing walked the codebase's tacit knowledge
before building. `/ratchet:map` walks high-uncertainty work (aperture A3–A4, unfamiliar
terrain, "I'll know it when I see it" taste, reference ports) through the four
unknown-quadrants — known knowns (settled ground with `file:line` evidence), known
unknowns (one blast-radius-ordered question at a time), unknown knowns (tacit taste
surfaced by putting concrete options in front of the user), unknown unknowns (a swept
landmine field) — and hands over one durable four-quadrant map, a build plan, and a
copy-paste implementation prompt before any code is written. CLI-backed
(`artifact kind:"unknown-map"`, decisions, assumptions, open loops), so its open items
drain `ratchet score confidence` until closed; no schema change. Method grafted from
dzhng/skills `explore-unknowns`, expressed in ratchet's own vocabulary. Aperture
auto-routing (scoring the task straight into the map) is deferred to a follow-up.

## [0.5.0] - 2026-07-04 — Receipt

0.2 gated proof; 0.3 gated the *seam* of that proof; 0.4 metered the *depth* of the loop.
Expand Down Expand Up @@ -213,7 +229,7 @@ Initial public release.
- Single-plugin marketplace manifest so the repo installs directly as a Claude Code plugin.
- Zero-dependency smoke test suites for the state engine and the evolution helpers.

[Unreleased]: https://github.com/TheLucidTech/torque-loop/compare/v0.4.0...HEAD
[Unreleased]: https://github.com/TheLucidTech/torque-loop/compare/v0.5.0...HEAD
[0.4.0]: https://github.com/TheLucidTech/torque-loop/compare/v0.3.0...v0.4.0
[0.3.0]: https://github.com/TheLucidTech/torque-loop/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/TheLucidTech/torque-loop/compare/v0.1.0...v0.2.0
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ when it isn't. In Codex, ask it to use the matching Torque Loop skill, for examp
| --- | --- |
| `/ratchet:ignite` | Run the full consequence loop on any messy task. |
| `/ratchet:lock` | Convert vague input into a locked, executable target. |
| `/ratchet:map` | Map the fog before building — walk the four unknown-quadrants, hand over a durable map. |
| `/ratchet:auction` | Rank the real blockers by leverage; pick the one bottleneck. |
| `/ratchet:cut` | Attack the hidden assumptions before you invest. |
| `/ratchet:mechanism` | Name the one mechanism under a confusing situation. |
Expand All @@ -201,6 +202,13 @@ when it isn't. In Codex, ask it to use the matching Torque Loop skill, for examp
| `/ratchet:status` | Read the current ratchet state. |
| `/ratchet:loop` | Repeat build → attack → patch → compile until it holds. |

> **When to reach for `/ratchet:map`.** High-uncertainty work — aperture **A3–A4**,
> unfamiliar terrain, reference-implementation ports, or "I'll know it when I see it"
> taste. Walk the four unknown-quadrants (known knowns · known unknowns · unknown knowns ·
> unknown unknowns) and hand over the map *before* `/ratchet:build`; at **A4**, stop after
> the map until constraints are locked. What you deliver is the map, not a build — a wrong
> assumption caught on the map is a one-line fix; caught mid-build it is a rewrite.

### Specialized

| Command | Purpose |
Expand Down
40 changes: 40 additions & 0 deletions reference/PROMPTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ prompt is the load-bearing intent — fix the skill.
| --- | --- |
| `/ratchet:ignite` | Master Ignition Prompt (consequence engine) |
| `/ratchet:lock` | 1 · The Target Is Not The Topic |
| `/ratchet:map` | The Fog Map (four-quadrant unknowns walk) |
| `/ratchet:auction` | 2 · The Friction Auction |
| `/ratchet:cut` | 3 · The Assumption Guillotine |
| `/ratchet:mechanism` | 4 · The Mechanism Knife |
Expand Down Expand Up @@ -124,6 +125,45 @@ Choose the target and make it operational.

---

## The Fog Map → `/ratchet:map`

The pre-build twin of the target lock: where `/ratchet:lock` says *infer and move*, the
Fog Map says *don't build on a high-blast-radius guess*. Run it when uncertainty earns it
(aperture A3–A4, unfamiliar terrain, "know it when I see it" taste, a reference port).
Method grafted from the `explore-unknowns` skill; expressed here in ratchet's own
vocabulary — general mechanism, own words — the same graft discipline as the aperture dial.

```text
Map the fog before you build.

Given this task and its codebase:

[PASTE CONTEXT]

Do not build yet. Scan the terrain first — existing, half-built, and reverted work —
then walk four quadrants in order, naming the current one:

1. Known knowns — state the settled ground, each fact cited to file:line. Mark every
assumption separately and say you will treat it as true until I correct it.
2. Known unknowns — ask ONE question at a time, widest-impact first. Give lettered options
with a recommended answer so I react in a few characters. Close each by:
user answer | territory (you researched it, show question + finding) | OPEN (+ what unblocks it).
3. Unknown knowns — surface my tacit taste and context. Don't make me imagine it; put
something concrete in front of me to react to (sample data, a throwaway mock, competing
design directions). Record what each reaction reveals.
4. Unknown unknowns — sweep for landmines: wrong-by-default data, stale denormalizations,
unwritten conventions, prior attempts that were abandoned or rolled back (and the reason
they died), latent bugs on this path. Each as a card: evidence (file:line) → why it bites
→ what it changes → decided | OPEN | sharp-edge.

Then hand over ONE page: the four-quadrant map (OPEN items stay on the map, not in chat),
a tweakable build plan ordered by what might change, and a copy-paste implementation prompt.

What you deliver is the map, not a build. Stop when I have it.
```

---

## 2 · The Friction Auction → `/ratchet:auction`

```text
Expand Down
138 changes: 138 additions & 0 deletions skills/map/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
---
name: map
description: Map the fog before you build. Use when uncertainty is high (aperture A3–A4), the terrain is unfamiliar, the taste is "I'll know it when I see it", or you are porting a reference implementation. Walks the task through four unknown-quadrants — known knowns (settled ground with file evidence), known unknowns (one blast-radius-ordered question at a time), unknown knowns (tacit taste surfaced by putting something concrete in front of the user), and unknown unknowns (a swept landmine field) — then hands over one durable four-quadrant map, a tweakable build plan, and a copy-paste implementation prompt. What you deliver is the map, not a build; you do not write code until it is handed over.
---

# /ratchet:map — the fog-of-war gate

When uncertainty is high, the expensive mistake is a confident build in the wrong
direction. `/ratchet:lock` says: infer the missing value, name the assumption, move. That
is correct for low-uncertainty work. This command is its counterweight for the
high-uncertainty case — it maps the terrain *before* the build, so a wrong assumption is a
one-line correction on paper instead of a rewrite three PRs deep. **What you deliver is the
map, not a build.** You do not write code until it is handed over.

> Method grafted from the `explore-unknowns` skill; expressed in ratchet's own vocabulary —
> general mechanism, own words, backed by ratchet state. (Same graft discipline as the
> aperture dial.)

Two moves make the walk work:

- **Show, don't ask.** Never make the user describe intent from a blank page. Put something
concrete in front of them — a sample, a throwaway mock, a few competing directions — and
let them point at it. Recognition is cheap; invention is expensive.
- **Pre-draft their reply.** Close each turn with lettered options answerable in a few
characters, so the user reacts instead of composing.

## Step 0 — Load state, then scan the terrain

```
ratchet status
ratchet snapshot repo
```

Scan first. Gather what already exists, what is half-built, and what was tried and
reverted — *before* you open your mouth. Serial questions on unread terrain waste the
user's attention.

## Procedure

Walk the four quadrants **in order**, naming the current one. Disclose material findings
the moment you hit them; never close a quadrant off-screen.

1. **Known knowns — settle the ground.** State the facts, each cited to `file:line`. Mark
every assumption *separately* and say you will treat it as true until corrected, so a
wrong premise gets caught now instead of after the build.

2. **Known unknowns — one question at a time.** Ask the single highest-blast-radius
question first (the answer that reshapes the most), not a wall of them. Give lettered
options with a **recommended** answer. Close each question exactly one way, in front of
the user: **user answer**, **territory** (you researched it, then show question +
finding), or **OPEN** (deferred, with what would unblock it).

3. **Unknown knowns — extract the tacit.** The user cannot articulate what they don't know
they know. Do not ask abstractly. Put something concrete in their hands — sample data, a
throwaway mock, three or four incompatible renderings of the same thing — and let the
reaction expose the taste. Probe the offhand context: the downstream consumer, the
runtime it lands in, the acceptance bar of whoever owns it next. Record what each
reaction changes.

4. **Unknown unknowns — sweep for landmines.** Hunt the silent failure modes a shallow read
misses: wrong-by-default data, stale denormalizations, **unwritten conventions** the code
enforces but no doc records, **prior attempts that were abandoned or rolled back — the
reason they died is usually the trap you are about to re-hit**, and latent bugs this path
inherits. Worst first. Each as a card:

```
evidence: <file:line> why it bites: <mechanism> what it changes: <task impact>
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.

## Output contract

```
QUADRANT WALK: current <quadrant> · coverage <n/4> · stopped for user reaction? <yes/no>

KNOWN KNOWNS:
- <settled fact> — evidence: <file:line>
- <assumption> — treated as true until challenged

KNOWN UNKNOWNS:
- Q: <question> | recommend: <lettered answer> | closed by: user | territory | OPEN | unblocks: <what>

UNKNOWN KNOWNS:
- tacit constraint: <extracted> | reshaped the target: <how>

UNKNOWN UNKNOWNS:
- landmine: <name> | evidence: <file:line> | why it bites: <mechanism> | changes: <impact> | status: decided | OPEN | sharp-edge

HANDOVER MAP: path <.ratchet/unknowns-map.md> · OPEN items <n> · build plan <yes/no>
IMPLEMENTATION PROMPT: <copy-paste line that launches the build with the map's context>
```

## Serialize

The map is durable state, not scrollback. Record it so the next context resumes cold:

```
ratchet artifact add '{"kind":"unknown-map","title":"unknowns map: <target>","status":"handoff","path":".ratchet/unknowns-map.md","holes":["<each OPEN item>"]}'
ratchet state append decisions '{"choice":"<closed known-unknown>","rejected":"<the option not taken>","tripwire":"<what would reopen it>"}'
ratchet state append assumptions '{"text":"<tacit/working assumption>","killTest":"<cheapest falsification>","status":"untested"}'
ratchet state append openLoops '{"text":"OPEN: <question> — unblocks: <what>","status":"open"}'
ratchet state set phase cut
ratchet state set nextCommand "/ratchet:build"
```

Real landmines that are actual failures (not just sharp edges) are defects, not notes:

```
ratchet defect add '{"severity":"high","summary":"<landmine that will bite the build>"}'
```

The map's OPEN loops, untested assumptions, and artifact holes all drain
`ratchet score confidence` on purpose — an unclosed unknown is tracked pressure, not a
forgotten one. The score cannot read ship-ready while the fog is still on the board.

## Meter — when to reach for this

Run `/ratchet:map` when the aperture earns it, not on a reversible one-liner:

```
ratchet score aperture '{"ambiguity":_,"terrain":_,"taste":_,"blastRadius":_,"reversibility":_}'
```

- **A0–A2** → don't. `/ratchet:lock` + infer-and-build is the right, anti-ceremony move.
- **A3** → map the fog, then build.
- **A4** → map the fog, hand over the plan/options, and **stop** — do not build until
constraints are locked.

Also reach for it directly (whatever the score) on a reference-implementation port, an
"I'll know it when I see it" request, or a mid-build deviation that needs capturing.

Next: when the map is handed over and the user picks the build plan → `/ratchet:build`.
At A4, lock the open constraints first (`/ratchet:lock`) and stop before building.
9 changes: 9 additions & 0 deletions test/plugin-shape.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,13 @@ ok('README does not mention removed command names', () => {
assert.ok(!readme.includes('/ratchet:ratchet-evolve'), 'no stale /ratchet:ratchet-evolve in README');
});

ok('the /ratchet:map fog gate is wired into the prompt catalog', () => {
// The generic loops above already force skills/map to carry frontmatter and be
// listed in the README. PROMPTS.md sync is otherwise untested, so guard it here:
// the map skill exists AND its canonical intent lives in the prompt source of truth.
assert.ok(skillDirs.includes('map'), 'skills/map exists');
const prompts = read('reference/PROMPTS.md');
assert.ok(prompts.includes('/ratchet:map'), 'PROMPTS.md references /ratchet:map');
});

process.stdout.write(`\n${passed} passed\n`);
Loading