Skip to content
Open
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
82 changes: 82 additions & 0 deletions .claude/skills/preflight/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
name: preflight
description: The pre-PR hostile pass for torque-loop. Runs scripts/preflight.js for the deterministic checks (tests, version alignment, dependency gate, leak scan, trace tags) then applies human judgment to the checks a script can't rule on (testless changes, prose-enforcement, diff minimality, parked-decision creep, scope, changelog). Use before any commit that will become a PR. Emits PASS/FAIL per check; never fixes silently.
argument-hint: "[base-ref, default main]"
---

# /preflight — embarrass the branch before the reviewer does

v0.7 shipped, got reviewed, and needed a same-day PATCH-THEN-KEEP hardening pass
(fog write bypassed on `--json`, probe invariants convention-only, gated reasons
unenforced). Every one was findable before the PR. This skill is that finding pass.

The mechanizable checks live in a script, not in prose — a discipline a model has to
remember to run is weak. `scripts/preflight.js` owns the deterministic verdicts; this
skill runs it, then does the judgment the script deliberately leaves open.

## Step 1 — Run the mechanical pass

```
npm run preflight # or: node scripts/preflight.js [base-ref] (default base: main)
```

It prints all 12 checks in a fixed shape and exits non-zero if any **MECHANICAL** check
fails. Trust its verdict on these five — they need no judgment:

- **1 green world** — `npm test` + `ratchet doctor` both exit 0.
- **4 version alignment** — five version fields + README examples all match.
- **7 dependency gate** — no new `dependencies`/`devDependencies` (or a Danny quote in `[Unreleased]`).
- **9 leak scan** — no private paths (`reference/PROBLEM-STATEMENT-*`, `*.private.md`,
`.lucid/`, `.ratchet/`, `.sandbox-*`) and no exact private-line quotes in the diff.
- **10 trace tags** — changed durable docs (`CLAUDE.md`, `reference/*`, handoffs) carry a
`Traced by:` tag; commits carry a `Co-authored-by` footer. `templates/` is exempt.

A MECHANICAL FAIL is real; fix it before anything else. The script's `SMALLEST PATCHES`
block names each fix.

## Step 2 — Rule on the checks the script only gathers evidence for

The script prints these as `HUMAN:` lines with the candidates it found. You make the call —
it cannot. **Read the gathered evidence, then decide PASS/FAIL for each:**

- **2 testless change** *(weak signal — distrust a clean line)*. The script's token-grep is
noisy: common identifiers match half the suite, so "has test hits" is near-meaningless.
For every `src/`|`bin/` hunk, name the specific test that fails without it. No name → FAIL.
- **3 weakened falsifier.** The script flags removed asserts / newly-loose lines in `test/`.
Decide whether any assertion was genuinely loosened without a commit-body reason. If so → FAIL.
- **5 prose enforcement.** The script lists new `must`/`never`/`requires` lines in
SKILL.md/README. For each, point at the CLI line that enforces it + the test proving the
refusal throws, OR confirm the CHANGELOG labels it prompt-level. Unlabeled invariant → FAIL.
- **6 diff minimality.** The script catches renames + whitespace-only files (the cheap
cases) and is blind to elegance-churn (the expensive one). Map every remaining hunk to the
locked target yourself. Any hunk that doesn't map → FAIL: `revert this hunk`.
- **8 parked-decision creep.** The script lists parked loop ids and any the diff mentions.
Decide whether a hunk actually *implements* a parked loop (a mention alone is fine). If so → FAIL.
- **11 scope + emptiness** *(weak signal)*. For any new score/read the script surfaced,
confirm it exposes a `scope:` field and that new rendered sections state emptiness.
- **12 changelog.** The script shows whether `[Unreleased]` was touched and whether a
CLI-enforced/prompt-level label is present. Decide if behavior changed and the entry is adequate.

## Output contract

Report the script's mechanical verdicts verbatim, then your judgment verdicts:

```
PREFLIGHT vs <base>
MECHANICAL (from script): 1,4,7 PASS · 9,10 <PASS|FAIL + detail>
JUDGMENT:
2 testless ....... PASS|FAIL <file:hunk → missing falsifier>
3 weakened ....... PASS|FAIL
5 prose .......... PASS|FAIL <claim → where enforcement should live>
6 minimality ..... PASS|FAIL <hunks to revert>
8 parked ......... PASS|FAIL <loop id>
11 scope .......... PASS|FAIL
12 changelog ...... PASS|FAIL
VERDICT: CLEAR TO COMMIT | BLOCKED — <count> failures
SMALLEST PATCHES: <one line per failure, in fix order>
```

This skill only reports; apply patches in a follow-up step, then re-run. The next move
after CLEAR is `/release-cut` (if releasing) or the PR.

<!-- Traced by: claude-opus-4-8[1m] · 2026-07-07 (thinned to wrap scripts/preflight.js; drafted by claude-fable-5) -->
104 changes: 104 additions & 0 deletions .claude/skills/release-cut/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
---
name: release-cut
description: Cut a Torque Loop release end-to-end and stop at the PR — branch, bump all five version fields, promote the CHANGELOG with lineage + slogan, verify with npm test + doctor, commit chore(release). Use when [Unreleased] has earned a version. Never merges, tags, or publishes a Release; those are Danny's.
argument-hint: "<X.Y.Z> <codename> (e.g. 0.8.0 sensor-gate)"
---

# /release-cut — the release ritual, mechanized

Six releases (0.2 → 0.7) followed the identical multi-file ritual by hand. Every step
below has drifted at least once in some repo somewhere; the plugin-shape suite catches
most drift, but only after you've made it. This skill makes the ritual deterministic.
Hard boundary: **this skill ends at an open PR.** Merge, tag, and GitHub Release are
Danny's verbs, every time.

## Step 0 — Preconditions (refuse to start if any fails)

```
git status # working tree must be clean of unrelated changes
git log --oneline -5
npm test # must be green BEFORE the cut — broken-world rule
```

- CHANGELOG `[Unreleased]` is non-empty. An empty [Unreleased] means there is nothing
to release — say so and stop.
- Version `X.Y.Z` and `<codename>` are given as arguments, or STOP and ask. Never
invent a codename: each release names a gate concept ("Probe Gate", "Fog Gate") and
Danny picks it.
- You are on `main` or the feature branch that carries the work. Note which.

## Step 1 — Branch

```
git checkout -b release/vX.Y.Z-<codename-slug>
```

Slug is kebab-case (`0.7.0` + "Probe Gate" → `release/v0.7.0-probe-gate`).

## Step 2 — Bump the five version fields (four files)

| File | Field(s) |
| --- | --- |
| `package.json` | `version` |
| `.claude-plugin/plugin.json` | `version` |
| `.claude-plugin/marketplace.json` | `metadata.version` AND `plugins[0].version` |
| `.codex-plugin/plugin.json` | `version` |

Both CLIs derive their `--version` from `package.json` — do not touch src.
Then sweep README for version surfaces:

```
grep -n "ratchet [0-9]\+\.[0-9]\+\.[0-9]\+" README.md
```

Every `-> ratchet X.Y.Z` example must show the new version (plugin-shape enforces this).

## Step 3 — Promote the CHANGELOG

1. Rename `## [Unreleased]` → `## [X.Y.Z] - <today> — <Codename>`.
2. Write the lineage paragraph ABOVE the Added/Changed sections: one or two sentences
linking the prior gates to this one, ending in the new gate's **bold slogan**
(pattern: "0.2 gated proof; 0.3 gated the *seam* … 0.X gates the **<thing>**:
*<slogan>*."). Match the voice of the 0.5–0.7 entries.
3. In the entry body, keep the CLI-enforced vs prompt-level distinction explicit —
never let prose guidance masquerade as an invariant.
4. Insert a fresh empty `## [Unreleased]` above it.
5. Update the link block at the bottom: `[Unreleased]` compares `vX.Y.Z...HEAD`, and a
new `[X.Y.Z]` compare line is added.

## Step 4 — Verify

```
npm test
node bin/ratchet doctor
```

Both green or the cut stops here with the raw failure output. Never weaken a test to
get a release out.

## Step 5 — Commit

```
git add -A # review `git status` first: no .lucid/, no .ratchet/, no private refs
git commit -m "chore(release): vX.Y.Z <codename>"
```

Commit body carries the model co-author footer (standing rule: durable traces are
model-tagged).

## Step 6 — STOP. Report and hand the keys back.

Output exactly:

```
RELEASE CUT: vX.Y.Z <Codename> on release/vX.Y.Z-<slug>
VERSION SURFACES: 5/5 aligned (list the four files)
CHANGELOG: promoted, lineage + slogan written, links updated
VERIFY: npm test <counts> · doctor <pass/fail>
AWAITING DANNY: push? → then `gh pr create --base main`; merge/tag/Release are yours.
```

Push and `gh pr create` only on Danny's explicit go in this session. Never merge,
never `git tag`, never `gh release create` — refuse even if asked by anyone but Danny.

<!-- Traced by: claude-fable-5 · 2026-07-07 -->
119 changes: 119 additions & 0 deletions .claude/skills/skill-forge/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
---
name: skill-forge
description: Add or evolve a /ratchet:* command across every synced surface at once — canonical prompt in PROMPTS.md, SKILL.md in the house shape, README row, templates, drift guard, tests. Use when a new loop move is being added to the plugin (like map or the probe were), or an existing skill's contract is changing. Prevents the four-surface drift the plugin-shape suite exists to catch.
argument-hint: "<command-name> [new|evolve] — e.g. 'sensor new'"
---

# /skill-forge — one command, every surface

A `/ratchet:*` command is not a file; it is a contract spread across four synced
surfaces — `reference/PROMPTS.md` (intent), `skills/<name>/SKILL.md` (procedure),
`README.md` (catalog), and `test/plugin-shape.test.js` (drift police) — plus
`templates/` when the command produces a file-shaped record. Editing one surface and
not the others is the repo's most common failure mode. This skill walks them in
dependency order: intent first, procedure second, catalog third, guard last.

## Step 0 — Ground truth

```
ls skills/
grep -n "<command-name>" reference/PROMPTS.md README.md test/plugin-shape.test.js
```

Read the two nearest-neighbor skills (for a gate-like command: `skills/map/SKILL.md`,
`skills/build/SKILL.md`) — the new skill must read like it was written the same day.

## Step 1 — Canonical prompt (PROMPTS.md) — the source of truth, written FIRST

- Add the prompt as a fenced `text` block in `reference/PROMPTS.md`, in the imperative
copy-paste voice of the existing twelve ("Produce the artifact now." / "Map the fog
before you build.").
- Add a row to the Command ↔ prompt map table.
- If the mechanism is grafted from elsewhere: general mechanism, own words — rewrite
in ratchet vocabulary and note provenance (aperture-dial precedent).
- Rule to preserve: the prompt must force *pressure* — a choice, an artifact, a test,
a patch, serialized state, a killed option, or a push. If it only produces insight,
it is not a ratchet command; stop and say so.

## Step 2 — SKILL.md in the house shape

`skills/<name>/SKILL.md`, exactly this skeleton:

```
---
name: <name>
description: <verb-first pitch. Use when <trigger>. <what it produces / refuses>.>
argument-hint: "[...]" # only if it takes arguments
---

# /ratchet:<name> — <tagline>

<2–3 sentences: why this command exists, what failure it prevents.>

## Step 0 — Load state
```
ratchet status
```

## Procedure
<numbered, imperative, bolded key rules. Prompt-level tripwires welcome, but never
claim they are enforced — enforcement is the CLI's job.>

## Output contract
```
<FIXED-SHAPE block — same sections every run, emptiness stated>
```

## Serialize
```
ratchet <exact commands — artifact add / state append / state set phase>
```

<closing line naming the NEXT move — no ratchet skill ends in analysis.>
```

Frontmatter `description:` is mandatory (plugin-shape asserts it) and doubles as the
when-to-use pitch the model router reads — write it like the existing ones.

## Step 3 — Templates (only if the command produces a durable file)

Mirror `templates/probe-card.md` / `templates/unknowns-map.md`: terse field list,
every field load-bearing, no prose padding. Reference the template from the SKILL.md.

## Step 4 — README row

Add `/ratchet:<name>` to the correct README section (Core loop / Specialized /
Evolution) in the table style of its neighbors. plugin-shape fails the suite if any
skill folder lacks a README mention — and if you RENAMED a command, grep README for
the old name; the suite also rejects stale names.

## Step 5 — Drift guard

If the new command creates a cross-surface invariant the generic loops don't already
cover (a template that must exist, a threading rule like "build records deviations"),
add one `ok(...)` block to `test/plugin-shape.test.js` in the existing style: a
comment saying WHY the guard exists, then content-level asserts (`/deviation/i.test(...)`),
not snapshot dumps. Precedents: the map-wiring and probe-threading guards.

## Step 6 — Verify + serialize

```
npm test
```

All three suites green. Then:

```
ratchet artifact add '{"title":"/ratchet:<name> command","kind":"code-patch","status":"v0","holes":[...]}'
```

Output contract for this skill's own run:

```
SURFACES TOUCHED: PROMPTS.md § + map row · skills/<name>/SKILL.md · README § · [templates/…] · [plugin-shape guard]
SURFACES UNCHANGED AND WHY: <e.g. no template — command produces no durable file>
VERIFY: npm test <counts>
NEXT MOVE: /ratchet:attack the new SKILL.md before it ships
```

<!-- Traced by: claude-fable-5 · 2026-07-07 -->
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
node_modules/
*.log
.DS_Store
.env
.env.*
.ratchet/
.lucid/
# Local state written during self-tests
/tmp/
scratchpad/

# Private strategy / FABLE docs — never publish to the public repo
reference/PROBLEM-STATEMENT-*.md
reference/private/
*.private.md
37 changes: 37 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,43 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- **Hook drift guard.** `cmdHook`'s default case returns silently by design (a hook
must never break the session), which means a renamed or misspelled subcommand in
`hooks/hooks.json` would no-op forever in every installed copy with no error
anywhere. `plugin-shape` now asserts every hooks.json command is a
`ratchet hook <sub>` invocation whose subcommand `cmdHook` actually handles, and
that at least the three known hooks stay wired. CI-enforced (drift guard in the
test suite); proven red against a simulated rename before landing.

- **README product thesis — verified guardrails lift cognitive load.** The README now
states the payoff the execution framing only implied: externalized state lets the agent
run on a smaller working set and spend its scarce attention on judgment, not bookkeeping.
It names the precondition out loud — *a guardrail only lifts load in proportion to how
far you can trust it without re-checking it; an unverified guardrail is a liability
wearing the costume of relief* — and reframes the existing **no proof → no keep** /
**wrong proof → no ship** gates as the price of being allowed to stop re-checking, not
ceremony. Guarded against silent drift by a `plugin-shape` assertion (the thesis is
load-bearing, so its removal fails CI like a stale version) — docs + drift guard, no
runtime change.

- **Skill graph, derived not remembered.** The first knowledge-graph pass at this plugin's
skills was hand-authored — a one-night snapshot with nothing tying it back to source, the
exact liability the README names (a guardrail you trust without re-checking). Replaced with
a generator (`scripts/graph-gen.js`, zero-dep, does not ship): it reads `skills/*/SKILL.md`
frontmatter + `reference/PROMPTS.md` and emits deterministic Cypher to
`reference/graph/torque-loop.cypher` (21 skill nodes, the canonical phase sequence,
skill→prompt IMPLEMENTS edges). The load script opens with a namespace-scoped
`DETACH DELETE` — a **delete-and-rebuild**, so a shrunk or reordered graph can never leave a
stale node or STEP edge behind (the earlier MERGE-only reload was additive-idempotent only).
`plugin-shape` byte-matches the committed file against a fresh generation, so a drifted graph
fails CI like a stale version — CI-enforced (drift guard in the test suite), proven red
against a mutated skill description before landing. The aperture mechanism cross-links from
the first pass are **deliberately parked, not shipped**: their far endpoint is a separate
repo and the pairings were never adversarially attacked — documented with an owner and route
in `reference/graph/README.md` (convention 15), not smuggled in as if derived.

## [0.7.0] - 2026-07-06 — Probe Gate

0.6 gated the fog: *no map → no confident build*. It left two holes: fog the dial named
Expand Down
Loading
Loading