fix(pi): align the doctor with the pi resolver, correct the strip rationale, update the skill

Second review pass on #282, the three items left open after f4dcfbe.

1. `codeman doctor` and the run mode disagreed about pi. The registry entry
   accepted a bare `which pi` hit while pi-cli-resolver demanded semver-shaped
   `--version` output, so the Dependencies panel could report an installed Pi CLI
   on a box where Run Pi stays hidden, which reads as a broken mode rather than a
   missing install. Both sides now share one exported PI_VERSION_REGEX, and
   PathResolver gains an opt-in `requireVersionMatch` so a binary that fails the
   shape check is reported MISSING instead of installed-with-unknown-version.
   Only pi sets it; every other tool keeps its current behaviour.

2. The isAltScreenStripMode comment justified excluding pi with "the alt screen
   is load-bearing for its fullscreen TUI". That is not what exclusion does: pi
   is tmux-backed, so it falls through to isMuxAltScreenOnlyStripMode, which
   strips the alt-screen toggles anyway. What exclusion actually preserves is
   `\x1b[3J` and the mouse DECSETs, which is the real reason (pi renders into the
   main screen and is mouse-aware). Comment and changeset now say that, and state
   the consequence: fullscreen pi paints into the main buffer, like vim in a tmux
   shell session.

3. skills/codeman still enumerated the five pre-pi modes in nine places, telling
   agents a backend does not exist and understating class-wide caveats by one
   mode. All updated, plus stale session.ts line references refreshed.

Tests: a new static guard derives the mode set from the Zod schema (not a copy)
and fails when a skill enumeration lists a partial set of external CLIs, verified
by mutation. It also documents the one legitimate exception it found: the "writes
no transcript" lists drop codex, which does write a rollout Codeman reads back.
Plus doctor cases for an unrelated `pi` on PATH and registry/resolver regex parity.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer
2026-08-13 17:41:44 +02:00
parent f4dcfbe6ca
commit 86c78fece3
11 changed files with 242 additions and 23 deletions
+26 -1
View File
@@ -7,6 +7,8 @@
* @module config/dependency-registry
*/
import { PI_VERSION_REGEX } from '../utils/pi-cli-resolver.js';
export type ProbeEnvironment = 'linux' | 'darwin' | 'win32' | 'wsl';
/** The valid `--category` filter values; single source of truth for the type, the CLI
@@ -20,6 +22,13 @@ export interface PathResolver {
bins: string[];
versionArg?: string; // default '--version'
versionRegex?: RegExp; // default matches first \d+.\d+(.\d+)?
/**
* Treat a binary whose version output does not match as NOT INSTALLED, instead of
* reporting it with an unknown version. Only for tools with a short, generic binary
* name (`pi`), where a `which` hit is not by itself evidence the right program is
* there and a false "installed" contradicts the run mode's own resolver.
*/
requireVersionMatch?: boolean;
}
/** Resolve a Windows-installed app reachable from win32 or WSL. */
@@ -112,7 +121,23 @@ export const DEPENDENCY_REGISTRY: ToolDependency[] = [
category: 'core',
required: false,
usedBy: ['Pi sessions'],
resolvers: [{ match: ALL, resolver: { kind: 'path', bins: ['pi'], versionArg: '--version' } }],
// The only entry that requires a version match, for the same reason
// pi-cli-resolver.ts probes: `pi` is a short generic name (Raspberry Pi tooling,
// personal scripts), so a `which pi` hit alone is not the coding agent. Both sides
// share PI_VERSION_REGEX, so the doctor and the run mode cannot drift into telling
// the user opposite things about the same binary.
resolvers: [
{
match: ALL,
resolver: {
kind: 'path',
bins: ['pi'],
versionArg: '--version',
versionRegex: PI_VERSION_REGEX,
requireVersionMatch: true,
},
},
],
},
{
id: 'libreoffice',