mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 12:39:42 +02:00
docs(cli-registry): name the real tests and fields the catalogue docs point at
Three instructions a future contributor would follow literally were stale after the last review round: the "Adding a CLI" checklist sent the agent-image reason to AGENT_IMAGE_SPECIAL_CASES, a constant that no longer exists (it is discovery.install.agentImageLayer on the entry in stock.ts), the trust-boundary paragraph credited the embedded-commands pin to the invariants test when it is test/cli-catalog-sync.test.ts, and install.sh claimed "the parity test" pinned the DeepSeek Harness banner when no test did. That pin now exists: the invariants test asserts the script's grep literal and the registry's discovery.identity.regex agree on "DeepSeek Harness", and the comment names it. docs/docker-cases.md separated the two reasons a CLI stays out of the shared npm layer (no npmPackage at all versus an agentImageLayer entry), which it had folded into one, and architecture-invariants no longer lists the agent image's CLI set by hand. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -156,9 +156,9 @@ Three rules, and the middle one is why the embed matters:
|
||||
|
||||
That is mechanical rather than a promise. `CLI_INSTALL_CMD_TRUSTED` is written only from the
|
||||
generated block and is the only array the installer ever runs or displays — there is no second
|
||||
array a refresh could rewrite, because there is no refresh. `test/install-sh-invariants.test.ts`
|
||||
asserts as much: the embedded commands are exactly the registry's, and nothing in `install.sh`
|
||||
`eval`s.
|
||||
array a refresh could rewrite, because there is no refresh. `test/cli-catalog-sync.test.ts`
|
||||
asserts that the embedded commands are exactly the registry's, and
|
||||
`test/install-sh-invariants.test.ts` that nothing in `install.sh` `eval`s.
|
||||
|
||||
### bash 3.2
|
||||
|
||||
@@ -181,7 +181,7 @@ A module-level const freezes at first import, and the failure is asymmetric: a C
|
||||
1. Add a `CliEntry` to `stock.ts`.
|
||||
2. Run `npm run generate:cli-catalog` and commit **both** artifacts (`config/clis.stock.json` and `install.sh`). The installer's detection, its install menu, its reminder text and the Docker agent image all follow from that one step — this is what makes upstream `b6d0f1fa` ("wire OMP into install.sh's CLI detection, it had none") impossible rather than merely fixed.
|
||||
3. Add a golden spawn-command pin to `test/cli-registry-spawn-golden.test.ts`, a row to `test/cli-capability-predicates.test.ts`, its remote/docker commands to `test/location-overlay-commands.test.ts`, and its search paths to `test/install-sh-detection-parity.test.ts`.
|
||||
4. Only if it cannot install with a plain `npm install -g <pkg>`: give it a layer in `docker/agent.Dockerfile` and a reason in `AGENT_IMAGE_SPECIAL_CASES` (`scripts/lib/cli-catalog.mjs`). The coverage test requires both, so an exclusion cannot quietly become an omission.
|
||||
4. Only if it cannot install with a plain `npm install -g <pkg>`: give it a layer in `docker/agent.Dockerfile` and set `discovery.install.agentImageLayer: { kind: 'dedicated', reason }` on its entry in `stock.ts`. `test/docker-agent-image-coverage.test.ts` requires both, so an exclusion cannot quietly become an omission. An entry with no `npmPackage` needs only the Dockerfile layer, since it never enters the shared npm layer in the first place.
|
||||
5. That is usually all. If you find yourself wanting to add an `if` somewhere, the guard test will tell you — and the answer is a capability field, or a named profile if it genuinely needs to run code.
|
||||
|
||||
## See also
|
||||
|
||||
@@ -34,9 +34,12 @@ must not change what is inside an image tagged `codeman/agent:base`, or two mach
|
||||
that tag hold different images and every cache decision downstream is a lie. Each entry's
|
||||
`enabled` flag IS honoured, so a CLI that ships disabled is never baked in.
|
||||
|
||||
Five CLIs keep hand-written layers, because the registry cannot express what makes them
|
||||
special (as a REGISTRY field now — `discovery.install.agentImageLayer` in `stock.ts` — rather
|
||||
than an id-keyed table duplicated between the two producers of the image's build args):
|
||||
Five CLIs keep hand-written layers, for two different reasons that are easy to conflate.
|
||||
`antigravity`, `grok` and `omp` declare no `npmPackage` at all, so they never enter the shared
|
||||
npm layer and each gets a vendor-installer layer instead. `pi` and `deepseek` ARE on npm but
|
||||
carry `discovery.install.agentImageLayer` in `stock.ts` (a REGISTRY field, rather than an
|
||||
id-keyed table duplicated between the two producers of the image's build args), which pulls
|
||||
them out of the shared layer because a plain `npm install -g` is not enough for them:
|
||||
|
||||
| CLI | Why it is not in the shared npm layer |
|
||||
| ------------- | ------------------------------------------------------------------------------------- |
|
||||
|
||||
+3
-2
@@ -452,8 +452,9 @@ dsh_banner_probe() {
|
||||
# DeepSeek stays a hand-written special case ON PURPOSE: the registry expresses
|
||||
# its identity check as `discovery.identity.regex`, a JavaScript regex, and
|
||||
# translating that into a `grep` pattern at install time is a transformation
|
||||
# nobody should be performing on a security-adjacent check. The parity test pins
|
||||
# that the registry still demands "DeepSeek Harness", so an upstream banner
|
||||
# nobody should be performing on a security-adjacent check. Instead
|
||||
# test/install-sh-invariants.test.ts pins the grep below against the registry's
|
||||
# `discovery.identity.regex`, so the two cannot drift apart: an upstream banner
|
||||
# change fails a test instead of silently mis-detecting here.
|
||||
_cli_candidate_ok() {
|
||||
case "$1" in
|
||||
|
||||
@@ -14,6 +14,7 @@ import { describe, expect, it } from 'vitest';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { STOCK_CLIS } from '../src/config/cli-registry/stock.js';
|
||||
|
||||
const INSTALL_SH = fileURLToPath(new URL('../install.sh', import.meta.url));
|
||||
const SOURCE = readFileSync(INSTALL_SH, 'utf-8');
|
||||
@@ -167,6 +168,23 @@ describe('install.sh runtime safety', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('install.sh DeepSeek identity probe', () => {
|
||||
it('greps for the same banner the registry identity regex demands', () => {
|
||||
// dsh_banner_probe is the ONE hand-written identity check left in the script (the
|
||||
// registry's is a JavaScript regex, deliberately not translated into grep at install
|
||||
// time). The two are pinned to each other here so an upstream banner change fails
|
||||
// this test instead of mis-detecting on one side only.
|
||||
const grepLine = CODE_LINES.find((line) => line.includes('grep -qi "DeepSeek Harness"'));
|
||||
expect(grepLine, 'the dsh banner grep is gone or its literal changed').toBeDefined();
|
||||
|
||||
const deepseek = STOCK_CLIS.find((entry) => entry.id === 'deepseek');
|
||||
const identity = deepseek?.discovery.identity;
|
||||
expect(identity, 'the deepseek entry no longer declares an identity probe').toBeDefined();
|
||||
expect(identity?.arg).toBe('--help');
|
||||
expect(new RegExp(identity!.regex, 'i').test('DeepSeek Harness')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('install.sh AI CLI install menu', () => {
|
||||
// The menu is the one interactive path in the script, which is why it used to be the
|
||||
// only part nothing exercised: choosing "s" (Skip) once fell straight into the shared
|
||||
|
||||
Reference in New Issue
Block a user