Repository navigation
fix(opencode): submit admitted native startup briefs without overwriting input - #24762
Conversation
Reuse captured composer readiness on local and paired execution hosts and revoke launching-shell paste anchors. Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
9356b67 to
42788e7
Compare
24ef5e8 to
6012c37
Compare
There was a problem hiding this comment.
Important
Two issues worth addressing before merge: the strip of --prompt is irreversible while delivery can still fail, so a slow start or one transient loopback error loses the startup brief that this PR exists to submit; and a Windows permission-recovery path is dropped for the legacy shared plugin write.
Reviewed changes
- Native startup-prompt intent —
shared/tui-agent-startup.tsandshared/opencode-startup-prompt.tsadd theORCA_OPENCODE_STARTUP_PROMPT_{SHA256,BODY,SHELL}env, andhappy/main/opencode/opencode-pty-launch.tsgates on a 2.0.16prefillprobe, strips the trailing--prompt <body>, and reserves a one-use claim. - Claim authorization — new
opencode-startup-prompt-claims.tspluscommitPtyWithOpenCodePromptIntent/bindOpenCodeStartupPromptOwner;TerminalRunFactsRegister.reserveSpawnCommitcaptures pre-commit driving input, andOrcaRuntimeWithRuntimeId.readOpenCodeStartupPromptOwnersupplies owner facts. - TUI plugin — generated
opencode-startup-prompt-source.tspolls the composer, claims over loopback, inserts the exact draft, and dispatchesprompt.submit;opencode-startup-prompt-installer.tsinstalls it in an owned overlay independent of status plugins. - Hook server lifecycle — the loopback listener now starts even with status hooks disabled,
setStatusHooksEnabledtoggles the status owner/binder/retries/polls, and/opencode/startup-prompt/claimis served on the existing authenticated listener. - Plugin install + atomic write — new
opencode-plugin-atomic-write.tsand extractedwindows-retry-file-operations.ts; overlay vs canonical symlink/mode handling; relay/WSL prompt-install plumbing.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
Preserve complete original 27-path contribution and current main credential fields. Private preparation only. Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Preserve complete original 14-path contribution and current main preparation. Keep native startup intent in its later topic. Private preparation only.
Preserve complete original 48-path contribution, atomic plugin permissions and current main cleanup. Keep run positional transport in its separate follow-up. Private preparation only.
Preserve complete original 27-path contribution and current main credential fields. Private preparation only. Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Restack on selected main a40, retain its jcode launch configuration and record the unchanged jcode fallback lane in the exhaustive test.
Preserve complete original 14-path contribution and current main preparation. Keep native startup intent in its later topic. Private preparation only. Restack on selected main a40, retain its jcode launch configuration and record the unchanged jcode fallback lane in the exhaustive test.
Preserve complete original 48-path contribution, atomic plugin permissions and current main cleanup. Keep run positional transport in its separate follow-up. Private preparation only. Restack on selected main a40, retain its jcode launch configuration and record the unchanged jcode fallback lane in the exhaustive test.
|
Installed OpenCode 2.0.16, genuine nested-launch before/after evidence. Both screenshots come from hidden, unfocused Orca renderers with a private loopback provider. Before ( After ( All 39 before and 48 after recorded processes exited and six ports closed in each run. The published stack ending at |
There was a problem hiding this comment.
Important
The restacked head no longer passes tc:node: opencode-pty-launch.ts calls isOpenCodeRunCommand with an argument the helper does not accept (inline). The source-provenance fix itself reads correctly and its focused tests pass.
Reviewed changes
- Real source provenance —
installOpenCodeStartupPromptForLaunchresolves the user's config throughresolveOpenCodeSourceConfigDirand recordsORCA_OPENCODE_SOURCE_CONFIG_DIR, so the second phase no longer treats the first prompt overlay as the user's source. - Compose into the existing status overlay — when
OPENCODE_CONFIG_DIRalready equalsORCA_OPENCODE_CONFIG_DIR, the newOpenCodeHookService.installIntoSourceOverlayverifies the directory is the expectedsource:overlay, refuses a symlinked/replaced overlay, and writes the prompt plugin beside the status plugin instead of building a second overlay. - Retain provenance through the provider deletion pass —
prepareOpenCodePtyLaunchremovesOPENCODE_CONFIG_DIR/ORCA_OPENCODE_CONFIG_DIR/ORCA_OPENCODE_SOURCE_CONFIG_DIRfromenvToDeleteafter a successful install. - Tests — added replaced-overlay refusal and opencode/opencode2 single-overlay composition cases, a source-proof deletion-pass test, and a lost-response wait in the source suite.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
- Extracted the OpenCode plugin-config writer —
hook-service.tsnow delegateswritePluginIntoOverlay/writePluginToConfigDirto the newopencode-plugin-config-writer.ts(writeOpenCodePluginConfig). The extraction is behavior-preserving: thetuiOnlyDirectoryearly return, theinstallsTuiPluginguard, the current-check selection, and the ownership-specific atomic write all match the two inline bodies it replaces. - Rewrote run-command detection —
opencode-headless-command.tsgains an optionalshellparameter and afindOpenCodeRunCommandthat resolves the executable position behind POSIX env assignments andenvprefixes (including-u/--unset/-C/--chdir/-P/-i/--), plus the PowerShell&call operator. This also fixes a latent miss where env-prefixedopencode runwas not recognized as a run command. Theshellparameter is optional, so the existing one-argument caller inopencode-startup-prompt.ts:24is unaffected. - Added focused tests —
opencode-headless-command.test.ts(29 cases) covers env-option argument position, the PowerShell call operator, and negative cases; they fail under the old implementation. - Resolved the prior
tc:nodefailure —isOpenCodeRunCommand(parsed.tokens, shell)atopencode-pty-launch.ts:94now typechecks against the two-argument helper. Verified locally:pnpm tc:nodepasses and the focused suite is 29/29.
All prior Pullfrog review threads (5393676719, 5401852342, 5402240688) are resolved and unchanged by this delta.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
This run re-reviews the single commit pushed since the prior pullfrog review at b43c77d7f. The delta is confined to the generated native startup-prompt TUI plugin and its test.
- Wait for authoritative location hydration before claiming or submitting — the generated plugin in
opencode-startup-prompt-source.tsnow callsctx.data.location.sync(ctx.location)once at setup and only setslocationReadywhen that promise resolves; the claim/insert/prompt.submitpath returns early until it does. That keeps OpenCode from selecting its first-catalog-entry(unavailable)model fallback while configuration is still hydrating. A missingsyncmakes setup a noop and a rejectedsyncroutes through the existingsettle(), so both fail closed. - Coverage for the new gate —
opencode-startup-prompt-source.test.tsadds asyncfixture, an ordering test that asserts the dispatch observes the configured model (it fails under the pre-gate implementation), an eight-reason cancellation matrix for delayed hydration, and missing/rejected-syncfail-closed cases.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
This run re-reviews the single commit pushed since the prior pullfrog review at 85efe85e. The delta is confined to the generated native startup-prompt TUI plugin and its test.
- Bind readiness to the live location — the generated plugin in
opencode-startup-prompt-source.tsreplaces the one-shot setupctx.data.location.sync(ctx.location)/locationReadyflag with a livelocationKey(JSON.stringify([directory, workspaceID])). Each 100ms poll re-hydrates{ directory, workspaceID }whenever the key changes, setsreadyLocationonly when the sync resolves andctx.locationstill matches, and re-checks the key on the claim, insert andprompt.submitpaths. This keeps a home-location change after setup (startup directory → home directory) from submitting with the wrong location's config, and refuses a grant that arrives after the location moved. - Coverage for the new gate —
opencode-startup-prompt-source.test.tsadds four tests: startup-directory → home-directory re-sync asserting the configured model at dispatch (fails under the old one-shot sync), waiting for a concrete location before any sync, workspace-ID-scoped readiness, and refusing a granted claim after the composer location changes.
The OpenCode contract this relies on is confirmed against v2.0.16: Location.Ref is { directory: string; workspaceID?: string }, data.location.sync(location?: LocationRef) accepts exactly that partial ref, and the TUI wrapper awaits syncInfo + location.sync + config.sync, so the gate does cover model/config hydration.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
Preserve OpenCode launch ownership and location-bound startup claims while inheriting current terminal observations and installer corrections.
Preserve OpenCode launch ownership and location-bound startup claims while inheriting current terminal observations and installer corrections.
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 3 remain after this review. 📝 WalkthroughWalkthroughThe change adds startup-prompt intent and delivery for OpenCode, including plugin installation, PTY launch preparation, runtime ownership checks, and claim handling. It also adds runtime status-hook controls and updates host and relay paths to install and report the startup-prompt plugin. Priority: ➖ Normal Merge Risk: ⚪ Minimal · up to No current merge-blocking issue is established for these changes; normal checks remain appropriate. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to Automatic startup submission is guarded by launch identity and checks that the terminal remains untouched. No authorization bypass was established. Incomplete baseline and downstream-permission coverage prevent a minimal-risk assessment. Retained concerns Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Repository UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
670299f6-be63-4bec-90fd-f4a0640701df
📒 Files selected for processing (52)
src/main/agent-hooks/server-startup-prompt-control.test.tssrc/main/agent-hooks/server/server-lifecycle.tssrc/main/agent-hooks/server/server-listeners.tssrc/main/agent-hooks/server/server-runtime-env.tssrc/main/agent-hooks/server/server-state.tssrc/main/agent-hooks/server/server-status-hook-lifecycle.tssrc/main/global-fetch-call-site-audit.test.tssrc/main/ipc/pty-controller-process-inventory.test.tssrc/main/ipc/pty-ipc-mock-registry.tssrc/main/ipc/pty/host-env/assembly.tssrc/main/ipc/pty/host-env/opencode-config.tssrc/main/ipc/pty/host-env/opencode-hook-installation.test.tssrc/main/ipc/pty/ipc/spawn-commit.tssrc/main/ipc/pty/ipc/spawn-options.tssrc/main/ipc/pty/runtime/spawn-commit.tssrc/main/ipc/pty/runtime/spawn-options.tssrc/main/opencode/hook-service.tssrc/main/opencode/opencode-overlay-manifest.tssrc/main/opencode/opencode-plugin-config-writer.tssrc/main/opencode/opencode-pty-launch.test.tssrc/main/opencode/opencode-pty-launch.tssrc/main/opencode/opencode-startup-prompt-claims.test.tssrc/main/opencode/opencode-startup-prompt-claims.tssrc/main/opencode/opencode-startup-prompt-installer.test.tssrc/main/opencode/opencode-startup-prompt-installer.tssrc/main/opencode/opencode-startup-prompt-owner.test.tssrc/main/opencode/opencode-startup-prompt-owner.tssrc/main/opencode/opencode-startup-prompt-runtime-identity.test.tssrc/main/opencode/opencode-startup-prompt-source.test.tssrc/main/opencode/opencode-startup-prompt-source.tssrc/main/orcad/orcad-entry.tssrc/main/orcad/orcad-push-startup.test.tssrc/main/providers/provider-dispatch.test.tssrc/main/runtime/orca-runtime-resolve-authoritative-terminal-wait-permission.tssrc/main/runtime/terminal-run-facts.test.tssrc/main/runtime/terminal-run-facts.tssrc/main/startup/headless-pty-hydration-ordering.test.tssrc/main/startup/main-process-pty-startup.tssrc/main/startup/main-process-ready-foundation.tssrc/relay/opencode-overlay-mirror.tssrc/relay/opencode-startup-prompt-install.test.tssrc/relay/plugin-overlay.tssrc/relay/pty-handler.tssrc/relay/relay-agent-hook-runtime.tssrc/relay/wsl-install-plugins-handler.tssrc/shared/opencode-headless-command.test.tssrc/shared/opencode-headless-command.tssrc/shared/opencode-startup-prompt-install.tssrc/shared/opencode-startup-prompt.test.tssrc/shared/opencode-startup-prompt.tssrc/shared/opencode-tui-plugin-install.tssrc/shared/tui-agent-startup.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 4 remain after this review.
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
This run re-reviews the single commit pushed since the prior pullfrog review at 1dc953cf (the 1f27c138 merge was already covered). The delta is confined to the claim handler's error path and its test.
- Retryable classification for an interrupted claim — in
server-lifecycle.ts, a claim request whose authenticated body is truncated by transport loss (isHookRequestTruncatedError) and was not ended by Orca's own slowloris cap now answers503instead of200 {"allowed":false}. Because the throw happens while reading the body,onStartupPromptClaimis never invoked, so the claim is not consumed; the generated plugin maps>=500to"pending"and retries with the samerequestId. Malformed JSON, oversized payloads, and slowloris-capped requests keep the200denial. - Coverage for the new branch —
server-transport-interference.test.tsparameterizespostStalledHookwith a pathname, then asserts the truncated claim produces[[503]]with the claim listener uncalled and no interference report, while the slowloris-capped claim still produces the200denial. The truncated case fails against the pre-change handler, which wrote200.
All prior Pullfrog review threads are resolved and unchanged by this delta. The change directly answers CodeRabbit review 5404664153, which marked the thread addressed.
Verified locally: focused suite server-transport-interference.test.ts 6/6 passes and pnpm tc:node passes.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏



ELI5
A startup brief could disappear after an interrupted authorization exchange, or lose status reporting under a separate configuration directory. A fresh terminal now keeps its real status plugin and receives an authorized brief once. Interrupted claim bodies receive a retryable response.
What Changed
Bind startup authorization to the terminal incarnation, launch token and absence of user input. A stable request ID retries transient delivery and can replay the same valid grant. Preserve selected XDG and OpenCode configuration directories through sparse launch overlays. Later launches reuse the original user configuration and add the prompt plugin to the verified status overlay. Flush pending terminal-status writes at shutdown while retaining atomic writes and permission recovery.
The claim handler now attempts
503when the authenticated body is truncated by transport loss. Malformed JSON and requests stopped by Orca's own slowloris limit retain200 {allowed:false}. The existing plugin already retries503with the same request ID.Why
Execution-owner facts protect user input and reattachments. Retrying a bounded grant handles interrupted delivery without a second insertion. Reusing the original configuration, existing overlay and dirty-write timer preserves status and avoids another store.
Linked Issue
Part of #22829. The host-capability prerequisite #24662 is merged; this PR targets main.
Visual Proof
Installed-CLI lost-response before/after evidence and the hidden fresh/nested completions are retained. Screenshots and actual evidence are pinned to their executed source.
Testing
Current
81354ff9passes 99 tests across five files, all three desktop typechecks, full changed-file lint/format and the six changed-code gates. A real authenticated loopback reset reproduces the handler's attempted200before and503afterward without consuming a claim. The reset peer cannot receive that response; this control establishes classification, without an observed lost brief. Existing generated-plugin tests cover retryable responses, lost grants and stable request IDs. Malformed payload and self-imposed timeout denial controls pass.The parent
1f27c138includes merged #24662 and named main5a2aa87f, with three typechecks and 284 tests across 12 files. Earlierd9285ae0full-scope checks, build and 359 tests across 29 files remain pinned to that source; counts overlap.Installed OpenCode 2.0.16 reproduced lost startup authorization and incorrect inherited configuration. Earlier combined
7c765fderetained an additional native failure whose complete cause was not captured. Repaired combinedc8fdfdbethen completed fresh and nested Unicode turns, used one status/prompt overlay, claimed each brief once, preserved user configuration and reported canonical working → done. Its genuine worker selected the private CLI and completedworker_doneonce. All 319 recorded process incarnations and four private ports closed. Those runs are on main2b1acd0d; current-source validation is separate, without a current-commit app-runtime claim.Review
Current source
81354ff9ae4838b6bd9ce581ac08ded23eda0e31retains the complete cumulative contribution across 120 files. The direct correction preserves 118 prior owned contents, changes the claim handler and adds the existing transport test to the scope. Every other file matches qualified parent1f27c138. Independent reviews checked the complete source, raw checks and 24 closed qualification process observations. Named main throughffd23fe2has no further changed files in this scope; fresh public CI will test the combined merge. Contributor ancestry and the six previously reviewed overlap resolutions remain retained.Agent skill upstream boundary
Notes
Credit Ahmed Nagy's atomic-write and permission work and Adnan Khan (@akhan157)'s accepted manifest reader from #13287/#24763. Authorization has a 20-second reservation followed by one 20-second reset at admission after spawn commit. The plugin has its own deadline; the earlier deadline wins. A composer that becomes ready after expiration is outside that recovery window.
Checklist