LearnNewsExamplesServices
Frontmatter
id14951
titleUse resolved Fleet executable for spawn and version probe
stateOpen
labels
bugai
assigneesneo-gpt
createdAt8:10 AM
updatedAt8:10 AM
githubUrlhttps://github.com/neomjs/neo/issues/14951
authorneo-gpt
commentsCount0
parentIssue13015
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]

Use resolved Fleet executable for spawn and version probe

neo-gpt
neo-gpt commented on 8:10 AM

Context

PR #14918 closes the default Codex/Claude sibling-launch rail at exact head f6cc606dc848d819d5f82bc3a1e744447719eb05. Its executable preflight now returns the absolute executable candidate that passed X_OK + file checks, but FleetLifecycleService.start() treats that return value as Boolean evidence and later invokes the original command token.

A terminal-review isolation probe exposed one bounded non-default mismatch: with child cwd=<tmp>, PATH=bin, and executable <tmp>/bin/h, preflight returned the absolute candidate and the supervised child stayed alive, but the best-effort --version probe executed bare h without the child cwd, failed ENOENT, and left binaryVersion: null. Directly probing the returned absolute executable produced relpath-v1.

This ticket transfers that proven residual to Euclid so PR #14918 can merge without another Mnemosyne author cycle.

The Problem

At FleetLifecycleService.mjs on PR #14918's exact head:

  • start() calls resolveExecutable(command, env.PATH, opts.cwd) only as a truthiness check and discards the returned absolute path.
  • the supervised spawn receives the original command;
  • the asynchronous execFile(command, ['--version'], {env}) probe also receives the original command and no cwd.

Those three operations therefore do not share one executable identity. The mismatch is observable for a bare command discovered through a relative child-PATH entry: launch works under the child cwd on the verified host, while version observability silently degrades to null. More generally, discovery can verify one path while later process calls re-resolve another token.

Empirical evidence (2026-07-10T06:09:49.845Z):

  • production resolver: resolveExecutable('h', 'bin', childCwd) -> <childCwd>/bin/h;
  • production service spawn: still running: true after 400 ms; clean SIGTERM stop;
  • current production version probe: binaryVersion: null;
  • direct execFile(<resolved absolute>, ['--version'], {env}): relpath-v1.

The Architectural Reality

  • Owning substrate: ai/services/fleet/FleetLifecycleService.mjs; the Agent OS structure map places the existing Fleet process supervisor and its executable discovery in ai/services/fleet/.
  • resolveExecutable() already owns platform/path/cwd resolution and returns String|null; no new resolver or config surface is needed.
  • start() owns both process calls: the supervised spawn and best-effort execFile --version.
  • Canonical tests remain in test/playwright/unit/ai/FleetLifecycleService.spec.mjs, beside the existing real-process preflight/liveness regressions.
  • The default family configuration remains unaffected: Codex is configured with an absolute binary; the current ambient PATH contains no relative or empty entries.

The Fix

Capture the non-null return from resolveExecutable() as the canonical resolved command and use that exact absolute candidate for both:

  1. the supervised spawn;
  2. the best-effort execFile(..., ['--version']) probe.

Keep the original configured token only for diagnostic/error prose. Add a real-process regression with child cwd, relative PATH=bin, and one executable fixture that supports both a long-lived normal mode and --version. Prove the child remains supervised and binaryVersion converges to the fixture version. Add an invocation-identity assertion showing spawn and version probe receive the same resolved absolute command.

Contract Ledger

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
executable selected by start() FleetLifecycleService.resolveExecutable() non-null resolved absolute candidate becomes the command for every child-process call unresolved => existing synchronous named failure before secrets service JSDoc focused real-process + invocation-identity specs
status(id).binaryVersion FleetLifecycleService.status() + version probe relative child-PATH launch reports the actual resolved executable's version probe failure remains non-fatal => null existing status JSDoc relative-PATH fixture returns relpath-v1
configured launch token AiConfig Fleet binary leaf / Brain-only override retained for configuration and error diagnostics; not independently re-resolved after preflight existing behavior for unresolved tokens existing launch JSDoc absolute and normal bare-PATH regression coverage

Decision Record impact

none — bounded correctness hardening inside the existing Fleet lifecycle ownership; no accepted ADR is amended or challenged.

Acceptance Criteria

  • start() captures the non-null absolute result from resolveExecutable().
  • supervised spawn and --version probe receive that same resolved absolute command.
  • a real relative-child-PATH fixture stays alive under supervision and produces a non-null expected binaryVersion.
  • unresolved/non-executable candidates still fail synchronously before credential resolution, token minting, spawn, or process-record publication.
  • existing absolute configured binaries and normal absolute-PATH bare commands retain their current behavior.
  • focused Fleet lifecycle specs pass with --workers=1; node --check and git diff --check pass.

Out of Scope

Per-home login automation; authenticated two-instance boot validation; new launch families; AiConfig changes; registry/wire changes; broader process-supervisor extraction; changing the non-fatal nature of version-probe failure.

Avoided Traps

  • Do not add a second path resolver around execFile; the existing resolver must be the single executable identity.
  • Do not reopen PR #14918's default launch/security contract for this non-default edge.
  • Do not inherit ambient parent secrets or add cwd only to the version probe while continuing to discard the verified candidate.

Related

Parent: #13015
Source rail: #14914 / PR #14918

Live latest-open sweep: checked latest 20 open issues at 2026-07-10T06:09:49.845Z; no equivalent found. Exact all-state GitHub search returned no matches. A2A in-flight claim sweep: latest 30 all-state messages checked; no overlapping lane claim/intent. Semantic ticket sweep found only the already-resolved restart-cwd issue #13344, which is distinct.

Origin Session ID: e9002a91-2695-492b-93ef-d6c34700ef72

Retrieval Hint: query_raw_memories("FleetLifecycleService relative PATH binaryVersion resolved executable PR 14918")
Retrieval Hint: exact source head f6cc606dc848d819d5f82bc3a1e744447719eb05