---
name: a-before-after-count-delta-asserts-the-whole-registry
description: A before/after count over a shared store asserts everything that touched it in the window, not your write — assert identity instead.
metadata:
  type: feedback
---

A before/after COUNT DELTA over a shared store is a claim about EVERY writer that
touched that store in the window — never about the write you just made. Anything
else retiring or adding a row inside the window breaks it, and the assertion
message you wrote will misname the failure as a defect in the thing you were
testing.

Measured 2026-09-09, spt-core r3, `webserve_attachment_e2e.rs:551` at c4919243.
ARM 11 asserted `after == before + 2` over `serve list --json` across a
two-attachment send. Three facts made it wrong, all readable at the sha:

- ARM 10, one arm above, deliberately mints a REAL 1s-ttl attachment then sleeps
  1500 ms — it leaves an EXPIRED, not-yet-reaped entry on purpose.
- `ServeRequest::List` answers `registry.entries().cloned().collect()` —
  UNFILTERED. Expiry is masked at SERVE time, not at LIST time, so the corpse is
  counted in `before`.
- the attachment TTL reaper rides the daemon's 5 s reconcile pulse.

A sweep landing between the two lists retires the corpse: +2 −1 = +1. Result:
`left: 4  right: 5`, reported as "each attachment registered its OWN entry" —
which reads as a product defect and is not one.

**4 reds in 15 Windows runs (26.7%), every one exactly −1.** The FASTEST run of
the 15 was a red and the SLOWEST was a pass, so elapsed does not correlate:
"slow box lost a margin" was the wrong read, it is the pulse's PHASE. Linux was
5/5 green at the same sha (9.9 s cell vs 21–29 s) — a smaller window per pulse.
**Green on the faster OS is not evidence of absence.**

**Why:** a count is a proxy. It cannot say WHICH row appeared, so it fails on
churn it never meant to observe, and it fails while claiming something else.

**How to apply:** before writing a count delta, ask what ELSE writes that store
in the window, on what cadence, and whether the LIST surface masks expiry. Then
don't write the count — assert IDENTITY: name the rows you expect and assert
those are present. Identity is strictly stronger and is immune to the retirement
of rows you did not create, including ones added by the next arm someone writes
above yours. Widening a margin is the fix that already failed; quiescing the
store (a Reconcile) removes today's corpse and leaves the coupling.

Sibling trap, and the sharp part: [[a-fallback-that-fires-only-in-release-is-untestable-by-construction]]
is about untested branches; this is about a hazard the file ALREADY NAMED. The
rider below this arm (afb711c9) had retired the same reaper race in ARM 12, and
ARM 12's own comment says depending on ARM 10's entry is "a race the reaper WINS
sometimes". Fixing one arm did not fix its sibling one arm up. **When you retire
a race, census every OTHER site in the file that depends on the same clock** —
see [[a-control-must-sever-the-branch-from-its-consequence]] for the same shape.
