refactor: hard-fork GSD -> MSD (Make Software Done)
Mechanical rename produced by scripts/msd-rename.cjs: gsd/Gsd/GSD -> msd/Msd/MSD across contents and paths, upstream package/repo coordinates -> @golem15/msd-core and golem15com/msd-core. Deep links into upstream history, sibling upstream packages, the GSD-2 import feature, CHANGELOG.md and .changeset/ are kept as-is. Hand edits on top: MSD block-letter banner and logos, LICENSE copyright line, package/plugin identity, regenerated lockfile, install-tree fixtures, derived registries and benchmark baseline; migration checksum baseline re-locked (MSD keeps its own install state, so no install had applied the old sums); sort-order and regex-escaped expectations in tests adjusted.
This commit is contained in:
@@ -61,7 +61,7 @@
|
||||
* (fixed the same way — its `local` artifactLayout previously declared
|
||||
* no `agents` kind at all, so the deleted inline loop's implicit
|
||||
* scope-gate was silently replaced with NO gate, dropping every
|
||||
* kimi-code local install's agents/gsd-*.md entirely).
|
||||
* kimi-code local install's agents/msd-*.md entirely).
|
||||
*
|
||||
* H8 is mandatory, not optional: a parity harness never demonstrated failing
|
||||
* is decoration. It feeds the oracle a DELIBERATELY WRONG (but real,
|
||||
@@ -95,7 +95,7 @@ const path = require('node:path');
|
||||
const { cleanup, createTempDir, sandboxHome } = require('./helpers.cjs');
|
||||
|
||||
const REPO_ROOT = path.join(__dirname, '..');
|
||||
const LIB_DIR = path.join(REPO_ROOT, 'gsd-core', 'bin', 'lib');
|
||||
const LIB_DIR = path.join(REPO_ROOT, 'msd-core', 'bin', 'lib');
|
||||
|
||||
const runtimeArtifactConversion = require(path.join(LIB_DIR, 'runtime-artifact-conversion.cjs'));
|
||||
const installModelOverrideResolver = require(path.join(LIB_DIR, 'install-model-override-resolver.cjs'));
|
||||
@@ -113,24 +113,24 @@ const installBin = require(path.join(REPO_ROOT, 'bin', 'install.js'));
|
||||
* ~/.claude/ + $HOME/.claude/ (anchored + bare) path forms, a Co-Authored-By
|
||||
* trailer, and one row-J4 "disallowedTools hit" agent name plus one "miss". */
|
||||
const SAMPLE_AGENTS = {
|
||||
'gsd-planner.md': [
|
||||
'msd-planner.md': [
|
||||
'---',
|
||||
'name: gsd-planner',
|
||||
'description: Plans phases for GSD workflows.',
|
||||
'name: msd-planner',
|
||||
'description: Plans phases for MSD workflows.',
|
||||
'tools: Read, Write, Edit, Bash',
|
||||
'---',
|
||||
'',
|
||||
'Reads @~/.claude/gsd-core/commands/gsd/plan-phase.md and $HOME/.claude/CLAUDE.md.',
|
||||
'Reads @~/.claude/msd-core/commands/msd/plan-phase.md and $HOME/.claude/CLAUDE.md.',
|
||||
'Bare forms too: ~/.claude and $HOME/.claude.',
|
||||
'References Claude Code and CLAUDE.md and .claude/settings.json.',
|
||||
'',
|
||||
'Co-Authored-By: Claude <noreply@anthropic.com>',
|
||||
'',
|
||||
].join('\n'),
|
||||
'gsd-plan-checker.md': [
|
||||
'msd-plan-checker.md': [
|
||||
'---',
|
||||
'name: gsd-plan-checker',
|
||||
'description: Checks plans for GSD workflows.',
|
||||
'name: msd-plan-checker',
|
||||
'description: Checks plans for MSD workflows.',
|
||||
'tools: Read, Grep, Glob',
|
||||
'---',
|
||||
'',
|
||||
@@ -140,27 +140,27 @@ const SAMPLE_AGENTS = {
|
||||
};
|
||||
|
||||
function buildSourceTree(agentFiles) {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-agent-parity-src-'));
|
||||
const commandsGsd = path.join(root, 'commands', 'gsd');
|
||||
fs.mkdirSync(commandsGsd, { recursive: true });
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-agent-parity-src-'));
|
||||
const commandsMsd = path.join(root, 'commands', 'msd');
|
||||
fs.mkdirSync(commandsMsd, { recursive: true });
|
||||
// Runtime Surface source providers are atomic across every source class a
|
||||
// layout needs. Keep this marker fixture complete for commands + agents so
|
||||
// the installer resolver does not correctly fall back to the package tree.
|
||||
fs.writeFileSync(path.join(commandsGsd, 'fixture-command.md'), '# Fixture command\n');
|
||||
fs.writeFileSync(path.join(commandsMsd, 'fixture-command.md'), '# Fixture command\n');
|
||||
const agentsDir = path.join(root, 'agents');
|
||||
fs.mkdirSync(agentsDir, { recursive: true });
|
||||
for (const [name, content] of Object.entries(agentFiles)) {
|
||||
fs.writeFileSync(path.join(agentsDir, name), content);
|
||||
}
|
||||
return { root, commandsGsd, agentsDir };
|
||||
return { root, commandsMsd, agentsDir };
|
||||
}
|
||||
|
||||
/** A fresh "install destination" dir with a `.gsd-source` marker pointing at
|
||||
* `commandsGsd` — the same marker findInstallSourceRoot/findAgentsSourceRoot
|
||||
/** A fresh "install destination" dir with a `.msd-source` marker pointing at
|
||||
* `commandsMsd` — the same marker findInstallSourceRoot/findAgentsSourceRoot
|
||||
* read (runtime-artifact-layout.cts). */
|
||||
function buildTargetDir(commandsGsd) {
|
||||
const targetDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-agent-parity-dest-'));
|
||||
fs.writeFileSync(path.join(targetDir, '.gsd-source'), commandsGsd);
|
||||
function buildTargetDir(commandsMsd) {
|
||||
const targetDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-agent-parity-dest-'));
|
||||
fs.writeFileSync(path.join(targetDir, '.msd-source'), commandsMsd);
|
||||
return targetDir;
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ function computeExpectedOutput(runtime, agentsDir, ctx, converterNameOverride) {
|
||||
if (!entry.isFile() || !entry.name.endsWith('.md')) continue;
|
||||
const agentSourcePath = path.join(agentsDir, entry.name);
|
||||
let content = fs.readFileSync(agentSourcePath, 'utf8');
|
||||
// Step 0 (#2995): strip gsd:section markers — same order the real
|
||||
// Step 0 (#2995): strip msd:section markers — same order the real
|
||||
// pipeline uses (stageAgentsForRuntimeWithConverter, install-profiles.cts).
|
||||
content = composeWorkflow(content, { sourcePath: agentSourcePath });
|
||||
const agentName = runtimeArtifactConversion.deriveAgentName(entry.name);
|
||||
@@ -229,8 +229,8 @@ function computeExpectedOutput(runtime, agentsDir, ctx, converterNameOverride) {
|
||||
if (MODEL_OVERRIDE_CONVERTER_NAMES.has(converterName)) {
|
||||
const modelOverride = installModelOverrideResolver.resolveAgentModelOverride(
|
||||
agentName,
|
||||
installModelOverrideResolver.readGsdEffectiveModelOverrides(targetDir),
|
||||
installModelOverrideResolver.readGsdRuntimeProfileResolver(targetDir),
|
||||
installModelOverrideResolver.readMsdEffectiveModelOverrides(targetDir),
|
||||
installModelOverrideResolver.readMsdRuntimeProfileResolver(targetDir),
|
||||
);
|
||||
content = fn(content, { isAgent: true, modelOverride });
|
||||
} else {
|
||||
@@ -244,7 +244,7 @@ function computeExpectedOutput(runtime, agentsDir, ctx, converterNameOverride) {
|
||||
content = runtimeArtifactConversion.normalizeAgentBodyForRuntime(
|
||||
content,
|
||||
runtime,
|
||||
runtimeArtifactConversion.readGsdCommandNames(),
|
||||
runtimeArtifactConversion.readMsdCommandNames(),
|
||||
);
|
||||
out.set(entry.name, content);
|
||||
}
|
||||
@@ -310,13 +310,13 @@ const J8_OVERRIDE_MODEL = 'shared/explicit-model';
|
||||
* model_overrides block for `runtime` through the real descriptor path.
|
||||
*/
|
||||
function _stageWithModelOverride(runtime, overrideModel) {
|
||||
const agentFiles = { 'gsd-planner.md': SAMPLE_AGENTS['gsd-planner.md'] };
|
||||
const { commandsGsd, root } = buildSourceTree(agentFiles);
|
||||
const targetDir = buildTargetDir(commandsGsd);
|
||||
const agentFiles = { 'msd-planner.md': SAMPLE_AGENTS['msd-planner.md'] };
|
||||
const { commandsMsd, root } = buildSourceTree(agentFiles);
|
||||
const targetDir = buildTargetDir(commandsMsd);
|
||||
fs.mkdirSync(path.join(targetDir, '.planning'), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(targetDir, '.planning', 'config.json'),
|
||||
JSON.stringify({ model_overrides: { 'gsd-planner': overrideModel } }),
|
||||
JSON.stringify({ model_overrides: { 'msd-planner': overrideModel } }),
|
||||
);
|
||||
try {
|
||||
const ctx = { pathPrefix: `${targetDir}/`, attribution: undefined, targetDir };
|
||||
@@ -328,8 +328,8 @@ function _stageWithModelOverride(runtime, overrideModel) {
|
||||
}
|
||||
|
||||
function comparePipelines(runtime, scope, converterNameOverride) {
|
||||
const { commandsGsd, agentsDir, root } = buildSourceTree(SAMPLE_AGENTS);
|
||||
const targetDir = buildTargetDir(commandsGsd);
|
||||
const { commandsMsd, agentsDir, root } = buildSourceTree(SAMPLE_AGENTS);
|
||||
const targetDir = buildTargetDir(commandsMsd);
|
||||
try {
|
||||
const ctx = { pathPrefix: `${targetDir}/`, attribution: undefined, targetDir };
|
||||
const expected = computeExpectedOutput(runtime, agentsDir, ctx, converterNameOverride);
|
||||
@@ -375,8 +375,8 @@ for (const [runtime, scope] of RUNTIME_SCOPE_PAIRS) {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
test('agent-descriptor-parity: H7 — a filename-only divergence fails the harness', (t) => {
|
||||
const { commandsGsd, agentsDir, root } = buildSourceTree(SAMPLE_AGENTS);
|
||||
const targetDir = buildTargetDir(commandsGsd);
|
||||
const { commandsMsd, agentsDir, root } = buildSourceTree(SAMPLE_AGENTS);
|
||||
const targetDir = buildTargetDir(commandsMsd);
|
||||
t.after(() => {
|
||||
cleanup(root);
|
||||
cleanup(targetDir);
|
||||
@@ -408,8 +408,8 @@ test('agent-descriptor-parity: H8 — a deliberately-wrong (but real, allowliste
|
||||
// still uses hermes's real (correct) converter, so this proves: IF
|
||||
// capability.json ever regressed to the wrong name, THIS harness's H row
|
||||
// for hermes would go red exactly like this.
|
||||
const { commandsGsd, agentsDir, root } = buildSourceTree(SAMPLE_AGENTS);
|
||||
const targetDir = buildTargetDir(commandsGsd);
|
||||
const { commandsMsd, agentsDir, root } = buildSourceTree(SAMPLE_AGENTS);
|
||||
const targetDir = buildTargetDir(commandsMsd);
|
||||
t.after(() => {
|
||||
cleanup(root);
|
||||
cleanup(targetDir);
|
||||
@@ -426,7 +426,7 @@ test('agent-descriptor-parity: H8 — a deliberately-wrong (but real, allowliste
|
||||
observedDiff = err.message;
|
||||
}
|
||||
assert.equal(threw, true, 'H8 FAILED: the harness did not go red for a deliberately-wrong expected converter');
|
||||
assert.match(observedDiff, /content diverged for gsd-(planner|plan-checker)\.md/, 'expected the content-diverged assertion to name the mismatched file');
|
||||
assert.match(observedDiff, /content diverged for msd-(planner|plan-checker)\.md/, 'expected the content-diverged assertion to name the mismatched file');
|
||||
// Verbatim red-proof output for the record (see CHANGES report):
|
||||
console.log(`H8 red-proof observed: ${observedDiff}`);
|
||||
});
|
||||
@@ -436,16 +436,16 @@ test('agent-descriptor-parity: H8 — a deliberately-wrong (but real, allowliste
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
test('agent-descriptor-parity: I3 — deriveAgentName matches the pipeline exactly, including a no-.md-suffix boundary', () => {
|
||||
assert.equal(runtimeArtifactConversion.deriveAgentName('gsd-planner.md'), 'gsd-planner');
|
||||
assert.equal(runtimeArtifactConversion.deriveAgentName('msd-planner.md'), 'msd-planner');
|
||||
// Boundary: a filename with no trailing .md is returned unchanged (the
|
||||
// regex has nothing to match) — matches `entry.name.replace(/\.md$/, '')`.
|
||||
assert.equal(runtimeArtifactConversion.deriveAgentName('gsd-planner'), 'gsd-planner');
|
||||
assert.equal(runtimeArtifactConversion.deriveAgentName('gsd-planner.MD'), 'gsd-planner.MD');
|
||||
assert.equal(runtimeArtifactConversion.deriveAgentName('msd-planner'), 'msd-planner');
|
||||
assert.equal(runtimeArtifactConversion.deriveAgentName('msd-planner.MD'), 'msd-planner.MD');
|
||||
});
|
||||
|
||||
test('agent-descriptor-parity: I2 — real descriptor path with no agentCtx is unaffected (converter-only)', (t) => {
|
||||
const { commandsGsd, agentsDir, root } = buildSourceTree(SAMPLE_AGENTS);
|
||||
const targetDir = buildTargetDir(commandsGsd);
|
||||
const { commandsMsd, agentsDir, root } = buildSourceTree(SAMPLE_AGENTS);
|
||||
const targetDir = buildTargetDir(commandsMsd);
|
||||
t.after(() => {
|
||||
cleanup(root);
|
||||
cleanup(targetDir);
|
||||
@@ -455,8 +455,8 @@ test('agent-descriptor-parity: I2 — real descriptor path with no agentCtx is u
|
||||
const agentsKindEntry = realLayout.kinds.find((k) => k.kind === 'agents');
|
||||
const stagedDir = agentsKindEntry.stage({ name: 'full', skills: '*', agents: new Set() }); // no agentCtx
|
||||
t.after(() => cleanup(stagedDir));
|
||||
const planner = fs.readFileSync(path.join(stagedDir, 'gsd-planner.md'), 'utf8');
|
||||
const original = fs.readFileSync(path.join(agentsDir, 'gsd-planner.md'), 'utf8');
|
||||
const planner = fs.readFileSync(path.join(stagedDir, 'msd-planner.md'), 'utf8');
|
||||
const original = fs.readFileSync(path.join(agentsDir, 'msd-planner.md'), 'utf8');
|
||||
assert.equal(planner, original, 'no agentCtx must leave content byte-identical to source (converter:null == identity)');
|
||||
});
|
||||
|
||||
@@ -465,8 +465,8 @@ test('agent-descriptor-parity: I2 — real descriptor path with no agentCtx is u
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
test('agent-descriptor-parity: J1 — claude effort is injected via applyAgentFrontmatterExtensions', () => {
|
||||
const content = '---\nname: gsd-planner\ndescription: x\n---\n\nBody.\n';
|
||||
const viaShared = runtimeArtifactConversion.applyAgentFrontmatterExtensions(content, { runtime: 'claude', agentName: 'gsd-planner', targetDir: null });
|
||||
const content = '---\nname: msd-planner\ndescription: x\n---\n\nBody.\n';
|
||||
const viaShared = runtimeArtifactConversion.applyAgentFrontmatterExtensions(content, { runtime: 'claude', agentName: 'msd-planner', targetDir: null });
|
||||
assert.match(viaShared, /^effort: /m, 'expected an effort: key to be injected for claude');
|
||||
});
|
||||
|
||||
@@ -476,20 +476,20 @@ test('agent-descriptor-parity: J2 — effort resolving to inherit writes NO effo
|
||||
// with it) and never called applyAgentFrontmatterExtensions at all — so
|
||||
// deleting the `universalEffort !== 'inherit'` guard at
|
||||
// runtime-artifact-conversion.cts:3504 left this row green. This revision
|
||||
// writes a REAL .planning/config.json under targetDir (readGsdEffectiveEffortConfig
|
||||
// writes a REAL .planning/config.json under targetDir (readMsdEffectiveEffortConfig
|
||||
// walks up from targetDir looking for it — install-effort-resolver.cts)
|
||||
// and calls the REAL applyAgentFrontmatterExtensions end to end, so removing
|
||||
// that guard makes THIS assertion fail (verified: red with the guard
|
||||
// removed, green with it restored — see CHANGES report).
|
||||
const targetDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-agent-parity-j2-'));
|
||||
const targetDir = fs.mkdtempSync(path.join(os.tmpdir(), 'msd-agent-parity-j2-'));
|
||||
t.after(() => cleanup(targetDir));
|
||||
fs.mkdirSync(path.join(targetDir, '.planning'), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(targetDir, '.planning', 'config.json'),
|
||||
JSON.stringify({ effort: { agent_overrides: { 'gsd-inherit-agent': 'inherit' } } }),
|
||||
JSON.stringify({ effort: { agent_overrides: { 'msd-inherit-agent': 'inherit' } } }),
|
||||
);
|
||||
const content = '---\nname: gsd-inherit-agent\ndescription: x\n---\n\nBody.\n';
|
||||
const out = runtimeArtifactConversion.applyAgentFrontmatterExtensions(content, { runtime: 'claude', agentName: 'gsd-inherit-agent', targetDir });
|
||||
const content = '---\nname: msd-inherit-agent\ndescription: x\n---\n\nBody.\n';
|
||||
const out = runtimeArtifactConversion.applyAgentFrontmatterExtensions(content, { runtime: 'claude', agentName: 'msd-inherit-agent', targetDir });
|
||||
assert.doesNotMatch(out, /^effort:/m, 'an agent resolving to "inherit" must get no effort: key at all — not even effort: inherit');
|
||||
// Sanity: injectEffortFrontmatter itself is dumb and WOULD write the
|
||||
// literal if called with it — the guard is applyAgentFrontmatterExtensions
|
||||
@@ -498,18 +498,18 @@ test('agent-descriptor-parity: J2 — effort resolving to inherit writes NO effo
|
||||
});
|
||||
|
||||
test('agent-descriptor-parity: J3 — a runtime NOT declaring agentFrontmatterExtensions gets nothing injected', () => {
|
||||
const content = '---\nname: gsd-plan-checker\ndescription: x\n---\n\nBody.\n';
|
||||
const out = runtimeArtifactConversion.applyAgentFrontmatterExtensions(content, { runtime: 'opencode', agentName: 'gsd-plan-checker', targetDir: null });
|
||||
const content = '---\nname: msd-plan-checker\ndescription: x\n---\n\nBody.\n';
|
||||
const out = runtimeArtifactConversion.applyAgentFrontmatterExtensions(content, { runtime: 'opencode', agentName: 'msd-plan-checker', targetDir: null });
|
||||
assert.equal(out, content, 'opencode declares no agentFrontmatterExtensions — output must be byte-identical to input');
|
||||
});
|
||||
|
||||
test('agent-descriptor-parity: J4 — disallowedTools injected only on a READONLY_AGENT_DISALLOWED_TOOLS hit', () => {
|
||||
const content = '---\nname: gsd-plan-checker\ndescription: x\n---\n\nBody.\n';
|
||||
const hit = runtimeArtifactConversion.applyAgentFrontmatterExtensions(content, { runtime: 'claude', agentName: 'gsd-plan-checker', targetDir: null });
|
||||
assert.match(hit, /^disallowedTools: /m, 'gsd-plan-checker is a declared read-only agent — expected a disallowedTools hit');
|
||||
const content = '---\nname: msd-plan-checker\ndescription: x\n---\n\nBody.\n';
|
||||
const hit = runtimeArtifactConversion.applyAgentFrontmatterExtensions(content, { runtime: 'claude', agentName: 'msd-plan-checker', targetDir: null });
|
||||
assert.match(hit, /^disallowedTools: /m, 'msd-plan-checker is a declared read-only agent — expected a disallowedTools hit');
|
||||
|
||||
const missContent = '---\nname: gsd-not-a-readonly-agent\ndescription: x\n---\n\nBody.\n';
|
||||
const miss = runtimeArtifactConversion.applyAgentFrontmatterExtensions(missContent, { runtime: 'claude', agentName: 'gsd-not-a-readonly-agent', targetDir: null });
|
||||
const missContent = '---\nname: msd-not-a-readonly-agent\ndescription: x\n---\n\nBody.\n';
|
||||
const miss = runtimeArtifactConversion.applyAgentFrontmatterExtensions(missContent, { runtime: 'claude', agentName: 'msd-not-a-readonly-agent', targetDir: null });
|
||||
assert.doesNotMatch(miss, /^disallowedTools:/m, 'an agent absent from READONLY_AGENT_DISALLOWED_TOOLS must get no disallowedTools key');
|
||||
});
|
||||
|
||||
@@ -518,24 +518,24 @@ test('agent-descriptor-parity: J4 — disallowedTools injected only on a READONL
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
test('agent-descriptor-parity: J5 — explicit model_overrides[agent] wins (highest precedence)', () => {
|
||||
const modelOverrides = { 'gsd-planner': 'anthropic/explicit-model' };
|
||||
const modelOverrides = { 'msd-planner': 'anthropic/explicit-model' };
|
||||
const runtimeResolver = { resolve: () => ({ model: 'anthropic/tier-model' }) }; // would win if precedence were wrong
|
||||
const result = installModelOverrideResolver.resolveAgentModelOverride('gsd-planner', modelOverrides, runtimeResolver);
|
||||
const result = installModelOverrideResolver.resolveAgentModelOverride('msd-planner', modelOverrides, runtimeResolver);
|
||||
assert.equal(result, 'anthropic/explicit-model');
|
||||
});
|
||||
|
||||
test('agent-descriptor-parity: J6 — falls back to the runtime tier resolver when no explicit override exists', () => {
|
||||
const runtimeResolver = { resolve: (agentName) => (agentName === 'gsd-planner' ? { model: 'anthropic/tier-model' } : null) };
|
||||
const result = installModelOverrideResolver.resolveAgentModelOverride('gsd-planner', null, runtimeResolver);
|
||||
const runtimeResolver = { resolve: (agentName) => (agentName === 'msd-planner' ? { model: 'anthropic/tier-model' } : null) };
|
||||
const result = installModelOverrideResolver.resolveAgentModelOverride('msd-planner', null, runtimeResolver);
|
||||
assert.equal(result, 'anthropic/tier-model');
|
||||
});
|
||||
|
||||
test('agent-descriptor-parity: J7 — neither configured resolves to null (omit), never "" or the string "null"', () => {
|
||||
const result = installModelOverrideResolver.resolveAgentModelOverride('gsd-planner', null, null);
|
||||
const result = installModelOverrideResolver.resolveAgentModelOverride('msd-planner', null, null);
|
||||
assert.equal(result, null);
|
||||
assert.notEqual(result, '');
|
||||
const contentWithoutModelOverride = installBin.convertClaudeToOpencodeFrontmatter(
|
||||
'---\nname: gsd-planner\ndescription: x\ntools: Read\n---\n\nBody.\n',
|
||||
'---\nname: msd-planner\ndescription: x\ntools: Read\n---\n\nBody.\n',
|
||||
{ isAgent: true, modelOverride: result },
|
||||
);
|
||||
assert.doesNotMatch(contentWithoutModelOverride, /^model:/m, 'an omitted override must not appear as a model: key at all');
|
||||
@@ -558,11 +558,11 @@ test('agent-descriptor-parity: J8 — kilo and opencode both resolve model overr
|
||||
// metachar-bearing value would silently widen the match).
|
||||
const expectedModelLine = `model: ${J8_OVERRIDE_MODEL}`;
|
||||
assert.ok(
|
||||
kiloOut.get('gsd-planner.md').split('\n').some((line) => line.trim() === expectedModelLine),
|
||||
kiloOut.get('msd-planner.md').split('\n').some((line) => line.trim() === expectedModelLine),
|
||||
'kilo must apply the shared model override via the real descriptor path',
|
||||
);
|
||||
assert.ok(
|
||||
opencodeOut.get('gsd-planner.md').split('\n').some((line) => line.trim() === expectedModelLine),
|
||||
opencodeOut.get('msd-planner.md').split('\n').some((line) => line.trim() === expectedModelLine),
|
||||
'opencode must apply the SAME shared model override via the real descriptor path',
|
||||
);
|
||||
});
|
||||
@@ -636,16 +636,16 @@ test('agent-descriptor-parity: K1 — every registry runtime declaring an agents
|
||||
// #3712: this loop reaches `codex`, whose global skills kind declares a `home`
|
||||
// override (`.agents`) resolved from os.homedir() rather than from targetDir.
|
||||
// Sandboxing targetDir alone does NOT contain it — before this line the call
|
||||
// below pruned every gsd-* skill from the developer's REAL ~/.agents/skills
|
||||
// below pruned every msd-* skill from the developer's REAL ~/.agents/skills
|
||||
// (71 -> 0) while the suite still exited 0. Sandbox HOME for the whole loop so
|
||||
// codex's skills land in <homeDir>/.agents/skills inside a temp dir we clean.
|
||||
const homeDir = createTempDir('gsd-adp-home-');
|
||||
const homeDir = createTempDir('msd-adp-home-');
|
||||
t.after(() => cleanup(homeDir));
|
||||
sandboxHome(t, homeDir);
|
||||
|
||||
for (const runtime of runtimesWithAgentsKind) {
|
||||
const { commandsGsd, root } = buildSourceTree(SAMPLE_AGENTS);
|
||||
const targetDir = buildTargetDir(commandsGsd);
|
||||
const { commandsMsd, root } = buildSourceTree(SAMPLE_AGENTS);
|
||||
const targetDir = buildTargetDir(commandsMsd);
|
||||
t.after(() => {
|
||||
cleanup(root);
|
||||
cleanup(targetDir);
|
||||
|
||||
Reference in New Issue
Block a user