---
name: torn-window-needs-reachability
description: "A writer's truncate-on-open window is not a defect until the reader is proven to run CONCURRENTLY with it — hertz claimed 3 false positives 2026-07-31 by skipping that step."
metadata: 
  node_type: memory
  type: feedback
  originSessionId: cc1be5ee-a7e1-4b7b-861d-4c0a98570a34
  modified: 2026-07-31T10:22:27.120Z
---

**A torn-write window in the WRITER is not a finding until you prove the READER can observe it.** Reachability is part of the finding, not a footnote after it.

**Why:** 2026-07-31, after the real advisory torn-read fix ([[a2-golden-r2-specimens]] #1), hertz swept the suite for the same class and reported 3 more sites to doyle with high confidence — `psyche_context_file_e2e:172` (writer = 40KB `cp`/`copy`), `psyche_event_turn_e2e:120` and `psyche_sid_custody_e2e:163/227` (writer = shell redirect `echo X> proof`, truncate-on-open). All three writers genuinely have empty windows. **All three were false positives:** the tests read only after `host.pulse_tick()` returns, and the turn goes through `run_bounded_stdin`, which runs the role **to completion** — the writer process has exited before the wait begins. Doyle had already approved a lane on the claim; retracted with the falsification.

The real advisory case differed by exactly one property that was never checked: its mock is a **long-running supervised process writing concurrently with the poll**. Concurrency was load-bearing.

**How to apply:** before reporting a torn-read/poll-race, answer "what runs the writer, and has it exited by the time the reader runs?" Then falsify: inject a *guaranteed* wide window into the writer and run the **unfixed** shape. If it still passes, there is no defect — and the timing delta tells you why (2.36s mutated vs 1.09s baseline proved `pulse_tick` absorbed the delay synchronously). Same mutate-to-prove rig that confirms a real one refutes a fake one, so it costs nothing to run first. See [[instrument-soundness-guards]], [[premature-closure-guards]].

Surviving real defect from that sweep: `resident_service_e2e.rs:215` — `wait_until` verdict **discarded** and paired with `unwrap_or_default()`, so a timeout silently reads as content. Not a race; a silent-timeout trap.
