---
name: never-send-a-claim-composed-before-its-check-ran
description: "Twice in three minutes (2026-09-06 08:24Z) I sent perri a claim written into the same script as its check — 'files present' when the dump had failed, 'BYTE-IDENTICAL' when cmp had failed on the line above — because the send line was not gated on the check's exit."
metadata: 
  node_type: memory
  type: feedback
  originSessionId: 12129c66-fecb-465a-915d-3520b949870c
  modified: 2026-09-06T08:25:27.097Z
---

2026-09-06 ~08:24Z, handing perri evidence bytes: one Bash call did dump → `wc`/`cmp` → `spt send "<claim>"`.
The dump failed (path-form bug) and `cmp` returned 1, but the send line was a SEPARATE statement, so
the message went out asserting "files present" and "BYTE-IDENTICAL" while my own log two lines up
said `No such file` and `differ: char 22`. Two corrections on the wire in three minutes, to the
peer who was about to debug HIS code on the strength of my measurement.

**Why:** a claim composed before its check has run is a prediction wearing the grammar of a
measurement. `&&` guards only the statement it is on; the outbound send on the next line runs
regardless. The failure is invisible in the terminal summary the operator sees (only my log
carries the `differ`), so it ships unless the SEND itself is gated. Same family as the harness
notification saying 0 while the exit FILE said 101 ([[v0630-arc-in-flight]]) — the verdict must be
read from the check's output, never from the fact that a script reached its last line.

**How to apply:** never put an outbound claim (`spt send`, alchemy comment, PR body, operator
report) in the same script as the check it depends on unless the send is INSIDE the guarded branch
(`cmp a b && msg="identical" || msg="differ at $(...)"`, then send `$msg`). Better: run the check,
READ its output, then compose the message in a second call. When a check fails after a claim has
gone out, correct by replacement with the measured fact — do not soften it. A message sent to a
peer is a measurement THEY will act on ([[commune-is-testimony-not-an-artifact]]).


2026-09-06 09:27Z RECURRENCE (3rd face, same session as the rule was written): a Python heredoc edit died on a SyntaxError (non-ASCII in a bytes literal) and the `spt send todlando` on the next line still ran, claiming 'IR-76 amended'. Newline-separated statements do not gate each other any more than `&&` does past the first. The claim was made true 40s later by a second edit, which is luck, not hygiene. Standing form: EDIT in one tool call, READ its verification output, SEND in the next call — the send is never in the same shell text as the thing it reports on.

## Second face, measured 2026-09-08 (v0.68.0 golden r1): the SAME-CALL HEREDOC

A heredoc written in the same tool call as the command that measures a value
**cannot contain that value** — the message text is fixed at compose time, the
measurement does not exist yet. I wrote `sha256sum <file>` and a `spt send`
heredoc citing "the sha256" into one Bash call, and the body carried a
FABRICATED 64-hex string (`71fbb1a6…`) while the command printed the real one
(`a8040e81…`) in the same output. The peer was told to cross-check their copy
against a hash that was never read off any file — a mismatch would have read as
"one of us has a truncated log."

This is not the `&&`-guard face; nothing failed, and every command exited 0. The
tell is a message that *narrates a measurement* sitting in the same call as the
measurement. **Rule: a value you cite must be substituted from a variable the
same shell already assigned (`H=$(sha256sum … | cut -d' ' -f1)` then `$H`), or
read in one call and composed in the next.** Never type a plausible-looking
digest, count, size, or sha into prose.

Correction sent immediately naming the invalid string so the peer discards it
rather than reasoning from a mismatch.


**Instance 2026-09-08 20:55Z (doyle):** told hertz "kitsubito is idle (golden twohost is Windows-only)" as a battery permission; the parenthetical was a BELIEF about job topology, never read. ps + the jobs API `runner_name` field two minutes later: twohost-b runs on kitsubito, the pair is cross-OS. Shape: a permission grounded in a topology claim needs the topology READ (jobs API runner_name, or ps on the box) in the same command that composes the send. Corrected within 2 min; no battery had started.
