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 isgate; anything that pushes, deploys, or waits on a human is its ownrelease/manualtask.**Review:**— optional,peerorlean. Markpeer— a second independent read of the same patch — where failure is costly or hard to see; unmarked islean.- There is no
Tierplan marker. Tier is a signed field of the intent document (One Driver spec §7), a spend authority — never written on a task here. Depends-onandCommuteslines 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 aMachine:line restating it in the system's own terms, its clauses numberedM1. … 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 aConsumes:; that is now the whole ordering story for test-only edges. Placeholders (none,nothing) are legal and quiet. Read everyConsumes:against its sibling'sProduces: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'sCreate:/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. ARun: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 withRun:commands, never with a test that matches sentences of a document. And oneRun: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 ownTest: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 noGuard:lives instead on the run's evidence tagultra/evidence/run-<N>, and publish strips it from the pull request. The examiner writes an unguarded exam undertests/exams/<run>/— a node exam underfleet/tests/exams/<run>/— so a.mjsexam's relative imports are written for that depth, two levels deeper thanfleet/tests/, not for the directory a guarded copy would sit in. Guard the claim a later run could break — run-8'srunner_forpin is that class, and aGuard: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, nottest_<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 aGuard: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 onefleet/tests/test_<task-noun>.mjsbehind, 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. Abyte-identical to BASEorgit 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 agit hash-objectsha written into the exam, or a full 40-hex sha fetched withgit fetch --depth=1 origin <sha>, becauseactions/checkoutleaves 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 aRun:— the driver hands that command the sha, and a depth-1 clone holds no other commit to compare against. ATest:file that does either drawsbase-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.
### 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:
- 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.
- No branch instructions. The executor owns branching.
- Concurrency-safe proofs. Same-wave suites run at once on one machine: unique port and temp path per test, no shared on-disk fixtures.
- 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. - 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.
- Isolate
CLAUDE_CONFIG_DIRin any task that spawns the agent CLI, or it writes false memories into the host project. - Greenfield targets take the Bun + TypeScript + TinyBase defaults —
bun installto bootstrap,bunx tsc --noEmit && bun testas 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/buntsconfig gotcha, the TinyApp shape, and where the restriction stops:references/greenfield-stack.md. In a TinyApp plan everypeertask names a state exam as its ProofTest:path, with seeds understate-exams/seeds/and expected states understate-exams/expected/(references/greenfield-stack.md§State exams).
Decomposition judgment
Independence is a property of contracts, not of files.
- 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'sProduces: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. - 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).
- 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. - 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
Modifylines collide. Non-text (binary, symlink) same-file pairs are ordered automatically. Blast radius follows the contract, not the file: a task that changes aProduces: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 tocompile_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. - 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
implementationtasks. - 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):
- 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. - Subagent-Driven — sequential, fresh context and review between tasks.
- 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.