Summary
When an agent's --version probe fails (non-zero exit, crash, or unparseable output), qtx ls / qtx inspect / qtx doctor report the version as unknown even though the provider observation conclusively knows the installed package version. The v1 inspection projection reads only the raw PATH-executable probe result and never falls back to the provider-reported version, even though the observation layer already computes that fallback in a merged field.
Environment
Reproduction
-
bun add -g @earendil-works/pi-coding-agent on a machine where the binary's --version crashes (any runtime incompatibility will do).
-
qtx ls:
Pi yes unknown bun managed —
-
qtx inspect pi omits the Version: row entirely.
-
qtx doctor shows Pi unknown managed and reports "No issues found".
-
bun pm -g ls reports @earendil-works/pi-coding-agent@0.85.1, and the lifecycle receipt in ~/.quantex/state.json even recorded "version": "0.85.1" at install time — the version is knowable, the display layer just does not use it.
Root cause
-
projectObservationToV1Inspection reads result.pathExecutable and sets installedVersion: executable.present ? executable.version : undefined (src/compatibility/agent-inspection.ts:8-15). pathExecutable is the raw where + <binary> --version observation (src/core/lifecycle/agent-observation.ts:79), so a crashing/failing version probe yields undefined.
-
The observation layer already computes a merged executable with a provider-version fallback — mergeExecutableObservation returns version: executable.version ?? providerObservation.version (src/core/lifecycle/agent-observation.ts:420-430) — and the bun provider probe does report the exact installed version (parseBunVersion over bun pm -g ls). This merged value is exposed as CoreAgentObservation.executable, but the v1 projection ignores it in favor of the raw pathExecutable.
-
Verified live on the affected machine by running the production read stack (createProductionCoreReadPorts({ providerRegistry: firstPartyProviderRegistry }).inspectAgent('pi', ...)):
pathExecutable: {"path":"C:\\Users\\drs\\.bun\\bin\\pi.exe","present":true} ← no version → "unknown"
executable (merged): {"path":"...\\pi.exe","present":true,"version":"0.85.1"} ← has the version
providerOutcome: {"kind":"success","value":{"kind":"present","version":"0.85.1"}}
-
Agents with a healthy --version (e.g. claude, codex) mask this because their raw probe succeeds; only agents with a broken/nonstandard --version surface it.
Observed instability (secondary)
The displayed version flapped: qtx ls/qtx inspect showed 0.85.1 in two runs immediately after fresh installs, then settled into persistent unknown. Per the code above the raw probe cannot succeed (10/10 deterministic crash), so the intermittent 0.85.1 display was not produced by the documented path; we could not reproduce or fully explain it. One qtx ls invocation also hung indefinitely after a reinstall (qtx bun process alive with no child processes, no timeout configured on read-only probes; killed manually, not reproducible). Both anomalies may deserve a closer look, but the deterministic projection gap above stands on its own.
Suggested fix
In projectObservationToV1Inspection (src/compatibility/agent-inspection.ts), source installedVersion (and arguably binaryPath/inPath) from the merged result.executable instead of the raw result.pathExecutable, so the provider-reported version is used whenever the live --version probe fails — the merged field already exists for exactly this purpose. Regression test: an agent whose version probe exits non-zero while the package provider reports present + version should display the provider version, not unknown.
Summary
When an agent's
--versionprobe fails (non-zero exit, crash, or unparseable output),qtx ls/qtx inspect/qtx doctorreport the version asunknowneven though the provider observation conclusively knows the installed package version. The v1 inspection projection reads only the raw PATH-executable probe result and never falls back to the provider-reported version, even though the observation layer already computes that fallback in a merged field.Environment
@earendil-works/pi-coding-agent@0.85.1engines: { node: ">=22.19.0" }and its bundled undici destructuresmarkAsUncloneablefromnode:worker_threads, which bun 1.3.11 does not implement (added upstream in node:worker_threads: +48 Node.js tests passing — MessagePort, stdio, SHARE_ENV, exit codes, transfer semantics, postMessageToThread + inspector oven-sh/bun#31216, first shipped in bun 1.4.0). As a resultpi --versiondeterministically crashes at module load withTypeError: webidl.util.markAsUncloneable is not a function(exit 1) — verified 10/10 runs, including when spawned with qtx's exactrunReadOnlyCommandsemantics.Reproduction
bun add -g @earendil-works/pi-coding-agenton a machine where the binary's--versioncrashes (any runtime incompatibility will do).qtx ls:qtx inspect piomits theVersion:row entirely.qtx doctorshowsPi unknown managedand reports "No issues found".bun pm -g lsreports@earendil-works/pi-coding-agent@0.85.1, and the lifecycle receipt in~/.quantex/state.jsoneven recorded"version": "0.85.1"at install time — the version is knowable, the display layer just does not use it.Root cause
projectObservationToV1Inspectionreadsresult.pathExecutableand setsinstalledVersion: executable.present ? executable.version : undefined(src/compatibility/agent-inspection.ts:8-15).pathExecutableis the rawwhere+<binary> --versionobservation (src/core/lifecycle/agent-observation.ts:79), so a crashing/failing version probe yieldsundefined.The observation layer already computes a merged executable with a provider-version fallback —
mergeExecutableObservationreturnsversion: executable.version ?? providerObservation.version(src/core/lifecycle/agent-observation.ts:420-430) — and the bun provider probe does report the exact installed version (parseBunVersionoverbun pm -g ls). This merged value is exposed asCoreAgentObservation.executable, but the v1 projection ignores it in favor of the rawpathExecutable.Verified live on the affected machine by running the production read stack (
createProductionCoreReadPorts({ providerRegistry: firstPartyProviderRegistry }).inspectAgent('pi', ...)):Agents with a healthy
--version(e.g. claude, codex) mask this because their raw probe succeeds; only agents with a broken/nonstandard--versionsurface it.Observed instability (secondary)
The displayed version flapped:
qtx ls/qtx inspectshowed0.85.1in two runs immediately after fresh installs, then settled into persistentunknown. Per the code above the raw probe cannot succeed (10/10 deterministic crash), so the intermittent0.85.1display was not produced by the documented path; we could not reproduce or fully explain it. Oneqtx lsinvocation also hung indefinitely after a reinstall (qtx bun process alive with no child processes, no timeout configured on read-only probes; killed manually, not reproducible). Both anomalies may deserve a closer look, but the deterministic projection gap above stands on its own.Suggested fix
In
projectObservationToV1Inspection(src/compatibility/agent-inspection.ts), sourceinstalledVersion(and arguablybinaryPath/inPath) from the mergedresult.executableinstead of the rawresult.pathExecutable, so the provider-reported version is used whenever the live--versionprobe fails — the merged field already exists for exactly this purpose. Regression test: an agent whose version probe exits non-zero while the package provider reportspresent+ version should display the provider version, notunknown.