import io

p = r'C:\Users\decid\Documents\projects\spt-claude-code\docs\KNOWN-HAZARDS.md'
s = io.open(p, encoding='utf-8').read()
NL = chr(10)

tail = '''- **Lane:** adapter-side entirely. Core states the exactly-once rule and declines to enforce it;
  keeping it is ours.
'''
assert s.count(tail) == 1
assert 'REQ-HAZARD-ACROSS-CLEAR-DISPATCH-DROP' not in s

entry = '''
<!-- [doc->REQ-HAZARD-ACROSS-CLEAR-DISPATCH-DROP] -->
### 8.3 Handing the dispatch to core makes every un-reported turn a silently unsent one

- **Failure shape:** the across-clear quiet window returns from `handle_stop` before the idle
  report, so that turn reports no payload. While this adapter owned the parser that cost nothing —
  `scan_and_dispatch` had already dispatched, higher up the same function, and the call site said so:
  *"The dispatch above already ran — outbound is never suppressed."* Under `[io] compliance` the
  dispatch is **core's**, and core only ever sees what we report. The same early return therefore
  stops dispatching every shortform tag written in that turn, with nothing anywhere recording it.
- **Why that turn in particular:** the quiet window is armed by a commune-across. It is the turn an
  agent writes its handoff in — often naming peers, often the last thing it says before the session
  is rebuilt. It is the worst turn in the system to lose a message on, and the loss is silent at both
  ends.
- **The general rule, which outlives this instance:** when a capability moves from the adapter to
  core, every path that *skips reporting* silently becomes a path that *skips the capability*. An
  early return that was previously about one concern (here: not marking idle) inherits every concern
  that now rides the report. Re-walk the early returns when you hand something over — the compiler
  cannot, because nothing about them changed.
- **Invariant (`REQ-HAZARD-ACROSS-CLEAR-DISPATCH-DROP`):** the quiet-window arm still reports the
  turn's batch, as a mid-turn span on the **busy** arm (`state busy --payload-stdin --mid`). That is
  compatible with the window rather than a hole in it: the window exists to keep the endpoint BUSY so
  inbound spools for the post-clear session, and `--mid` marks busy (idempotent) rather than idle. The
  text reaches core's parser, the endpoint stays ACTIVE, and the window keeps doing its job.
- **Accepted and named:** a bare (odd, unpaired) `;;` seal marker in that turn is refused as
  `SEAL_BARE_MIDTURN` — mid-turn, *"through the end of your output"* names text core has not been
  given yet, and a short seal looks exactly like a correct one. Seal pairs mint normally. Recorded
  rather than worked around: closing the pair is the author's fix.
- **Lane:** adapter-side. Core's rule is that it parses what it is given; choosing to give it
  nothing is ours.
'''

s = s.replace(tail, tail + entry, 1)
io.open(p, 'w', encoding='utf-8', newline=NL).write(s)
print('added 8.3')
