# r2 — resolved runtime pins and the focused control plan

hertz, 2026-09-13. Implementation under doyle's grant W4C2QFLE / W6WACIVM, with the control
plan AUTHORIZED and amended by doyle 23YE7ZXG and OCTAXWYQ. Nothing has been provisioned, signed,
applied, launched or queried. Parsing is not behavioural verification and none is claimed here.

**What doyle changed, and this document now says rather than merely records.** Groups A, B, C and E
are authorized against throwaway subjects, including A3/A4's child-specific process reading and the
timeout termination of those throwaway children. Groups D and F as first written are REJECTED —
"no grep-based proof of wiring or wording" — and are replaced below by behavioural arms. Section 4's
claim that the product has no local-stage verb was WRONG and is replaced: the supported maintainer
route is `xtask debug-rollout --stage-dir`. Provisioning itself remains unaccepted; signing, key
generation, artifact placement, apply and field execution remain unauthorized.

## 1. What was built

| artifact | sha256 | what it is |
|---|---|---|
| `fp-driver-d2.sh` | `e093e80dcf41247e0a855408661092602709131bdf34b44c072b41d81ac6575b` | the FROZEN predecessor — an immutable INPUT, never written |
| `fp-driver-d2-r2.sh` | `67913bd653667ca7ae19a41df4dd9be713fe1b0c1177a0fe50a1f04f78899e7a` | the successor |
| `provision-rig.sh` | `7add2d4ad9be0419d2e18bcd1a6121d9ac19a02c401407d912331b9b4b450bae` | the FROZEN predecessor of the mutating phase — an immutable INPUT after doyle's staging correction, never written |
| `provision-rig-r2.sh` | `1a959d1730f733e8bec5bf6be12820bcc841d39ef743c79e8318a48b698a61a3` | the staging correction — now itself a FROZEN input to the seed-scope correction |
| `provision-rig-r3.sh` | `81f65ee38344b486cbe995c775fe347b1d9638e623e2b233aa612e3746806228` | the mutating phase as it stands: supported staging, and the seed never exported (doyle WD47ADZV) |
| `build-provision-r3.py` | `9d29f4e16d291f55361055fed699d5b476c0c1e2ccb7f07ea25ccc19d308eacd` | its anchored builder: 4 anchors, each matched exactly once |
| `build-provision-r2.py` | `bc178c7a07e736e16fd0d24847ea5396f80a898438a7691268d22befdee12e43` | its anchored builder: source sha asserted, 14 anchors each matched exactly once |
| `fp-driver-d2-r1-to-r2.diff` | `bc4dc32410b57d5a7c013caf53fc6e1fe5fec46625a6058ab7838a77f92ae827` | the integrated diff: 25 hunks, +483 / −51 |

The successor is **built, not edited**: three anchored builder scripts read the frozen file,
assert its sha256 first, and assert every anchor matches **exactly once** before replacing it.
A drifted anchor fails the build rather than silently landing a partial edit.

## 2. Resolved pins

| pin | value | note |
|---|---|---|
| `CAPTURE_SHA` | `69b8506ac932841223996e7d5ad5ab03a51662ce4eacc6da77dad458a03f620c` | the integrated capture successor; the chain a0e7afbe → af29bbb3 → 010666e7 → 69b8506a is preserved in `history/`, none replaced |
| capture exit contract | 0 / 2 / 3 / 4 / 5 | now written out at the record site; the predecessor documented only 0/2/3, so a 4 or 5 reached the ledger as an unlabelled nonzero. That coupled change is closed |
| `d2_validate.py` | `fe950722…` | UNMODIFIED, never a subject of this change |
| `EXE_SHA` (subject) | `72d309011415b419aabfdb0b4065df1183bfd0069a9f95b5779da62e43349b10` | unchanged. The rig executable is a COPY of this and must hash to it |
| `TEARDOWN_B64_SHA256` | `416280dbece2601203c74c3f8e2c46e13009125fa5870166894e079329fb1d43` | unchanged, still verified twice (pre-GO and pre-dispatch) |
| `CONTROL_RULE` / `ABSENT_CONTROL` / rule names / `PORT` 29470 / `GUARD_PORT` 5470 | unchanged | |
| `PREP_BUDGET_S` / `EXP_BUDGET_S` / `CLEANUP_REPORT_S` | 600 / 300 / 180 | **no budget increase**, per the ruling |
| `LEDGER_RESERVE_S` | 30 | policy allocation: the ledger's own interval |
| `KILL_GRACE_S` | 5 | inside every bound, so TERM+KILL completes BY the deadline |
| `HANDOFF_CAP_S` | 120 | policy allocation, not derived from the 94s/134s samples |
| `HOST_TRIPLE` | `x86_64-pc-windows-msvc` | the `artifacts/<triple>.bin` name the set gate looks up |
| `SUBJECT_EXE` / `WORKTREE_EXE` | `$W/target/release/spt.exe` | the copy's source; never applied from |

## 3. UNRESOLVED pins — each is a refusal to start, not a default

| pin | why it is empty | who resolves it |
|---|---|---|
| `RIG_ROOT` (both files) | no rig has been provisioned; the driver refuses with an empty pin exactly as it does with an empty teardown pin | provisioning, once run under its own grant |
| `SET_VERSION` | the staging verb's `--version`. PINNED rather than left to its own monotonic sequence, so the staged version is stated and a downstream mismatch is a refusal | whoever provisions, once authorized |
| `XTASK_BIN` / `XTASK_SHA` | the PREBUILT maintainer `xtask` that stages and signs. Prebuilt on purpose: `cargo run -p xtask` inside provisioning would build into some tree's `target/` and take a build-cache pool as a side effect (AGENTS.md, releases#103) | whoever provisions |
| `SPT_DEBUG_RELEASE_SEED` | an ENVIRONMENT input, never a pin and never an argument. **No key has been generated**, and `xtask debug-keygen` is key generation, which was explicitly NOT granted | doyle (authority) |
| `TRUST_KEY_ID` / `TRUST_KEY_HEX` | **no key has been generated.** Key generation was explicitly NOT granted. The id and the PUBLIC hex are what `xtask debug-pin --home` writes into the rig home's trust overlay | doyle (authority) |
`SET_FILE` and `SET_SHA` have STOPPED BEING PINS. On the supported route no signed set
pre-exists as a file to copy — the staging verb mints and signs one from the artifact it is given —
so a pin for it would pin a file the script never sees.

`FLEET_EXE` is RESOLVED: `C:/Users/decid/AppData/Local/spt-core/bin/spt.exe`, **a configured
exclusion supplied by doyle 23YE7ZXG and explicitly NOT a fresh canonical measurement of this box's
install location.** It exists so the fleet binary can be refused BY NAME. If the real install
moves, this pin is stale and the refusal it powers is weaker, so it is re-resolved rather than
trusted on age.

## 4. Staging goes through the supported maintainer verb — and the claim this replaces

**The claim that had to be withdrawn.** The r1 plan and the r1 script said *"`spt update` has no
local-stage verb"* and placed the bytes into the release cache's own layout —
`releases/release.json` plus `releases/artifacts/<triple>.bin`. The premise was too narrow: `spt
update`, the PUBLIC surface, indeed has no local-stage subcommand, but the MAINTAINER surface does,
and doyle named it. The conclusion drawn from that premise — that a rig must therefore invent its
own cache-writing convention — was wrong, and the placement is gone.

**The supported route** (`docs/DEBUG-ROLLOUT.md`, `crates/xtask/src/main.rs`):

| verb | what it does for the rig |
|---|---|
| `xtask debug-keygen <id>` | mints the debug signing seed and its public hex. **Key generation, not granted** |
| `xtask debug-pin --home <H> --key-id <id> --public-key <hex>` | writes `<H>/identity/release-keys.json`: ADDS the key, leaves existing keys, sets the home's channel to `debug` |
| `xtask debug-rollout --stage-dir <H>/releases --version <N> --key-id <id> --artifact <triple>=<exe>` | SIGNS a set over those exact bytes, verifies it against its own key, and stages it through `ReleaseCache::stage_update_set` |

`stage_update_set` (relcache.rs:266-282) writes the signed record and `artifacts/<platform>.bin`
atomically and removes a stale single-artifact stamp. **That is precisely what the r1 script wrote
by hand**, so the hand placement was a re-implementation of a product function — and the on-disk
layout coupling the r1 plan declared as its one honest coupling **does not exist any more**: the
corrected script names no cache file at all.

**Two couplings replace it, both stated.**

1. **The verb SIGNS**, so the r1 script's claim that it never handles a signing secret is withdrawn.
   `debug_signing_identity()` reads `SPT_DEBUG_RELEASE_SEED` from the environment. Under doyle
   OCTAXWYQ the seed is bounded to the signing subprocess: read once at preflight, immediately
   unset from the environment, exported for the staging call alone, unset again on the next line,
   and its ABSENCE asserted before the apply. It is never an argument — an argument is readable
   from the process table by every other process on the box — never printed, never written to
   evidence, never archived.
2. **`--state` and `--build-current`.** The verb's default state path is a repo `target/` file and
   `--build-current` would run cargo; both would make provisioning take a build-cache pool as a
   side effect. `--state` is pinned inside the rig and `--build-current` is never passed.

**The applied record is still never written by the rig.** `xtask debug-mark-applied` exists and
writes `AppliedRecord::Applied{version}` for a hand-staged set — and doyle ruled OCTAXWYQ that it is
**not authorized**: a supported command that writes Applied still does not demonstrate the
transition this rig is required to exercise. The genuine apply/promotion stays, with
`AppliedPending` and `RolledBack` reported as themselves.

## 5. The focused control plan

**Standing rules for every arm.** A run-specific output directory per arm; an existing
destination is REFUSED, never cleared; failed arms are preserved as evidence; the **negative
control runs FIRST in each group and must FAIL**, because a group whose arms cannot fail
measures nothing.

### Group A — `bounded()`, the launch register, termination (throwaway subjects only)

| arm | what it establishes |
|---|---|
| **A0** | NEGATIVE CONTROL: an assertion that must fail (a bound the harness claims was refused when it ran). Proves the arms can fail |
| A1 | remaining < `KILL_GRACE_S` ⇒ `NOT_STARTED`, **no child launched**, phase recorded TRUNCATED |
| A2 | a fast child's exit is returned verbatim, **nonzero included** |
| A3 † | a child that outlives its bound ⇒ `BOUND_EXPIRED`, and `TERMINATION` is MEASURED — never inferred |
| A4 † | the register carries `kind=wrapper` and `kind=native` separately; a child that exited before registration is `ATTRIBUTION_INCOMPLETE`, **never `CONFIRMED_GONE`** |
| A5 | `preserve_unverified` copies a partial under `.unverified`, sizes and hashes it, leaves the original untouched, and records an absent file as absent |

† A3 and A4 read the **process table** (`Win32_Process`) for the throwaway child. No firewall,
no provider, no daemon. Withhold these two separately if that reading is outside the grant.

### Group B — R6, the completion predicate (pure: synthetic receipts, no host at all)

| arm | what it establishes |
|---|---|
| **B0** | NEGATIVE CONTROL: a receipt that satisfies nothing, asserted PROVEN. Must fail |
| B1-B3 | absent receipt / wrong or duplicated nonce / two `exit=` records (255) ⇒ `UNPROVEN` |
| B4 | **`exit=1` with sound stamps ⇒ PROVEN.** A nonzero native exit is a COMPLETED outcome; failed execution is not outstanding execution |
| B5 | `setup-return.utc` ABSENT or UNPARSEABLE ⇒ `UNPROVEN` |
| B6 | `TS_ORDER` VIOLATED or UNMEASURED ⇒ `UNPROVEN` |
| B7 | no setup ever dispatched ⇒ `NOT_REQUESTED`, and the existing marker/measurement gates decide on their own |
| B8 | with the setup OUTSTANDING, **all three** cleanup mutations are withheld — listener stop, rule teardown, daemon stop — each with its own `WITHHELD_OUTSTANDING_SETUP` line |
| B9 | POSITIVE CONTROL for B8: with the setup PROVEN, the same three sites reach their normal gates. Without this, B8's absence of a dispatch proves only that the predicate never fired |

### Group C — the clocks (pure arithmetic)

C1 the three instants, `WORK_DEADLINE = REPORT_DEADLINE − 30` · C2 `cur_deadline()` picks by
phase (pre-GO / in-window / cleanup) · C3 the handoff bound is `min(cap, remaining)` · C4 every
bound is `deadline − now − KILL_GRACE_S` and refuses at ≤ 0.

### Group D′ — the deferral, MEASURED (doyle 23YE7ZXG replaces the grep arms)

The rejected arms proved a *text* property: no `d2_validate_at` call appears between `go()` and
`end_experimental`. These arms prove a *runtime* property instead — that validation is ENTERED
after activity end — by running the driver's own pinned functions under an injected clock.

**The mechanism (doyle WD47ADZV: the ordering under test must be the DRIVER's, never the
harness's).** The harness does not call `end_experimental` and then a validation — that would
measure the harness's own sequence. Instead:

1. the frozen driver's sha256 is asserted;
2. the **actual contiguous CALL-SITE REGIONS** are extracted BY RANGE from those bytes — the
   top-level tail that ends the experimental window, and the cleanup region that carries the
   deferred validations and the ledger — together with the real function definitions they call;
3. every EXTERNAL EFFECT reachable from those regions is replaced by a **harmless boundary**: a
   stub that records that it was entered, and returns. Nothing reaches a provider, a firewall, a
   daemon, the field, or the fleet home;
4. the clock is **INJECTED** — small budgets rather than a 300s wait, because a control that waits
   out a real window measures the wait;
5. the verdict is read from the run's own `record` stream, in the order the extracted regions
   produced it.

**The boundary, stated because it cannot be closed under this grant.** The driver's pins refuse a
mock subject, so the field driver cannot be run end-to-end. What these arms exercise is the pinned
driver's own contiguous sequence with its external effects bounded — **fixture evidence, not
provisioned-field acceptance** (doyle WD47ADZV), and reported as exactly that.

| arm | what it establishes |
|---|---|
| **D′0** | NEGATIVE CONTROL: the same extracted region, with the deferral BROKEN by injecting a validation call into the region before its activity end, asserted to satisfy the deferral. Must FAIL — an ordering check that can only pass measures nothing |
| D′1 | in the extracted region, `end_experimental` is entered and every `d2_validate_at` entry is stamped AFTER it. The order is the pinned region's, not the harness's |
| D′2 | a validation entered while the experimental clock is still open is STAMPED as such, so the arm can tell a deferral from an absence of validation |
| D′3 | the reserved ledger interval is honoured: `REPORT_DEADLINE − WORK_DEADLINE` equals `LEDGER_RESERVE_S` from the values the real functions computed, and the ledger emits within it |

### Group E — `provision-rig.sh` refusals (all of them BEFORE any mutation)

E0 negative control · E1 each of the eleven unpinned pins refuses at exit 3 with nothing
created · E2 a subject that does not hash to its pin refuses · E3 a non-hex or wrong-length
trust key refuses, and a set file mentioning private material refuses before it is copied
anywhere · E4 an existing `RIG_ROOT` refuses and the existing directory is untouched (exclusive
`mkdir`, not test-then-create) · E5 a rig executable canonically equal to the fleet install or
the worktree subject fails before any apply.

**E4 and E5 create a throwaway directory tree** under a scratch path to have something to
refuse. Nothing under a real home, no `target/`, and the tree is preserved, not cleared.

### Group F′ — the ledger PRESERVES a nonzero capture outcome (doyle 23YE7ZXG)

The rejected arm read the record line's wording. These arms run the real ledger over a synthetic
run state and read WHAT IT EMITS.

| arm | what it establishes |
|---|---|
| **F′0** | NEGATIVE CONTROL: a ledger emission that drops the capture exit entirely is asserted to preserve it. Must FAIL |
| F′1 | a capture exit of **4** — nonzero, and one the predecessor's line did not name — survives into the ledger VERBATIM and is labelled, not collapsed into a generic failure |
| F′2 | the same emission makes **no artifact-absence claim**: a nonzero capture outcome means the capture did not complete, which is not a reading that the artifact is absent. The absence of that claim is checked in the emitted text, over a positive control proving the checker can see such a claim when one IS present |
| F′3 | exits 0, 2, 3, 4 and 5 each reach the ledger as themselves — the five-way contract exercised as five outcomes, not as one sentence naming five numbers |

### What NO arm does

No arm runs the real capture against a provider, provisions a home, signs or generates a key,
applies an update, launches a daemon, touches the firewall, or reaches the field. The two arms
that read the process table are marked † above so they can be withheld on their own.


## 6. RESULTS — what ran, what it measured, and what it does NOT establish

hertz, 2026-09-13. Every group ran with its negative control FIRST and that control FAILED first.
A negative control that exits with a harness error (71/65/66) is NOT accepted as a failure — that
rule was added after group D's first attempt, where all five arms errored at 71 and D0 read OK.

| group | arms | out dir | subject |
|---|---|---|---|
| A | A0-A7, 8 | `20260913T091213Z-A` (A1,A2,A4,A5) · `…091608Z-A` (A3) · `…091640Z-A` (A6) · `…092001Z-A` (A7) | `bounded()`, the register, termination |
| B | B0-B7, 8 | `20260913T092306Z-B` | the R6 region, pure synthetic receipts |
| C | C0-C4, 5 | `20260913T090931Z-C` | the clocks |
| D′+B8/B9 | 5 | `20260913T093518Z-D` | the pinned `cleanup()` region 1487-1883, boundaries only |
| E | E0-E6, 7 | `20260913T093852Z-E` | `provision-rig-r4.sh` refusals + the sentinel scope reading |
| F′ | F0-F3, 4 | `20260913T093337Z-F` | the real `d2_ledger()` |
| G | G0-G3, 4 | `20260913T093635Z-G` | the R6 dispatch window in r2 |
| H | H0-H4, 5 | `20260913T094739Z-H` | the R6 correction in `fp-driver-d2-r3.sh` |
| disposition | — | `disposition-20260913T092245Z` | read-only re-query of every registered identity |

**THIS IS FIXTURE EVIDENCE, NOT PROVISIONED-FIELD ACCEPTANCE** (doyle WD47ADZV), and two groups
must not be read as green:

- **Group A carries an UNRESOLVED DEFECT.** A7 passes *by demonstrating* that the registered
  `kind=native` identity is the WRAPPER (`timeout.exe`), not the subject. `measure_termination`
  therefore re-queries the wrapper, a surviving subject is invisible, and A3's `CONFIRMED_GONE` is a
  statement about `timeout.exe` alone — doyle JDCJYANF withdrew its subject-termination acceptance.
  The correction is designed in `LAUNCH-IDENTITY-DESIGN.md` and is **the outstanding process-safety
  blocker**; process-launch controls are PAUSED until it is ruled on.
- **Group G proves a defect EXISTS; it does not prove a repair.** Only H speaks to the repair, only
  for R6, and only as fixture evidence.

**The R6 correction** (`fp-driver-d2-r3.sh` `48f1afcf…`, from frozen r2 by `build-driver-r3.py`, one
anchor, 22 diff lines, CRLF preserved) was **accepted by doyle on direct diff review (AHLVTXUC)**:
marker-set with an unassigned receipt path now withholds all three cleanup mutations.

**Launches, stated rather than implied.** Groups B, C, D′, F′, G and H launched nothing: every
effectful helper is a boundary and PATH is shadowed. Group A launched throwaway children (`true`,
`sleep`, a bash one-liner, `pwsh Start-Sleep`). **Group E DID launch**: E6's four probes each ran
`timeout -k 2 10 bash -c …`, so a `timeout` and a `bash` child per probe. Each printed one
environment variable and returned promptly. They were not registered as identities, so no
independent post-state verification of them exists — which limits verification without erasing the
observed returns (doyle AHLVTXUC).
