import io
p = 'docs/INFRA-REGISTER.md'
s = io.open(p, encoding='utf-8', newline='').read()

a107 = '\n### IR-108 - four brainproc'.replace(' - ', ' — ')
assert s.count(a107) == 1, ('anchor107', s.count(a107))
add107 = (
 "- **Instances 9-11, all 2026-09-12, #304 W-2 (one night, three different surfaces).** NINTH (doyle's gate leg, 03:20Z):"
 " `cargo ... | tail` over non-interactive ssh to kitsubito returned 0 while cargo was off PATH in the non-login shell —"
 " already named in releases#304 comment 5643115673 and filed here for the count. TENTH (hertz, 05:30Z, while writing"
 " register entries about instruments that lie): `traceable-reqs check 2>&1 | tail -20; echo \"CHECK_EXIT=$?\"` printed"
 " `CHECK_EXIT=0` — tail's exit over a checker that exits 1, i.e. a 312-finding red read as clean. He re-ran it only"
 " because the register had made him suspicious of his own zero, which is the entry doing its job and not a skill."
 " ELEVENTH (todlando, 05:20Z, a NEW surface — the harness itself): `cargo nextest run ... | tail -30` wedged at"
 " `--list --format terse`; he killed cargo and nextest by pid, and the HARNESS task summary then reported"
 " \"completed (exit code 0)\" because the pipeline's exit is tail's. A killed run with ZERO tests executed was rendered"
 " as a success by a first-party tool — the same generalisation IR-116 instance 2 forced. Near-miss in the same arm:"
 " a 0-byte output file read as the wedge when it is just tail buffering until EOF. Fix adopted: the rerun writes to a"
 " file and the verdict reads the file; no pipe between a test runner and a verdict.\n"
)
s = s.replace(a107, add107 + a107, 1)

a115 = '\n### IR-116 — a watchdog'
assert s.count(a115) == 1, ('anchor115', s.count(a115))
add115 = (
 "- **Addendum 2026-09-12 03:20Z (doyle, #304 W-2 A5/A4): the Windows Firewall event log is DIRECTION-BLIND, so a rig"
 " that keys \"written\" or \"removed\" on it cannot fail in the direction it claims.** Population controlled over one"
 " read (2011x48 / 2052x6 / 2097x6, a 400-event re-read of the same window returning the identical six): id 2052 fires"
 " on creates AND deletes in the observed population, id 2097 is create-specific, and NOTHING observed is"
 " delete-specific. The CENSUS carries the sign; the log carries only the instant. The same read established a MEASURED"
 " gap (zero events between A5's end and A4's start) and that nothing commits after the client dies — both usable,"
 " neither a direction. Kin: the firewall status fields do not discriminate either, since an admitting hand rule reads"
 " the same `PrimaryStatus`/`EnforcementStatus` strings as a non-admitting product pair on the same query.\n"
)
s = s.replace(a115, add115 + a115, 1)

tail_new = u"""
### IR-119 — a control that only had to prove a ROUTE served a real directory; and a rig is not torn down until its last process is gone, whatever the analysis says

- **Status:** OPEN, mechanisms recorded 2026-09-12 05:46Z (doyle) from hertz's unprompted self-disclosure. The security remedy is an OPERATOR item, filed on releases#304 comment **5643876746** (rotate the kitsubito self-hosted runner's registration credential); this entry carries only the reusable mechanisms.
- **Instance.** The accepted-connection control for the W-2 packet capture was `python3 -m http.server 29472 --bind 0.0.0.0` with **cwd `/home/reavus`** — the self-hosted runner account's home — for **1 h 59 m 54 s**. The off-box bind was REQUIRED (the peer dialled from another machine); the working directory was the whole defect. An empty temp dir returns the identical HTTP 200 and proves exactly as much. `http.server` builds its index from `os.listdir` and filters nothing, so 20 dotfiles including the runner credential files were listed and fetchable; mode 0600 did not protect one of them, because the server ran AS that user. kitsubito's posture was separately verified as RSTing with **no** host filter (ufw inactive, nft input policy accept on both tables), so nothing sat behind the bind.
- **Mechanism.** A route control and a file server are the SAME COMMAND, so the cheapest way to answer "can the peer reach this port" silently publishes whatever directory the shell was sitting in, and the excess is invisible in the result — the 200 looks identical either way. Same family as a pattern-kill that matches its own ssh line: a tool doing more than the measurement asked for.
- **Second mechanism, and it is why two hours passed rather than two minutes.** The author tore down the CAPTURE, named the outcome, and stopped — treating "the verdict is named" as "the leg is finished". **Naming an outcome is a milestone in the ANALYSIS, never in the RIG.** A rig is torn down when its last process is gone, and the artefact you are proud of is not the only thing you left running. Found only because a stale wake line replayed his own teardown list back to him two hours later.
- **Rule.** (1) A control that proves a route binds an EMPTY throwaway directory, never a home, a repo or a working dir, and it goes down in the SAME breath as the capture it controls. (2) Every rig's teardown is a list of PROCESSES asserted gone against a live positive control, never a list of conclusions. (3) A teardown note written BEFORE a ruling does not license deleting the ruling's cited evidence: `/tmp/hz-cap.pcap` and `/tmp/hz-cap.log` were KEPT by ruling, twice, because they are the primary record of a posted verdict.
- **Evidence quality worth copying.** The window was MEASURED (1 h 59 m 54 s), not estimated; the served-request record was complete (2 requests, both ours, `GET /`, no descent, no file fetch) and its LIMIT was stated rather than implied — a server log is evidence about requests SERVED, never about the network. An independent wire instrument (the pcap, 0 dropped by kernel) covered **4.4%** of the window, and that figure is the capture PROCESS LIFETIME: reading the 2.08 s packet span as the coverage would have understated the evidence 150-fold, because a running capture with no packets is still observing.
- **Kin:** [[IR-116]] (assert the post-state, never an echo), [[IR-118]] (an instrument complete about what it measures and silent about the rest), memory rig-ownership-reap-only-your-own, reap-root-needs-authenticated-ancestry.
- **Ripe when:** now — both rules are one line each in any rig. · **Size:** procedure.

### IR-120 — a claim named for the one axis nobody varied: six readings over two routes and two libraries, all on ONE box, reported as a property of the platform

- **Status:** OPEN, mechanism recorded 2026-09-12 05:47Z (doyle); the instance is liam's, refuted by hertz's own arm and conceded by its author.
- **Instance.** The ~2.05 s Windows refused-connect latency was filed as "the WINDOWS refusal latency" on six readings that varied ROUTE (loopback, LAN hop to Linux) and LIBRARY (curl, .NET TcpClient) and held HOST constant — every one on HFENDULEAM. Route- and library-independence were measured; "Windows" was the name of the box. A per-host WFP callout, endpoint agent or filter driver swallowing RSTs would have produced exactly those six readings on exactly those two routes and generalised nothing. Settled only by going to get the missing axis: a second Windows box (Win10 19045 against the first's Win11 26200) read 2077.3 ms, inside 30 ms of the band. The claim survived; it was not ENTITLED to until then.
- **The control the claim also lacked.** Nothing in the record distinguished "Windows pays 2 s" from "TCP to a closed port costs 2 s" or "curl reports refusals slowly" — because every reading was Windows, the word could not be earned from them, only assumed for want of an alternative. The Linux arm supplied it: closed port and open port within **66 microseconds** of each other on the same libraries, so the refusal costs ~0 there and cannot be told from an open port by latency at all. With that control "Windows" is measured; without it, it was a label.
- **Mechanism.** Breadth along the axes you happened to vary reads as generality. The check is cheap and nobody runs it: write the claim's subject noun, ask which axis that noun names, then ask whether that axis was varied. Second instance from the same author in one night (a PowerShell-edition confound priced as the product's cost), and a sibling shape in the same leg: "the box was quiet" inferred from the absence of ANNOUNCED work, when silence is exactly what an unannounced three-minute recursive grep produces — quiet was never measured for that window either.
- **Rule.** A claim names its population and its varied axes in the same sentence, and the axis in the claim's NOUN must be one of the varied ones. One host is a host, not a platform; one edition is an edition, not a cost. A quantity claimed as a property of a class carries a NEGATIVE CONTROL from outside that class, or it is a label. Corollary already ruled: a constant measured only on our boxes does not enter product code as a threshold — see [[IR-117]].
- **Kin:** memory verified-members-are-not-an-enumerated-population, one-sample-is-not-a-negative, tool-claim-must-name-its-environment, absence-needs-sibling-probe, windows-client-refused-connect-costs-2s.
- **Ripe when:** now — it is a sentence-shape check at authoring time. · **Size:** procedure.
"""

s = s.rstrip('\r\n') + '\n' + tail_new
s = s.replace('\r\n', '\n').replace('\n', '\r\n')
io.open(p, 'wb').write(s.encode('utf-8'))
print('OK')
