refactor: drop 12 runtimes, keep Claude, Codex, OpenCode, Cursor, ZCode, Antigravity

Removes kilo, kimi, kimi-code, copilot, windsurf, augment, trae, qwen, hermes,
cline, codebuddy and pi end to end: capability descriptors, installer branches
and converters (bin/install.js 14.9k -> 11.2k lines), TypeScript converters,
hook surfaces and runtime homes, review lanes qwen/kimi-code, the two pi
migrations, Kimi payload normalization in the hook guards, dead hostBehaviors
vocabulary, launcher home probes, fixtures, runtime-specific tests and the
prose that presented them as supported.

Installer output for the six kept runtimes is byte-identical to before the
prune. The Kimi tool-vocabulary tests in workflow-guard, read-guard and
read-injection-scanner are left in place pending a decision.
This commit is contained in:
Jakub Zych
2026-10-06 20:02:40 +02:00
parent 12ee75a509
commit 6cfa0c55d2
509 changed files with 1869 additions and 47737 deletions

View File

@@ -3,16 +3,12 @@
/**
* #3023 — shared hook bundle directory-name resolution.
*
* Coverage gaps closed here (tests/install-minimal-hooks.test.cjs already
* covers the installed-tree rows — pi local+global: no `hooks/`, bundle at
* `msd-hooks/`, manifest keys — and is not duplicated):
* Coverage here:
*
* GROUP A bin/install.js `resolveSharedHooksDirName(runtime)` — the
* descriptor-driven sanitizer that rejects anything that is not a
* plain, non-empty, separator-free, non-dot, non-absolute,
* NUL-free single path segment.
* GROUP B pi/msd.cjs `_internals.resolveSharedHooksDir(engineRoot)` — the
* adapter-side probe over `SHARED_HOOKS_DIR_CANDIDATES`.
* GROUP C the two latent bundle-directory-NAME dependencies:
* hooks/msd-check-update-worker.js (stale-hook scan) and
* hooks/msd-read-injection-scanner.js (own-bundle exclusion).
@@ -55,8 +51,6 @@ const PROPERTY_DRIVER_TIMEOUT_MS = 60000;
// Requiring the installer (not as main) never runs the CLI — matches the
// existing tests/claude-imperative-reference.test.cjs convention.
const installMod = require('../bin/install.js');
const piExtension = require('../pi/msd.cjs');
const { resolveSharedHooksDir, SHARED_HOOKS_DIR_CANDIDATES } = piExtension._internals;
// ---------------------------------------------------------------------------
// GROUP A.1 — real registry, real runtimes (in-process, no stubbing needed)
@@ -64,7 +58,7 @@ const { resolveSharedHooksDir, SHARED_HOOKS_DIR_CANDIDATES } = piExtension._inte
describe('GROUP A.1: resolveSharedHooksDirName — real registry, real runtimes', () => {
test('absent sharedHooksDirName field resolves to the default "hooks"', () => {
for (const runtime of ['claude', 'kimi', 'cursor', 'opencode']) {
for (const runtime of ['claude', 'codex', 'cursor', 'opencode']) {
assert.equal(
installMod.resolveSharedHooksDirName(runtime),
'hooks',
@@ -73,10 +67,6 @@ describe('GROUP A.1: resolveSharedHooksDirName — real registry, real runtimes'
}
});
test('the real pi descriptor resolves to "msd-hooks" (#3023)', () => {
assert.equal(installMod.resolveSharedHooksDirName('pi'), 'msd-hooks');
});
test('an unknown runtime id, and an empty-string runtime id, both degrade to the default and never throw', () => {
assert.doesNotThrow(() => installMod.resolveSharedHooksDirName('__nonexistent_runtime__'));
assert.equal(installMod.resolveSharedHooksDirName('__nonexistent_runtime__'), 'hooks');
@@ -358,160 +348,6 @@ describe('GROUP A.2: resolveSharedHooksDirName — malformed/hostile values + pr
});
});
// ---------------------------------------------------------------------------
// GROUP B — pi/msd.cjs _internals.resolveSharedHooksDir(engineRoot)
// ---------------------------------------------------------------------------
describe('GROUP B: pi adapter resolveSharedHooksDir (pi/msd.cjs)', () => {
// A real staged bundle always has at least one hook file in it; these tests
// populate every "should qualify" candidate with a placeholder file so they
// exercise the same non-empty invariant defect 2's fix enforces, rather than
// relying on an literally-empty directory that no real install ever produces.
function populate(dirPath) {
fs.mkdirSync(dirPath, { recursive: true });
fs.writeFileSync(path.join(dirPath, 'msd-placeholder-hook.js'), '// placeholder\n');
}
test('candidate order is exactly ["msd-hooks", "hooks"] (a reordering that silently prefers the stale dir must fail loudly)', () => {
assert.deepEqual(SHARED_HOOKS_DIR_CANDIDATES, ['msd-hooks', 'hooks']);
});
test('only msd-hooks/ exists (populated) -> returns that path', (t) => {
const root = createTempDir('fix-3023-adapter-');
t.after(() => cleanup(root));
populate(path.join(root, 'msd-hooks'));
assert.equal(resolveSharedHooksDir(root), path.join(root, 'msd-hooks'));
});
test('only hooks/ exists (dev-tree back-compat, populated) -> returns that path', (t) => {
const root = createTempDir('fix-3023-adapter-');
t.after(() => cleanup(root));
populate(path.join(root, 'hooks'));
assert.equal(resolveSharedHooksDir(root), path.join(root, 'hooks'));
});
test('both exist and both populated (half-upgraded tree) -> msd-hooks wins deterministically', (t) => {
const root = createTempDir('fix-3023-adapter-');
t.after(() => cleanup(root));
populate(path.join(root, 'msd-hooks'));
populate(path.join(root, 'hooks'));
assert.equal(resolveSharedHooksDir(root), path.join(root, 'msd-hooks'));
});
test('neither exists -> null, does not throw', (t) => {
const root = createTempDir('fix-3023-adapter-');
t.after(() => cleanup(root));
assert.doesNotThrow(() => resolveSharedHooksDir(root));
assert.equal(resolveSharedHooksDir(root), null);
});
test('msd-hooks exists as a FILE, not a directory -> skipped; falls through to a populated hooks/ when present', (t) => {
const root = createTempDir('fix-3023-adapter-');
t.after(() => cleanup(root));
fs.writeFileSync(path.join(root, 'msd-hooks'), 'not a directory');
populate(path.join(root, 'hooks'));
assert.equal(resolveSharedHooksDir(root), path.join(root, 'hooks'));
});
test('msd-hooks exists as a FILE and hooks/ is absent -> null', (t) => {
const root = createTempDir('fix-3023-adapter-');
t.after(() => cleanup(root));
fs.writeFileSync(path.join(root, 'msd-hooks'), 'not a directory');
assert.equal(resolveSharedHooksDir(root), null);
});
// ── Defect 2 (adversarial review): empty-bundle qualification ────────────
// An install interrupted between mkdirSync(msd-hooks) and the file copy
// leaves a directory that EXISTS but is EMPTY. Since msd-hooks is probed
// FIRST, an empty msd-hooks/ must lose to a fully-staged legacy hooks/ —
// otherwise every hook silently no-ops (runHook's fs.existsSync guard
// degrades per-file, producing no error at all).
test('regression: msd-hooks/ exists but is EMPTY, hooks/ is populated -> resolves hooks/ (fails before the fix)', (t) => {
const root = createTempDir('fix-3023-adapter-');
t.after(() => cleanup(root));
fs.mkdirSync(path.join(root, 'msd-hooks'), { recursive: true }); // empty — no files written
populate(path.join(root, 'hooks'));
assert.equal(
resolveSharedHooksDir(root),
path.join(root, 'hooks'),
'an empty msd-hooks/ must not win over a fully-staged legacy hooks/',
);
});
test('msd-hooks/ populated, hooks/ populated -> resolves msd-hooks/', (t) => {
const root = createTempDir('fix-3023-adapter-');
t.after(() => cleanup(root));
populate(path.join(root, 'msd-hooks'));
populate(path.join(root, 'hooks'));
assert.equal(resolveSharedHooksDir(root), path.join(root, 'msd-hooks'));
});
test('both msd-hooks/ and hooks/ exist but are BOTH empty -> null', (t) => {
const root = createTempDir('fix-3023-adapter-');
t.after(() => cleanup(root));
fs.mkdirSync(path.join(root, 'msd-hooks'), { recursive: true });
fs.mkdirSync(path.join(root, 'hooks'), { recursive: true });
assert.equal(resolveSharedHooksDir(root), null);
});
test('msd-hooks/ is empty, hooks/ does not exist -> null', (t) => {
const root = createTempDir('fix-3023-adapter-');
t.after(() => cleanup(root));
fs.mkdirSync(path.join(root, 'msd-hooks'), { recursive: true });
assert.equal(resolveSharedHooksDir(root), null);
});
});
// ---------------------------------------------------------------------------
// GROUP D — parity assertion: installer descriptor vs pi's own candidate list
// ---------------------------------------------------------------------------
//
// bin/install.js derives the shared-hooks directory NAME for a runtime from
// the capability registry (resolveSharedHooksDirName). pi/msd.cjs cannot read
// that registry at runtime — it must resolve correctly in a dev checkout AND
// in a half-upgraded tree, where the registry's CURRENT answer would be the
// wrong one to probe for (see the SHARED_HOOKS_DIR_CANDIDATES doc comment in
// pi/msd.cjs) — so it keeps its own hardcoded probe list instead. That is two
// independent sources of truth for the same name: exactly the "Generative Fix
// Divergence" anti-pattern (CLAUDE.md -> KNOWN DEFECTS: "When sharing
// constants/arrays/parsers between parallel surfaces, add a parity assertion
// test that fails if they diverge."). If a future descriptor rename is not
// mirrored into pi/msd.cjs, this is the guard that fails loudly instead of
// every pi hook going quiet with no error.
describe('GROUP D: parity — installer descriptor vs pi/msd.cjs SHARED_HOOKS_DIR_CANDIDATES', () => {
const REMEDY = 'if the descriptor changes, update SHARED_HOOKS_DIR_CANDIDATES in pi/msd.cjs to match';
test('the installer-resolved pi descriptor name is a member of the adapter probe list', () => {
const descriptorName = installMod.resolveSharedHooksDirName('pi');
assert.ok(
SHARED_HOOKS_DIR_CANDIDATES.includes(descriptorName),
`pi's capability descriptor resolves to "${descriptorName}", which is NOT in pi/msd.cjs's ` +
`SHARED_HOOKS_DIR_CANDIDATES (${JSON.stringify(SHARED_HOOKS_DIR_CANDIDATES)}) — ${REMEDY}.`,
);
});
test('the installer-resolved pi descriptor name is the FIRST candidate (must outrank the legacy dir)', () => {
const descriptorName = installMod.resolveSharedHooksDirName('pi');
assert.equal(
SHARED_HOOKS_DIR_CANDIDATES[0],
descriptorName,
`pi/msd.cjs's SHARED_HOOKS_DIR_CANDIDATES probes "${SHARED_HOOKS_DIR_CANDIDATES[0]}" first, but the ` +
`installer's current descriptor for pi resolves to "${descriptorName}" — a half-upgraded tree (both dirs ` +
`present) would bind to the stale bundle first. ${REMEDY}, with the descriptor's current name listed first.`,
);
});
test('the back-compat default ("hooks") is present in the adapter probe list', () => {
assert.ok(
SHARED_HOOKS_DIR_CANDIDATES.includes(installMod.SHARED_HOOKS_DIR_DEFAULT),
`pi/msd.cjs's SHARED_HOOKS_DIR_CANDIDATES (${JSON.stringify(SHARED_HOOKS_DIR_CANDIDATES)}) no longer ` +
`contains the installer's back-compat default ("${installMod.SHARED_HOOKS_DIR_DEFAULT}") — dropping it ` +
`breaks the dev-checkout/back-compat path (a checkout with only a legacy hooks/ dir would resolve to null). ${REMEDY}.`,
);
});
});
// ---------------------------------------------------------------------------
// GROUP C — bundle-directory-NAME-agnostic hook scripts
// ---------------------------------------------------------------------------