|
| 1 | +## 2026-08-30 — E-DESTRUCTIVE-PREPEND-TRUNCATES-BEFORE-READ-1 — the prepend one-liner `open(p, "w").write(entry + open(p).read())` destroyed 5876 lines of PR_ARC_INVENTORY; the pattern is now PROHIBITED |
| 2 | + |
| 3 | +**Status:** FINDING + PROHIBITION (operator-directed, 2026-08-30). Measured on |
| 4 | +a real loss, restored same day (#1082, merge `82679c3a`), pattern banned in |
| 5 | +`CLAUDE.md` § In-Session Orchestration Discipline in the same PR. |
| 6 | +**Confidence:** Certain — the mechanism is Python evaluation order, reproduced |
| 7 | +and named, not inferred. |
| 8 | + |
| 9 | +The #1081 board-hygiene commit prepended its arc entry to |
| 10 | +`.claude/board/PR_ARC_INVENTORY.md` with |
| 11 | + |
| 12 | +```python |
| 13 | +open(p, "w").write(entry + "\n" + open(p).read()) # PROHIBITED |
| 14 | +``` |
| 15 | + |
| 16 | +Python evaluates `open(p, "w")` — which **truncates the file to zero bytes** — |
| 17 | +before the argument expression's `open(p).read()` runs. The read-back returns |
| 18 | +the empty string, and the write emits only the new entry: the append-only |
| 19 | +ledger collapsed 5876 → 32 lines on main, leaving a dangling #1079 |
| 20 | +self-reference as the visible wound. The same holds for every |
| 21 | +truncate-then-read-same-path shape in any language (`>` shell redirection into |
| 22 | +a pipeline that reads the same file, `fs.writeFileSync(p, x + fs.readFileSync(p))` |
| 23 | +is safe only because JS evaluates arguments first — do not rely on remembering |
| 24 | +which language does which). |
| 25 | + |
| 26 | +**The prohibition (P0, workspace-wide):** never open a file for |
| 27 | +writing/truncation in the same expression, pipeline, or statement that still |
| 28 | +needs to READ that file. Prepends are three steps: (1) read into a variable, |
| 29 | +(2) compose in memory, (3) write — or use the `Edit` tool, which is |
| 30 | +read-anchored by construction and the default for board files anyway. |
| 31 | + |
| 32 | +**The falsifier (mandatory after every ledger write):** `wc -l` the file. |
| 33 | +An append-only file that got SHORTER is always a defect — no exceptions, no |
| 34 | +"it probably deduplicated something". |
| 35 | + |
| 36 | +Cross-refs: census trap 10 |
| 37 | +(`docs/architecture/COGNITIVE-FABRIC-CENSUS-2026-08-30.md` §8.3); restore PR |
| 38 | +#1082; the pre-existing "Read before Write, always" P0 in `CLAUDE.md` — this |
| 39 | +entry is its sharper edge: read-before-write applies WITHIN a single |
| 40 | +expression's evaluation order, not just across tool calls. |
| 41 | + |
| 42 | +--- |
| 43 | + |
1 | 44 | ## 2026-08-30 — E-A-FLOOD-THROTTLE-IS-NOT-A-DISCRIMINATOR-1 — the census equated `hub_indegree` with a specificity test; they are opposite where it matters |
2 | 45 |
|
3 | 46 | **Status:** FINDING (measured, review-driven). Raised as codex P2 on #1079, |
|
0 commit comments