# Negative results — lane f3, site-program 2026-09

A result that fails its pre-registered bar is recorded here with the same care as one that passes,
and spending on it stops. A candidate that hits its kill criterion before producing a measurement is
recorded here too, with the blocker named and the work that would unblock it priced — because "we
did not run it, and here is exactly why" is a different statement from silence.

Every row names the sealed bar it was measured against. Seals live in `artifacts/prereg/` and were
committed before their runs.

---

## S06-1 · The seventh MCP server — NOT RUN, kill criterion fired

**Seal:** `artifacts/prereg/capinfer_git_bar.json`, sha256 `f1ebc6e8d6e716e2…`, sealed at commit
`ee30602` **before** `mcp-server-git` was ever executed under this repository's sandbox.

**The prediction, which stands unexecuted.** From the verbatim capture
`xdomain/mcp/servers/git.json` alone, five of the twelve tools were named as contradicting their own
declared hints — `git_status`, `git_diff`, `git_diff_unstaged` and `git_diff_staged` on rule R1
(`readOnlyHint=true, observed writing to the filesystem`, because git refreshes `.git/index` on a
dirty stat cache), and `git_checkout` on rule R5 (`destructiveHint=false`, while switching branches
overwrites working-tree files the call did not author) — and seven were named as honest. The bar was
two-sided: a run flagging everything would fail it exactly as a run flagging nothing would.

**Negative control, run first and passed.** `python3 scripts/check_capinfer.py` → `GREEN: 15/15
legs green`, with leg 15 reproducing the `sequentialthinking` finding live in the sandbox
(`out/s06/c1_control_six_servers.log`). The instrument was working before the target was approached.

**Blocker, which is the second clause of the sealed kill criterion verbatim.** The server needs a
git repository that the sandbox seed cannot provide. Confirmed by reading the harness rather than by
inference: `capinfer/sandbox.py:203-215` `seed_workspace()` writes declared seed files with
`open(path, "w")` — text only, no binary — and there is no setup, init or exec hook anywhere in
`capinfer/*.py`. A git repository requires a binary index and zlib-compressed objects. Separately,
the pinned image carries no `git`, `uv` or `uvx`
(`docker run --rm --entrypoint sh capinfer-sandbox:1 -c "command -v uvx uv git python3"` → nothing),
though it does carry `python3-venv`, so the server itself would follow the existing two-venv pattern
in `capinfer/sandbox/Dockerfile`.

**What would unblock it, priced.** A `workspace_seed_cmd` hook in `seed_workspace()` that runs a
declared command in the workspace before the server launches (for git: `git init`, one file, one
commit), plus a third venv and the `git` binary in a SEPARATE image tag so `capinfer-sandbox:1` and
its gate stay untouched — `CAPINFER_IMAGE` already exists in `capinfer/sandbox.py:26` for exactly
that. Estimated 1 turn, $0. **The seal does not expire:** the prediction was registered before any
observation, so whenever the hook lands, the test is still a prediction and not a postdiction.

**Cost: $0.** No retry budget was spent, as the seal required.

---

## S06-6 · The Linux kernel's verifier ran, and it rejected our monitor

**Seal:** `artifacts/prereg/bpf_kernel_load_bar.json`, sha256 `f9a13ba976b65806…`, sealed at commit
`c9cf3c8` before any load was attempted. The bar's FAIL branch was written as publishable: *"the
Linux verifier rejects our compiled monitor, and here is its log."* This is that branch.

**What was blocked, and no longer is.** This estate's own 2026-08 audit named "code compiled from
our proof passes the Linux kernel's own verifier" as its single best unspent hour, blocked because
the host is a Mac and macOS has no `bpf()` syscall. It does have a Linux VM: kernel
`6.10.14-linuxkit`, aarch64, reached through a privileged container. The blocker was a host fact.

**The result.** `monitorgen/generated/monitor_bpf.c`, compiled to a real `elf64-bpf` object (112
instructions, `e_machine` 247), was submitted to `bpf(BPF_PROG_LOAD)` as a socket filter. The kernel
**rejected it** with `EACCES` and 424 bytes of verifier log. The verifier walked the program and
stopped at instruction 6:

```
0: (b4) w0 = 0                        ; R0_w=0
1: (66) if w1 s> 0x7 goto pc+86       ; R1=ctx()
...
4: (18) r3 = 0x0                      ; R3_w=0
6: (71) r2 = *(u8 *)(r3 +5)
R3 invalid mem access 'scalar'
processed 6 insns (limit 1000000)
```

**What that says about our own claim — CORRECTED S08, 2026-09-04, by this lane against itself.**
The original paragraph here read: "the generated monitor reads its input through a null base rather
than through the socket-filter context the program type provides." That attribution is wrong, and
the orchestrator amplified it within the hour on the strength of controls that answered a different
question.

The object carries **twelve `R_BPF_64_64` relocations against the program section**, eleven to
`mon_bss` and one to `mon_verdict` (`llvm-readelf -r out/s06/bpf/monitor_bpf.o`). The instruction
the verifier stopped on is the first of them, at section offset `0x20`:

```
4: (18) r3 = 0x0 ll        <- R_BPF_64_64  mon_bss, unapplied
6: (71) r2 = *(u8 *)(r3 +5)
R3 invalid mem access 'scalar'
```

`scripts/bpf_kernel_load.py` parses the section bytes and calls `bpf(BPF_PROG_LOAD)` directly. It
applies no relocations and creates no `.bss` map. libbpf and bpftool both synthesise an internal
`.bss` map and rewrite that `lddw` into a map-value pointer *before* loading. So the kernel saw a
load through literal zero because our loader handed it one.

**The measurement stands exactly as recorded. The attribution does not.** The monitor reads its own
STATE through an unrelocated global, not its input through a null context. The emitter's comment —
"State as a .bss global. Supported by BPF directly, so this program needs no map"
(`monitorgen/generated/monitor_bpf.c:91-92`) — is true only under a relocating loader. The input
path (`int ev = (int)(unsigned long)ctx`, `monitor_bpf.c:98`) is a second, separate defect the
verifier had not yet reached.

**The control that was missing.** S06's controls proved the verifier was REACHED (a corrupted twin
was rejected differently). None of them proved the loader FAITHFUL: no object carrying a `.bss`
global was ever shown to load successfully through it. A control that establishes reachability and
is read as establishing correctness is the same defect class this lane audits other lanes for.
Receipt: `monitorgen/artifacts/kernel_load.json` (`verifier_verdict: rejected`,
`in_kernel_verifier_run: true`); diagnosis: `llvm-readelf -r out/s06/bpf/monitor_bpf.o`.

**The control, and two failures of my own before it worked.** The bar required a malformed object to
be REJECTED, so an acceptance could not be an artefact of a harness that never reached a verifier.
That control failed vacuously twice before it discriminated, and both failures are instructive:
(1) the loader used the x86_64 `bpf()` syscall number on aarch64 and got `ENOSYS` for *everything*,
at which point "the malformed object was rejected" was true and meaningless; (2) the control
truncated the end of the ELF *file*, which left the program section untouched, so both objects were
literally the same program and produced identical logs. The working control removes the final
instruction from the section the verifier walks: `EINVAL` for the control, `EACCES` with an
instruction-walking log for the real object. The loader now refuses to report at all unless the two
differ (`control_discriminating`).

**Reusable, per the lane note.** `scripts/bpf_kernel_load.py` takes `--object`, `--section`,
`--type` and `--image`, imports nothing from monitorgen, and uses no bpftool or libbpf. Another lane
can point it at its own object — and after S08 it must be handed over with the sentence above
attached: **it does not relocate, so it is sound only for objects with no relocations against the
program section.** f5's staged `sf_gate.bpf.o` is exactly such an object (0 relocations against
`classifier` or `xdp`), which is why its verdict is loader-independent and f3's is not.

**CLOSED 2026-09-04, and the retraction was right.** f2 ran this same object under a relocating
libbpf loader on its Linux 6.8 rig: all 12 `R_BPF_64_64` relocations applied, the `.bss` map
synthesised (`f3_monit.bss`, ks=4, vs=12, fd=3), instruction 4 resolved to `r3 = map_value(...)`,
and instruction 6 — the one that failed here — read `*(u8 *)(r3 +5)` cleanly. **The kernel ACCEPTED
it**: 182 insns processed, 17 total states, every back-edge closing `safe`.

So the sentence this lane published at S06 — that the Linux kernel refused the monitor this
repository compiles from its proofs — is **withdrawn**. The kernel never refused the monitor. It
refused a loader, and the loader was ours.

Two things must travel with that. **This lane did not measure the acceptance.** f2 did, on f2's
hardware, and the record is outside this repository at
`~/Documents/portfolio-control/site-program/exchange/inbox/f3__sealed_prediction_about_f5_object.md`
(read-only). What this repository can still regenerate is the rejection under its own loader, which
is exactly what `monitorgen/artifacts/kernel_load.json` records. And **f2 sealed a prediction
against this outcome and lost it** — it expected four backward jumps carrying a `.bss` progress
variable to trip `infinite loop detected`; state pruning converged where it expected divergence. 2
of 11 keys violated, published in f2's own negative results, with a third key flagged as holding
only vacuously rather than banked as a success.

**What the estate gained by the whole sequence.** A retraction that was written from a relocation
table, before anyone could check it, turned out to be correct when someone did. The original
finding did not survive; the discipline that produced the retraction did.

**Cost: $0.**

---

## S06 · Candidates not reached, and why

Four of the twelve approved candidates were not started. They are listed here rather than left
silent, because "we ran out of turn before this one" is a different statement from "this failed".

- **5 · guard elision from an ∀-trust impossibility.** The claimable mechanism in the list: a
  composition proven hazard-impossible for every trust model may omit its runtime guard, with the
  proof attached as an offline-verifiable certificate. Two turns of build. Not started. Its
  prerequisite is now stronger than when it was planned: the full-factorial re-derivation
  (`out/s06/c2_full_factorial.log`) confirms the 62 impossible slots at 9,216 assignments per
  semantic row, so the certificate would rest on a re-derived result rather than a sampled one.
- **9 · a tighter distributed-attention network floor.** The v101 artifact's own audit note says the
  counting bound is "deliberately loose" and a tight bound is open. Two turns of derivation. Not
  started. Overlaps the inference lane and is an S07 ownership question regardless.
- **11 · DICHASUS Doppler probe.** Half a turn to answer whether any carded scenario carries a time
  axis at all. Not started.
- **12 · isolating the three red unlisted validators.** One turn. Not started; the S04 isolation runs
  (`out/s04/red_validators_isolated.log`) stand as the current record, and the causes remain
  unnamed.

**Spend across all twelve: $0.00.** The approved ceiling was $150. The only candidate that would have
cost money, 7(b)'s live droplet run, was not needed to make 7(a)'s point.

## S08-O11 · The capinfer observation was NOT RUN, and the reason is the result

**Seal:** `artifacts/prereg/s08_capinfer_estate_servers.json`, sealed at `54f7fdb` before any estate
MCP server was read. Its `no_hint_no_grade` clause was written before the census: *"if a server
declares no hints, capinfer has nothing to contradict. Reporting '0 disagreements' for such a server
would be the estate's signature defect — a green that means nothing. Those servers are reported
UNGRADABLE, not clean."*

**Control first, and it passed.** `python3 scripts/check_capinfer.py` is 15/15 green in this session,
including leg 15's LIVE re-run inside the sandbox (`out/s08/o11_capinfer_control.log`). The
instrument works today. What follows is a property of the servers, not a broken tool.

**The census.** Ten MCP server modules across eight lanes
(`artifacts/backends/mcp_annotation_census.json`). **Zero declare `readOnlyHint`,
`destructiveHint`, `idempotentHint` or `openWorldHint`.** Six are hand-written JSON-RPC with no SDK
dependency at all; f5's own docstring explains why ("WHY NO SDK"). capinfer's entire result — rank 3,
five disagreements across six third-party servers — is a comparison between a DECLARED hint and an
observed syscall window. With nothing declared there is nothing to contradict.

**So the observation half was not run**, including on this lane's own `oss/minicheck-mcp`. Running
it would have produced a clean-looking artifact that establishes nothing, which is the defect this
estate exists to catch. The prediction sealed before the census said "most estate MCP servers
declare no tool annotations at all"; the answer is all of them.

**The ask, which is cheap and belongs to each lane.** Declaring annotations on the tools you already
ship is a few lines per tool and makes your server gradable by an instrument that already exists and
is already green. Until then no honest disagreement count for these servers is possible.

**Four blind spots in my own detector, all caught before the count was published.** The census is
guarded by a leg that requires it to find every server already known to exist. That leg failed three
times: an SDK-shaped detector reported zero servers for three lanes that each ship one; a keyword
`inputSchema=` was missed; an `@server.list_tools()` style was missed. A fourth was caught by a
different leg: unanchored decorator patterns counted two of genesis's *audit scripts* as MCP servers
because they quote `@mcp.tool` in comments while counting it. A census that misses servers, or
invents them, is not a census.

**Cost: $0.**

---

## S08-O9 · A stated coverage boundary, predicted before it was met

**Seal:** `artifacts/prereg/s08_scope_defaults_estate.json`. The two-sided bar named f5's
`results/data/champion_search.json` as the foreign positive and recorded, before f5's tree was read,
the expectation that the scanner would **NOT** flag it: *"f5's own words are 'the producer as
committed searches 60', which reads as a literal in the source rather than a flag default."*

**It did not flag it, and the diagnosis is exact.** `experiments/run_champion_search.py:168` does
carry `ap.add_argument("--configs", type=int, default=60)`, so the defect IS argparse-shaped — the
prediction was right for the wrong reason, which is worth saying plainly. The pairing failed at a
different step: line 238 writes `os.path.join(C.DATA_DIR, "champion_search.json")`, so the directory
is a **module constant**, and the sealed pairing can only anchor a path on string literals.

That is the same class of miss the S06 three-way control caught one level shallower (literal versus
`os.path.join` of literals), and it is now a stated boundary rather than a surprise. A
unique-basename fallback was added AFTER the sealed run, with its own control leg reproducing the f5
shape synthetically (v1 misses, v2 catches) and a second leg requiring an ambiguous basename to be
refused rather than guessed. **v1's numbers are published beside v2's, not replaced by them**
(`n_flags_total_v1_sealed` in the artifact).

**Three false positives, refuted by hand before anything reached a lane.** The first estate run
produced five unresolved flags. Two were real. Three were numeric co-occurrences between an option
and a count field sharing no name: f2's `crosscheck.py` runs three seeds and writes 24 rows, and
24 > 3 is not a defect; genesis's `PROV_1_FAB_OS/cli.py` is a multi-subcommand CLI where `--max-iter`
belongs to one subcommand and `training/n_samples` to another; and f5's real defect appeared a second
time against `--seeds`, meaninglessly. A confidence tier now separates a name-matched pairing from a
co-occurrence, and only the former is addressed to a lane.

**Cost: $0.**
