fix(pm): post-stamped exits non-zero when the platform did not store the body - #18690
Merged
os-justin merged 2 commits intoSep 17, 2026
Merged
Conversation
…the body The read-back already detected the mutation and printed it; the exit code stayed 0, so a caller obeying every discipline the header prescribes — no pipe, `$?` checked — walked on as if the body had landed. The verdict now carries an exit code. One question decides it: did every byte this act sent reach the platform? The three declared normalisations all keep the sent body whole and still exit 0. `mutated` splits in two on an exact-bytes measurement (`footerReAnchored`, one spelling shared with the classifier's comment-only footer class): a footer the platform re-anchored took nothing away and keeps its 0, everything else is EXIT_NOT_STORED (4). ⛔ classifyReadBack is untouched — the class, the warning line, the offset and `body_mutated` are all as pinned. What changed is what `$?` says. Claude-Session: https://claude.ai/code/session_01Gqi43smmqjJ5sUrhfoPeKu Co-authored-by: Claude <noreply@anthropic.com>
…st-stamped-body-unstored-exit
This was referenced Sep 17, 2026
os-justin
marked this pull request as ready for review
September 17, 2026 15:16
This was referenced Sep 17, 2026
os-justin
deleted the
claude/issue-18663-post-stamped-body-unstored-exit
branch
September 17, 2026 15:58
This was referenced Sep 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #18663
Clause-②: no
The defect
scripts/pm/post-stamped.mjsalready DETECTED the write the platform never stored — it read theartefact back, classified the difference as
mutated, printed the byte counts and the firstdiffering offset — and then returned
0. On the filed hit (a seat-post body refresh, 2026-09-17)it sent 263,533 bytes, the platform stored 257,945 — the byte count of the version BEFORE that
write — with the first difference at byte 6792, where the new block began: the old body had been
kept whole and not one byte of the new one was there. A caller obeying every discipline this file's
own header prescribes — no pipe,
$?captured before any pipe — was still told the body hadlanded, and went on to post the comments that say the conclusion had already been written into it.
That is the opposite direction from the pipeline trap the header already warns about: that one is
about a caller throwing the code away, this was the tool handing out a zero.
The discriminating predicate, and the verdict fields it reads
One question decides the exit code: did every byte this act sent reach the platform?
All three benign classes answer yes by construction and are untouched —
identicalby definition,trailing-newline-strippedgives up only newlines the platform does not keep,footer-appendedadds without removing.
mutatedis the only class the rule reads, and it splits in two:Two fields of
readBackVerdict's own verdict object, and nothing else:readBack.classclassifyReadBackis not touchedreadBack.footerReAnchoredPLATFORM_COMMENT_FOOTER.footerReAnchoring()is the one spelling of that comparison, shared with the classifier's comment-onlyfooter-appendedclass rather than written a second time⛔ Not a byte-count heuristic. The platform normalises blank lines around a trailing rule in both
directions, so a length comparison answers a different question: "stored is shorter" is neither
necessary (a re-anchored footer is LONGER) nor sufficient (an equal-length substitution loses just
as much). ⛔ And it does not need the pre-write body, which only
--bodyever holds: "the platformkept the old one" is one INSTANCE of the class, not its definition — whatever is stored, a byte
that differs INSIDE the body this act sent is a byte this act did not get onto the platform. The
same predicate therefore covers the filed hit, a truncation, a sanitizer substitution, and a
--commentwrite.--commentdoes share the verdict:mainbuilds onereadBackVerdictfor both acts and passesmode, so the same predicate judges both. A comment the sanitizer chewed now exits non-zero; thecomment footer append it is built to forgive is already clean one class earlier.
⛔ What did NOT change:
classifyReadBack's classes and exemptions, the warning line, the offsetline,
body_mutatedin--json, what is SENT, and the stamp contract. There is no retry logic.The one shape that must stay at 0, and does. A
--bodyrefresh where the platform appends its58-byte footer classifies as
mutated— the issue-body footer cell is unmeasured, and this PR doesnot forgive it in the classifier. It exits 0 because nothing was lost. Measured on the fixture,
byte-for-byte the shape the seat hits on every seat-post refresh:
The exit register, before and after
PREREQUISITE NOT MET— no route, no token. No act at allEXIT_NOT_STORED— written, and the platform did NOT store itWhat a caller does with a 4 is in the header and in the tool's own stderr report: re-read the
artefact; ⛔ do not retry blindly — the measured hit was a size refusal the platform never
reported, so an identical second write reproduces it exactly and a retry loop writes that failure
into the card over and over.
⛔
unreadableis deliberately NOT widened into the new code. "The platform returned no readablebody" is a failure to VERIFY, not a measured failure to store; it keeps its
UNVERIFIEDline andits 0 until somebody measures what that cell means — the same reason the body-footer cell is not
forgiven in the classifier. The boundary is recorded in the header, not quietly crossed.
Pins
New battery in the file's
--self-test, registered the way the ten existing ones are (battery()opens it,
t()attributes to the one most recently opened, the floor is evaluated last):$?, or it reaches nobody」SELF_TEST_BATTERIESSELF_TEST_BATTERY_FLOOR: 10 → 11What they pin: the filed shape (stored = the pre-write body, first difference inside the sent body)
⇒ 4 · a body-mode footer re-anchoring ⇒ 0, and still
mutatedwith its offset · a re-anchoring overa stripped trailing newline ⇒ 0 · a trailing-newline strip ⇒ 0 · an identical read-back ⇒ 0 · a real
mutation underneath an appended footer ⇒ 4 (the footer masks no loss) · a chewed
--commentread-back ⇒ 4, the
--commentfooter append ⇒ 0 · a truncation ⇒ 4 ·unreadable⇒ 0, not widened ·the five register values distinct · the footer measured as exactly the declared bytes and not as a
58-byte delta (58 bytes of
xanswersnull).Ablation
From the committed fix, on disk, under a
trap, with absolute paths: the predicate's last linereturn readBack.footerReAnchored === true;replaced byreturn true;— which is exactly what thetool did before this PR.
Direction predicted before the run and observed: turns red, and only in the new battery — the ten
existing batteries stay green, so the ablation moves exactly what it claims to move. The six that
fall are the six that read
exit/landedon a lost body; the footer-re-anchoring controls staygreen under the ablation by construction (a predicate that always answers "landed" still exits 0
there), which is why the filed-shape pins and not the controls are the ones that prove the fix.
Restore is proven by blob hash and by an empty
git diff HEAD, not by an exit code;git checkout HEAD -- PATHnames HEAD explicitly so a polluted index cannot serve the mutation back.Self-test
233 → 257 cases, 10 → 11 batteries.
Derived gates
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackfrom the worktreeat
2f7df2abc(no hand-fed path list; change set =scripts/pm/post-stamped.mjs, 1 path).29 derived, 29 run, 0 NOT-MEASURED, 0 UNRUN; every exit code captured with redirect-then-
$?,never across a pipe. Reconciled with
--ran:All 29 exited 0:
Plus the repo-wide scan the dispatch asked for, run whole and not narrowed:
And, beyond
pnpm check:nul-bytes(exit 0 above), the author-side control-byte scan on the onechanged file:
grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]' scripts/pm/post-stamped.mjs→ nohits (exit 1).
⛔ Not a complete account of what CI runs here: the derivation also names 53 artifact-roster
families, 11 declared-wide-population families, 14 pending-changeset families and 1 path-scheduled
CI job, each outside the 29 and each printed under its own heading by a run without
--commands.skip-changeset:scripts/pm/**is repo tooling and is in no package'sfiles[]— nothingpublished moves.
Acceptance notes
synthesises a footer for a footer-less ISSUE BODY is unmeasured … a footer on a body read-back
stays MUTATED until somebody measures it」 — and somebody now has: the skills seat reports hitting
exactly that shape (sent N, stored N+58, the difference being the declared footer) on every
seat-post refresh. The file's own stated condition for moving the cell is met and the cell has not
moved, so
--bodykeeps printing a MUTATED warning on nearly every write, which is the noise[finding] post-stamped:
readBackVerdictcompares stored to sent byte-for-byte, so the platform's trailing-newline strip (and the footer append on comments) reads as 「the platform MUTATED the body」 on nearly every write — the one warning meant for the sanitizer is now noise #18296 removed for the other classes. This PR deliberately does not move it (the card pins theexemptions as they are) and closes only the exit-code half. Dedupe words:
post-stamped,classifyReadBack,footer-appended, issue body, unmeasured cell,platform-readings.unreadableread-back still exits 0, so a caller checking$?walkson with a write the tool could not verify. No repro is in hand — the platform would have to
return a body-less object — so it is an observation, not a defect card; the boundary is now
written into the header rather than left implicit. Successor: whoever lands the card above, who
edits this same function.
Session: https://claude.ai/code/session_01Gqi43smmqjJ5sUrhfoPeKu
Generated by Claude Code