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

@@ -14,7 +14,7 @@ const { installerEnv, RUNTIME_META } = require('./helpers/install-shared.cjs');
const { INSTALL_TIMEOUT_MS } = require('./helpers/timeouts.cjs');
const REPO_ROOT = path.join(__dirname, '..');
const { appendAgentTools, buildKimiAgentArtifacts, convertClaudeAgentToQwenAgent, convertClaudeAgentToZcodeAgent, _decodeToolScalar } = require('../msd-core/bin/lib/runtime-artifact-conversion.cjs');
const { appendAgentTools, convertClaudeAgentToZcodeAgent, _decodeToolScalar } = require('../msd-core/bin/lib/runtime-artifact-conversion.cjs');
const { parseFrontmatter } = require('../msd-core/bin/lib/frontmatter.cjs');
function parseTools(content) {
@@ -209,13 +209,6 @@ test('host converters receive canonical grants without changing their omissions
assert.ok(artifacts.some((artifact) => artifact.includes('mcp__configured__grant')),
`${runtime} must expose the configured canonical grant in its existing host form`);
}
const kiloArtifacts = emittedAgentArtifacts(installRuntime(t, 'kilo', { defaults }), 'msd-executor');
assert.ok(kiloArtifacts.some((artifact) => {
const configured = artifact.indexOf(' configured_grant: allow');
const wildcard = artifact.indexOf(' first_*: allow');
return configured >= 0 && wildcard > configured;
}),
'Kilo must translate safe canonical MCP grants into native permission keys in first-seen order');
for (const runtime of ['zcode', 'opencode']) {
const artifacts = emittedAgentArtifacts(installRuntime(t, runtime, { defaults }), 'msd-executor');
assert.ok(artifacts.every((artifact) => !artifact.includes('mcp__configured__grant')),
@@ -223,71 +216,6 @@ test('host converters receive canonical grants without changing their omissions
}
});
test('Kimi receives canonical grants before its existing mapper runs (#4032)', (t) => {
const install = installRuntime(t, 'kimi', {
defaults: { agent_tools: { 'msd-executor': ['WebFetch'] } },
scope: 'global',
});
const artifacts = emittedAgentArtifacts(install, 'msd-executor');
assert.ok(artifacts.some((artifact) => artifact.includes('kimi_cli.tools.web:FetchURL')),
'Kimi must map a configured canonical WebFetch tool through its existing converter');
});
test('Kimi project selectors override matching global selectors (#4032)', (t) => {
const install = installRuntime(t, 'kimi', {
defaults: { agent_tools: { 'msd-executor': ['WebFetch'] } },
projectConfig: { agent_tools: { 'msd-executor': ['WebSearch'] } },
scope: 'global',
});
const artifacts = emittedAgentArtifacts(install, 'msd-executor');
assert.ok(artifacts.some((artifact) => artifact.includes('kimi_cli.tools.web:SearchWeb')),
'Kimi must map the project grant through its existing converter');
assert.ok(artifacts.every((artifact) => !artifact.includes('kimi_cli.tools.web:FetchURL')),
'the matching global selector must not survive the project override');
});
test('Kimi neutralizes ~/.claude/msd-core references instead of leaking a repointed path (#4032)', (t) => {
// Routing Kimi through the ADR-1235 pre-converter pipeline (needed so
// project-scoped agent_tools selectors reach it, see the test above) also
// runs _applyAgentPathRewrites. Kimi's own neutralizeKimiAgentPrompt expects
// to see the ORIGINAL `~/.claude/msd-core` text; kimi/kimi-code capability.json
// now opt out via hostBehaviors.noPathRewrite so that still holds.
const install = installRuntime(t, 'kimi', { scope: 'global' });
// Inspect generated prompts, not the installation-owned raw source corpus.
const artifacts = emittedAgentArtifacts(install, 'msd-executor', path.join(install.configDir, 'agents'));
assert.ok(artifacts.some((artifact) => artifact.includes('MSD core')),
'a ~/.claude/msd-core reference must neutralize to prose, not a repointed Kimi path');
assert.ok(artifacts.every((artifact) =>
!artifact.includes('~/.claude/msd-core') &&
!artifact.includes('$HOME/.claude/msd-core') &&
!artifact.includes('config/agents/msd-core/references')),
'no raw Claude- or Kimi-prefixed msd-core path may leak into the Kimi prompt body');
});
test('Kilo global install resolves project agent_tools from the working directory (#4032)', (t) => {
const install = installRuntime(t, 'kilo', {
defaults: { agent_tools: { 'msd-executor': ['mcp__global__loser'] } },
projectConfig: { agent_tools: { 'msd-executor': ['mcp__project__winner'] } },
scope: 'global',
});
const artifacts = emittedAgentArtifacts(install, 'msd-executor');
assert.ok(artifacts.some((artifact) => artifact.includes(' project_winner: allow')),
'the combined-family path must discover project config from cwd during a global install');
assert.ok(artifacts.every((artifact) => !artifact.includes('global_loser')),
'the matching global selector must not survive the project override');
});
test('Kilo permission-key collision resolves deterministically to first-seen (#4032)', (t) => {
// mcp__a_b__c and mcp__a__b_c both derive Kilo's native "a_b_c" key — the
// `{server}_{tool}` format is Kilo's own fixed contract, not ours to widen.
const install = installRuntime(t, 'kilo', {
defaults: { agent_tools: { 'msd-executor': ['mcp__a_b__c', 'mcp__a__b_c'] } },
});
const artifacts = emittedAgentArtifacts(install, 'msd-executor');
assert.ok(artifacts.some((artifact) => (artifact.match(/^ {2}a_b_c: allow$/gm) || []).length === 1),
'a colliding pair must still emit exactly one permission line');
});
test('every installable runtime accepts a configured MCP grant without crashing (#4032)', (t) => {
// Shallow, broad: appendAgentTools runs pre-converter for every runtime, but
// only 6 have deep per-runtime assertions elsewhere in this file. This locks
@@ -297,17 +225,14 @@ test('every installable runtime accepts a configured MCP grant without crashing
// support varies per runtime, global does not). Search from `install.home`,
// not `install.configDir`: a nested-home runtime (e.g. antigravity) places
// agents in a sibling directory outside its own configDir subtree.
const NO_SUBAGENT_TOOLKIT = new Set(['pi']); // programmatic dispatch, no named-dispatch agent files
// Runtimes empirically verified (see PR #4238 remediation) to pass an
// arbitrary mcp__ grant through recognizably — either verbatim or via
// Kilo's {server}_{tool} transform. Every other runtime filters unknown
// arbitrary mcp__ grant through recognizably (verbatim). Every other runtime filters unknown
// tool names through its own built-in vocabulary (a legitimate, unrelated
// per-runtime design choice, not an agent_tools omission) and is checked
// for a clean, non-crashing install only. This is an allowlist, not a
// guess-based omit-list, so it can't silently drift as runtimes are added.
const GRANT_SURVIVES_RECOGNIZABLY = new Set(['claude', 'codex', 'copilot', 'hermes', 'kimi-code', 'kilo', 'qwen']);
const GRANT_SURVIVES_RECOGNIZABLY = new Set(['claude', 'codex']);
for (const runtime of Object.keys(RUNTIME_META)) {
if (NO_SUBAGENT_TOOLKIT.has(runtime)) continue;
const install = installRuntime(t, runtime, {
defaults: { agent_tools: { 'msd-executor': ['mcp__smoke__probe'] } },
scope: 'global',
@@ -315,8 +240,8 @@ test('every installable runtime accepts a configured MCP grant without crashing
const artifacts = emittedAgentArtifacts(install, 'msd-executor', install.home);
assert.ok(artifacts.every((artifact) => artifact.length > 0), `${runtime} must emit non-empty msd-executor artifact(s)`);
if (!GRANT_SURVIVES_RECOGNIZABLY.has(runtime)) continue;
assert.ok(artifacts.some((artifact) => artifact.includes('mcp__smoke__probe') || artifact.includes('smoke_probe')),
`${runtime} must carry the configured grant (raw or Kilo-style transformed) — this must fail if agent_tools is reverted`);
assert.ok(artifacts.some((artifact) => artifact.includes('mcp__smoke__probe')),
`${runtime} must carry the configured grant — this must fail if agent_tools is reverted`);
}
});
@@ -358,7 +283,7 @@ test('reinstall remains idempotent and preserves Claude read-only restrictions (
'the existing Claude read-only deny-list must survive augmentation');
});
test('quoted scalar identity is shared by append, Kimi, and Qwen (#4191)', () => {
test('quoted scalar identity is shared by append (#4191)', () => {
for (const [raw, expected] of [
['"\\x6dcp__server__tool"', 'mcp__server__tool'],
['"\\u006dcp__server__tool"', 'mcp__server__tool'],
@@ -374,16 +299,6 @@ test('quoted scalar identity is shared by append, Kimi, and Qwen (#4191)', () =>
for (const content of [inline, block]) {
const once = appendAgentTools(content, ['WebFetch', 'WebSearch']);
assert.strictEqual(once, content, 'quoted values must already satisfy append idempotency');
const kimi = buildKimiAgentArtifacts({ subagents: [{ path: 'agents/msd-test.md', content }] });
assert.ok(kimi.subagents[0].yaml.includes('kimi_cli.tools.web:FetchURL'));
assert.ok(kimi.subagents[0].yaml.includes('kimi_cli.tools.web:SearchWeb'));
assert.ok(!kimi.subagents[0].yaml.includes('unterminated'));
const qwen = convertClaudeAgentToQwenAgent(content);
assert.match(qwen, /^ {2}- WebFetch$/m);
assert.match(qwen, /^ {2}- WebSearch$/m);
assert.doesNotMatch(qwen, /unterminated/);
}
});
@@ -476,27 +391,6 @@ test('appendAgentTools recognizes an existing block item with a trailing comment
assert.match(once, /^ {2}- "Write"$/m, 'the genuinely new grant must still be appended');
});
test('parseFrontmatterTools (Qwen conversion) does not silently drop a block list under a comment-only header (#4032)', () => {
// Sibling of the appendAgentTools fix (finding 4): parseFrontmatterTools's
// own comment-only-header check (`if (value) {...}` treated `# note` as
// truthy content instead of falling through to `collecting = true`) is a
// separate parser reached by Kimi and Qwen conversion, downstream of
// appendAgentTools's own output.
const agent = '---\nname: msd-executor\ndescription: test\ntools: # note\n - Read\n - Write\n---\nbody\n';
const qwen = convertClaudeAgentToQwenAgent(agent);
assert.match(qwen, /- Read/);
assert.match(qwen, /- Write/);
});
test('parseFrontmatterTools (Qwen conversion) does not tear a quoted scalar containing a literal comma (#4032)', () => {
const agent = appendAgentTools(
'---\nname: msd-executor\ndescription: test\ntools: Read, "mcp__x, y"\n---\nbody\n',
[],
);
const qwen = convertClaudeAgentToQwenAgent(agent);
assert.match(qwen, /- "mcp__x, y"/, 'the quoted scalar must survive as one tool, not torn on its internal comma');
});
test('ZCode strips an undecodable mcp__ scalar instead of keeping it (fail-closed) (#4032)', () => {
// An unterminated quote makes decodeToolScalar return null. ZCode's contract
// is "never emit mcp__*" (a required-MCP-server hard-fail otherwise), so a