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:
@@ -318,86 +318,10 @@ describe('msd-write-guard.js: deliberately narrow trigger (no-op paths)', () =>
|
||||
});
|
||||
|
||||
// ────────────────────────────────────────────────────────────────────────
|
||||
// #2304 — Kimi tool vocabulary engages the guard
|
||||
// Payload shapes mirror kimi-cli's actual tool schemas
|
||||
// (src/kimi_cli/tools/file/write.py): WriteFile takes `path`/`content`,
|
||||
// not Claude's `file_path`. See PR #2326 for the sibling guards.
|
||||
// Payload normalization is total (#2595 class)
|
||||
// ────────────────────────────────────────────────────────────────────────
|
||||
|
||||
describe('#2304: Kimi tool vocabulary engages the write guard', () => {
|
||||
test('Kimi WriteFile catastrophic shrink is BLOCKED like Write', () => {
|
||||
fs.writeFileSync(roadmapPath, lines(292));
|
||||
const r = runHook({
|
||||
hook_event_name: 'PreToolUse',
|
||||
tool_name: 'WriteFile',
|
||||
tool_input: { path: roadmapPath, content: lines(16) },
|
||||
});
|
||||
assert.equal(r.status, 2, `Kimi WriteFile shrink must be blocked. Got ${r.status}; stdout: ${r.stdout}`);
|
||||
const out = JSON.parse(r.stdout);
|
||||
assert.equal(out.decision, 'block');
|
||||
assert.equal(out.oldLines, 292);
|
||||
assert.equal(out.newLines, 16);
|
||||
});
|
||||
|
||||
test('module-qualified kimi_cli.tools.file:WriteFile is recognized', () => {
|
||||
fs.writeFileSync(roadmapPath, lines(292));
|
||||
const r = runHook({
|
||||
hook_event_name: 'PreToolUse',
|
||||
tool_name: 'kimi_cli.tools.file:WriteFile',
|
||||
tool_input: { path: roadmapPath, content: lines(16) },
|
||||
});
|
||||
assert.equal(r.status, 2, `qualified Kimi WriteFile shrink must be blocked. Got ${r.status}; stdout: ${r.stdout}`);
|
||||
assert.equal(JSON.parse(r.stdout).decision, 'block');
|
||||
});
|
||||
|
||||
test('block reason reaches stderr (Kimi feeds stderr back to the model on exit 2)', () => {
|
||||
fs.writeFileSync(roadmapPath, lines(292));
|
||||
const r = runHook({
|
||||
hook_event_name: 'PreToolUse',
|
||||
tool_name: 'WriteFile',
|
||||
tool_input: { path: roadmapPath, content: lines(16) },
|
||||
});
|
||||
assert.equal(r.status, 2);
|
||||
assert.ok(r.stderr.length > 0, 'stderr must be non-empty — it is the channel Kimi feeds back');
|
||||
assert.equal(r.stderr, JSON.parse(r.stdout).reason,
|
||||
'stderr must carry exactly the typed reason — the same contract, without pinning prose');
|
||||
});
|
||||
|
||||
test('Kimi StrReplaceFile stays exempt (Edit-class, out of scope by design)', () => {
|
||||
fs.writeFileSync(roadmapPath, lines(292));
|
||||
const r = runHook({
|
||||
hook_event_name: 'PreToolUse',
|
||||
tool_name: 'StrReplaceFile',
|
||||
tool_input: { path: roadmapPath, edit: { old: 'line 1', new: 'line one' } },
|
||||
});
|
||||
assert.equal(r.status, 0, 'StrReplaceFile is unmapped in this guard (Edit-class, out of scope by design #2255) and must fall through to the non-Write exemption');
|
||||
assert.equal(r.stdout, '');
|
||||
});
|
||||
|
||||
test('Kimi WriteFile of a non-curated path stays exempt', () => {
|
||||
const otherPath = path.join(projectDir, 'notes.md');
|
||||
fs.writeFileSync(otherPath, lines(300));
|
||||
const r = runHook({
|
||||
hook_event_name: 'PreToolUse',
|
||||
tool_name: 'WriteFile',
|
||||
tool_input: { path: otherPath, content: lines(5) },
|
||||
});
|
||||
assert.equal(r.status, 0);
|
||||
assert.equal(r.stdout, '');
|
||||
});
|
||||
|
||||
test("a spurious model-supplied file_path cannot shadow Kimi's authoritative path (#2595 class)", () => {
|
||||
fs.writeFileSync(roadmapPath, lines(292));
|
||||
const r = runHook({
|
||||
hook_event_name: 'PreToolUse',
|
||||
tool_name: 'WriteFile',
|
||||
tool_input: { path: roadmapPath, file_path: '', content: lines(16) },
|
||||
});
|
||||
assert.equal(r.status, 2,
|
||||
`kimi-cli executes on \`path\`, so \`path\` must win outright — a spurious file_path:'' shadowed it pre-fix and the guard read '' and exited 0. Got ${r.status}; stdout: ${r.stdout}`);
|
||||
assert.equal(JSON.parse(r.stdout).decision, 'block');
|
||||
});
|
||||
|
||||
describe('payload normalization is total', () => {
|
||||
test('null and primitive payloads fall through deliberately (total normalization, #2595 class)', () => {
|
||||
for (const payload of ['null', '42', '"write"']) {
|
||||
const r = runHook(payload);
|
||||
|
||||
Reference in New Issue
Block a user