* fix(#1151): drive codex sandbox_mode emission from runtime descriptor sandboxTier axis The sandboxTier runtime-capability axis was cosmetic: declared and validated on all 16 descriptors but read by nothing. The codex per-agent sandbox_mode line was emitted unconditionally from the hardcoded CODEX_AGENT_SANDBOX map, so the descriptor field drove no behaviour (ADR-857 audit finding F10; the "rides along in 5e/5g" promise in ADR-1016 §8 never landed). Make the axis load-bearing: - resolveInstallPlan projects sandboxTier as a 7th InstallPlan axis and fails loud (throws) on a missing/invalid value rather than coercing to 'none'. - installCodexConfig / generateCodexAgentToml gate sandbox_mode emission on sandboxTier !== 'none'. - The per-agent CODEX_AGENT_SANDBOX map is kept: it is GSD agent policy, not a runtime-descriptor property (different layer). Full removal of that map is tracked under #1138 (phase-6 descriptor-residue removal). For codex (sandboxTier === 'codex-agent-sandbox') the emitted TOML is byte-identical to before; for 'none' runtimes sandbox_mode is omitted. Adds leaf, projection, and installCodexConfig threading-seam regression tests; updates the enh-1082 InstallPlan golden master with sandboxTier for all 16 runtimes. Confirmed hypothesis: schema-first vocabulary closure outran consumer wiring, with no conformance gate to catch the orphaned axis. Closes #1151 Refs #857, #1138 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(#1151): stamp changeset with PR number 1152 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
239 lines
7.3 KiB
JavaScript
239 lines
7.3 KiB
JavaScript
'use strict';
|
|
|
|
/**
|
|
* Golden-master test for resolveInstallPlan — ADR-857 phase 5g capstone.
|
|
*
|
|
* Pins the exact InstallPlan shape for all 16 runtimes to guard against
|
|
* descriptor drift. Derived from actual resolveInstallPlan output at the time
|
|
* the seam was introduced (2026-06-11). Behavioral: calls the exported
|
|
* function and asserts on typed fields — no source-grep.
|
|
*/
|
|
|
|
const { describe, it } = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const { resolveInstallPlan } = require('../gsd-core/bin/lib/runtime-config-adapter-registry.cjs');
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Frozen golden-master table — derived from actual resolveInstallPlan output
|
|
// ---------------------------------------------------------------------------
|
|
|
|
const EXPECTED = {
|
|
claude: {
|
|
runtime: 'claude',
|
|
installSurface: 'settings-json',
|
|
writesSharedSettings: true,
|
|
finishPermissionWriter: null,
|
|
hookEvents: 'claude',
|
|
extendedHookEvents: ['SubagentStop', 'Stop', 'PreCompact', 'FileChanged'],
|
|
hooksSurface: 'settings-json',
|
|
sandboxTier: 'none',
|
|
},
|
|
codex: {
|
|
runtime: 'codex',
|
|
installSurface: 'codex-toml',
|
|
writesSharedSettings: false,
|
|
finishPermissionWriter: null,
|
|
hookEvents: 'claude',
|
|
extendedHookEvents: [],
|
|
hooksSurface: 'codex-hooks-json',
|
|
sandboxTier: 'codex-agent-sandbox',
|
|
},
|
|
antigravity: {
|
|
runtime: 'antigravity',
|
|
installSurface: 'settings-json',
|
|
writesSharedSettings: true,
|
|
finishPermissionWriter: null,
|
|
hookEvents: 'gemini',
|
|
extendedHookEvents: [],
|
|
hooksSurface: 'settings-json',
|
|
sandboxTier: 'none',
|
|
},
|
|
gemini: {
|
|
runtime: 'gemini',
|
|
installSurface: 'settings-json',
|
|
writesSharedSettings: true,
|
|
finishPermissionWriter: null,
|
|
hookEvents: 'gemini',
|
|
extendedHookEvents: ['BeforeAgent', 'AfterAgent', 'BeforeModel'],
|
|
hooksSurface: 'settings-json',
|
|
sandboxTier: 'none',
|
|
},
|
|
cursor: {
|
|
runtime: 'cursor',
|
|
installSurface: 'cursor-hooks-json',
|
|
writesSharedSettings: false,
|
|
finishPermissionWriter: null,
|
|
hookEvents: 'claude',
|
|
extendedHookEvents: [],
|
|
hooksSurface: 'cursor-hooks-json',
|
|
sandboxTier: 'none',
|
|
},
|
|
opencode: {
|
|
runtime: 'opencode',
|
|
installSurface: 'settings-json',
|
|
writesSharedSettings: true,
|
|
finishPermissionWriter: 'opencode',
|
|
hookEvents: undefined,
|
|
extendedHookEvents: [],
|
|
hooksSurface: 'none',
|
|
sandboxTier: 'none',
|
|
},
|
|
kilo: {
|
|
runtime: 'kilo',
|
|
installSurface: 'settings-json',
|
|
writesSharedSettings: false,
|
|
finishPermissionWriter: 'kilo',
|
|
hookEvents: undefined,
|
|
extendedHookEvents: [],
|
|
hooksSurface: 'none',
|
|
sandboxTier: 'none',
|
|
},
|
|
copilot: {
|
|
runtime: 'copilot',
|
|
installSurface: 'copilot-instructions',
|
|
writesSharedSettings: false,
|
|
finishPermissionWriter: null,
|
|
hookEvents: undefined,
|
|
extendedHookEvents: [],
|
|
hooksSurface: 'copilot-inline',
|
|
sandboxTier: 'none',
|
|
},
|
|
augment: {
|
|
runtime: 'augment',
|
|
installSurface: 'settings-json',
|
|
writesSharedSettings: true,
|
|
finishPermissionWriter: null,
|
|
hookEvents: 'claude',
|
|
extendedHookEvents: [],
|
|
hooksSurface: 'settings-json',
|
|
sandboxTier: 'none',
|
|
},
|
|
trae: {
|
|
runtime: 'trae',
|
|
installSurface: 'profile-marker-only',
|
|
writesSharedSettings: false,
|
|
finishPermissionWriter: null,
|
|
hookEvents: undefined,
|
|
extendedHookEvents: [],
|
|
hooksSurface: 'none',
|
|
sandboxTier: 'none',
|
|
},
|
|
qwen: {
|
|
runtime: 'qwen',
|
|
installSurface: 'settings-json',
|
|
writesSharedSettings: true,
|
|
finishPermissionWriter: null,
|
|
hookEvents: 'claude',
|
|
extendedHookEvents: ['SubagentStop', 'Stop', 'PreCompact'],
|
|
hooksSurface: 'settings-json',
|
|
sandboxTier: 'none',
|
|
},
|
|
hermes: {
|
|
runtime: 'hermes',
|
|
installSurface: 'settings-json',
|
|
writesSharedSettings: true,
|
|
finishPermissionWriter: null,
|
|
hookEvents: 'claude',
|
|
extendedHookEvents: [],
|
|
hooksSurface: 'settings-json',
|
|
sandboxTier: 'none',
|
|
},
|
|
codebuddy: {
|
|
runtime: 'codebuddy',
|
|
installSurface: 'settings-json',
|
|
writesSharedSettings: true,
|
|
finishPermissionWriter: null,
|
|
hookEvents: 'claude',
|
|
extendedHookEvents: [],
|
|
hooksSurface: 'settings-json',
|
|
sandboxTier: 'none',
|
|
},
|
|
cline: {
|
|
runtime: 'cline',
|
|
installSurface: 'cline-rules',
|
|
writesSharedSettings: false,
|
|
finishPermissionWriter: null,
|
|
hookEvents: undefined,
|
|
extendedHookEvents: [],
|
|
hooksSurface: 'cline-rules',
|
|
sandboxTier: 'none',
|
|
},
|
|
kimi: {
|
|
runtime: 'kimi',
|
|
installSurface: 'profile-marker-only',
|
|
writesSharedSettings: false,
|
|
finishPermissionWriter: null,
|
|
hookEvents: undefined,
|
|
extendedHookEvents: [],
|
|
hooksSurface: 'none',
|
|
sandboxTier: 'none',
|
|
},
|
|
windsurf: {
|
|
runtime: 'windsurf',
|
|
installSurface: 'profile-marker-only',
|
|
writesSharedSettings: false,
|
|
finishPermissionWriter: null,
|
|
hookEvents: undefined,
|
|
extendedHookEvents: [],
|
|
hooksSurface: 'none',
|
|
sandboxTier: 'none',
|
|
},
|
|
};
|
|
|
|
const ALL_RUNTIMES = Object.keys(EXPECTED);
|
|
|
|
describe('resolveInstallPlan — ADR-857 phase 5g golden master', () => {
|
|
it('covers exactly 16 runtimes', () => {
|
|
assert.strictEqual(ALL_RUNTIMES.length, 16);
|
|
});
|
|
|
|
for (const runtime of ALL_RUNTIMES) {
|
|
it(`resolveInstallPlan('${runtime}') matches frozen plan`, () => {
|
|
const actual = resolveInstallPlan(runtime);
|
|
assert.deepStrictEqual(actual, EXPECTED[runtime],
|
|
`InstallPlan for '${runtime}' drifted from golden master`);
|
|
});
|
|
}
|
|
|
|
it('resolveInstallPlan throws TypeError for unknown runtime', () => {
|
|
assert.throws(
|
|
() => resolveInstallPlan('bogus'),
|
|
(err) => err instanceof TypeError && /bogus/.test(err.message),
|
|
);
|
|
});
|
|
|
|
it('extendedHookEvents is always an array for every runtime', () => {
|
|
for (const runtime of ALL_RUNTIMES) {
|
|
const plan = resolveInstallPlan(runtime);
|
|
assert.ok(Array.isArray(plan.extendedHookEvents),
|
|
`${runtime}: extendedHookEvents should be an array`);
|
|
}
|
|
});
|
|
|
|
it('hooksSurface is always a non-empty string for every runtime', () => {
|
|
for (const runtime of ALL_RUNTIMES) {
|
|
const plan = resolveInstallPlan(runtime);
|
|
assert.strictEqual(typeof plan.hooksSurface, 'string',
|
|
`${runtime}: hooksSurface should be a string`);
|
|
assert.ok(plan.hooksSurface.length > 0,
|
|
`${runtime}: hooksSurface should not be empty`);
|
|
}
|
|
});
|
|
|
|
it('parity: resolveInstallPlan config-intent fields match resolveRuntimeConfigIntent', () => {
|
|
// Guard that resolveInstallPlan composes resolveRuntimeConfigIntent correctly —
|
|
// any drift between the two would silently break install().
|
|
const { resolveRuntimeConfigIntent } = require('../gsd-core/bin/lib/runtime-config-adapter-registry.cjs');
|
|
for (const runtime of ALL_RUNTIMES) {
|
|
const plan = resolveInstallPlan(runtime);
|
|
const intent = resolveRuntimeConfigIntent(runtime);
|
|
assert.strictEqual(plan.installSurface, intent.installSurface,
|
|
`${runtime}: installSurface mismatch between plan and intent`);
|
|
assert.strictEqual(plan.writesSharedSettings, intent.writesSharedSettings,
|
|
`${runtime}: writesSharedSettings mismatch`);
|
|
assert.strictEqual(plan.finishPermissionWriter, intent.finishPermissionWriter,
|
|
`${runtime}: finishPermissionWriter mismatch`);
|
|
}
|
|
});
|
|
});
|