Repository navigation
fix(claude): delivery rollback reads the attribute-aware composer (#1291) - #1309
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#1291) After absorption timed out, the rollback classified the composer text-only, and Claude repaints placeholder text (a prompt suggestion, a hint) into an emptied composer, which text-only reads as a draft: 4 of 5 recorded rollbacks exhausted 64 kills and yanked the prompt back, stranding it. It now prefers the session's attribute-aware reading (the one the prompt gate uses), keeping the fail-closed text read as fallback. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ttribute-composer
Juliusolsson05
added a commit
that referenced
this pull request
Sep 25, 2026
…ate rule, #1309 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d needs a painted placeholder to call it empty - A1: the cached composer state moves only on a throttled (and stallable) screen event, slower than the 25 ms kill loop, so it could keep saying 'drafted' over an emptied composer. The rollback now reads text and cell attributes from the live buffer at the same instant (claude-code-headless getComposerAttributes, bumped to #63's head). - A2: attributes alone called a leftover character under the inverse cursor 'empty'. The text read stays the base; it is overruled to 'empty' only when dim placeholder cells are painted and nothing is typed. - Tests: dim suggestion (cleared), inverse residual (not cleared), bare marker without attributes (cleared). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…al headless frame; evidence stated precisely - The classifier is exported and tested with a real ClaudeCodeHeadless: painted frames go through the live screen and attribute pipeline (dim suggestion empty, typed text drafted, bare marker empty). - The comment now cites the whole corpus (4 exhausted, 1 cleared, 7 unobserved) and says the placeholder repaint fits the exhausted records rather than being observed in them (no screens were recorded). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… is a draft The text-only read allowlists "Press up to edit" as empty. A kill clears only the current visual row, so a prompt whose first row reads like that hint could be left behind, plain, and reported cleared with retrySafe. Live plain cells now veto that empty. Tests pin the real painted frame, the rollback outcome, the continuation-row guard and ClaudeSession.readComposer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
Author
|
Round 2 disposition (final round), head ab9ab02
205 Claude runtime tests pass; 🤖 Generated with Claude Code |
Juliusolsson05
added a commit
that referenced
this pull request
Sep 25, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ttribute-composer
…ttribute-composer
Owner
Author
|
Gate check before merge: head 🤖 Generated with Claude Code |
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 #1291.
Found by the Stage 3 C1 hunt. Plan:
docs/plans/2026-09-25-claude-rollback-attribute-composer.md(first commit). This PR needs claude-code-headless#63 (merged,64fd0eaf), and the submodule is bumped to it.Evidence
The paste-debug corpus (1,082 journals) holds 4
rollback-exhausted {presses: 64}, 1rollback-clearedand 7rollback-unobserved. After a kill empties Claude's composer, Claude repaints placeholder text (a prompt suggestion, or a hint). The text-only read calls it a draft, so every kill looks like a failure and the prompt is yanked back.The exhausted journals carry no screen, so the repainted placeholder is the explanation that fits them (one prompt was a typical suggestion, "yes fix all 9"), not a recorded observation.
What merges
ClaudeSession.readComposer()returns the screen and the composer cell attributes (getComposerAttributes(), from style(dispatch): pad content from status index #63) from the LIVE terminal buffer in one call. It never uses the throttled per-frame state, which lags a 25 ms kill loop (review round 1).classifyRollbackComposer):emptyis trusted for a bare marker.emptyonly when the live attributes show a painted placeholder: dim cells, no plain cells, and an attribute-aware read ofempty(which also checks continuation rows).draftedwhen text-only saysemptyfor an allowlisted hint ("Press up to edit") but the live cells are plain (review round 2). A kill clears only the current visual row, so typed text reading like a hint can remain, and a retry would append to it.drafted.Tests
rollback-clearedafter one kill (red on main), an inverse leftover and a typed known-hint row are not cleared, and a bare marker with no attributes clears.ClaudeCodeHeadless-painted frame test: dim suggestion, typed text, a bare marker, a dim hint, and a typed hint.drafted.ClaudeSession.readComposer: null without a headless, and screen and attributes read together.The Claude runtime suite passes, and
npx tsc -bis clean.Residual
An all-dim draft (for example native voice interim text) could look like a placeholder. No recorded rollback frame shows it; tracked with #1294.
🤖 Generated with Claude Code