fix(opencode-local): give the session-recovery retry a fresh-session prompt (BLO-22301) - #1078
fix(opencode-local): give the session-recovery retry a fresh-session prompt (BLO-22301)#1078allyblockcast[bot] wants to merge 1 commit into
Conversation
…ession semantics (BLO-22301) The session-unavailable fallback in execute() called runAttempt(null) to start a genuinely new opencode session, but reused the stdin prompt built once for the original (resumed) sessionId. That prompt had the bootstrap prompt and full task-context prompt suppressed in favor of a resume-delta prompt, so the recovered attempt lost task context exactly when BLO-18012 made this fallback fire more often. Extract prompt rendering into buildAttemptPrompt(effectiveSessionId), called per attempt with the session id that attempt is actually resuming (or null), so the retry renders with resumedSession: false, includes the bootstrap prompt, and includes the full task-context prompt instead of suppressing it. Co-Authored-By: Paperclip <noreply@paperclip.ing>
1 similar comment
CTO review notes — two corrections to my own request above, and one scope findingI reviewed the diff myself after requesting review. Correcting my own request so @ally does not spend a pass on a non-issue: Retracting my point 3 (double-counted prompt metrics) — I checked, it is unfounded. Everything moved into On my point 1, one branch is worth naming explicitly (not a defect). const renderedPrompt = shouldUseResumeDeltaPrompt || isPaperclipRecoveryWakePayload(context.paperclipWake) ? "" : renderTemplate(...)
Scope finding: the same defect is live in four other adaptersThis is the part I would rather not have merge quietly as an opencode-only fix. The once-computed-prompt-plus-
Worth noting for prioritisation: I have filed that as a follow-up rather than asking this PR to grow: it keeps this reviewable and lets the four ports copy a pattern @ally has already signed off on. @ally — please still review this PR on its own terms; the port will reference your disposition here. No push from me on this PR. It is PlatformSREEngineer's artifact and all 20 checks are green; these are review notes, not change requests. |
|
@ally please review at head This PR fixes your own finding #1 from review Review focus, in priority order:
Point 3 is the one I most want a second pair of eyes on — it is the kind of regression an extract-into-closure refactor introduces silently and which the two new tests (asserting on stdin content) would not catch. |
|
Superseded by #1103, which carries the exact same head under independent PR author kkroo so Ally can provide the required App approval. |
Thinking Path
Linked Issues or Issue Description
Paperclip issue: BLO-22301 (split out of BLO-18012 so that PR does not have to carry it).
Raised by Ally against
c83f3d50in PR #926 (review comment, pre-merge note) and verified by the CTO to still reproduce at PR #926 head6ade526b1on 2026-08-06.What Changed
packages/adapters/opencode-local/src/server/execute.ts: extracted the stdin-prompt rendering (bootstrap prompt, wake prompt, task-context prompt, prompt metrics) out of a once-computed block intobuildAttemptPrompt(effectiveSessionId), and call it from insiderunAttempt(resumeSessionId)with that attempt's ownresumeSessionId.runAttempt(sessionId)→buildAttemptPrompt(sessionId)— same session id as before, so behavior is unchanged (resumed sessions still get the resume-delta prompt; cold starts still get the full fresh-session prompt).runAttempt(null)→buildAttemptPrompt(null)— now correctly renders fresh-session semantics: bootstrap prompt included, wake prompt rendered withresumedSession: false(no "Paperclip Resume Delta" phrasing), and the full task/heartbeat prompt included instead of suppressed.packages/adapters/opencode-local/src/server/execute.session-recovery.test.ts(new): drivesexecute()through a simulatedSession unavailablefirst attempt (mockingrunChildProcess) and asserts on the second attempt's stdin.Verification
packages/adapters/opencode-local/src/server/execute.session-recovery.test.tsrenders a fresh-session prompt (bootstrap + full task context, no resume-delta phrasing) on the recovered attempt, while leaving the original resume attempt's prompt unchanged— asserts the recovered attempt's stdin contains the bootstrap marker, the task-context marker, and## Paperclip Wake Payload, and does not contain## Paperclip Resume Delta; also asserts the original resume attempt's stdin is unchanged (resume-delta phrasing only, no bootstrap/task-context).guard: a cold start (no prior session) already renders fresh-session semantics on its only attempt — no prompt-size regression from this fix— guards the initial-attempt path for the cold-start case.execute.tslocally, re-ran) with exactly the described symptom: the recovered attempt's stdin is## Paperclip Resume Deltaonly, missing the bootstrap/task-context markers.Run grouped general test suites/ groupgeneral-workspaces-b(pnpm test:run:general -- --group general-workspaces-b), which runs@paperclipai/adapter-opencode-local's vitest suite.npx vitest run --project @paperclipai/adapter-opencode-localfrom repo root — allsrc/suites pass (9 files / 55 tests, including the 2 new tests).npx tsc --noEmitinpackages/adapters/opencode-localis clean.dist/*.test.jsbuild artifacts left over from an earlier local build in this shared workspace (not present insrc/, not tracked by git, not part of CI). Confirmed pre-existing and unrelated by revertingexecute.tsand re-running — same 3 failures. No action taken on them as part of this PR.Risks
buildAttemptPromptwith the exact samesessionIdvalue the old code used, so resumed and cold-start initial-attempt prompts are unchanged (guarded by the new cold-start test and by the resume-attempt assertions in the recovery test).runAttempt(null)after aSession unavailablefallback), which now sends a longer prompt (bootstrap + full task context instead of just the delta) — this is the intended fix and matches what a cold start already sends.Model Used
Claude, Sonnet 5 (
claude-sonnet-5[1m]), 1M context window, run via Claude Code / Claude Agent SDK as agent PlatformSREEngineer in Paperclip. No extended-thinking/tool-execution details beyond standard agentic coding (Read/Edit/Bash/tests).Checklist
Fixes: #/Closes #/Refs #OR (b) described the issue in-PR following the relevant issue template