chore: clear dead test and allowlist leftovers of dropped runtimes
Some checks failed
Tests / PR mergeability (push) Successful in 18s
Tests / Base branch health (push) Successful in 9s
Tests / Detect test scope (push) Successful in 16s
Tests / lint-tests (push) Failing after 1m43s
Tests / plugin-validate (push) Successful in 58s
Tests / test (ubuntu-latest, 24, shard 1/3) (push) Failing after 19s
Tests / test (ubuntu-latest, 24, shard 2/3) (push) Failing after 20s
Tests / test (ubuntu-latest, 24, shard 3/3) (push) Failing after 20s
Tests / test (ubuntu-latest, 24) (push) Failing after 18s
Tests / test (inert CI) (push) Has been skipped
Tests / QA loop walk (smell ratchet) (push) Failing after 19s
Tests / Coverage gate (merged shards) (push) Has been skipped
Tests / Publish emitted-baseline artifact (push) Has been skipped
Duplicate auto-close sweep / sweep (push) Successful in 19s
CI timeout budget report / report (push) Failing after 14s
Close Draft PRs (sweep) / Sweep open draft PRs (push) Successful in 9s
Dismiss Unauthorized PR Approvals / dismiss-unauthorized-approval (push) Successful in 9s
Tests / conformance test (macos-latest, 24) (push) Has been cancelled
Tests / conformance test (windows-latest, 24, shard 1/3) (push) Has been cancelled
Tests / conformance test (windows-latest, 24, shard 2/3) (push) Has been cancelled
Tests / conformance test (windows-latest, 24, shard 3/3) (push) Has been cancelled
Tests / Required tests (push) Has been cancelled

This commit is contained in:
Jakub Zych
2026-10-06 20:30:09 +02:00
parent 792139b5ed
commit fe3ed06691
83 changed files with 308 additions and 1997 deletions

View File

@@ -30,49 +30,16 @@ const SUPPORTED_RUNTIMES = installModule.allRuntimes;
const RUNTIME_INSTALL_CONTRACTS = {
claude: { surface: 'flat-skills', settings: true, hooksPackageJson: true },
antigravity: { surface: 'flat-skills', settings: true, hooksPackageJson: true },
augment: { surface: 'flat-skills', settings: true, hooksPackageJson: true },
cline: { surface: 'clinerules', settings: false, hooksPackageJson: false },
codebuddy: { surface: 'flat-skills', settings: true, hooksPackageJson: true },
// codex/cursor/windsurf: #2717 stages their .js hooks via dedicated paths
// codex/cursor: #2717 stages their .js hooks via dedicated paths
// (skipSharedHooksInstall / the !isCodex gate keep them out of the shared
// bundle) and writes the marker beside those scripts, so hooks/package.json
// is expected for all three. Measured on this tree: codex stages 3 .js hooks,
// cursor 6, windsurf 2 — each with the marker.
// is expected for both. Measured on this tree: codex stages 3 .js hooks,
// cursor 6 — each with the marker.
codex: { surface: 'flat-skills', settings: false, hooksPackageJson: true, codexConfig: true },
copilot: { surface: 'flat-skills', settings: false, hooksPackageJson: false, copilotInstructions: true },
cursor: { surface: 'flat-skills', settings: false, hooksPackageJson: true },
gemini: { surface: 'commands-msd', settings: true, hooksPackageJson: true },
hermes: { surface: 'hermes-skills', settings: true, hooksPackageJson: true },
kimi: { surface: 'kimi-skills-agents', settings: false, hooksPackageJson: false },
// #2454: Kimi Code (Node CLI) has NO custom named subagents (per official
// docs), so its install surface is skills-only (flat-skills), NOT
// kimi-skills-agents. The kimi-agents YAML layout is Python kimi-cli only.
'kimi-code': { surface: 'flat-skills', settings: false, hooksPackageJson: false },
// #2305: Kilo's native plugin spawns the staged guard hooks, so it receives
// the shared hooks bundle + the CommonJS package.json marker, like OpenCode.
// (#1821 excluded Kilo on the false premise that it had no plugin surface.)
kilo: { surface: 'flat-command', settings: false, hooksPackageJson: true },
// #2329: OpenCode discovers commands from the PLURAL `commands/` dir — the
// singular `command/` (still correct for Kilo) made all /msd-* commands
// invisible to OpenCode. commandDirName overrides the flat-command default.
// #2329: OpenCode discovers commands from the PLURAL `commands/` dir.
opencode: { surface: 'flat-command', settings: true, hooksPackageJson: true, commandDirName: 'commands' },
// #2102 Stage 1/2: pi is a PLUGIN-ONLY install (hostBehaviors.pluginOnlyInstall)
// for commands/agents/skills — NO commands/, agents/, or skills/ dir. pi's
// /msd command is registered programmatically by the native extension
// (extensions/msd.cjs) and dispatches via a bounded subprocess to
// msd-tools.cjs; it has no host-read markdown surface. Stage 2 (adversarial-
// review fix): pi's native extension DOES spawn the shared hooks/*.js bundle
// as bounded subprocesses (session_start/before_agent_start/session_before_
// compact bridges) and its /msd tokenizer requires hooks/lib/git-cmd.js, so
// `hostBehaviors.skipSharedHooksInstall` was removed — pi now receives
// hooks/ + hooks/lib/ + the {"type":"commonjs"} package.json marker, exactly
// like OpenCode and (since #2305) Kilo — architecturally identical:
// hooksSurface:'none' + a native plugin that spawns the staged hooks — NOT
// like ZCode (no plugin surface, where the same hooks are dead weight).
pi: { surface: 'plugin-only', settings: false, hooksPackageJson: true },
qwen: { surface: 'flat-skills', settings: true, hooksPackageJson: true },
trae: { surface: 'flat-skills', settings: false, hooksPackageJson: false },
windsurf: { surface: 'global-artifacts-noop', settings: false, hooksPackageJson: true },
// #1821: ZCode (hooksSurface:none, no plugin surface) no longer receives the
// dead hook scripts or the CommonJS package.json marker.
zcode: { surface: 'flat-skills', settings: false, hooksPackageJson: false },
@@ -237,40 +204,31 @@ function assertFreshInstallContract(runtime, targetDir) {
const contract = RUNTIME_INSTALL_CONTRACTS[runtime];
assert.ok(contract, `missing runtime install contract for ${runtime}`);
// #3023: the shared hooks bundle's staged directory name is per-runtime
// (hostBehaviors.sharedHooksDirName; pi renames it to `msd-hooks/` to avoid
// pi's own host-reserved `hooks/`) — resolve it the same way the installer
// (hostBehaviors.sharedHooksDirName) — resolve it the same way the installer
// does rather than hardcoding 'hooks', which is only the default.
const hooksDirName = installModule.resolveSharedHooksDirName(runtime);
if (contract.workflowPayload !== false) {
assert.equal(
fs.readFileSync(path.join(targetDir, 'msd-core', 'VERSION'), 'utf8'),
pkg.version,
`${runtime} should install the package VERSION`
);
assert.ok(
fs.existsSync(path.join(targetDir, 'msd-core', 'bin', 'msd-tools.cjs')),
`${runtime} should install the MSD tool payload`
);
assert.ok(
fs.existsSync(path.join(targetDir, 'msd-file-manifest.json')),
`${runtime} should write the install manifest`
);
assert.equal(
fs.readFileSync(path.join(targetDir, 'msd-core', 'VERSION'), 'utf8'),
pkg.version,
`${runtime} should install the package VERSION`
);
assert.ok(
fs.existsSync(path.join(targetDir, 'msd-core', 'bin', 'msd-tools.cjs')),
`${runtime} should install the MSD tool payload`
);
assert.ok(
fs.existsSync(path.join(targetDir, 'msd-file-manifest.json')),
`${runtime} should write the install manifest`
);
const manifest = JSON.parse(fs.readFileSync(path.join(targetDir, 'msd-file-manifest.json'), 'utf8'));
assert.equal(manifest.version, pkg.version, `${runtime} manifest should record the package version`);
assert.equal(manifest.mode, 'full', `${runtime} manifest should record a full install`);
assert.ok(
manifest.files['msd-core/VERSION'],
`${runtime} manifest should track the installed VERSION file`
);
} else {
assert.equal(
fs.existsSync(path.join(targetDir, 'msd-core')),
false,
`${runtime} should not install the MSD workflow payload`
);
}
const manifest = JSON.parse(fs.readFileSync(path.join(targetDir, 'msd-file-manifest.json'), 'utf8'));
assert.equal(manifest.version, pkg.version, `${runtime} manifest should record the package version`);
assert.equal(manifest.mode, 'full', `${runtime} manifest should record a full install`);
assert.ok(
manifest.files['msd-core/VERSION'],
`${runtime} manifest should track the installed VERSION file`
);
if (contract.surface === 'flat-skills') {
if (runtime === 'codex') {
@@ -295,131 +253,33 @@ function assertFreshInstallContract(runtime, targetDir) {
// the same flat-skills surface as the other runtimes.
assertHasMsdDirectory(targetDir, 'skills');
}
} else if (contract.surface === 'hermes-skills') {
// Hermes layout uses prefix: '' — skill dirs have bare stem names (no msd- prefix).
// Assert that the category dir contains at least one skill dir with SKILL.md.
const hermesMsdDir = path.join(targetDir, 'skills', 'msd');
const hermesSkillCount = fs.existsSync(hermesMsdDir)
? fs.readdirSync(hermesMsdDir, { withFileTypes: true })
.filter(e => e.isDirectory() && fs.existsSync(path.join(hermesMsdDir, e.name, 'SKILL.md')))
.length
: 0;
assert.ok(hermesSkillCount > 0, `skills/msd should contain generated MSD entries (got ${hermesSkillCount})`);
assert.ok(
fs.existsSync(path.join(targetDir, 'skills', 'msd', 'DESCRIPTION.md')),
'Hermes should install the nested MSD category description'
);
} else if (contract.surface === 'flat-command') {
// #2329: dir name is per-runtime (opencode='commands', kilo stays 'command').
// #2329: dir name is per-runtime (opencode='commands').
const commandDirName = contract.commandDirName || 'command';
assert.ok(
listDirNames(targetDir, commandDirName).some((name) => name.startsWith('msd-') && name.endsWith('.md')),
`${runtime} should install flattened command markdown files in ${commandDirName}/`
);
} else if (contract.surface === 'plugin-only') {
// #2102 Stage 1/2: pi — PLUGIN-ONLY install for commands/agents/skills
// (hostBehaviors.pluginOnlyInstall). pi's /msd command is registered
// programmatically by the native extension and dispatches via a bounded
// subprocess to msd-tools.cjs — pi has no host-read markdown surface, so
// NO commands/, agents/, or skills/ dir is written. The extension DOES
// spawn the shared hooks bundle as bounded subprocesses (Stage 2
// adversarial-review fix — hooksSurface:'none' no longer implies
// skipSharedHooksInstall for pi, mirroring OpenCode), so the bundle + the
// git-cmd.js tokenizer helper ARE part of the artifact surface now. #3023:
// that bundle is staged under `msd-hooks/` for pi (hooksDirName above), not
// the generic `hooks/` — pi reserves `hooks/` for its own deprecated
// extension location.
// #2470: the dest filename comes from pi's descriptor, and must satisfy
// pi's isExtensionFile() auto-discovery filter (.ts/.js only) — otherwise
// the file installs but pi never loads it and /msd never registers.
const piNativePlugin = JSON.parse(
fs.readFileSync(path.join(__dirname, '..', 'capabilities', 'pi', 'capability.json'), 'utf8')
).runtime.hostBehaviors.nativePlugin;
assert.ok(
piNativePlugin.file.endsWith('.ts') || piNativePlugin.file.endsWith('.js'),
`${runtime}'s extension "${piNativePlugin.file}" must end in .ts or .js for pi to discover it (#2470)`
);
assert.ok(
fs.existsSync(path.join(targetDir, piNativePlugin.dir, piNativePlugin.file)),
`${runtime} should install the native extension file at ${piNativePlugin.dir}/${piNativePlugin.file}`
);
assert.ok(
fs.existsSync(path.join(targetDir, hooksDirName, 'msd-ensure-canonical-path.js')),
`${runtime} should install the shared ${hooksDirName}/ bundle (spawned by the native extension's event bridges)`
);
assert.ok(
fs.existsSync(path.join(targetDir, hooksDirName, 'lib', 'git-cmd.js')),
`${runtime} should install ${hooksDirName}/lib/git-cmd.js (the /msd command tokenizer)`
);
assert.equal(
fs.existsSync(path.join(targetDir, 'commands')),
false,
`${runtime} should NOT install a commands/ dir (plugin-only, no host-read markdown surface)`
);
assert.equal(
fs.existsSync(path.join(targetDir, 'agents')),
false,
`${runtime} should NOT install an agents/ dir (plugin-only, no named-dispatch toolkit)`
);
assert.equal(
fs.existsSync(path.join(targetDir, 'skills')),
false,
`${runtime} should NOT install a skills/ dir (plugin-only)`
);
} else if (contract.surface === 'commands-msd') {
assert.ok(
listDirNames(targetDir, path.join('commands', 'msd')).length > 0,
`${runtime} should install commands/msd entries`
);
} else if (contract.surface === 'kimi-skills-agents') {
assertHasMsdDirectory(targetDir, 'skills');
assert.ok(
fs.existsSync(path.join(targetDir, 'agents', 'msd.yaml')),
'Kimi should install the root agent YAML'
);
assert.ok(
fs.existsSync(path.join(targetDir, 'agents', 'msd.md')),
'Kimi should install the root agent prompt'
);
assert.ok(
fs.existsSync(path.join(targetDir, 'agents', 'subagents', 'msd-executor.yaml')),
'Kimi should install MSD subagent YAML'
);
} else if (contract.surface === 'clinerules') {
// #787: Cline now uses the .clinerules/ directory form (rules at msd.md).
assert.match(
fs.readFileSync(path.join(targetDir, '.clinerules', 'msd.md'), 'utf8'),
/MSD workflows live in `msd-core\/workflows\/`/,
'Cline should install .clinerules/msd.md guidance'
);
} else if (contract.surface === 'global-artifacts-noop') {
assert.equal(
fs.existsSync(path.join(targetDir, 'skills')),
false,
`${runtime} should not install unsupported global skills artifacts`
);
assert.equal(
fs.existsSync(path.join(targetDir, 'workflows')),
false,
`${runtime} should not install unsupported global workflow artifacts`
);
}
if (contract.surface !== 'kimi-skills-agents' && contract.surface !== 'global-artifacts-noop' && contract.surface !== 'plugin-only') {
if (runtime === 'antigravity') {
// #3738: antigravity agents install under the sandboxed home's
// .gemini/config root (see the flat-skills branch above), not targetDir.
const agySandboxHomeForAgents = path.join(path.dirname(targetDir), 'home');
assert.ok(
listDirNames(path.join(agySandboxHomeForAgents, '.gemini', 'config'), 'agents').some((name) => name.startsWith('msd-')),
`${runtime} full install should install agents`
);
} else {
assert.ok(
listDirNames(targetDir, 'agents').some((name) => name.startsWith('msd-')),
`${runtime} full install should install agents`
);
}
if (runtime === 'antigravity') {
// #3738: antigravity agents install under the sandboxed home's
// .gemini/config root (see the flat-skills branch above), not targetDir.
const agySandboxHomeForAgents = path.join(path.dirname(targetDir), 'home');
assert.ok(
listDirNames(path.join(agySandboxHomeForAgents, '.gemini', 'config'), 'agents').some((name) => name.startsWith('msd-')),
`${runtime} full install should install agents`
);
} else {
assert.ok(
listDirNames(targetDir, 'agents').some((name) => name.startsWith('msd-')),
`${runtime} full install should install agents`
);
}
assert.equal(
@@ -428,9 +288,9 @@ function assertFreshInstallContract(runtime, targetDir) {
`${runtime} settings.json presence should match the runtime contract`
);
// #2544: the CommonJS marker lives in the shared hooks dir (the dir MSD
// fills with its own .js scripts — `msd-hooks/` for pi, `hooks/` for every
// other runtime, #3023), never at the config root — that file is user-owned
// territory on OpenCode/Kilo and was being clobbered on every install.
// fills with its own .js scripts — `hooks/` unless a runtime overrides it,
// #3023), never at the config root — that file is user-owned
// territory on OpenCode and was being clobbered on every install.
assert.equal(
fs.existsSync(path.join(targetDir, hooksDirName, 'package.json')),
contract.hooksPackageJson,
@@ -449,14 +309,6 @@ function assertFreshInstallContract(runtime, targetDir) {
'Codex should install config.toml with the MSD marker'
);
}
if (contract.copilotInstructions) {
assert.match(
fs.readFileSync(path.join(targetDir, 'copilot-instructions.md'), 'utf8'),
/MSD Configuration/,
'Copilot should install managed copilot instructions'
);
}
}
describe('installer migration install integration', { concurrency: false }, () => {
@@ -618,11 +470,7 @@ describe('installer migration install integration', { concurrency: false }, () =
assert.match(output, /Installing for /);
assert.match(output, /Installer migrations/);
assert.match(output, /removed\s+hooks\/statusline\.js/);
if (runtime === 'kimi') {
assert.match(output, /Generated Kimi root agent/);
} else {
assert.match(output, /Installed workflow assets/);
}
assert.match(output, /Installed workflow assets/);
assert.match(output, /Done!/);
assert.equal(fs.existsSync(path.join(targetDir, 'hooks/statusline.js')), false);