Skip to content

fix(paste): a half-arrived long send is no longer send evidence - #113

Merged
AltanS merged 1 commit into
mainfrom
fix/110-partial-arrival
Aug 17, 2026
Merged

fix(paste): a half-arrived long send is no longer send evidence#113
AltanS merged 1 commit into
mainfrom
fix/110-partial-arrival

Conversation

@AltanS

@AltanS AltanS commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Fixes #110.

Reproduced live in the collie-demo sandbox before changing anything: a six-line send whose final chunk never arrived rendered as [Pasted text #3 +5 lines] TAIL-ONE… TAIL-TWO…, and pasteCarriesSend accepted it — the guard would have fired Enter on half a message. Both screens (partial and complete) are committed as byte-faithful corpus fixtures; the complete one is the positive control that keeps the fix from regressing into stalls.

The rule (rule 5): when the draft ends in literal text, that trailing text must be a suffix of the whitespace-stripped sent text. In the split shape the token comes first and the tail after, so the last thing on the row is the last thing that arrived — if it isn't the end of our message, bytes are still missing. The issue's alternative (newline accounting) turned out to be structurally dead, not just awkward: the box wraps and extractInputDraft space-joins rows, so the tail's newlines never exist anywhere in the pipeline.

Residual hole, deliberate and documented at the rule: a draft that ends on a token keeps the old rule — the message end is inside the token where nothing is visible, that shape was never observed under truncation, and rejecting a screen we can't read would convert working sends into permanent stalls (the worse failure per ADR 0010's budget). Pinned by a test as deliberately loose.

No version bump — release deferred; PATCH axis, wants a loud CHANGELOG line when 0.31.0 is cut.

Tests: web 2307 pass / 0 fail (every pre-existing fixture still accepts), root 617 pass, tsc clean both packages.

🤖 Generated with Claude Code

`pasteCarriesSend` accepted the token + literal tail shape whenever the tokens
claimed no more lines than we sent and every literal fragment occurred in order.
A truncated tail satisfies both — `Σ M ≤ S` is deliberately loose, and a
truncated tail is still a prefix-ordered substring — so a send whose later chunks
never landed looked exactly like a complete one and the guard pressed Enter on it.

When the draft ENDS in literal text, that trailing text must now be the END of
what we sent, not merely somewhere inside it. That is the one question the screen
can answer: per-fragment newline accounting is unrecoverable, because the box
wraps and `extractInputDraft` space-joins the rows. A draft that ends ON a token
keeps the old rule — the end of the message is invisible there, and rejecting a
shape we cannot read would turn working sends into permanent stalls.

Re-probed live 2026-08-17 (collie-demo, pane `w6:p1`, 200-col PTY); both halves
of the split shape are now in the corpus as
`claude--draft-paste-split-{partial,tail}.txt` and pinned by the conformance and
chrome suites.

Fixes #110

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@AltanS
AltanS merged commit 5a4e6c9 into main Aug 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Send guard can accept a partially arrived long send as evidence (paste.ts, ADR 0010)

1 participant