You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
bug(claude): a short prompt already contained in the composer's dim suggestion never confirms #1230
Delivery confirms a short prompt by finding its tail (the last 24 normalised characters) in activeClaudeComposerText. When the baseline composer ALREADY contains that tail, tailAlreadyPresent disables the inline signal. A short raw write never produces a [Pasted text #N] placeholder, so the delivery can never confirm. It waits the full 5 s, rolls back, and fails.
Two shapes reach this:
A prompt contained in Claude's dim placeholder suggestion. The suggestion renders in the empty composer, and activeClaudeComposerText reads it as text. Example: baseline ❯ Try "git status" or "/help" to get started with prompt git status.
A prompt that is exactly the marker ❯. The idle composer segment is ❯. This is only reachable from remote or mobile input.
Measured in the #1226 review (reviewer A, scratch simulator on the recorded 2.1.278 frame):
new | 'git status' + image | ok=False code=absorption-timeout enter=False
old | 'git status' + image | ok=True enter=True
The text-only path has made the same trade for every short prompt since #1219. #1226 extends it to image sends.
Evidence still needed (staged decomposition)
A recorded frame with a dim suggestion in the composer, with cell attributes. The one hint so far is the user note in testing/fixtures/image-reads/claude-user-attachment.json: "prompt lns are shown with less opacity in the composer, fooling our system".
Whether readiness (which is attribute-aware) and activeClaudeComposerText (which is not) disagree on that frame.
Likely fix direction
Take the composer text with dim cells excluded, the way readiness already classifies the empty composer. The alternative is to accept "composer text changed from baseline AND contains the tail" when the tail was already present. Decide from the recording.
Attribute, from source: the vendored Claude Code source settles it. hooks/renderPlaceholder.ts renders the suggestion as chalk.dim(placeholder) (SGR 2), with the first character chalk.inverse when the input and terminal are focused. HeadlessTerminal's composer cell classification already counts isDim() cells, so readiness can tell a placeholder from typed text.
Recordings: the real ones confirm the text but not the attributes. Debug bundle 2026-06-04T09-09-57-625-4177cefbtail-samples.jsonl has ❯ Try "fix lint errors", plain text only. No bundle or fixture holds the raw PTY bytes of that frame.
Why the fix is not a one-liner:pollPasteAbsorbed receives plain screen text (activeClaudeComposerText(screen)), so it cannot see the dim cells. The fix is to pass the attribute-aware composer classification (dim-only means empty) into the baseline, so tailAlreadyPresent is false for a placeholder.
Still needed before building it: one raw PTY capture of an idle Claude composer showing a suggestion, to calibrate on. A synthesized SGR frame would be invented data (steering q10).
Activity
Juliusolsson05 commentedon Sep 25, 2026
Evidence step (quality loop, 2026-09-25):
hooks/renderPlaceholder.tsrenders the suggestion aschalk.dim(placeholder)(SGR 2), with the first characterchalk.inversewhen the input and terminal are focused.HeadlessTerminal's composer cell classification already countsisDim()cells, so readiness can tell a placeholder from typed text.2026-06-04T09-09-57-625-4177cefbtail-samples.jsonlhas❯ Try "fix lint errors", plain text only. No bundle or fixture holds the raw PTY bytes of that frame.pollPasteAbsorbedreceives plain screen text (activeClaudeComposerText(screen)), so it cannot see the dim cells. The fix is to pass the attribute-aware composer classification (dim-only means empty) into the baseline, sotailAlreadyPresentis false for a placeholder.Keeping this needs-evidence.