Skip to content

fix(spawn): spawn the detected absolute CLI path, not the bare name (#104)#105

Merged
chorus-codes merged 1 commit into
mainfrom
fix/spawn-detected-abs-path
Jun 1, 2026
Merged

fix(spawn): spawn the detected absolute CLI path, not the bare name (#104)#105
chorus-codes merged 1 commit into
mainfrom
fix/spawn-detected-abs-path

Conversation

@chorus-codes
Copy link
Copy Markdown
Owner

Closes #104.

Problem

Detection (cli-detect.ts:detectAllClis) resolves a concrete absolute path per CLI (PATH lookup → fallback-dir scan → manual override) and verifies it runs. But the daemon spawned reviewers by bare name (command: 'kimi'), re-resolving against the merged spawn PATH. The two resolutions could diverge:

Fix

  • resolveCliBinaryPath(command) (new export, cli-detect.ts): bare known-CLI name → detection's verified absolute path. Passthrough when the command already has a path separator, isn't a known CLI binary name (e.g. the script PTY wrapper), or detection currently can't find it → preserving the existing Unix-PATH / Windows-where fallback. Reads cached detectAllClis (30s TTL).
  • headless.ts:resolveBinaryPath calls it first — covers the 6 direct bare-name spawns (claude/codex/gemini/kimi-cli/grok/agy) and Windows opencode. A resolved absolute path short-circuits the Windows where lookup; bare names (detection-not-found) still flow through where unchanged.
  • opencode.ts + kimi.ts resolve opencode before wrapWithPty() — the PTY wrapper embeds the binary in argv (script -qfec '<bin> …'), so the spawn core only ever sees script and can't resolve it.

No behaviour change when detection has no path — the bare name flows to the unchanged PATH/where resolution.

Tests

  • tests/cli-detect-resolve.test.ts — resolver unit tests against real staged detection (prepended-PATH executables): bare→abs resolution, already-a-path / unknown-name / not-found passthrough, and a per-CLI mirror property.
  • tests/headless-spawn-windows.test.ts — new spawn integration tests for the abs-path case (Linux + Windows, asserting where is skipped) plus the detection-not-found fallback; existing tests reconciled with an identity stubCliDetect so their bare-name/where assertions remain under test.

Full suite: 1033 passing, 1 skipped. typecheck + lint clean.

Review

chorus self-review (review-only, 7 reviewers): approved, no changes requested.

🤖 Generated with Claude Code

…104)

Detection (cli-detect) resolves a concrete absolute path (PATH lookup →
fallback-dir scan → manual override), but headless spawns re-resolved by
bare name against the daemon PATH. The two could disagree:

  - ENOENT: a CLI found only via the fallback-dir scan (its dir not on the
    spawn PATH) couldn't be launched by bare name.
  - shadowing: two same-named binaries (e.g. ~/.kimi/bin/kimi vs
    ~/.kimi-code/bin/kimi) — bare-name spawn could run a different build
    than detection (and the #101 transport decision) resolved.

Add resolveCliBinaryPath(command): bare known CLI name → detection's
verified absolute path, else passthrough (already-a-path, unknown name,
or not-found → preserves the existing PATH/`where` fallback).

  - headless.ts:resolveBinaryPath calls it first — covers the 6 direct
    shims (claude/codex/gemini/kimi-cli/grok/agy) and Windows opencode.
  - opencode.ts + kimi.ts resolve opencode before wrapWithPty — the PTY
    wrapper embeds the binary in argv, so the spawn core only sees
    `script` and can't resolve it (covers the POSIX PTY path).

No behaviour change when detection has no path: the bare name flows to
the unchanged Unix-PATH / Windows-`where` resolution.

Tests: resolver unit tests against real staged detection; headless spawn
integration tests for the abs-path case (Linux + Windows) plus the
detection-not-found fallback. Full suite 1033 passing.
@chorus-codes chorus-codes merged commit 4a21422 into main Jun 1, 2026
2 checks passed
@chorus-codes chorus-codes deleted the fix/spawn-detected-abs-path branch June 1, 2026 00:03
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.

Spawn the detected absolute CLI path instead of the bare binary name

1 participant