scripts: update reproduction script with fix documentation

This commit is contained in:
Mayuresh Kadu
2026-06-20 09:35:11 +01:00
parent d781c302e2
commit 390a7d0a66
+64 -31
View File
@@ -10,10 +10,11 @@
* Detection chain in packages/web/server/lib/opencode/env-runtime.js: * Detection chain in packages/web/server/lib/opencode/env-runtime.js:
* Step 1: Check env vars (OPENCODE_BINARY, OPENCODE_PATH, etc.) * Step 1: Check env vars (OPENCODE_BINARY, OPENCODE_PATH, etc.)
* Step 2: searchPathFor('opencode') — walks process.env.PATH * Step 2: searchPathFor('opencode') — walks process.env.PATH
* Step 3: Hardcoded fallback paths (includes /opt/homebrew/bin/opencode, * Step 3a: Hardcoded fallback paths (includes /opt/homebrew/bin/opencode,
* /usr/local/bin/opencode, etc.) * /usr/local/bin/opencode, etc.)
* Step 3b: Fast-path: /bin/sh -c 'command -v opencode' (with timeout)
* Step 4: Shell probing — $SHELL -lic 'command -v opencode' * Step 4: Shell probing — $SHELL -lic 'command -v opencode'
* (⚠️ NO TIMEOUT on spawnSync) * (with timeout, fixed)
* *
* On macOS, apps launched from the Dock/Finder inherit a minimal PATH: * On macOS, apps launched from the Dock/Finder inherit a minimal PATH:
* /usr/bin:/bin:/usr/sbin:/sbin * /usr/bin:/bin:/usr/sbin:/sbin
@@ -24,9 +25,9 @@
* spawnSync($SHELL, ['-il', '-c', 'env -0'], { timeout: 5000 }) * spawnSync($SHELL, ['-il', '-c', 'env -0'], { timeout: 5000 })
* *
* If the shell startup is slow (>5s due to nvm, pyenv, etc.), this times * If the shell startup is slow (>5s due to nvm, pyenv, etc.), this times
* out and PATH stays minimal. The server-side probing (in index.js:652) * out and PATH stays minimal. The fast-path (Step 3b) catches standard brew
* also calls spawnSync but with NO timeout at all — potentially hanging * paths even with minimal PATH, and all shell probes now have a 5s timeout
* the module initialization indefinitely. * to prevent blocking startup indefinitely.
*/ */
import fs from 'node:fs'; import fs from 'node:fs';
@@ -208,6 +209,30 @@ async function main() {
if (ok) foundInFallbacks = true; if (ok) foundInFallbacks = true;
} }
// 3c-fp. Fast-path (command -v via /bin/sh)
console.log('\n 🔹 Step 3c-fp: Fast-path (command -v via /bin/sh)');
let fastPathFound = false;
try {
const fastResult = spawnSync('/bin/sh', ['-c', 'command -v opencode'], {
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'pipe'],
timeout: 5000,
});
if (fastResult.status === 0) {
const found = (fastResult.stdout || '').trim().split(/\s+/).pop() || '';
if (found && isExecutable(found)) {
console.log(` ✓ Found: ${found}`);
fastPathFound = true;
} else {
console.log(` ✗ Not found (${found || 'empty'})`);
}
} else {
console.log(` ✗ Status ${fastResult.status} (${fastResult.error?.message || ''})`);
}
} catch (err) {
console.log(` ⚠ Exception: ${err.message}`);
}
// 3d. Shell probing (last resort) // 3d. Shell probing (last resort)
console.log('\n 🔹 Step 3d: Shell probing (last resort)'); console.log('\n 🔹 Step 3d: Shell probing (last resort)');
const shellCandidates = [ const shellCandidates = [
@@ -255,7 +280,7 @@ async function main() {
section('Root Cause Analysis'); section('Root Cause Analysis');
const found = pathResult || foundInFallbacks || shellFound || (whichPath && isExecutable(whichPath)); const found = pathResult || foundInFallbacks || fastPathFound || shellFound || (whichPath && isExecutable(whichPath));
if (found) { if (found) {
console.log(` console.log(`
@@ -263,28 +288,36 @@ async function main() {
this system. However, this does not rule out the bug on all this system. However, this does not rule out the bug on all
macOS configurations. macOS configurations.
⚠️ POTENTIAL ISSUES (macOS-specific): 🔧 FIXES APPLIED (issue #1720):
1. SHELL PROBING HAS NO TIMEOUT (env-runtime.js:366): 1. ✅ SHELL PROBING TIMEOUT (env-runtime.js):
The shell probing step at line 366 calls spawnSync without All 4 shell probe spawnSync calls now have a 5-second
a timeout. If the user's shell startup is slow (>5s due to timeout. Prevents indefinite blocking on slow shells.
nvm, pyenv, etc.), this blocks indefinitely.
2. ELECTRON PROBE HAS 5s TIMEOUT (main.mjs:1023): 2. ✅ FAST-PATH PROBE (env-runtime.js):
The Electron main process probes the shell with a 5-second Added /bin/sh -c 'command -v opencode' before the full
timeout. If the shell takes >5s, PATH is NOT augmented. login shell probe. Catches brew binaries at ~10ms instead
of potentially seconds. (Standard brew paths are also
covered by hardcoded fallbacks.)
3. SERVER-SIDE SHELL PROBE HAS NO TIMEOUT (env-runtime.js:205): 3. ✅ TOOLCHAIN_SEGMENTS (path-utils.js):
The server's getLoginShellEnvSnapshot() also has no timeout, Added '/usr/local/' to TOOLCHAIN_SEGMENTS so a PATH
potentially blocking module initialization at index.js:652. containing /usr/local/bin is recognized as user-configured.
4. FILE-SYSTEM PERMISSION ISSUE: 4. ✅ VS CODE FALLBACK ORDER (opencode.ts):
On macOS with Full Disk Protection, the Electron sandbox Brew fallback order now matches server: /opt/homebrew
may restrict access to files outside the app container. (Apple Silicon) before /usr/local (Intel).
5. BREW INSTALLATION PATH NOT COVERED: ⚠️ REMAINING ISSUES (not addressed by this fix):
If brew is installed at a custom prefix (not /opt/homebrew
or /usr/local), the hardcoded fallbacks won't match. 1. FILE-SYSTEM PERMISSION ISSUE:
On macOS with Full Disk Protection, the Electron sandbox
may restrict access to files outside the app container.
2. CUSTOM BREW PREFIX:
If brew is installed at a custom prefix (not /opt/homebrew
or /usr/local), the hardcoded fallbacks won't match — but
the fast-path (command -v via sh) may still find it.
`); `);
} else { } else {
console.log(` console.log(`
@@ -308,14 +341,14 @@ async function main() {
console.log(` console.log(`
────────────────────────────────────────────────────────── ──────────────────────────────────────────────────────────
Recommended fixes: Fixes applied:
1. Add a timeout to ALL spawnSync calls in the detection chain 1. ✅ All 4 shell probe spawnSync calls now have a 5s timeout
(especially env-runtime.js lines 205, 366) (SHELL_PROBE_TIMEOUT_MS, added at env-runtime.js module level)
2. Consider using 'which opencode' or 'command -v opencode' 2. ✅ Fast-path via /bin/sh -c 'command -v opencode' added
as a standalone fallback with a short timeout before login shell probing in all 3 resolvers
3. The existing hardcoded paths DO cover standard brew paths, 3. ✅ /usr/local/ added to TOOLCHAIN_SEGMENTS in path-utils.js
so if the binary is at /opt/homebrew/bin/opencode or 4. ✅ Brew fallback order fixed in VS Code extension
/usr/local/bin/opencode, detection should work (/opt/homebrew before /usr/local)
`); `);
} }