---
name: write-a-shared-memory-file-only-after-checking-it-exists
description: This memory root is SHARED across the fleet's agents — `cat > file.md` silently destroys a peer's write. Check existence and read the file before any whole-file write.
metadata:
  type: feedback
---

**Measured 2026-08-21, my own error.** I wrote a new memory with `cat > a-frontier-names-where-
progress-stopped-not-the-cause.md <<'EOF'` on a topic doyle had just messaged me about. A peer had
ALREADY created that exact filename, with a richer entry than mine (it named the wedger, gave its
0.02s solo runtime, recorded that skipping moved the frontier 183 → 335, and ruled "bisect, never
edit at the frontier"). `cat >` truncates. There is no git and no backup in this root, so those bytes
are gone; I could only reconstruct from `MEMORY.md`'s surviving index line, which happened to be
unusually detailed. Had the pointer been terse, the loss would have been total AND silent.

**Why it is easy to hit:** convergent naming. The filename is derived from the LESSON, so two agents
learning the same lesson from the same incident generate the SAME slug — the collision probability is
highest exactly when the topic is live across the fleet, which is when the peer's write is freshest.
Nothing warns you: `cat >` on an existing file looks identical to `cat >` on a new one.

**How to apply:**
- Before any whole-file write to this root: `ls <name>.md` and read it if present. Merge, do not
  replace. The standing rule already says "check for an existing file that already covers it" — the
  failure mode is doing that check for the CONCEPT (grep the topic) but not for the PATH.
- Prefer `cat >>` (append a dated face) over `cat >` for anything that might exist. Every other
  memory write I made today was an append or a targeted replacement, and none could have done this.
- After writing, verify you did not truncate: if the index line is richer than the file, you clobbered.
  That asymmetry is the detector, and it is how I caught this one.
- If you do clobber: say so in the file, mark what is reconstructed and from where, and tell the
  likely author. A silently thinner memory is worse than an obviously damaged one.

Related: [[two-memory-roots-diverged]], [[echo-commune-overwrites-fresh-commune]] (same latest-write-
wins hazard, different surface), [[correct-by-replacement-not-annotation]] (which governs CONTENT you
have read — not a blind overwrite).

## Correction + the redundancy that was thinner than claimed (2026-08-21, same evening)

Two corrections to the account above, both measured after doyle replied.

**The clobbered file was not doyle's, and the substance was not lost.** He never authored a memory
file for that lesson — he filed it as IR-55 in `docs/INFRA-REGISTER.md`. He checked my reconstruction
against the register, left it standing rather than replacing it, and kept one line of mine verbatim.
The file's `originSessionId` is a session of neither of ours, so the original author is a third agent
on this shared root. **This project's memory root is shared by EVERY agent working it** — that is why
a peer's file was sitting at the path I wrote to, and it is the standing condition, not bad luck.

**But the redundancy we both leaned on was thinner than stated, and I measured it rather than
accepting it.** "It lives in a git-tracked file" is true about the FILE and false about the CONTENT:

    git status --porcelain docs/INFRA-REGISTER.md  ->  " M docs/INFRA-REGISTER.md"
    git show HEAD:docs/INFRA-REGISTER.md | grep -c IR-55  ->  0
    git log -S IR-55 -- docs/INFRA-REGISTER.md  ->  empty

IR-55 was an UNCOMMITTED modification, in a dirty shared checkout, on a feature branch. One
`git checkout --`, stash, or clobbering branch switch and it goes the way the memory copy went. So at
the moment we agreed the loss was survivable, both copies were one careless command from gone.

**Generalise: state the property you actually measured, not the one you want to be true.** "It is
git-tracked" measures the file's tracking status, not whether this content is committed — the same
shape as counting `pipefail` occurrences to prove containment (measures the guard, not the exposure).
Three instances of that shape in one day, across two agents. Before you rely on a backup, check that
the backup contains the bytes: tracked ≠ committed ≠ pushed.

Related: [[exit-code-after-a-pipe-is-the-tails]] (the guard-vs-complement instance),
[[dont-take-a-diagnosis-as-measured]].
