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

@@ -145,7 +145,7 @@ describe('commonjs-marker: ownership predicate', () => {
// #2717 added a SECOND copy of these helpers in runtime-hooks-surface.cts
// for the runtimes that stage .js hooks via dedicated paths
// (cursor/windsurf/codex). That copy probed with `fs.existsSync`, which
// (cursor/codex). That copy probed with `fs.existsSync`, which
// follows symlinks and reports false for a DANGLING one — so it classified
// the link `absent` and wrote straight through it, landing outside the
// directory MSD owns. #2544 makes it delegate to commonjs-marker instead.
@@ -182,7 +182,7 @@ describe('commonjs-marker: ownership predicate', () => {
// That is the same write-into-territory-MSD-did-not-fill this issue is about,
// and it is what `stagedHooks` guards on the shared-bundle path. These pin the
// matching gate on the two dedicated writers.
for (const rt of ['cursor', 'windsurf']) {
for (const rt of ['cursor']) {
test(`${rt}: staging zero hook scripts leaves hooks/ marker-free`, (t) => {
const hooksSurface = require('../msd-core/bin/lib/runtime-hooks-surface.cjs');
const root = mkTmp(`msd-2544-${rt}-nostage-`);
@@ -195,10 +195,7 @@ describe('commonjs-marker: ownership predicate', () => {
const targetDir = path.join(root, 'target');
fs.mkdirSync(targetDir, { recursive: true });
const write = rt === 'cursor'
? hooksSurface.writeCursorHooksJson
: hooksSurface.writeWindsurfHooksJson;
write(targetDir, emptySrc);
hooksSurface.writeCursorHooksJson(targetDir, emptySrc);
const hooksDir = path.join(targetDir, 'hooks');
const staged = fs.existsSync(hooksDir)
@@ -549,98 +546,6 @@ describe('#2544 regression: install must not clobber the config-root package.jso
);
});
test('pi: the extensions/ marker is installed and reclaimed on uninstall', (t) => {
const root = mkTmp('msd-2544-pi-');
t.after(() => cleanup(root));
runInstall(root, 'pi');
const marker = path.join(root, 'extensions', 'package.json');
assert.ok(fs.existsSync(marker), 'pi extensions/package.json marker must be staged');
assert.equal(JSON.parse(fs.readFileSync(marker, 'utf8')).type, 'commonjs');
runInstall(root, 'pi', ['--uninstall']);
assert.ok(!fs.existsSync(marker), 'uninstall must remove the extensions/ marker it wrote');
});
test('pi: a user-authored extensions/package.json survives install and uninstall', (t) => {
const root = mkTmp('msd-2544-pi-user-');
t.after(() => cleanup(root));
const extDir = path.join(root, 'extensions');
fs.mkdirSync(extDir, { recursive: true });
const userPkg = path.join(extDir, 'package.json');
fs.writeFileSync(userPkg, USER_PACKAGE_JSON);
const before = sha256(fs.readFileSync(userPkg));
runInstall(root, 'pi');
assert.equal(sha256(fs.readFileSync(userPkg)), before,
'install must not overwrite a user-authored extensions/package.json');
runInstall(root, 'pi', ['--uninstall']);
assert.ok(fs.existsSync(userPkg), 'uninstall must not remove it either');
assert.equal(sha256(fs.readFileSync(userPkg)), before);
});
test('kimi: the marker lives under hooks/, and the legacy root marker is retired', (t) => {
const root = mkTmp('msd-2544-kimi-');
t.after(() => cleanup(root));
// HOME is redirected to `root`, so kimi's native hook root
// (resolveKimiHooksTomlDir → the `.kimi` dot-home) resolves inside the
// temp tree. That root is OUTSIDE kimi's configDir, which is why migration
// 007 cannot reach it and bin/install.js retires it directly.
const kimiRoot = path.join(root, '.kimi');
runInstall(root, 'kimi');
assert.ok(
fs.existsSync(path.join(kimiRoot, 'hooks', 'package.json')),
'kimi marker must be staged inside .kimi/hooks/',
);
assert.ok(
!fs.existsSync(path.join(kimiRoot, 'package.json')),
'kimi must not carry a marker at its native hook root',
);
// Model a pre-#2544 install, which left the marker at the .kimi root, then
// upgrade. The stale marker must be retired by the install itself.
fs.writeFileSync(path.join(kimiRoot, 'package.json'), `${COMMONJS_MARKER}\n`);
runInstall(root, 'kimi');
assert.ok(
!fs.existsSync(path.join(kimiRoot, 'package.json')),
'upgrading must retire the pre-#2544 marker at kimi\'s root',
);
});
test('kimi: a user-authored package.json at the .kimi root is never retired', (t) => {
const root = mkTmp('msd-2544-kimi-user-');
t.after(() => cleanup(root));
const kimiRoot = path.join(root, '.kimi');
fs.mkdirSync(kimiRoot, { recursive: true });
const userPkg = path.join(kimiRoot, 'package.json');
fs.writeFileSync(userPkg, USER_PACKAGE_JSON);
const before = sha256(fs.readFileSync(userPkg));
runInstall(root, 'kimi');
assert.ok(fs.existsSync(userPkg), 'a user file at the .kimi root must survive');
assert.equal(sha256(fs.readFileSync(userPkg)), before);
});
test('kimi: uninstall reclaims the hooks/ marker', (t) => {
const root = mkTmp('msd-2544-kimi-uninstall-');
t.after(() => cleanup(root));
const kimiRoot = path.join(root, '.kimi');
runInstall(root, 'kimi');
assert.ok(fs.existsSync(path.join(kimiRoot, 'hooks', 'package.json')));
runInstall(root, 'kimi', ['--uninstall']);
assert.ok(
!fs.existsSync(path.join(kimiRoot, 'hooks', 'package.json')),
'uninstall must remove the kimi hooks/ marker it wrote',
);
});
test('uninstall retires a pre-#2544 config-root marker', (t) => {
const root = mkTmp('msd-2544-legacy-');
t.after(() => cleanup(root));