mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-07 16:09:43 +02:00
CI caught three cron-service failures. Both are mine, from converting cron's per-mode ladders to capability reads without checking what each ladder's scope actually was. **The pre-flight.** cron only ever pre-flighted `deepseek` — dsh is a profile LAUNCHER, so "installed" is not "runnable" and a bare `dsh` can boot a profile that cannot drive a pane. I replaced that with an unscoped `resolveCliLaunchError(mode)`, which pre-flights EVERY mode, so a claude cron job on a box with no claude binary now failed with "Claude CLI not found" instead of reaching tmux-manager's own throw. Three tests assert the latter. It is now gated on `discovery.launcherProfile !== undefined`, which is byte-identical to the `mode === 'deepseek'` check it replaces and generalises to the next launcher. The equivalent HTTP-route conversion was already scoped (to `capabilities.external`, matching what that route has always pre-flighted); I simply failed to carry the same reasoning across. **The model.** cron's ladder was `mode !== 'shell' && mode !== 'deepseek'`, and I read it as `capabilities.model.source === 'claude-settings-file'` — which is the HTTP route's question, not cron's. There, every external CLI reads its model from its own config object earlier in the chain, so only claude reaches the global default; cron has no such config, so the same expression silently narrowed the default model from eight modes to one. Now `!== 'none'`, which is exactly the two entries the ladder excluded. Not caught by a test — found by re-deriving each ladder's scope after the first failure. Also names a fourth deliberate behaviour change in the changeset, found while tracing these: `session.ts` carried a hand-written list of modes with no direct-PTY fallback and OMP was missing from it, though CLAUDE.md's own text says "all eight require tmux". `requiresMux` comes off the entry now, so an omp session whose mux creation fails refuses instead of silently starting outside tmux. Verified by diffing failing tests BY NAME against an upstream/master baseline, rather than by file as before — which is how the regression slipped through: the three new failures landed inside a file already failing for unrelated Windows-path reasons, and the aggregate count happened to collide. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WQkoi1cNegqVwZHgzx5SbJ
58 lines
3.8 KiB
Markdown
58 lines
3.8 KiB
Markdown
---
|
|
'aicodeman': minor
|
|
---
|
|
|
|
CLI backends are now a data-driven registry instead of a hardcoded set of run modes. Every
|
|
CLI (Claude Code, Terminal/Shell, OpenCode, Codex, Gemini, Antigravity, Pi, Grok, DeepSeek
|
|
Harness and OMP) is a `CliEntry` in `src/config/cli-registry/`, and the code that used to
|
|
branch on a CLI's name now reads capability flags off that entry instead.
|
|
|
|
This is an **internal refactor with no behaviour change**: no new endpoints, no new settings,
|
|
no change to any request or response shape, and the spawn command every CLI receives is
|
|
byte-identical to what the hand-written builders produced. `test/cli-registry-spawn-golden.test.ts`
|
|
pins those command lines as literal strings, captured from the previous builders before they
|
|
were removed, and `test/location-overlay-commands.test.ts` does the same for every remote and
|
|
in-container pane command.
|
|
|
|
What the registry owns: binary discovery (search paths, version and identity probes), the
|
|
launch argv template, environment handling (exports, `tmux setenv` keys, the env-override
|
|
allowlist), the multi-user privileged-parameter and privileged-env-key clamps, the
|
|
remote/docker location overlays, and the behavioural capabilities the rest of the app reads
|
|
(`isExternalCliMode`, `isAltScreenStripMode`, `hooksAvailableForMode`, alt-screen strip class,
|
|
echo policy, transcript format, and friends). `codeman doctor`'s per-CLI rows are generated
|
|
from the same entries, so its version rules and the run modes' resolvers can no longer
|
|
disagree about whether a given binary counts as installed.
|
|
|
|
Registry data is resolved **at call time**, never frozen at module import: session-mode and
|
|
env-prefix validation, the doctor's tool list, and each resolver's search directories all
|
|
re-read the catalog, so a CLI enabled while the server is running moves every surface at once
|
|
rather than only the run menu.
|
|
|
|
Four user-visible changes, all small and all deliberate:
|
|
|
|
- `probeDockerCliVersion()` derives the in-container binary name from the registry rather
|
|
than assuming it equals the mode name. Only Claude reaches that path today, so nothing was
|
|
broken in practice, but `antigravity` runs `agy` and the assumption would not have survived
|
|
the next CLI that needs a version.
|
|
- The remote CLI version probe now covers **Grok and DeepSeek**, which the hardcoded map it
|
|
replaces simply omitted — its own comment said the rule was "every mode except shell", so
|
|
the two were an oversight from when those CLIs were added, and a remote session in either
|
|
mode reported no version at all.
|
|
- OMP now requires tmux like its seven siblings. `session.ts` carried a hand-written list of
|
|
modes with no direct-PTY fallback and omp was missing from it, even though CLAUDE.md's own
|
|
text says "all eight require tmux" — so an omp session whose mux creation failed silently
|
|
fell back to a direct PTY. `requiresMux` comes off the entry now, so the list cannot drift
|
|
from the rule again.
|
|
- `codeman doctor`'s CLI rows come from the registry, so Claude's install hint is now the
|
|
documented install command rather than a docs URL, five CLIs gain install hints they never
|
|
had, and the row order follows the catalog (Claude now sorts below tmux).
|
|
|
|
A user-editable `~/.codeman/clis.json` can override any stock entry or add a custom CLI. It
|
|
is READ-ONLY in this release — nothing writes it, so importing the registry has no filesystem
|
|
side effects. Config never contains shell text: an entry declares typed argv tokens, every
|
|
literal is validated against a safe-word pattern at load, and values resolve through named
|
|
patterns that live in code, so a `clis.json` cannot widen its own validation.
|
|
`test/cli-registry-no-id-branching.test.ts` fails the build if per-CLI-id branching reappears
|
|
outside the stock catalog, in any of its four shapes (`===`, `!==`, `switch`/`case`, and
|
|
`includes`).
|