# Ultrawrite

> Use when writing ANY implementation plan — this plugin's owned authoring skill. Elicits the operator's claim, shapes the decomposition into signed contracts, runs the proof gate, and emits a claims-v1 plan that /ultrapowers compiles into waves. Replaces the marker-layering skill and the external writing-plans dependency for plan bodies.

- Skill: `popmechanic/ultrawrite` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add popmechanic/ultrawrite`
- Raw SKILL.md: https://api.skillmd.com/api/skills/popmechanic/ultrawrite/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: popmechanic (https://skillmd.com/u/popmechanic)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/popmechanic/ultrawrite

---


> **Audience: the authoring agent.** The operator brainstorms, answers elicitation and
> signs; they never write this artifact. Every imperative below addresses the agent doing
> the authoring.

# Ultrawrite — author signed, claim-first plans

A task says **what will be true** and **how that is examined**. It never says how to do
the work: there is no Steps slot, so procedure has nowhere to live. The implementer
derives it from a contract and an exam, against real code the plan never saw.

**Announce at start:** "I'm using ultrawrite to author this plan."

## The document

Above the first task: `**Grammar:** claims-v1` (absent, the compiler parses the legacy
grammar — that is the rollback path, not a choice), one `**Claim:**` line — the operator's
own do:/see: sentence about what they will see after the run, closed `(elicited)` when they
said it to you and `(quoted from #NNN)` when an issue already carries that sentence
verbatim; those two tags and no third — then `**Goal:**`, `**Tech Stack:**`, the spec path,
and `## Global Constraints`.

Directly under that `**Claim:**` line — the next line, no blank between — the plan carries
one `**Summary:**` paragraph: three sentences in the operator's register saying what this
is, why it exists and how it benefits the user. The author writes those sentences and the
operator confirms them in the same touch as the Claim, never a second one, and the pull
request the run opens quotes them verbatim, so what a reader meets is what the operator
signed. It is one paragraph running to the next blank line, no markdown inside; like
`**Closes:**` it is free prose to the compiler — nothing parses it.

Beside `**Tech Stack:**`, an optional `**Exam command:**` line names how this project's
tests are run, as a template whose `{paths}` token — exactly one — stands for a task's own
Proof `Test:` paths (`npx vitest run {paths}`). Without it the compiler derives each task's
command from the paths alone, and it knows only pytest, `node fleet/tests/test_*.mjs` and
`bun test`; a `**Review:** peer` task whose Proof names some other shape is refused at
`--check` until one of the two is true.

An optional `**Closes:**` line names the tickets the plan closes. It sits directly under
`**Goal:**` — the next line — and is one line: `**Closes:** #660 #668`, the numbers
space-separated, each an issue of the target repository (a bare `#N` means the target to
GitHub, so a foreign target's plan names that repository's issues, never this plugin's).
The sandbox reads exactly that line from `.ultrapowers/plan.md` and appends one
`Closes #N` per number to the pull request body, so the run's merge closes them; a plan
without the line closes nothing. The line is free prose to the compiler — nothing parses
it, so a number scraped from `**Goal:**` is never used: the Goal line cites decisions as
well as tickets, which is why scraping it was rejected.

## Task shape — pinned to what the parser actually reads

`### Task N: <title>`, then the header block, then the Files block, then exactly six body
slots.

Header markers: **Type:** and optionally **Review:** — nothing else; **Files:** is not a marker and ends the header block.

The compiler closes the header block at the first line that is not marker-shaped, so a
marker written below the Files block is not read — it is dropped and surfaced as a
conflict. Keep both markers in the contiguous run directly under the heading.

- `**Type:**` — `implementation` (the default, and the only Type that waves),
  `gate`, `release`, `manual`. A write-nothing verification task is `gate`; anything that
  pushes, deploys, or waits on a human is its own `release`/`manual` task.
- `**Review:**` — optional, `peer` or `lean`. Mark `peer` — a second independent read of
  the same patch — where failure is costly or hard to see; unmarked is `lean`.
- There is no `Tier` plan marker. Tier is a signed field of the *intent document* (One
  Driver spec §7), a spend authority — never written on a task here.
- `Depends-on` and `Commutes` lines are refused outright. Ordering is derived from
  Interfaces token-matching and Files overlap; same-path overlap is derived from Files.
  An operator who does not read diffs cannot verify an edge, so no edge is signed.

The Files block carries canonical `Create:` / `Modify:` / `Delete:` / `Test:` bullets, backticked
paths, no globs and no open write sets. It is doubly load-bearing: wave shape *and* edge
derivation.

### The six body slots, in this order

- **Claim:** the bilingual pair. The operator's own sentence, verbatim, closed by
  `(quoted from #NNN)`, `(elicited)`, or `(derived)` when it descends from the plan-level
  Claim rather than a sentence the operator said about this task; then a `Machine:` line
  restating it in the
  system's own terms, **its clauses numbered `M1. … M2. …`** — one clause per thing the
  exam must establish. Write do:/see: interactions, never system states. Register drift
  between the two halves is a defect the gate checks.
- **Authorized-by:** the reference licensing this task — issue, spec §, decision record.
- **Interfaces:** `Consumes:` / `Produces:` — exact signatures, exact test names, **one
  symbol per bullet** (the compiler reads the first symbol of a bullet and nothing after
  a comma, so a line listing three symbols derives no edge for the other two). **A test's
  import of a sibling's symbol is a `Consumes:`**; that is now the whole ordering story
  for test-only edges. Placeholders (`none`, `nothing`) are legal and quiet. Read every
  `Consumes:` against its sibling's `Produces:` yourself, because with no marker backstop
  a typo and a prose sentence are both silently missing edges, and nothing warns on one.
- **Context:** what the implementer must know that the repo cannot tell it. Keep it short;
  nothing refuses on its length. Steps prose smuggled in here is
  caught structurally instead: fences are illegal outside Proof, and a task-reference
  ordering phrase (`after Task 2`) orders nothing at all.
- **Proof:** the exam — tests, golden pairs, fixtures, executable probes. The only slot
  where code fences are legal. Its `Test:` paths must be **disjoint** from this task's
  `Create:`/`Modify:` paths: the exam is a distinct artifact. Its legs — `(a) … (b) …` —
  **each cite the clause they establish, `[M2]`**; the compiler refuses a clause no leg
  cites, a leg citing nothing, or a citation of a clause that does not exist. A universal
  or negation clause (`every`, `no`, `byte-identical`) wants a leg that names what fails
  or is absent; an enumerated clause (`for each of node, pytest`) wants one leg per row —
  check both yourself, since nothing flags them: that is the species run-51's gate rejected
  11 of 24 pairs for.
  A `Run:` bullet names a command the driver executes in the task's clone after the
  implementer's patch lands; its exit code and output are evidence the reviewer reads
  against the legs, and a non-zero exit sends the task to the fix loop. A task whose
  deliverable is prose proves itself with `Run:` commands, never with a test that
  matches sentences of a document.
  And one `Run:` names one probe — a command the driver pays once, never a loop over a glob
  of sims (run-87 paid 175 s per boot sim, three passes, for two such lines). A sweep over
  every sim belongs to the one task that owns the sims, as one line, or nowhere.
  A `- Guard:` bullet in this slot names **one of this Proof's own `Test:` paths**, and it
  is the one way an exam file reaches the pull request: the peer examiner still writes the
  exam, but the file it names is written at that path and is merged with the task. An exam
  with no `Guard:` lives instead on the run's evidence tag `ultra/evidence/run-<N>`, and
  publish strips it from the pull request. The examiner writes an unguarded exam under
  `tests/exams/<run>/` — a node exam under `fleet/tests/exams/<run>/` — so a `.mjs` exam's
  relative imports are written for that depth, two levels deeper than `fleet/tests/`, not
  for the directory a guarded copy would sit in. Guard the claim a *later run* could break
  — run-8's `runner_for` pin is that class, and a `Guard:` is what protects it; a claim
  only this run's own diff can break needs none.
  Name **one exam file per behaviour surface**, named for it (`test_fold_wave.py`, not
  `test_<task-noun>`): a later task on that surface — a later wave or a later plan —
  extends that file instead of opening a second one, and its legs sit under a comment
  naming the task. Under the reserved directory an unguarded exam is a new file per run by
  construction, so *extending the existing file* is now exactly what a `Guard:` on that
  path buys — only a guarded exam sits at a stable path a later task can extend. Five
  plans on 2026-09-03 each left one `fleet/tests/test_<task-noun>.mjs`
  behind, which is the shape this replaces; two *same-wave* tasks appending to one file are
  the adjacent-insert shape rule 4 names, not this one.
  A `byte-identical to BASE` or `git show HEAD:` comparison is a **tautology at the
  integration head**, where HEAD already carries the edit — so the exam carries the value
  measured *before* it: a **frozen pre-edit literal**, such as a `git hash-object` sha
  written into the exam, or a full **40-hex sha** fetched with
  `git fetch --depth=1 origin <sha>`, because `actions/checkout` leaves the clone at
  depth 1 and a short or unfetched sha is not in it.
  That frozen literal is the *only* lawful sha in an exam: a committed exam
  **never reads ULTRA_BASE** and never **freezes a commit sha** of this repository, because
  a BASE comparison is a `Run:` — the driver hands that command the sha, and a depth-1
  clone holds no other commit to compare against. A `Test:` file that does either draws
  `base-sha-in-suite`.
- **Stale-if:** predicates, one per line — `path-exists:` / `path-absent:` /
  `sha-matches: <path>@<sha>` / `issue-open: #NNN` / `issue-closed: #NNN`. A free sentence
  is a refusal; an undecidable staleness test is inert prose.

```markdown
### Task 2: The widget catalog

**Type:** implementation
**Review:** peer

**Files:**
- Create: `widgetkit/catalog.py`
- Test: `tests/test_catalog.py`

**Claim:** An operator lists the sizes they want and gets one widget per size, in the
order they asked. (quoted from #489)
Machine: M1. `catalog([1, 3])` returns two `Widget`s whose `size` values are `[1, 3]`.
M2. `catalog([])` returns an empty list.

**Authorized-by:** #489; spec `docs/superpowers/specs/2026-08-31-owned-authoring-skill.md` §3

**Interfaces:**
- Consumes: `make_widget(n: int) -> Widget`
- Produces: `catalog(sizes: list[int]) -> list[Widget]`

**Context:** The catalog is a thin mapping over the constructor — it neither validates
sizes nor caches, so a bad size surfaces as the constructor's own `ValueError`.

**Proof:**
- Test: `tests/test_catalog.py`
- Legs: (a) `catalog([1, 3])` yields exactly two widgets with sizes `[1, 3]` in that
  order [M1]; (b) `catalog([])` is exactly `[]` [M2].

**Stale-if:**
- path-absent: `widgetkit/widget.py`
```

## Elicit the claim — never draft it for countersigning

**From a filed issue** (the common path, and what keeps autonomous drains working): quote
the operator's own words as the Claim, anchored to the issue; bind the machine
restatement; show the pair once for confirmation — confirmation, not authorship.
**Quote desired-state sentences, never diagnosis sentences**: an issue's description of
the defect ("today X happens") makes a claim a passing exam renders *false* — the gate
rejects it. Quote the sentence that says what should be true instead.

**From a bare idea:** ask scenario questions — *"after this run, what can you see or do
that you couldn't before?"* — offering 2–3 pre-chewed do:/see: options via
AskUserQuestion. The operator's pick plus their edits is the claim.

**The summary rides with the claim.** Draft the three `**Summary:**` sentences yourself —
what this is, why it exists, how it benefits them — in the operator's register, off the
issue or the conversation, and put that draft to the operator inside the *same*
AskUserQuestion that carries the Claim: one touch, not two. The operator adjudicates and
never authors: their edits are the summary. A summary written in the technical register —
a file name, a function name, a sha — is a defect you fix before the gate.

Aim claims where the suite is structurally blind: integration seams, visual states, CLI
output, error-path wording. A claim that only restates what a test already asserts buys
nothing.

## Authoring a queue

A sitting's queue of well-defined issues drains by partitioning it by files into
disjoint bundles: two plans that would touch one file go in one bundle, since same-file
edits fold inside one run and never across two PRs. Dispatch one author subagent per
bundle — each loads this skill, pins its own BASE facts, dispatches its own fresh gate
readers per task, and compiles to `PLAN OK`. The issue's desired-state sentence is the
plan's Claim, quoted rather than drafted, exactly as the elicitation path above has it.
Grill an issue only when its ticket carries the `wayfinder:grilling` label; an undecided
choice found mid-authoring comes back as a question, not as a guess.

Hold the operator to one Claim confirmation and one execute choice per plan, each asked
with AskUserQuestion. Launches stay serial: N plans are N launches back to back, because
concurrent launches race on the run number (#667). The 2026-09-05 clock census of runs
10–12 found authoring throughput, not the sandbox, was the first bound on how many runs
could be live at once — a queue authored in parallel is what lifts it.

## The proof gate — before any compile

One fresh-context subagent per task, asked one question: *if this exam passes, is the
sentence necessarily true, at the right layer? And is every concrete literal a Machine
clause pins satisfiable under the clauses' own rules — compute it.* Layer mismatch means
no compile until the task is revised. The second half is there because on walk run-10 a
Claim pinned `4` vowels in `Ada Lovelace` — `6` under its own M1 and M2 — and the reader
passed the legs on shape without ever computing the number, where a reader asked exactly
this computed six on the re-read and passed the corrected plan.
Run `compile_plan.py --check` first: the mechanical gaps (an uncited
clause, an uncited leg) are refusals there, so the gate reads the pair clause by clause
with those already closed and spends its judgment on the species only it can see — does
leg (b) actually falsify M2, or merely mention it?

Its diet is capped mechanically, not by the reader's restraint:

    UW=${CLAUDE_PLUGIN_ROOT}/skills/ultrawrite/scripts
    python3 $UW/extract_gate_input.py <plan.md> --task <id>

Feed the subagent **only** that output — no plan body, no ledger, no sibling tasks. Write
each verdict, keyed on the hash the extractor prints, into the sibling
`<plan-stem>.gate-verdicts.json`, with the run's `tally`. The compiler reads exactly this
shape: `{"tasks": {"<id>": {"hash": "<the extractor's hash>", "verdict": "pass" | "fail",
"reason": "<one sentence>"}, …}, "tally": {…}}` — `tasks` keyed by task id with those three
fields, `verdict` one of `pass`/`fail`, `tally` a free-form count object (`dispatched`,
`rejected`, per-round counts) that is kept for the record and not validated; any extra
key, such as a `history` array of every round's verdicts, is tolerated. A missing task, a
stale hash, or a `fail` is a compile refusal. The verdict is an artifact, not
a memory: the compiler refuses a plan whose record is missing or whose hashes are stale,
so an edited Claim or Proof re-dispatches. The gate agent never authors proofs, and the
wave author never chooses which proof a task satisfies.

Dispatch is **per task**, not per round, and every reader runs in the foreground. Dispatch
it with the Agent tool, `subagent_type: "general-purpose"`, `run_in_background: false` —
one call per task, and several such calls may share one message, but none of them is
backgrounded, because a backgrounded reader's verdict is delivered to the session that
spawned the author rather than to the author, who then stops to wait for a message that
never arrives (2026-09-08: of four concurrent authors, three had backgrounded their
readers and had to be resumed by hand with the verdict pasted in, two of them with no
`.gate-verdicts.json` written at all). In the foreground the verdict returns to the author
that dispatched it, as that call's result: the reader answers with its verdict line and one
sentence, and `<plan-stem>.gate-verdicts.json` is written by the author from that returned
verdict, never by the reader — the reader sees only the extractor's output and has no plan
path to write beside. A task whose verdict lands first gets its next
reader the moment its Claim or Proof is edited: re-extract that one task with
`extract_gate_input.py`, dispatch one reader for it, and do not wait for the round's
other verdicts to arrive — the verdict is still keyed on the hash, so the edit is what
re-dispatches, and a round boundary buys nothing. Measured 2026-09-04: the four wide
rounds took 13 of the 22 minutes; rounds five through nine were one or two tasks apiece,
each of them idle behind a barrier it did not need.

Then resolve provenance and compile:

    python3 $UW/check_provenance.py <plan.md>
    python3 ${CLAUDE_PLUGIN_ROOT}/skills/ultrapowers/scripts/compile_plan.py --check --base <checkout-dir|sha> <plan.md>

`check_provenance.py` (needs `gh`) resolves every anchor and string-matches every
`quoted from #NNN` claim against its issue body at signing time. The plan is done when
`compile_plan.py --check` prints `PLAN OK` and those two checks — the proof gate and
`check_provenance.py` — have passed.

`--base` takes a checkout directory or a 40-hex sha, and a sha must be present locally:
the compiler reads that commit's tree with `git show`/`git ls-tree` in the plan's own
repository, so every BASE fact — which paths exist, which file mentions a `Produces:`
symbol, which test pins a Machine-clause span — resolves against the exact commit
`launch.mjs --base` will hand the run, not against whatever the working tree happens to
hold. Unset, `--base` defaults to the plan's own git toplevel.

With a base, the verdict is followed by the tree's own facts about the plan, one
`BASE fact:` line each (#896): what a `- Delete:` file holds at BASE (its line count,
test-case count and section banners — read them before signing a sentence about what
the file is; run-90 deleted five exams on the sentence "entirely the check-runs poll"),
and every file outside a task's Files that carries a literal its Machine clauses pin —
the shape that parked runs 84, 88 and 90. A carrier that pins the value the task
changes goes into that task's Files; the line is a fact, never a refusal. The launcher
runs this same compile at `--base` before it pushes anything and prints the same
lines, so a plan that does not compile at the launch base is refused on the laptop
(#865), and a `**BASE facts:**` block generated at another sha is refused with the
re-pin command.

The rejection species are listed in `references/authoring-gotchas.md` and read by the
author before a reader is dispatched — nothing prints them.

## The worktree-pure contract

Every `implementation` task is a pure diff against the integration branch:

1. **Self-contained bodies.** A task agent sees only its own body — every coordination
   note (port assignments, shared literals) lives in the body of each task it affects,
   never only in a preamble.
2. **No branch instructions.** The executor owns branching.
3. **Concurrency-safe proofs.** Same-wave suites run at once on one machine: unique port
   and temp path per test, no shared on-disk fixtures.
4. **Name only what exists.** Every path a slot cites must exist at BASE or be created by
   a task this one derivably follows. `docs/superpowers/` is untracked (#544) and absent
   from every sandbox, so a spec path is a reference for the reader, never something a
   worker is asked to open — put what the worker needs from a spec into Context.
5. **Claims about the live world carry their evidence.** A task asserting what a live
   system does is unverifiable from a sandbox — paste the commands and their output into
   Context so review checks correspondence to a record, not truth it cannot reach.
6. **Isolate `CLAUDE_CONFIG_DIR`** in any task that spawns the agent CLI, or it writes
   false memories into the host project.
7. **Greenfield targets take the Bun + TypeScript + TinyBase defaults** — `bun install` to
   bootstrap, `bunx tsc --noEmit && bun test` as the suite, one TinyBase store as the
   app's state; the synced shape (store → WsSynchronizer → Durable Object) is a *TinyApp*.
   Both knobs verbatim, the `@types/bun` tsconfig gotcha, the TinyApp shape, and where the
   restriction stops: `references/greenfield-stack.md`. In a TinyApp plan every `peer` task
   names a state exam as its Proof `Test:` path, with seeds under `state-exams/seeds/` and
   expected states under `state-exams/expected/` (`references/greenfield-stack.md`
   §State exams).

## Decomposition judgment

Independence is a property of contracts, not of files.

1. **Split by default.** Every piece of work that can carry its own contract — a module
   with its own exports and its own tests — is its own task. Where a consumer would wait
   on a producer, put the shared shape (a schema, a signature, a file format) as one
   literal in the Context of every task that touches it; the critic checks that the
   implementations agree with it. A `Consumes:` of a sibling's `Produces:` orders the two;
   a shared literal does not, so prefer the literal wherever the consumer only needs the
   shape. Workers have no shared memory — a chain of two tasks is two strangers in
   sequence, not one mind holding a design — so a chain buys no coherence, only the wait.
2. **A chain must justify itself.** The only reason to make task B wait on task A is that
   B needs A's *runtime behaviour*, not A's shape — something no contract can promise.
   Name that behaviour in B's Context, in one sentence. "At this size", "a good engineer
   would keep this together" and "it is one file" are not reasons: same-file edits fold,
   and size is what width is for. Measured 2026-09-02: the same tool built as a two-task
   chain took 79 min with one fix round; as nine contracts, seven wide, it took 49.5 min
   with none (#541).
3. **State the width.** The plan's `**Parallelization rationale:**` line names each
   wave's width and every chain longer than one with its sentence from rule 2. Concluding
   that a plan is genuinely linear is still a legal outcome — it just has to say why.
4. **Let same-file edits stand.** Concurrent same-file *text* writes fold at merge, so a
   shared hot file is never a reason to reshape a plan — let colliding `Modify` lines
   collide. Non-text (binary, symlink) same-file pairs are ordered automatically. Blast
   radius follows the contract, not the file: a task that changes a `Produces:` shape owns
   every strict-equality pin of it, in any sibling's file — list that file in its own
   Files block. One shape does not fold, though: N tasks that each add one line to one
   list are N **adjacent inserts at one location**, which the fold sends to a resolver —
   run-12 (2026-09-05, PR #662) had five tasks each append one registration line to
   `compile_plan.py`, and the fold spent three resolver workers
   (3.4 worker-minutes, 6.6 of the 13-minute post-review tail) ordering
   five lines any order would have satisfied. Give each such task its **own region or
   file**: a registration is a new file discovered by glob, never an appended line.
5. **Prefer several small concurrent plans** folding into one frontier over one large plan
   (N=3 drains measured 0.26× batch). Until that fold lands (Tier 2), an effort split
   across plans gives the **final** plan an integration-spanning acceptance — per-phase
   green never establishes integrated green — or declares the gap explicitly at the final
   gate. Never silently.

## Global Constraints discipline

`## Global Constraints` is forwarded to every reviewer as its attention lens. Copy the
spec's binding, cross-cutting requirements: version floors, naming and copy rules,
platform requirements. State what must be true **of the result**. Process rules — TDD
ordering, commit cadence, "write the failing test first" — are never Global Constraints:
no diff evidences the order work was done in, so as a lens they yield only unverifiable
findings, one per task.

The section holds two kinds of bullet, and they are read by different machinery. A
`- Check:` bullet is a command the driver executes in every task's clone before review
and once on the adopted tree — blocking, unless it ends `(minor)`, which is recorded and
never dispatched. A prose bullet is only the referee's attention lens: it is what decides
whether a finding is minor, and nothing runs it. So a constraint a command can decide is
written as a Check:, never as prose — prose is where the undecidable half goes. A prose
bullet naming a byte-identical file or a script's output is one the driver could have run,
so write it as a `Check:` beside the prose. Such a comparison has a base to compare
against: a `Check:` or `Run:` that compares the tree against BASE writes `$ULTRA_BASE`,
which the driver sets, in the environment of every `Check:` and `Run:` it executes, to the
run's base sha — so `- Check: git diff --quiet $ULTRA_BASE -- fleet/` is writable without
knowing the sha, where a frozen `git hash-object` literal is the shape for a single file.
And a `Check:` that runs a sim is paid by every task on every pass, where the same command
in the owning task's `Run:` is paid once: put it there, and keep this section for what no
single task owns.
## Execution handoff — analyze, then recommend

Offer three options, parallel first, and do **not** default to the parallel lane. Read
three signals off the plan:

- **T** — the number of `implementation` tasks.
- **parallel width** — is there a wave with ≥2 independent tasks, after treating non-text same-file edits between tasks as dependencies (text overlap folds at merge)? Compute it from derived edges plus the Files blocks.
- **risk** — a high-stakes surface (auth, payments, migrations, data integrity, public
  API, loops/cursors/pagination/budgets/termination logic), or behavior hard to verify by
  reading.

First match wins: risk → Ultrapowers (the **risk override** — independent per-task review
is the value, not speed); parallel width and T≥3 → Ultrapowers; T≤2 → Inline;
else → Subagent-Driven. Show a one-line analysis, then the three options, tagging the
winner **(recommended)**:

1. **Ultrapowers** — `/ultrapowers <plan-path>`: commits the plan and drives it on the
   exe.dev fleet (parallel waves in a sandbox, per-task review, the orchestrator opens the
   PR). Selecting it authorizes execution: the plan is committed and the fleet run
   launches immediately, without a further approval pause.
2. **Subagent-Driven** — sequential, fresh context and review between tasks.
3. **Inline** — continuous inline execution.

A claims-v1 plan has no steps to follow, but a sequential executor can implement
task-by-task from contract plus proof.

## Self-review

The author reads `references/authoring-gotchas.md` — the lessons every claims-v1 sitting
since run-45 paid for, each a rule with its reason — before the gate readers are
dispatched, and checks the plan against each of them; the file also names the compiler
refusals that already catch the mechanical half, so those are read off
`compile_plan.py --check` rather than re-derived here. Everything else in it is the
author's own to check — nothing prints it.

- Every task carries all six slots, in order, none empty, and no checkbox steps.
- The plan carries one `**Claim:**` above the first task, elicited or quoted from an
  issue. Every task Claim is either the operator's words with a provenance tag or
  `(derived)` under the plan-level Claim, paired with a machine restatement at the same
  layer, and its gate verdict is recorded and fresh.
- The plan carries one `**Summary:**` paragraph of three sentences directly under that
  Claim, in the operator's register — what this is, why it exists, how it benefits them.
- Every Stale-if entry is a predicate; every Proof `Test:` path is disjoint from the
  task's own writes; every fence sits in Proof.
- No Proof pins a sentence of a document as its evidence; a prose task's Proof is a
  `Run:`.
- Every exam file is named for its behaviour surface, and a task that extends one groups
  its legs under a comment naming the task.
- Every Machine clause is numbered and cited by a leg; every universal or negation clause
  has a leg that names what fails or is absent; every enumerated row has its own leg.
- Every cross-task edge is derivable — Interfaces symbols match a sibling's `Produces:`,
  or the Files blocks overlap. Nothing rides on prose.
- The rationale line states each wave's width; every chain longer than one names the
  runtime behaviour its consumer needs (rule 2), and any exam that quantifies over a
  directory was checked against BASE for pre-existing violators (#536).
- Global Constraints state results, not process.
- The `**Closes:**` line, when present, sits directly under `**Goal:**` and names only the
  target repository's issues.
- No pinned number is a guess: every pinned literal was computed, not assumed — the author
  ran the command or did the arithmetic at BASE and pasted back what it printed, rather
  than the figure the sentence wanted to be true.

