import sys, os
sys.path.insert(0, os.path.dirname(__file__))
from crlfpatch import patch

P = 'traceable-reqs.toml'

old_docs = 'title = "THE-FORKENING W3 (ADR-0036 §4, operator-ruled crate-over-handroll + port 5474): the daemon (broker side — docs are up whenever the daemon is) serves'
new_docs = 'title = "THE-FORKENING W3 (ADR-0036 §4, operator-ruled crate-over-handroll + port 5474): the daemon (brain side since releases#305 — docs are up whenever the supervised brain is; see REQ-WEB-SERVING-IN-BRAIN for the availability coupling) serves'

old_port = "The broker exposes that bound port; serve listings,"
new_port = "The broker exposes that bound port, as announced by the live supervised brain generation that owns the listener (REQ-WEB-BOUND-PORT-GENERATION-SCOPED, releases#305); serve listings,"

anchor = '''id = "REQ-LOCAL-GATE-EXECUTION-EVIDENCE"'''
new_rows = '''id = "REQ-WEB-SERVING-IN-BRAIN"
title = "THE NODE-LOCAL HTTP LISTENER IS A BRAIN RESOURCE (releases#305, SEAMLESS-UPDATES W9, doyle ruling 2026-09-25, ADR-0004 amendment). The loopback listener and all request handling (docshost + webserve + the cross-node proxy leg) run in the SUPERVISED BRAIN CHILD, so a brain restart — `spt daemon refresh` or a brain-only apply — serves the new image's code with no daemon flip. The broker keeps PTYs, the QUIC endpoint, seed control, the serving-registry boot reconcile, the LAN bootstrap listener and the t=0 canonical-exe capture (KH 6.11); the LAN listener therefore stays refresh-blind, stated rather than silent. The cross-node proxy keeps dialling through the broker socket. AVAILABILITY COUPLING (a behaviour change): loopback serving now lives and dies with the brain — a crashed or rolling-back brain takes it down until the supervisor respawns one; the rebind gap is the accepted cost and is MEASURED on both boxes, never gated on a budget. MIXED VERSION: a W9 brain on a pre-W9 broker finds the port held and logs the bind failure loud while the old broker keeps serving its old code; the W9 set classifies BRAIN_ONLY (additive IPC kind, no protocol or resource-ABI bump), so the benefit arrives at a node's FIRST broker flip, and the release notes say so (doyle ruling). A pre-W9 brain on a W9 broker (a rollback across the boundary) serves NOTHING and the port reports as unavailable — accepted, no broker fallback. Gate: doc — ADR-0004 amendment + CONTEXT Docs Server entry; impl — the brain-side bring-up and the broker block that no longer binds; unit — the bring-up resolves port/node and degrades loud; int — a field-shaped rig changes a served byte, runs `spt daemon refresh`, and reads the new byte with the broker pid unchanged, red at base by construction."
required_stages = ["doc", "impl", "unit", "int"]  # ACTIVATED W9 build (todlando 2026-09-25, releases#305).

[[requirements]]
id = "REQ-WEB-BOUND-PORT-GENERATION-SCOPED"
title = "THE REPORTED DOCS PORT BELONGS TO ONE BRAIN GENERATION (releases#305, W9). With the listener in the brain, the broker answers DocsStatus from what the brain ANNOUNCED: the brain binds, then announces {generation, port} over the broker IPC; the broker records it only when the generation equals the child it currently supervises (the coordinator-image discipline — any other Role::Brain client, the CLI's cold start included, cannot satisfy it), and the record is retired when that child exits. DocsStatus never reports a dead brain's port: a replaced or crashed generation reads as unavailable, which REQ-WEB-URL-BOUND-PORT already requires be answered without a guessed URL. An in-process listener (the IR-136 serving fixture) still publishes directly. An older broker answers the announce with `unknown command kind`, drained on the round-trip. Gate: impl — announce client, broker record, supervisor retire; unit — accept on exact generation, refuse others, retire on exit, in-process listener wins; int — rides REQ-WEB-SERVING-IN-BRAIN's refresh: the port is re-announced by the new generation."
required_stages = ["impl", "unit", "int"]  # ACTIVATED W9 build (todlando 2026-09-25, releases#305).

[[requirements]]
''' + anchor

grp_old = '''  "REQ-DOCS-LOCAL-SERVER",
  "REQ-WEB-URL-BOUND-PORT",
'''
grp_new = '''  "REQ-DOCS-LOCAL-SERVER",
  "REQ-WEB-URL-BOUND-PORT",
  "REQ-WEB-SERVING-IN-BRAIN",
  "REQ-WEB-BOUND-PORT-GENERATION-SCOPED",
'''

patch(P, [(old_docs, new_docs), (old_port, new_port), (anchor, new_rows), (grp_old, grp_new)])
