import io
p='docs/INFRA-REGISTER.md'
s=io.open(p,encoding='utf-8',newline='').read(); nl='\r\n' if '\r\n' in s else '\n'
old='- **Status:** BUILT (hertz, 2026-09-24, fix candidate (a) as ruled by doyle; lane `ci/ir147-push-docs-only`):'
assert s.count(old)==1
new=('- **Status:** DONE (hertz, 2026-09-24; accepted by doyle). **Acceptance:** push run '
 '[`36001575121`](https://github.com/BigscreenVR/spt-bs-core/actions/runs/36001575121) at `79f67567` '
 '(the IR-146 (c) lane, 2 docs-only commits), pre-registered in 3 versions before the run '
 '(`.spt/preserved/331/hertz/ir147-acceptance/`): `CLASSIFY_BEFORE` == `657fda0d` (condition held), '
 '`CLASSIFY code=false reason=docs-only`. **The acceptance rests on the discriminators, NOT on the unit '
 'job list**, which reads the same with or without IR-147 because IR-144 reuse also skips unit. (1) The '
 'LAST `UNIT_REUSE` line reads `run-unit=true reason=both-unit-jobs-not-successful`: reuse declined, so '
 'the skip is `code=false` alone. (2) Lint was SKIPPED here and RAN on the code push `36001478480` at '
 '`657fda0d`, where unit was skipped by `exact-pr-proof`. Grep trap: the FIRST `UNIT_REUSE` match in a '
 'changes log is always the workflow echoing its fallback (`reason=helper-failed`); the verdict is the '
 'LAST. **Field defect found and fixed on the way** (`657fda0d`, core PR #258): a stale '
 '`before` object on the reused kitsubito workspace short-circuited the deepen, giving '
 '`before-not-ancestor` on a true ancestor (run 35998753683). The probe now deepens until '
 '`is-ancestor` succeeds and reports `before-undecidable` for a still-shallow graph. The acceptance run '
 'exercised that deepen, shown on the runner checkout, not in the log (see [[IR-148]]). '
 'Built as: BUILT (hertz, 2026-09-24, fix candidate (a) as ruled by doyle; lane `ci/ir147-push-docs-only`):')
s=s.replace(old,new)
anchor='### IR-147 — a docs-only PR skips'
entry=nl.join([
'### IR-148 — the change classifier\'s deepen/connectivity mechanism leaves no log trace, so IR-147\'s acceptance proves the outcome and never the mechanism',
'- **Status:** OPEN (hertz, 2026-09-24, filed at doyle\'s request; wanted built soon). Origin: IR-147 acceptance run [`36001575121`](https://github.com/BigscreenVR/spt-bs-core/actions/runs/36001575121).',
'- **Measured.** To show that run exercised #258\'s deepen, hertz had to read the kitsubito runner\'s checkout over ssh after the run: 70 commits reachable from HEAD, `0511877c` showing parent `657fda0d` and absent from `.git/shallow`, `is-ancestor` 0. The job log itself only allows INFERENCE: a 1.85 s gap between the `CLASSIFY_BEFORE` echo and the `CLASSIFY` line. `classify-changes.py` runs its `fetch --deepen` and `merge-base --is-ancestor` silently.',
'- **Mechanism.** A probe that cannot witness its own instrument. On a WARM workspace, where `before` is already connected at depth 2, a regression that silently stops the deepen from ever running would still print a correct-looking `CLASSIFY code=false reason=docs-only`. The acceptance record cannot tell "the deepen works" from "the deepen was not needed", and the ssh read is not repeatable after the next run overwrites the workspace. Same class as a telemetry that fires only on failure.',
'- **Fix (proposed, doyle\'s shape).** Next to the `CLASSIFY` line, the classifier prints ONE line naming the step that connected: `step=0`, `deepen=50`, `deepen=500`, or none. It also prints whether the repo was still shallow at decision time, e.g. `CLASSIFY_PROBE connected_at=deepen50 shallow=true`. The selftest pins that line for each arm. No behaviour change.',
'- **Ripe when:** next touch of `.github/ci/classify-changes.py`; hertz CI lane, small. **Acceptance:** one field push run whose log carries the probe line, and whose value matches a field-shaped local rebuild of the same range.',
'',''])
i=s.index(anchor)
s=s[:i]+entry+s[i:]
io.open(p,'w',encoding='utf-8',newline='').write(s)
print('ok')
