---
name: the-first-claim-on-a-foreign-pool-must-refuse
description: "A foreign pool's FIRST pool-claim always refuses — the claim tool builds through the pool it is claiming — so the hatch is the only door, for that one leg; and invoked.timestamp is the only artifact that can say whether the guard RAN on a silent leg."
metadata:
  type: project
---

**2026-09-08 W3 (todlando), measured on both halves.**

**The bootstrap refusal.** doyle released `ws272-w3`'s pool to me and my very first leg —
`pool-claim --pool <it> --label <mine> --foreign-pool`, run from my own worktree, exactly as
AGENTS.md prescribes — exited 101 with `SPT_POOL_FOREIGN` naming the pool as owned by his gate
tree and `lane: <none claimed>`. That is not a misconfiguration and not ir56: **`cargo run -p
xtask` BUILDS xtask through `CARGO_TARGET_DIR`, which is the pool it is about to claim**, so the
guard fires before the claim can be written. The refusal's own remedy line says so — it leads
with `SPT_POOL_UNCHECKED=1` and the parenthetical "the hatch is required here". Hatch that ONE
leg; every leg after it builds under the written claim, unhatched.

**Why:** the guard is in the BUILD (`crates/spt-store/build.rs`), and the claim verb is a cargo
target like any other. Any tool that writes the record has to compile through the thing the
record governs. There is no ordering that avoids it.

**How to apply:** put the hatch on the claim leg alone, never on the battery. In bash write it
as its own command (`SPT_POOL_UNCHECKED=1 cargo run …`) and check the later raws — a leaked
export shows up as the banner in every subsequent leg. Also expect the release verb to leave
ownership recorded as YOUR tree (`released (still owned by <you>)`), so the next agent's
claim-back hits the same bootstrap refusal: tell them before they read it as a defect.

**The instrument, and its limit (hertz's find, my limit).** A clean guard pass prints NOTHING,
so no raw can separate "ran and passed" from "never ran" — the absence-with-no-way-to-appear
class. `target/debug/build/<pkg>-<hash>/invoked.timestamp` (stamped when the script ran) beside
`output` (what it printed) does separate them: fresh stamp + 0-byte output = ran and passed
silently. **But it is the LAST invocation per UNIT, overwritten in place, never a log** — after
another battery runs over the pool, your legs' stamps are gone, and N stamps are N units, not N
legs. It can prove the guard runs, and it can TIME-EXCLUDE an agent (my release finished
13:10:33.495Z; the hatched stamp was 13:11:11Z, so that build was not mine), but it cannot
reconstruct a past run. The fix is driver-side: snapshot stamp+output between legs and print a
three-valued `POOL_GUARD: leg=<n> ran=<ts|UNCHANGED> banner=<none|text>` line.

Related: [[pool-claim-writes-a-record-the-BUILD-enforces]],
[[prebuilt-xtask-bakes-its-build-trees-root]], [[pool-refusal-tail-reads-as-release-confirmation]].
