Skip to content

fix(opencode): preflight a shell-free launch plan#3927

Merged
BunsDev merged 2 commits into
mainfrom
fix/opencode-preflight
Jul 26, 2026
Merged

fix(opencode): preflight a shell-free launch plan#3927
BunsDev merged 2 commits into
mainfrom
fix/opencode-preflight

Conversation

@BunsDev

@BunsDev BunsDev commented Jul 26, 2026

Copy link
Copy Markdown
Member

Summary

  • replace the merged PowerShell/npm OpenCode transport with a proven shell-free native target while preserving passive preflight
  • keep launch arguments option-only and write the exact multiline, Unicode-safe prompt to UTF-8 stdin, including prompts larger than 40 KiB
  • carry the exact command, fixed target files, environment, and resolution state through the shared availability contract used by chat and /api/harnesses
  • reject unresolved shims, inspection failures, missing commands, and missing required launch artifacts before chat, capability, or model probes can spawn
  • preserve verified-capability fallback, POSIX/WSL runtime behavior, and post-spawn auth/provider/model/no-output classifications

Context

PR #3907 established the initial OpenCode preflight on main. Its Windows matrix then proved that the PowerShell transport was lossy at its final native-process hop: PowerShell reserialized the complete argv when invoking OpenCode. Keeping the prompt in argv also exposed valid large or multiline input to platform command-line limits and quoting rules.

This follow-up reads a standard npm shim only to prove its target, calls Node spawn() on that native target with an option-only argv array, and sends the prompt through an observed UTF-8 stdin pipe. No prompt is evaluated as command syntax, no shell: true path is introduced, and an unproven launch plan fails closed.

Verification

Exact signed head: 09f51f3a86d1151b70b72f15b472b1fb76798a30

Built directly on origin/main at da2cf1046714c445a3bc8e8d4e06820ae5f660f0; final feature diff is 18 files.

  • pnpm test:app — 921/921 test files passed
  • pnpm test:api — 278/278 test files passed
  • pnpm test:conformance — 3/3 local files passed; 2 explicit Windows-host scenarios run in CI
  • pnpm typecheck
  • pnpm lint
  • pnpm check:tests-wired — 1,269/1,269 files (1 allowlisted)
  • focused OpenCode resolution/model, capability, runtime-availability, harness-routing, and real-route preflight tests
  • git diff --check
  • exact-head Windows cross-environment job and CodeQL matrix passed

Credit

Builds on the OpenCode preflight contributed by @CompleteDotTech in #3907. The signed head and final squash preserve Timothy Wayne Gregg as a co-author.

Copilot AI review requested due to automatic review settings July 26, 2026 19:45
Comment thread src/app/api/chat/send/route-opencode-preflight.integration.test.ts Fixed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR formalizes OpenCode’s two-stage launch plan (PowerShell host + inner opencode resolution on Windows) into the shared runtime-availability contract, then reuses that canonical probe across the chat route’s early plan, immediate pre-spawn recheck, and /api/harnesses availability reporting—while preserving stdin JSON argv transport and existing post-launch error classification.

Changes:

  • Add openCodeAvailabilityProbe() to encode the exact launch plan + spawn env into a RuntimeAvailabilityProbe without consulting user prompt contents.
  • Reuse the canonical probe in /api/harnesses and /api/chat/send for both the early “plan” gate and the just-before-spawn recheck.
  • Add unit + route-level integration coverage to prove metacharacter prompts remain data and started-CLI failures keep their existing classification.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/lib/opencode-bin.ts Adds openCodeAvailabilityProbe() to map OpenCode’s launch plan/env into the shared availability model.
src/lib/opencode-bin.test.ts Adds focused unit coverage for missing/ready/unlaunchable/probe_failed classification and prompt-independence.
src/app/api/harnesses/route.ts Switches OpenCode availability to the canonical probe so /api/harnesses matches the real launch plan/env.
src/app/api/chat/send/route.ts Uses the canonical probe for early planning and the immediate pre-spawn recheck (preventing drift).
src/app/api/chat/send/route-opencode-preflight.integration.test.ts New integration test exercising the real route: metacharacter prompt remains data; started CLI failure stays post-launch classified/persisted.
src/app/api/chat/send/harness-routing-opencode.test.ts Updates route-shape assertions to pin canonical-probe usage and the pre-spawn recheck behavior.
scripts/run-tests.mjs Wires the new integration test into the API suite and alias-loader set.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@BunsDev
BunsDev force-pushed the fix/opencode-preflight branch 2 times, most recently from d78c65a to 69e93f2 Compare July 26, 2026 20:24
@BunsDev
BunsDev requested a review from Copilot July 26, 2026 20:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@BunsDev
BunsDev force-pushed the fix/opencode-preflight branch from 69e93f2 to 38f197f Compare July 26, 2026 20:58
@BunsDev BunsDev changed the title fix(opencode): preflight the two-stage launch plan fix(opencode): preflight a shell-free launch plan Jul 26, 2026
@BunsDev
BunsDev requested a review from Copilot July 26, 2026 20:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

src/lib/coven-bin.ts:449

  • windowsShimTargetFromFile() currently swallows all read/exists errors and returns null, which means permission/IO failures (e.g. EACCES when reading a PATH-winning .cmd shim) get misclassified as unresolvedWindowsShim instead of resolutionFailedruntime_probe_failed. That loses the intended “could not verify” remediation and incorrectly tells users to reinstall. Consider rethrowing non-missing errors from the shim parser so OpenCode’s resolver can fail closed with resolutionFailed and the shared availability contract can surface the probe_failed copy.
export function windowsShimLaunchCommandForBinary(
  binary: string,
  platform: NodeJS.Platform = process.platform,
): CovenLaunchCommand {
  if (platform !== "win32" || !/\.(cmd|bat)$/i.test(binary)) {

@BunsDev
BunsDev force-pushed the fix/opencode-preflight branch from c4ab3a1 to d4fd287 Compare July 26, 2026 22:49
Co-authored-by: Timothy Wayne Gregg <5861166+CompleteDotTech@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/app/api/chat/send/chat-send-capabilities.ts:621

  • openCodeRunSupportsModel() checks isOpenCodeLaunchSpawnable() but doesn’t gate on launch.requiredFiles. On Windows, a resolved node <script> launch can be “spawnable” yet still broken if the fixed script target has been removed/unreadable, and this code would still spawn (potentially returning false due to an unrelated failure rather than lack of --model support). Consider preflighting with evaluateRuntimeAvailability(openCodeAvailabilityProbe(launch, env)) and returning false when it is not ready, to keep capability probes passive/fail-closed when the launch plan is incomplete.
export function openCodeRunSupportsModel(): Promise<boolean> {
  const env = openCodeSpawnEnv();
  const launch = openCodeLaunch(["run", "--help"], process.platform, env);
  if (!isOpenCodeLaunchSpawnable(launch)) return Promise.resolve(false);
  return (openCodeModelFlagProbe ??= probeHelp(
    launch.command,
    launch.args,
    (help) => /(^|\s)--model(?![\w-])/m.test(help),
    env,
  ));

Comment thread src/lib/server/opencode-models.ts
Comment thread src/app/api/chat/send/chat-send-capabilities.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 1 comment.

Comment thread src/lib/runtime-availability.ts
@BunsDev
BunsDev merged commit 4c6ab2b into main Jul 26, 2026
16 checks passed
@BunsDev
BunsDev deleted the fix/opencode-preflight branch July 26, 2026 23:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants