import io

# --- the topic file: v0.37.0 shipped, then FAILED its field test -------------------------------
p = r"C:\Users\decid\.claude-spt\accounts\alt\projects\C--Users-decid-Documents-projects-spt-claude-code\memory\v0370-commune-drop-detect.md"
s = io.open(p, encoding="utf-8").read()

old_desc = 'description: "2026-09-06 SHIPPED v0.37.0 — the across-commune boundary now keys on the DROP FILE, not on the Write tool; claude-spt-bs#25. Carries the event-vs-state trigger rule and the ResidentService auth gap (spt-bs-releases#275)."'
new_desc = 'description: "2026-09-06 SHIPPED v0.37.0 (#25) and then FIELD-FAILED it: ingest is 2.8-5.8s, not >15s, so the drop is gone before the next hook looks. Carries the I-BUILT-ON-AN-UNMEASURED-NUMBER lesson and the event-vs-state trigger rule."'
assert s.count(old_desc) == 1
s = s.replace(old_desc, new_desc)

old_head = "**2026-09-06 — claude-spt v0.37.0 SHIPPED, `claude-spt-bs#25` DONE** (release roundup names it).\nOperator report: agents increasingly write their across-commune with Bash, and no boundary fired."
new_head = """**2026-09-06 — claude-spt v0.37.0 SHIPPED, `claude-spt-bs#25` DONE — AND THEN FAILED ITS FIELD TEST.**
Follow-up filed the same hour. Read the next section before reusing anything here.

## \u2b50 THE LESSON: I BUILT ON THE ONE NUMBER I NEVER MEASURED

The operator said core's commune ingest takes ">15 seconds". Every design decision hung off it:
the io funnel was rejected as unreadable from a hook, a ResidentService was investigated for a day,
and the whole file-stat design exists *because* a drop was believed to sit on disk for 15+ seconds.
I even wrote the dependency down as the design's single point of failure, in the call site and in
the requirement title, phrased so it could be falsified. **I never spent the two minutes to falsify
it.**

MEASURED, three times, right after shipping: **2.8s / 3.8s / 5.8s.** The gap between consecutive
hooks includes the agent's own thinking time, so the drop is typically gone before the next hook
looks. Two real field drops (`cp` and `>`): no boundary, and `state/commune-seen/` stayed EMPTY —
no leg ever *examined* them. The binary is correct (a synthetic payload detects, logs and arms
exactly as designed); the window it needs does not exist.

**Naming a load-bearing assumption is not the same as testing it.** Writing "this holds only while
X" earns nothing if X is someone's estimate and the check is two minutes of work. The cheapest
measurement in the whole project decided its outcome, and I did it after the release instead of
before the design. Sibling of [[signature-match-is-not-root-cause]]: a plausible mechanism, adopted
without the one observation that could have refuted it.

**What it makes true instead:** after ingest, the `COMMUNE` io frame is the ONLY surviving evidence
— the file is gone. And `api io-events --session-id <sid>` is authenticated by the sid every hook
already carries, so a hook CAN read the funnel. The ">15s" figure is the only reason that looked
impossible. The operator's original instinct was right, for a sharper reason than either of us had.

**v0.37.0 is a strict improvement that stops short**, not a regression: the instrument-keyed
predicate is gone, the three legs and arms-once stamp are tested, and a drop written mid-work with a
tool call following inside ~3s does fire. The handoff case — commune as the turn's final act — does
not. Not reverted; v0.38.0 adds the funnel leg.

## The original defect (still correctly diagnosed)

Operator report: agents increasingly write their across-commune with Bash, and no boundary fired."""
assert s.count(old_head) == 1
s = s.replace(old_head, new_head)

old_risk = """**ACCEPTED RISK, in the call-site comment so it can be falsified:** this holds only while core's
ingest is *slower than a hook cycle*. Sub-second ingest would let a Bash-written drop vanish unseen,
and the funnel/service path becomes necessary."""
new_risk = """**THE ACCEPTED RISK THAT WAS ALREADY REALITY:** the call-site comment says this holds only while
core's ingest is slower than a hook cycle, and guesses that only *sub-second* ingest would break it.
Both halves were wrong in the same direction — the true window is 2.8-5.8s, and a hook cycle is
routinely longer than that. The wording made a live failure sound like a remote hypothetical."""
assert s.count(old_risk) == 1
s = s.replace(old_risk, new_risk)

s = s.replace(
    "Floor unchanged 0.66.0; skeleton unchanged 0.1.18 (brief text ships in `adapter.spt`). Published,\nnotes verified at the consumer, mirrored (`3e0b8e9`), installed here.",
    "Floor unchanged 0.66.0; skeleton unchanged 0.1.18 (brief text ships in `adapter.spt`). Published,\nnotes verified at the consumer, mirrored (`3e0b8e9`), installed here — and then field-failed, see top.\nAll of that ceremony was clean; none of it was the thing that mattered.",
)
io.open(p, "w", encoding="utf-8", newline="\n").write(s)

# --- the index line --------------------------------------------------------------------------
ip = r"C:\Users\decid\.claude-spt\accounts\alt\projects\C--Users-decid-Documents-projects-spt-claude-code\memory\MEMORY.md"
i = io.open(ip, encoding="utf-8").read()
old_line = [l for l in i.split("\n") if l.startswith("- [v0.37.0 across-commune drop detect]")]
assert len(old_line) == 1, len(old_line)
new_line = (
    "- [v0.37.0 across-commune drop detect](v0370-commune-drop-detect.md) \u2014 2026-09-06 SHIPPED (#25) "
    "then **FIELD-FAILED**: ingest is 2.8-5.8s, not the >15s I was told, so the drop is gone before the "
    "next hook looks. \u2b50 I named the load-bearing assumption, wrote it down as falsifiable, and never "
    "spent the two minutes to falsify it (more \u2b50 in file)."
)
io.open(ip, "w", encoding="utf-8", newline="\n").write(i.replace(old_line[0], new_line))
print("ok")
