## OPEN
…
### IR-18 — resident_service_e2e kills breadcrumb pids BARE (stale-breadcrumb tree-kill; kill-side twin of IR-15)
- **Status:** BUILT 2026-08-04 — the named acceptance carrier RAN and the condition is DISCHARGED,
…
- **Size:** small.

### IR-19 — Docs-only pushes to main run full unit legs (classifier is PR-only) — intent unverified
- **Status:** RETIRED 2026-08-18 — intentional for main pushes, not a classifier defect. · **Origin:** hertz observation 2026-08-03 (register-push
  cadence gated his rig behind repeated hfenduleam unit legs); mechanism verified by doyle at
  source same night.
- **What/why:** `ci.yml`'s `changes` job classifies docs-only diffs ONLY for `pull_request` events
  — push events hardcode `code=true` (ci.yml:45–48, an explicit branch, not a fallthrough), so
  every docs-only push to main spins both full unit legs. Tonight: five register docs pushes each
  queued a Windows unit leg on hfenduleam; concurrency kept one running + one pending (main is
  never cancelled in-progress, pending runs supersede — the recorded behavior matches ci.yml:9–13).
  FINDING SETTLED (deployah, same night, from the workflow): this is not intent — it is a scope
  the classifier never had; the `*.md` / `traceable-reqs.toml` case arms are only ever REACHED on
  pull_request (the early-return precedes them), and golden.yml's own hardcoded `code=true` is
  unrelated (golden triggers only on golden/**). REMEDY STILL OPEN on a named tension: extending
  the classifier to pushes leaves a docs-only main TIP with no run of its own — fine if
  tested-sha==merged-sha means "the code at this sha was tested" (it was, at the last code sha),
  not fine if any gate or reader takes "main tip has a green run" as the check. One person reads
  the consuming gates before any remedy (doyle, at the next CI-touching wave) — three assuming is
  how this class ships.
- **Resolution:** the consuming contract already answers the held question:
  `REQ-CI-DOCS-ONLY-THIN` is PR-only and explicitly says ADR-0050 supersedes
  it for main pushes. Main-tip evidence remains full by design; no classifier
  branch was widened.
- **Interim rule (doyle, same night):** batch register edits into one push instead of landing them
  as they occur — the cadence is a real gate on whoever is queued behind the runner.
- **Ripe when:** next CI-touching wave, after the intent question is answered on the REQ record.
- **Size:** small (one conditional, if the answer is "extend").
- **Composed:** LOCKSMITH (#132) — doyle reads the consuming gates during the batch's CI-touching
  wave (the intent question), BEFORE any classifier remedy. 2026-08-03.

### IR-20 — resident_service_e2e's `spt daemon stop --force` does not stop the daemon; teardown is complete only because the kills are
- **Status:** open · **Origin:** hertz 2026-08-03, measured on the IR-18 lane's own clean run
  (hfenduleam, log kept); routed text, doyle-landed.
- **MEASURED:** teardown runs `spt(&["daemon","stop","--force"])` then reaps. At reaper fire, every
  target was still ALIVE and every verdict was `Killed`, not `gone` — verdicts=[boot Killed,
  rel Killed, brain Killed]; the brain's kill line names it `(child process of PID 46896)` — the
  daemon — so the daemon was still resident too and was taken down by the `Child` handle, not the
  stop. A stop that worked would have left the reaper `gone`. This rules OUT the innocent reading
  (stop doesn't manage services): the stop did not reach the DAEMON either.
- **NOT ESTABLISHED — two rungs, neither discriminated:** (1) the rig seeds a `doyle` perch with
  `std::process::id()`, satisfying `ceremony_agent_ground`'s pid-ancestry rung for every child of
  the harness; (2) the rig never scrubs `OWL_SESSION_ID`/`SPT_AGENT_ID`/`SPT_ENDPOINT_ID` from its
  teardown commands, and the measuring run launched from a live agent session, so the env rung was
  live too. `--force` overrides neither. The stop's output is discarded at the call site
  (`let _ = spt(...)`) — no diagnostic names a denial, and no claim is made that one fired.
  Settling it is one run with the stop's stderr captured — on the CI runner AS WELL AS the dev box,
  since the rungs fire on different machines.
- **Why it matters beyond this rig:** REQ-TEST-RIG-DAEMON-TEARDOWN-PROVEN's own failure shape
  inside a rig that passes — teardown completeness rested entirely on breadcrumb kills that were,
  until IR-18, bare `taskkill /F /T` on unauthenticated pids; the most trustworthy-LOOKING
  component (an explicit `--force` stop) was doing nothing while the least trustworthy one did all
  the work. Exactly why the population gate exists rather than per-pid checks alone.
- **Remedy caution (the sentence that must not drop):** the prescribed fix (seed pid 0, scrub the
  three markers — REQ-TEST-RIG-DAEMON-TEARDOWN-PROVEN's own gate) is NOT free here: this rig's
  `doyle` perch pid is load-bearing for the shell bind-by-token legs, so the two remedies are not
  interchangeable — a lane taking this must check which legs depend on the pid before changing it,
  or it fixes the stop and breaks the REQ-INSTALL-11 legs the rig exists for. Kin:
  REQ-BROKER-STOP-ENDPOINT-DENY (the refusal being worked around).
- **LANE-LINKED 2026-08-30 (#242 close sweep):** hertz's queued daemon-leak fixup lane carries
  this entry (brief cites IR-7/17/20/34/35/63); leaves the register when that lane lands.
- **Ripe when:** a hertz test-hardening wave, or alongside the (b) helper lane's touch of this rig.
- **Size:** small (stderr-captured discrimination run × two machines, then the scoped remedy).

### IR-54 — golden-head-intake runbook: three properties this cut proved should be construction, not discipline
- **Status:** BUILT 2026-08-29 — PR #176 (`880b3b9c`, landed on main via `37368263`).
  · **Origin:** PORTER (#205) v0.59.0 cut, 2026-08-21 — doyle (gater) + deployah (driver),
  both mechanisms measured at the cut, neither cost this run anything because the driver caught
  them by hand. Filed at the release-close register sweep.
- **What/why (three runbook amendments, one lane):**
  1. **Release-shaping at ASSEMBLY intake, not post-golden.** The head arrived code-complete
     but not release-shaped (no version bump, stale CHANGELOG top section) — 5 of the last 6
     cuts. v0.59.0 fixed it by authoring version material BEFORE the golden run, which is what
     produced the four-name shape (ruled sha == main tip == golden ref == tag == `c62904e7`,
     first time in six cuts; the previous five each argued a post-golden delta inert). Amend
     `docs/golden-head-intake` so the gater's assembly checklist asks the release-shaping
     question at intake and the driver never authors on top.
  2. **Never-executed-cells list is a hand-off artifact.** The runbook makes it a
     gater-compiles / driver-re-checks item; PORTER's handoff omitted it and the driver had to
     ask. Name it in the assembly checklist beside the greenlit-form delta: which new cells'
     first CI execution is this golden, and where each HAS executed (lane gate / assembled
     head) — it converts a golden red from an RCA into a lookup.
  3. **Lockfile-refresh rule states the PROPERTY, not the command.** Step 1 prescribes
     `cargo metadata --offline`; the driver used `cargo update --workspace --offline` and
     proved the actual rule by diff (workspace members only, third-party pins untouched —
     14 first-party line pairs, 90 third-party unchanged). The property is the rule and the
     diff is its evidence (the standing by-diff rule exists because counting misread v0.39.4
     and v0.41.0 in opposite directions — and the `windows-sys` 0.59.0 collision was LIVE at
     this cut, the exact condition where counting fabricates a 15th "first-party" bump);
     demote the command to an example vehicle.
- **Built evidence:** `docs/RELEASE-RUNBOOK.md` now asks the release-shaping question at assembly
  intake, makes the never-executed-cells list part of the hand-off itself, and states lock refresh
  as a diff-proven property with commands demoted to example vehicles. PR #176 passed
  `traceable-reqs check`; the v0.65.0 cut had already exercised the release-shaped-head rule.
- **Size:** small (one runbook doc lane; no code).

## IN-FLIGHT ON THE BOARD (not re-homed — live WIP lanes)

- releases#93 (servicehost swap test pid-inequality), releases#47 (thin-lane unit(Windows)
  isolation class), releases#32 (worker_lifecycle_e2e Phase A intermittent) — infra-shaped but WIP;
  a live lane is never re-homed mid-flight. When each closes, any residue lands here as a new entry.

## BUILT / RETIRED

### IR-15 — provably_gone is pid-only on Windows: teardown tests can fabricate reds
- **Status:** BUILT 2026-08-03 · **Origin:** golden 30776330383 red on the #125 fix lane (2026-08-02)
- **Lane:** hertz `golden/ir15` @a5042ec — REQ-TEST-LIVENESS-ORACLE-AUTHENTICATED (impl+unit): one
  shared authenticated death-oracle test helper backed by `spt_procident::process_identity`
  (identity pinned at find time, re-verified at assert), both pid-only polling sites repinned
  (daemon.rs teardown test; endpoint_lifecycle.rs relay_pid). Ruled polarity held: Absent⇒gone,
  Present(same start)⇒not gone, Present(different)⇒gone, Unproven⇒NOT gone, missing-stamp
  degrades to pid-only loudly — every unknown errs toward the recoverable red, zero new
  false-green paths. Linux caveat documented in the helper (10ms jiffies: Present(different) is
  narrowing, not decisive; same-tick reuse errs red, safe).
- **Golden:** run 30782259675 red on `resident_service_e2e` bring-up — delta exonerated (unrelated
  family, now [[IR-17]]; same job minted [[IR-8]]'s defining specimen). Same-sha rerun 30784469908
  GREEN; main ff'd to a5042ec.
- **A/B discriminator (hertz):** 80/80 green both arms, quiet + churn phases; churn arm
  positive-controlled (pid-allocator wrap observed <400ms, so reuse pressure was REAL in the churn
  arm); rule-of-three bounds the original flake at ~7.5%/run/sha. Specimen 30776330383 remains
  not-reproduced, cause unidentified — the repin removes the false-red MECHANISM; it does not
  adjudicate the specimen. [[IR-16]]'s kill-side arm (TerminateJobObject return discarded) stays
  a live discriminating instrument for any recurrence — and since 2026-08-03 it is no longer the
  only one: [[IR-18]] (the test's OWN bare breadcrumb tree-kill) is the second kill-side candidate,
  test-side rather than product-side. A recurrence must discriminate between them, not assume
  either: IR-16's arm is a job whose termination silently half-fails (survivor still holds the
  captured image); IR-18's is a victim killed by a bare pid it no longer owns —
  `broker_survived=false` with the boot service still ALIVE and its message spooled. (An earlier
  spelling of IR-18's signature here said "empty stderr"; retracted — empty stderr is present on
  healthy runs and discriminates nothing.)

### IR-21 — CLASS: a helper binary's build is never requested, only its LOCATION is, so any narrow invocation manufactures a red that belongs to the rig
- **Status:** BUILT 2026-08-18 on KEYSTONE #182 hygiene lane. · **Origin:** todlando 2026-08-03. Filed as one instance, rewritten as a CLASS the
  same day when a second member appeared, rewritten AGAIN when the mechanism was measured — the
  first two versions described symptoms and got the remedy wrong. **Corrected a fourth time the same
  day**: remedy (1) claimed the 11 same-package sites were missing a build edge, and todlando
  falsified that by measurement while executing it (replicated independently by doyle). The error was
  doyle's to carry — it was ruled on, not just written. The general rule that refutes it was already
  in this entry's own CI-member section; diagnosing a class does not inoculate you against drawing
  its opposite consequence one section later.
- **Numbers below re-derived on `main` @`3efd7e6` over `git ls-files` (tracked files only). Each
  carries its command; re-run rather than cite.**
- ⚠ **Scan-root hazard, measured 2026-08-03 and worse than first reported:** a naive recursive
  `grep -r` from the project root inflates by **~35×**, not the ~5× an earlier draft of this entry
  claimed — 426 tracked `.rs` against 14,865 on disk with `target/` excluded, because `.worktrees/`
  holds full copies of the tree. **And the unscoped grep does not COMPLETE** (still running at a
  120s timeout while `git ls-files` returns instantly), so the failure mode is not only a wrong
  number but a command that reads as hung on a tree where dozens of worktrees are normal. Use
  `git grep` or `git ls-files | xargs grep`; both are scoped to tracked files by construction.

#### THE MECHANISM (measured, both ends)

**Build end — `cargo test` with a narrow target selector compiles a `[[bin]]` AS A TEST HARNESS and
never emits the plain executable.** Measured: `cargo test -p spt --bins` on a clean pool produced
five executables, every one hash-suffixed under `target/<profile>/deps/`, and ZERO plain exes in
`target/<profile>/`. The bin was built. The file the test looks for was not written.

**Consumer end — the resolver borrows a guaranteed binary's path to locate an unguaranteed one.**
All 29 copies of `sibling_bin` in `crates/spt/tests/` reduce to two textual variants (22 + 7) of one
body:

```rust
fn sibling_bin(name: &str) -> PathBuf {
    PathBuf::from(env!("CARGO_BIN_EXE_spt"))
        .with_file_name(format!("{name}{}", std::env::consts::EXE_SUFFIX))
}
```

`CARGO_BIN_EXE_spt` is used **only as a directory anchor**. Cargo therefore sees a dependency on
`spt` and on nothing else; the `{name}` half is a string join it cannot observe. The dependency edge
does not exist at any level a build system could act on — which is why "use the wider command" is
not the fix and why the failure is invisible on a warm pool where some earlier run happened to leave
the file behind.

The unit-test resolver at `crates/spt/src/cli.rs:25601` reaches the SAME directory from a different
anchor (`current_exe()` → `deps/` → parent) for the same reason: its own doc comment records that
unit tests get no `CARGO_BIN_EXE_*` at all.

**That mechanism explains both original members at once, including the polarity inversion that made
them look like different bugs:** whether `cargo test -p spt` or `cargo test -p spt --bins` happens
to leave a plain exe behind is incidental to a dependency neither command was told about.

#### SCOPE — WHERE IT BITES, AND WHERE IT DOES NOT

**It bites NARROW invocations — `-p <pkg>`, `--bins`, `--lib` — i.e. gate rigs and local runs.**
Both members were hit on the LOCKSMITH t1 lane against fresh throwaway pools; each was discharged
in-lane as a rig artifact. That is the whole field population to date.

**GOLDEN IS ACQUITTED, and the acquittal is measured rather than assumed.** `cargo test --workspace
--no-run` emits all 13 plain binaries — mock-session, mock-shell, capture-player,
console-mode-probe, service_fixture and the rest — so a workspace build produces the cross-package
helpers by construction. Confirmed under nextest, the tool CI actually runs, with a real compile.

⚠ **The measurement that establishes this is not the obvious one.** Deleting the plain exe and
watching it reappear is NOT evidence of a rebuild: cargo's uplift restores a hardlink from an intact
`deps/` artifact, with link count 3 and an UNCHANGED mtime, which looks exactly like a build and
says nothing about a pool that never had the file — and a pool that never had it is the only kind a
rig runs on. The sound probe removes the plain exe AND both `deps/` artifacts, confirms all three
absent, then watches the target actually recompile (mock-adapter, 5.77s, fresh mtime). The first two
attempts were setup, not measurement.

⚠ **The suspicion this acquits is structurally well-founded, so record the answer, not just the
verdict.** `twohost-a`/`twohost-b` are `needs: test`, so the only mock-adapter prebuild runs AFTER
the phases that use it; `target/` is gitignored, so checkout never cleans it on a persistent
self-hosted workdir. Every precondition for artifact leakage is present — the build simply does not
need it. The next person who reads that job graph will form the same hypothesis; this is the answer
waiting for them.

#### THE ONE CI-SIDE MEMBER THAT IS REAL

`crates/spt/src/cli.rs::adapter_translate_proof_gates_on_commit` is a **unit** test (`kind(bin)`),
and `CARGO_BIN_EXE_*` is set only for integration tests and benches of the declaring package. A unit
consumer therefore CANNOT express the dependency through the env var at all — it has no choice but
to resolve by path. That is why `.github/workflows/ci.yml:105-106` carries a hand-written
`cargo build -p spt --bin translate_proof_fixture` before the unit lane, with a comment
(`ci.yml:102-104`) stating this exact mechanism.

**Deleting that step would red the unit lane on a clean pool, and it would read as a code red.**
Somebody already hit this class, fixed their own leg correctly, and never turned it into a rule —
the comment at `ci.yml:102` is IR-21 written a milestone early, in the one place only its author
would find it.

#### POPULATION

**13 bin targets in the workspace** (`cargo metadata --no-deps`, not a grep — an auto-target under
`src/bin/` and `xtask` are both invisible to a `[[bin]]` grep). Two are not helpers (`spt`, `xtask`);
the other **11 are test helpers**, across three packages:

| package | helpers |
|---|---|
| `adapters/mock` | mock-session, mock-shell, capture-player, console-mode-probe |
| `crates/spt-daemon` | dispatch_fixture, service_fixture, summarizer_fixture, xlate_choreo_fixture (⚠ this row was mis-"corrected" 2026-08-22 to claim `xlate_choreo_fixture` no longer existed — IT DOES, as an AUTODISCOVERED `src/bin/` target with no `[[bin]]` stanza; the original row was right and merely predated `summarizer_fixture`. See IR-58) |
| `crates/spt` | translate_proof_fixture, post_step_fixture, gh_fixture, git_fixture |

**44 literal `sibling_bin("…")` call sites**, all in `crates/spt/tests/`, served by **29 copied
resolvers**. Split by whether the BUILD IS ALREADY GUARANTEED — which is not the same question as
whether the env var is available, and an earlier version of this entry conflated the two:

| class | sites | detail | build guaranteed? |
|---|---|---|---|
| **cross-package** | **33** | mock-session 26, mock-shell 6, service_fixture 1 | **NO — the hazard members** |
| **same-package** | **11** | translate_proof_fixture 7, git_fixture 2, post_step_fixture 1, gh_fixture 1 | **YES — already, by construction** |

⚠ **MEASURED TWICE, and it falsifies what this entry said on 2026-08-03 before this revision:** cargo
builds **every bin target of a package whenever it builds ANY integration test of that package** —
that same act is what sets `CARGO_BIN_EXE_*` in the first place. So the 11 same-package sites were
never unexpressed in a way that could bite, and the hazard population is **33 cross-package sites
plus the one unit-test member = 34**, not 44.

- **Probe 1 (todlando, root pool):** deleted all four `translate_proof_fixture` artifacts (both
  hash-suffixed harness exes, the `deps/` plain exe, the uplifted plain exe), confirmed absent, then
  built ONE UNRELATED and UNMODIFIED integration test of the same package —
  `cargo test -p spt --test attach_wedge_e2e --no-run`, exit 0, 14.45s. Both plain exes returned with
  fresh mtimes; the hash-suffixed harness exes stayed absent, which is what distinguishes a bin
  DEPENDENCY build from a `--bins` harness build.
- **Probe 2 (doyle, `.worktrees/gate-ec5f38a` pool, independent replication with a different fixture
  and a different probe test):** deleted `gh_fixture`'s plain exe, its `deps/` plain exe AND its
  hash-suffixed harness exe, confirmed all three absent, then built `--test json_emit --no-run`
  (exit 0) — a test that never names `gh_fixture`. The plain pair returned at a FRESH mtime (09:13
  against the 09:00 it carried before), so this is a real build and not the hardlink uplift this
  entry warns about elsewhere; the harness exe stayed absent.
- **Neither probe needs a baseline arm:** the probe test is unmodified and references nothing under
  edit, so what it measures is cargo's behaviour, not anyone's change.
- **Corroborated by this entry's own field data:** neither original member was a same-package
  integration site — member 1 is a UNIT test, member 2 is CROSS-package. The class never had a
  same-package integration member, and the CI-member section below already stated the governing rule
  (`CARGO_BIN_EXE_*` is set only for integration tests and benches of the declaring package) one
  section before the remedy drew the opposite consequence from it.

Command: `git ls-files '*.rs' | xargs grep -hon 'sibling_bin("[a-z_-]*"' | sed 's/.*sibling_bin("//;
s/"//' | sort | uniq -c`.

⚠ An earlier report gave 48 sites and a 6/11/37 split. Take the table above: it counts only literal
call sites in tracked files and it ships its command. The 11 is the same 11 in both counts.

**The LOCATION half of this class is already closed** by `crates/spt-term/tests/support/fixture_bin.rs`
— a shared resolver rather than 29 copies. It does not close the BUILD half, and should not be
mistaken for having done so.

#### REMEDY SHAPE (not ruled)

The distinction that matters is location vs. build:

1. **The 11 same-package sites are NOT hazard members and need no build fix.** Their build edge
   already exists (see the two probes in POPULATION above); `env!("CARGO_BIN_EXE_<name>")` for the
   fixture itself would add nothing to it. Converting them is a **CLARITY** change, worth doing on
   its own smaller merits — the path becomes the one cargo actually emitted rather than a string-join
   of a directory anchor and `EXE_SUFFIX`, five copies of `sibling_bin` stop existing (29 → 24), and
   it completes a migration already paid for: `crates/spt/tests/fixtures/translate_proof_fixture.rs:7-12`
   records that the fixture was re-homed into `spt` precisely to obtain
   `CARGO_BIN_EXE_translate_proof_fixture`, and then all 7 call sites resolved by path anyway. **It is
   not a build fix and must not be filed as one.**
2. **The 33 cross-package sites cannot**, by cargo's design. Their options are an asserted build in
   the test's own setup, a `dev-dependencies` artifact dependency, or an explicit documented
   prebuild — the ci.yml:106 shape, made a rule instead of a local fix.
3. **Standardising on one wider invocation is NOT a remedy.** It changes which pools happen to work;
   it does not create the dependency edge, and the two original members had opposite polarity under
   exactly that theory.
4. Collapsing the 29 resolver copies is worth doing on the `fixture_bin.rs` model, but on its own it
   makes the class HARDER to see — one shared resolver still anchored on `CARGO_BIN_EXE_spt` hides
   the 33 genuinely unexpressed dependencies among its 44 call sites behind one function.

#### SUPERSEDED FRAMING, KEPT SO IT IS NOT RE-DERIVED
- **Status of the original filing:** open · **Origin:** todlando 2026-08-03, both members hit on the
  LOCKSMITH t1 lane against fresh throwaway pools; each discharged in-lane as a rig artifact, filed
  here so the next clean rig does not re-diagnose them as code reds.
- The first two versions of this entry framed the class as "the rig's command does not build what
  the test needs" and proposed standardising on a wider invocation. **Both are superseded by the
  measured mechanism above** — the dependency is not under-expressed, it is INEXPRESSIBLE in the
  form these call sites use, so no choice of invocation creates it. Kept only as the two FIELD
  MEASUREMENTS that produced the class, which remain true:
- **MEMBER 1 — MEASURED:** `cli::tests::adapter_translate_proof_gates_on_commit` failed on the
  first `cargo test -p spt --bins` run. Its fixture binary `translate_proof_fixture` (a
  `tests/`-homed `[[bin]]`) was ABSENT from the pool — `ls` on the path returned No such file.
  Building it explicitly and re-running the IDENTICAL command PASSED, after which the full `--bins`
  suite passed 584/585 with only the releases#117 probe red (that one RED by design). So the
  discriminator is the fixture's presence, not the tree: same command, same sha, red then green
  across one `cargo build` of the fixture.
- **MEMBER 2 — MEASURED:** `cargo test -p spt` does not build `mock-adapter --bin mock-session`, so
  `attach_wedge_e2e` panics `"the dummy-harness program must be built"`. Note the polarity is
  INVERTED against member 1 — there the narrower `--bins` was the defective invocation and
  `cargo test -p spt` the correct one; here `cargo test -p spt` is itself insufficient. So the
  class is NOT "use the wider command"; it is that the dependency is not expressed to the build at
  all, and which invocation happens to work is incidental.
- **What/why (still true):** on a WARM pool the helper is already there from some earlier run and
  the test passes, so the defect is invisible exactly where most people work and fires only on a
  clean pool — i.e. on a GATE RIG, which is the one place a false red costs the most.
- **The sweep this entry once called its first step HAS BEEN RUN** (todlando 2026-08-03) and its
  result is the POPULATION section above. It is no longer outstanding.

- **Why it is register debt and not a lane bug:** nothing in the product is wrong. The gap is
  between what a test needs built and what the rig's command builds, and the fix belongs to the
  tests' declarations, not to whoever is running a gate that day. Sibling rule:
  [[gate-clean-target-not-incremental]].
- **Built evidence:** golden now names every cross-package fixture prebuild
  (`mock-session`, `mock-shell`, `capture-player`, `console-mode-probe`,
  `service_fixture`) explicitly; `xtask binedge-check` reports zero missing
  edges. All 29 local `sibling_bin` resolvers collapsed into
  `tests/common/mod.rs`; the shared precondition names the missing fixture and
  its package-correct build command before any product timeout.
- **Ripe when:** the next gate-rig or CI-touching wave. Cheap, and it pays for itself the first time
  it stops someone chasing a phantom red on a clean pool.
- **Size:** remedy (1) is small AND optional — it buys clarity and subtraction, never a build edge;
  medium for (2), which is a design call before it is an edit and is the only remedy that closes the
  class.

### IR-22 — An inherited identity env var fails a test, and the diagnostic names them ONE AT A TIME so a correct fix reads as no fix
- **Status:** open · **Origin:** todlando 2026-08-03, chasing what looked like an `attach_wedge_e2e`
  code red on the LOCKSMITH t1 lane; root-caused to the runner's own process environment.
- **MEASURED:** `attach_wedge_e2e` failed for an INHERITED PROCESS-GLOBAL and nothing in the tree:
  the daemon-stop refusal fired on the running session's own identity env. It named
  `$OWL_SESSION_ID`; clearing that made it name `$SPT_ENDPOINT_ID`. With `OWL_SESSION_ID`,
  `SPT_ENDPOINT_ID`, `SPT_AGENT_ID` and `SPT_SESSION_ID` all cleared: exit 0, 1 passed.
- **The finding is the DIAGNOSTIC SHAPE, not the env hygiene.** Naming one variable at a time means
  a correct partial fix produces an identical-looking failure, so the natural reading of "I cleared
  it and it still fails" is that the clearing did not work — when in fact each step was right and
  the message had simply moved on to the next name. A refusal that can only ever name one member of
  a set it is checking teaches the person debugging it the wrong lesson. Compare the same class in
  [[IR-15]]/[[IR-18]] terms: the instrument is competent and the report is not.
- **Why it matters beyond one test:** any agent running suites from a live spt session carries these
  vars, so this fires for every builder on a perched session and for nobody running from a bare
  shell — which is precisely the split between how builders work and how CI runs.
- **Candidate remedies (not ruled):** have the refusal name EVERY identity var it found set, in one
  line, rather than the first; and/or have the affected tests clear the identity set in their own
  setup so a perched session is not a special environment. The first is the one that pays off
  outside this test.
- **Ripe when:** next CI/test-hygiene wave. **Size:** small.

### IR-23 — `endpoint_teardown_authority_e2e`'s two tests collide with EACH OTHER through the machine-global spt home
- **Status:** BUILT 2026-08-18 on KEYSTONE #182 hygiene lane. · **Origin:** todlando 2026-08-03, LOCKSMITH t1 lane.
- **MEASURED:** both tests copy a psyche binary fixture into `perch::spt_home()/srcs/dummyharness/`
  (`crates/spt/tests/endpoint_teardown_authority_e2e.rs:399`), which is process-global, so run in
  parallel inside one binary each holds the file the other wants: `os error 32`, "used by another
  process". **Signature: WHICH of the two fails alternates between runs.** Under
  `--test-threads=1`: 2 passed, exit 0 — and the wall clock drops from 182s to 14s.
- **What/why:** two defects in one, and they should not be conflated. (1) The tests are not
  isolated from each other. (2) The staging path is the MACHINE-GLOBAL spt home rather than the
  test's own temp home — on a box that is also a CI runner, so the blast radius is not confined to
  the suite. (2) is the one worth fixing; (1) is a symptom of it.
- **Note on why this is not already caught:** the standing rule is that integration tests run
  through nextest, which gives each test its own process and hides the collision entirely. So this
  is latent on the sanctioned path and only bites the bare `cargo test` path — the rule is working
  and masking a real defect at the same time, which is why the entry exists rather than a shrug.
- **Candidate remedy (not ruled):** stage the fixture into the test's own temp home. Sweep for
  siblings first — any other test writing under `perch::spt_home()` rather than a temp home shares
  the shape, and nobody has counted them.
- **Built evidence:** adapter source, manifest registration, and psyche fixture
  staging now use the rig TempDir. The two process-global resolver users are
  explicitly serialized, and the bare `cargo test` path passes both cells with
  `--test-threads=2` in 13.82s after the declared fixture prebuild.
- **Ripe when:** next test-hygiene wave; the 182s -> 14s figure makes it pay for itself on the
  bare path. **Size:** small per test, unknown until the sweep.

### IR-24 — `reap::terminate_job` discards `TerminateJobObject`'s return, alone among its own module's siblings
- **Status:** BUILT — landed `3d12cf3` on main (2026-08-03), fulfilment verified against this
  entry's own wanted list by doyle 2026-08-04, not merely mapped to the commit: the return is
  audited and the loss NAMED (`REAP_JOB_TERMINATE_FAIL: brain subtree NOT reaped (<os error>); …
  the daemon holds no other handle to reach them` — which also ANSWERS the cost-of-loss question
  this entry said nobody had written down); the "first thing to check" was checked and the ruling
  came out OPPOSITE to IR-16's site in one respect, documented as measured asymmetry in the doc
  comment: `TerminateJobObject` has NO ordinary failing path (zero only for a broken handle) so a
  zero is a real loss, while `TerminateProcess` fails `ERROR_ACCESS_DENIED` on the ordinary
  already-exited path and is deliberately NOT checked — the premise is unit-PINNED both directions
  (`terminate_job_return_discriminates_broken_handle_from_ordinary_states`, cfg(windows), with a
  memberless-job false-positive arm). No `job != 0` re-check (second-weaker-rule prohibition
  honored, same as IR-16). Golden evidence: rides `4b37512` (run 30873007187 attempt 5, 9/9
  green; the premise unit observed PASS in-pool on the Windows leg, Linux leg green — the
  cross-platform quiet-`ESRCH` concern stays with `ec5f38a`'s coverage as before). Path
  correction to this entry's MEASURED line: the site is `crates/spt-daemon/src/reap.rs` (brain
  subtree reaper), not `crates/spt/src/reap.rs` as first filed ·
  **Origin:** todlando 2026-08-03, swept while building [[IR-16]]; deliberately
  NOT folded into that lane (doyle ruling, same day) and filed instead.
- **MEASURED:** `crates/spt/src/reap.rs:207-211` calls `TerminateJobObject` and discards the result,
  the identical shape [[IR-16]] closed at `spt-daemon`'s `kill_tree`. Its own module's
  create/assign siblings at `:178` and `:202` ARE instrumented, so this call is the odd one out
  where it lives — the module already decided that these returns are worth reading.
- **Why it was NOT folded into IR-16:** different subject. IR-16's site is a SUPERVISED SERVICE's
  teardown, where the loss is "a supervised service's descendants survive" and the promise it
  breaks is `REQ-RESIDENT-SERVICE`'s tree claim. This site is the BRAIN SUBTREE's kill-on-close
  job, which has its own lifetime, its own caller and its own answer to "what does a failed
  termination cost here" — and that answer has not been written down by anyone. Folding it in would
  have meant settling that question in passing, inside a commit about the supervisor, which is how a
  second ruling gets smuggled into a lane scoped to one.
- **What it needs that IR-16's fix does not supply:** IR-16 ruled a LOUD REFUSAL (option B) on the
  ground that the alternative — a process-table tree-walk fallback — is measured blind in exactly
  that failure state ([[IR-18]]: descent breaks at the dead middle hop) and would trade a silent
  loss for a false clean. Whether the same reasoning holds here depends on whether this site kills
  its direct process in the same breath, which is what makes the middle hop dead by construction
  there. **That is the first thing to check, and it is not assumed.**
- **Ripe when:** any wave touching reap/teardown; it inherits IR-16's vocabulary and its
  discrimination note, so the second one is cheaper than the first. **Size:** small, once the
  cost-of-loss question is answered for this subject.

### IR-25 — `spt-daemon --lib` reds 2-in-3 under concurrent load with bare `cargo test`, and holds green under nextest
- **Status:** open · **Origin:** doyle 2026-08-03, found while gating LOCKSMITH tranche 1 in an
  isolated worktree; chased to a mechanism and scoped OUT of the release path before the head was
  assembled.
- **MEASURED, four arms, same box, same hour, matched load** (a second `cargo test -p spt-store
  --lib` loop running throughout; `spt-store` itself stayed green in every round, so the box was not
  generically failing):

  | tree | instrument | result |
  |---|---|---|
  | lane `ec5f38a` | `cargo test --lib`, at rest | 821/821 ×4 |
  | lane `ec5f38a` | `cargo test --lib`, under load | **2 of 3 RED** (142s, 117s) |
  | lane `ec5f38a` minus its 5 new tests | `cargo test --lib`, under load | 3 of 3 green (117s, 84s, 105s) |
  | main `932e14b` | `cargo test --lib`, under load | 3 of 3 green (97s, 119s, 104s) |
  | lane `ec5f38a` | **`cargo nextest run`, under load** | **3 of 3 green, 821/821** (88s, 85s, 72s) |

- **Three DIFFERENT victims across two loaded runs**, all process/timing-shaped, all PRESENT AT MAIN
  and green there: `servicehost::…a_service_that_ignores_the_stop_marker_is_force_killed_and_confirmed_dead`
  (panics `ForceKilled must MEAN the owned child is gone` right after `SERVICE_KILL_UNCONFIRMED`),
  `applyhost::…broker_reports_its_compiled_image_version_over_ipc`, and
  `daemon::…a_tree_teardown_reaches_a_grandchild_the_service_spawned`.
- **MECHANISM: in-process thread interference, not product code.** Bare `cargo test` runs a crate's
  tests as threads in ONE process. The lane's five new tests are process-spawning kill-tree tests;
  under load they starve confirm windows of NEIGHBOURING tests that were always marginal. Removing
  exactly those five flips 2-of-3-red to 0-of-3-green at the same sha, in the same binary, at the
  same durations — one of the green runs sits at 117s, precisely a duration that had produced two
  failures with them present.
- **IT DOES NOT REACH GOLDEN.** nextest gives every test its own process, and golden runs nextest.
  The population is GATE RIGS AND LOCAL RUNS — the same population as [[IR-21]], reached by a
  different mechanism, which is why these are two entries and not one.
- ⚠ **The instrument switch is the whole finding.** Measured with bare `cargo test`, this reads as a
  lane blocker; measured with the tool CI actually runs, it is a rig-scoped nuisance. Anyone
  re-opening this must state WHICH instrument produced their observation before quoting a verdict.
  The same tool gap acquitted [[IR-21]]'s golden question the same day.
- ⚠ **The pre-existing fragility is NOT thereby closed.** Those three tests were marginal before this
  lane and the lane only exposed them; "make the new tests quieter" would re-hide a real weakness.
  Hardening them is test-side work (hertz's lane by the dispatch split), not the builder's.
- **Two rig defects of the gater's, recorded because they nearly cost the verdict:** (1) a first
  re-run at rest came back 4/4 green and proves NOTHING — a sequential idle probe cannot express a
  load-sensitive failure, so that is a competence-controlled zero, not an acquittal; (2) the first
  baseline attempt ran its two arms UNSYNCHRONISED (the load generator finished while the measured
  arm was still on run 1), which would have compared a loaded lane against an idle main and read as
  "the lane broke it". A discriminator whose arms ran under different conditions cannot discriminate.
- **Ripe when:** alongside [[IR-21]] on the next gate-rig or CI-touching wave, or immediately if
  anyone starts gating on bare `cargo test` on a loaded box. **Size:** small to document the rig
  rule (gate with nextest); medium to harden the three marginal tests.

### IR-26 — POOL-OWNER claims authorize takeover from a DEAD holder, so releases#103's hazard reaches through the guard
- **Status:** open, LANE BUILT BUT UNCOMMITTED (see the warning below — this is not a figure of
  speech) · **Origin:** hertz 2026-08-03/04, found by its own test rather than by reading, and
  reported unfiled for composition. Composition ruling is doyle's, 2026-08-04.
- **What/why:** a POOL-OWNER claim named a holder pid; lane liveness was read from whether that pid
  was alive. hertz MEASURED the failure on this box: **3 of 3 claims had dead holders while one of
  those lanes was live** — so the guard authorized exactly the interleaving takeover releases#103
  exists to prevent. The remedy records the lane's GIT IDENTITY (branch + the base sha it carried at
  claim time) and reads lane state from ancestry: in flight while the tip is not contained in
  `origin/main`; settled once merged, once the branch is gone, or once the branch no longer carries
  the claimed base (the branch-level twin of a recycled pid). Holder pid demotes to advisory — a
  LIVE holder still refuses, a dead one no longer authorizes.
- **The strongest finding in it, and it is a filter-competence one:** without the base anchor, a
  missing branch read as "settled, branch gone" **out of a directory that was not a repository at
  all**. An unanchored Settled verdict is a clean zero produced by a filter that cannot express the
  question. A Settled verdict now requires the base object to be present in the reading repo;
  unanchored is UNKNOWN. Sibling of [[zero-match-filter-reads-as-absent]] in the pool domain.
- ⚠ **POLARITY, stated rather than buried:** the new arm (dead holder + unlanded lane => REFUSE)
  converts a false-TAKEOVER into a false-REFUSAL. That is the better failure but not a free one, and
  its triggering case is not exotic — it is an agent going down mid-lane, which happened to hertz
  itself this same batch and cost [[IR-1]]/[[IR-4]]/[[IR-9]] their landing. **The open gating
  question, put to hertz 2026-08-04 and NOT yet answered:** from the refusal state, does
  `pool-release` still clear a claim whose holder is dead and whose lane is unlanded, or does the new
  arm refuse that too? A guard whose only escape is the blanket `SPT_POOL_UNCHECKED=1` trains people
  onto the blanket override. The refusal must NAME the remedy, not only the witness, and the remedy
  must be exercised FROM the refusal state rather than reasoned about ([[remedy-must-run-from-refusal-state]]).
  If the answer is "it refuses", that is a design change and returns to doyle before the lane lands.
- **COMMITTED 2026-08-04 (was uncommitted when first measured):** `ci/poolowner-lane-claim` =
  `8ce40d9` (the change) + `98cfafe` (the remedy fix below), both off `b7b00c3`. The original
  measurement found ZERO commits and six modified files in `.worktrees/hertz-poolowner`, i.e. every
  reported number had been measured against a tree no git object captured; the builder committed on
  being told. Recorded because the near-loss is the lesson, not the correction.
- **THE REMEDY DID NOT RUN — measured from the refusal state, which is the only place the question
  can be asked.** The refusal named its witness AND a command, and executing that command verbatim
  failed with the IDENTICAL `SPT_POOL_FOREIGN` block that printed it: **xtask depends on spt-store,
  so every command that builds the tool goes through the pool being refused.** This is the same dead
  end the unclaimed-foreign arm already hit in the field and fixed by leading its line with the
  hatch — adding a second refusal arm re-broke it immediately. FIXED at `98cfafe`: the in-flight
  remedy now leads with the hatch and names `pool-claim`, the command that actually resolves
  ownership. Full chain re-measured on hfenduleam: refuse → verbatim remedy fails → hatch-prefixed
  form succeeds → build proceeds.
- **Answer to "does `pool-release` clear a dead-holder + unlanded claim", two-part:** it DOES — it
  never consults the verdict, it rewrites `lane=None` — **but it is NOT the exit**, because after
  release the same build is refused again on the pre-existing unclaimed-foreign arm ("no lane has
  claimed this pool"). Release moves you from one refusal to another. `pool-claim` is the exit.
- **The guard is a POPULATION, not a row** (builder's generalization, adopted by doyle as the
  standard for this class): one test poses all three refusal arms and asserts that any remedy naming
  a command leads with the hatch, PLUS membership — three posed, three refused — so no arm passes by
  never being reached. The rule had been learned once already and the next arm added broke it, which
  is the definition of something that needs a population test rather than a better comment. 26/26.
- ⚠⚠ **FLEET PROPERTY — the rig refuted itself, and this is the entry's most important line.** The
  first arm did NOT refuse, it TOOK OVER: the arriving worktree was at `b7b00c3`, so the build script
  that ran was ITS OWN, pre-identity. **Enforcement code comes from the ARRIVING tree, never from
  the claim.** So until this lands everywhere, an old tree still takes a live lane's pool, and the
  guard is only ever as new as the tree that arrives. Found by measurement; reasoning would have
  reported a refusal the rig never produced.
- **RULING on the fleet property (doyle 2026-08-04) — a stamp VERSION LINE is REFUSED, and not on
  taste: it cannot work.** The tree that must refuse is the OLD one, and an old build script does not
  read a new stamp field because it does not know the field exists. You cannot make a stale enforcer
  honor a new rule by writing something new into the record it enforces against — **the reader is
  the problem, not the record.** A version line would help only a CURRENT tree explain itself while
  doing nothing to the population it is aimed at, i.e. it would retire the worry without retiring the
  risk. Ruled instead, in priority order: **(1)** land it and state the migration window honestly —
  the arm protects a lane only when the ARRIVING tree carries the change, coverage grows as trees
  turn over, never retroactive; **(2)** NAME THE LOSS YOU CANNOT PREVENT ([[IR-16]]'s pattern) — the
  claiming side may be able to notice afterwards that its pool was taken and say so loudly, turning
  silent artifact corruption into a named event; scope separately and MEASURE whether the claiming
  side can observe it at all before committing; **(3)** SHRINK THE POPULATION — old enforcers are old
  trees, this box carries ~45 worktrees and most are stale, so reaping them is real mitigation and
  cheaper than code. (2) and (3) do NOT ride this lane.
- **The unanchored row, as asked:** `a_claim_from_another_repository_reads_unknown_not_settled` was
  RED before the base-object requirement existed. Verbatim: `left: Settled { reason: "lane branch
  build/lane-x no longer exists" }  right: Unknown`, out of a tempdir that was not a repository at
  all. It fails without the requirement and passes with it — a real negative control, not a row that
  only ever passed.
- **Builder's evidence (as reported, against that uncommitted tree):** spt-poolguard 25/25 with 7 new
  rows, one per precedence cell, two carrying their own negative control; pool_guard_canary 3/3;
  `cargo check -p xtask -p spt-store --all-targets` clean; clippy clean on the three touched crates;
  `traceable-reqs check` exit 0 at 745/745 with new `REQ-POOL-LANE-IDENTITY` complete at doc+impl+unit.
- **Composed:** its OWN thin lane, riding the same next golden batch as the CI-rider cluster but NOT
  merged into it (doyle ruling 2026-08-04). A red must stay attributable: the riders change what the
  pipeline measures, this changes a build-time REFUSAL, and a guard whose failure mode is refusing
  builds is the worst thing to make inseparable from a pipeline change. IR-14's four-trees-into-one-
  unclaimed-pool finding stays OUT of this lane and stays IR-14's, on the same ground [[IR-24]] was
  kept out of [[IR-16]] — folding it in settles its question in passing.
- **Ripe when:** next CI/infra batch, gated on the polarity question above being answered first.
  **Size:** small once the remedy question is settled.
- **FALSE-LIVE, first specimen of the blocking polarity (hertz sweep, measured 2026-08-04):**
  `.worktrees\hertz-ci-riders\target\POOL-OWNER.json` named `holder_pid 31380` with
  `holder_started_at 134302739211259713` = 2026-08-03 16:38:41. Pid 31380 on that box at read time was
  `claude.exe -n "doyle @ HFENDULEAM (spt-core/)"`, created 17:31:11, FILETIME 134302770715019370.
  Same boot, ~52 minutes apart, stamps MISMATCH. The claiming process died and the OS reissued its pid
  to the gater's own session. Every previously measured recycle produced a false-DEAD (reads free
  while the lane is live — the corrupting direction); this one produces a **false-LIVE**: a bare-pid
  guard reads the claim as held by a running holder and refuses, naming doyle as the holder of hertz's
  pool — the blocking direction, first time caught. The `holder_started_at` arm shipped in `8ce40d9`
  discriminates it correctly — that field caught defending, not asserted to defend
  ([[stable-anchor-is-not-a-recycling-defense]]).
- **The mirror image, same box, same hour:** `.worktrees\ir24-reap\target` named `holder_pid 33612`,
  DEAD — while that lane was genuinely LIVE, with `cargo clippy -q -p spt-daemon --lib --tests`
  (pid 22452) running under todlando's session as it was read. Two claims, opposite errors, inside one
  hour: liveness misreads in BOTH directions on the same box in the same hour. Holder liveness has no
  sound polarity as a lane-state oracle. Ancestry decides ([[pool-claim-holder-death-is-not-lane-state]]).
- **THE BARE-CLAIM GAP — a claim the stamp arm cannot adjudicate at all.** The main checkout's own pool
  (`<root>\target`, 72,001,016,671 B = 67.06 GiB) carries
  `{"owner_tree": "...\\spt-core", "written_by": "spt-poolguard"}` — no `lane_label`, no `holder_pid`,
  no `holder_started_at`, no `lane_branch`, no `lane_base`. `read_owner` maps that to `lane: None`, so
  every arm the lane-identity work added is unreachable for it: it cannot be read as in-flight,
  settled, or recycled. **FIVE of the eight** claims found on this box are this shape — `<root>\target`,
  `<root>\target-seam` (below), `gate-target-render`, `ir21-xtask\target`, `locksmith-t1\target` —
  against three carrying a lane identity (`hertz-ci-riders`, `hertz-poolowner`, `ir24-reap`). A claim
  written by a plain build rather than by `pool-claim` is structurally un-adjudicable, and it is the
  MAJORITY shape in the field. Whatever IR-26 does next has to say what an identity-less claim means —
  "the stamp arm handles it" is false for most claims that actually exist.
- **The fifth bare claim was invisible to the first inventory, and the miss is its own lesson:**
  `<root>\target-seam`, **52.06 GiB**, real dir, gitignored on its own line (`/target-seam`, added
  `5ae68f8`, v0.12.1 era), created 2026-06-18, last written 2026-08-02 — nothing in the tracked tree
  references it (grep over rs/toml/md/yml/ps1/sh: zero hits outside this file). The inventory predicate
  was "a directory named `target` inside a worktree"; a second root-level pool under a different name
  is not expressible in that filter, so it returned a clean zero that was reported as a population
  ([[verdict-from-probe-competence]] in the field). Corrects the earlier "72 GB root pool is the
  biggest object by 9x": the two root pools are 67.06 + 52.06 = 119.1 GiB of a 133.43 GiB box pool
  total, so the 44-tree sweep covered ~61% of pool bytes, not the population. **Ruling (doyle,
  2026-08-04): target-seam stands for now** — free space is ~115 GB against the 32 GB golden floor, so
  there is no pressure; it was written to yesterday, so "cold" is one day deep and its writer is
  unidentified. It becomes a reap candidate at the next free-space squeeze, after a fresh last-write
  check and identification of what wrote it on 08-02 — reaping a pool whose writer you cannot name is
  how the v0.51.0 fabricated-red class starts.
- **CLAIM-OBSERVABILITY, MEASURED (hertz, 2026-08-04, three-arm rig with competence control):** a
  displaced claimant CANNOT distinguish takeover from never-claimed — the two states are byte-identical
  on disk (arm 1 vs arm 2 identical; arm 3 proves the rig separates states that differ, so the null is
  real). The takeover is silent on BOTH sides: the taker's `pool-claim` prints ordinary success naming
  no prior owner. Mechanism at `b75258d`: `pool_claim` never calls `read_owner` — it constructs its own
  `PoolOwner` and `fs::write`s unconditionally. The displaced lane's only channel is its next build's
  refusal, which reports a STATE ("this pool belongs to B"), never a transition, and arrives pull-only
  and arbitrarily late while interleaved-artifact harm is already underway. Labelled holes: measured
  against the origin/main xtask binary (lane-tip carry is a source read, not a measurement);
  pool-sweep-as-channel not exercised; single-process holder pid in all arms.
- **Bootstrap property, not a defect (hertz, measured 2026-08-03 while claiming pools for the lanes
  3-4 rebases):** a lane DELIVERING claim-identity cannot claim its own pool WITH that identity until
  it lands — the prebuilt origin/main `xtask.exe` writes old-shaped stamps (owner_tree, lane_label,
  holder pid+stamp; no lane_branch, no lane_base). Enforcer turnover surfacing at CLAIM time rather
  than build time: coverage grows only as trees turn over. Recorded because it reads as a bug the
  first time someone meets it in the field. Related lane-craft fact from the same queue: a rebase
  changes SHAS necessarily but hunk OFFSETS only incidentally — todlando's main.rs hunks stayed at
  @20/@53/@70 across the f2e4516→2f427b2 rebase; treat pre-rebase overlap measurements as stale by
  construction and re-measure, but expect the geometry to usually hold.
- **Bootstrap property FIELD INSTANCE, main checkout (todlando 2026-08-04, IR-12 rig):** the
  prebuilt `target/debug/xtask.exe` in the MAIN checkout pool was stale against main's own source
  at `11169c1` — it printed `(holder pid …, born …)` and wrote a FLAT identity-less claim
  (owner_tree/lane_label/holder_pid/holder_started_at/written_by) where main's source
  (main.rs:2282) prints `(branch …, base …; advisory holder pid …)` and writes the nested lane.
  A lane claimed with a stale tool records NO git identity and demotes its own adjudication back
  to the refused bare-pid predicate. DETECTION that worked and is the reusable part: read the
  claim line the tool PRINTS against the source just read — a mismatch names the stale enforcer
  before it writes. REMEDY at claim time: rebuild xtask FROM THE LANE'S WORKTREE before
  `pool-claim` (which the protocol's claim-from-your-own-worktree rule already implies; this
  instance is why it is load-bearing and not ceremony).
- **RULING (doyle, 2026-08-04) — the claim path must run the same guard the build path runs, and a
  takeover becomes an event.** The documented design already says a finished lane is "taken over
  loudly, not refused"; a silent unconditional overwrite violates the spelling the protocol shipped
  under. Remedy, both halves, one small lane: (ii) `pool-claim` reads the prior owner before writing —
  prior lane LIVE (ancestry + stamp arm, never bare pid) ⇒ refuse exactly as build.rs would; prior
  lane finished ⇒ proceed AND announce the displacement, naming the displaced lane in the success
  line; plus (i) a `displaced` field (prior owner + takeover stamp) rides the new claim, so the fact
  survives in the artifact the late-reading claimant already reads. The identity-less bare claim
  (majority field shape, above) must be handled explicitly by the same change: a bare claim carries no
  lane to adjudicate, so takeover of a bare claim always proceeds-and-announces, and the announcement
  names the claim as identity-less — never silently, never refused. Ripe: next CI/infra batch, same
  lane as or beside the IR-26 remedy. Size: small.

### IR-27 — A junction-pooled rig is TWO objects and teardown only ever removes one
- **Status:** open, found in the wild 2026-08-04 · **Origin:** hertz's 44-tree worktree sweep
  (IR-26 follow-on 3) · **Cross-ref:** [[IR-14]] (unclaimed pools), [[worktree-target-junction]]
…

…
  at the end. · **Size:** a between-run census step plus a scoped reap in the harness.