Repository navigation
fix(claude): reclaim a prompt Agent Code stranded in the native composer - #1358
Conversation
… composer (#1350) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ser instead of refusing it as a human draft A delivery whose bytes painted after its rollback stopped watching left them in Claude's composer, and the gate then refused every later delivery as a human draft. SessionManager now marks a session stranded while no other writer has touched the PTY since; the next delivery clears the composer under its reservation and continues. inputInspect reports the mark. Fixes #1350 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he late paint, never reclaim image strands Round-1 review of #1358 (steering q75): a late failure of a replaced process could mark the same-id successor and clear its human draft; a delivery inside the recorded 0.7-3.8 s paint lag skipped the reclaim; image pills are not proven safe to kill. Refs #1350 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…unknown outcome Codex writes paste+Enter atomically, so the Codex test never reached the kind check (it passed with the guard deleted). Pi's bridge 'unknown' outcome reports promptWritten && !enterWritten, which does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mutation battery on 6eeac3b: the write-side entry check, the strandedComposer handoff check and the exit clear each survived alone, because the other layer covered for them. A replacement registered before the old process's generation-owned cleanup now pins the read side; the map itself pins the write side and the exit clear (their only effect once the row is gone is not retaining the dead RegistryEntry). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1358 verification a (blocker): an image delivery that reclaimed a text mark and then stranded left the old mark standing, so the next delivery Ctrl+U'd a composer holding image pills. Any delivery that wrote now clears the mark before deciding whether to set its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1358 verification b: the only window test reinstalled fake timers, which reset the clock and put strandedAt in the future, so a 500 ms window survived. One clock throughout; the next delivery starts 6 s after the failure and the text paints at +7 s. Red with 500 ms and 6.5 s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review disposition. Round 1 at Fixed
Declined, as suspicions without evidence (a, round 1): provider-internal PTY writers that bypass Unproven, out of scope: whether Ctrl+U/Ctrl+Y is safe on a real Claude image pill (#1359). 🤖 Generated with Claude Code |
Fixes #1350 for text prompts. Image deliveries are split out to #1359; see "Not in this PR" and the scope comment on #1350.
Plan:
docs/plans/2026-09-27-claude-stranded-prompt-reclaim.md(first commit; it holds the full evidence).Problem
A Claude delivery writes its prompt, then waits up to 5 s to see it in the composer. While Claude is busy mid-turn the text may not paint. Absorption times out, and the rollback watches about 0.4 s for our bytes before it may clear them. When it never sees them it gives up: "composer could not be recovered",
do-not-retry.The bytes then paint. Claude's gate reads any drafted composer as a human draft, deliberately with no timeout, so every later delivery is refused as "occupied by a human draft". The agent is unreachable for orchestration until someone clears the composer by hand.
Recorded: three incidents on 2026-09-27 in the lifecycle journal.
ac_agents_promptcalls over about 50 minutes, with an empty Agent Code draft.The paste-debug journals hold 7 more
rollback-unobserveddeliveries, all reaching that verdict 5.6–5.7 s after the write.What merges
[Pasted text #N].SessionManagerkeeps a stranded-delivery mark per session.promptWritten && !enterWrittenand not ok.recordInputWrite, so any write whose origin is notdeliveryclears the mark: raw terminal typing, remote input, a condition answer.strandedComposer: { strandedAt }. If the composer reads ready while the mark stands, the recorded late paint (0.7–3.8 s) may still be coming, so the delivery holds the reservation and polls up to 8 s (STRANDED_PAINT_WINDOW_MS) for it. Writing at once could put the new prompt beside our late bytes, and one Enter would submit both. If the gate then saysoccupied, it holds the reservation and clears the composer with the existing verified kill loop (the helper shared with the rollback, nowkillComposerToEmpty). It then re-awaits readiness and delivers.sessions.inputInspect(ac_agents_input_inspect) reportsnativeDraft.strandedDelivery: true, with a matching reason, while the mark stands.Not in this PR
Tests
promptDelivery.strandedReclaim.test.ts:sessionManager.strandedDelivery.test.ts, through the manager and the real Claude delivery code:write()in between voids the mark and the delivery is refused;inputInspectreportsstrandedDelivery: true;npx tsc -bis clean. The focused suites (Claude runtime, session-manager delivery, screen gate, control SDK, sessions) pass on770e6922(main merged): 48 files, 343 tests.🤖 Generated with Claude Code