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:
Jakub Zych
2026-10-06 01:47:40 +02:00
parent fe069b2a56
commit a9a7a328e6
2763 changed files with 78465 additions and 78434 deletions

View File

@@ -10,32 +10,32 @@ const path = require('path');
describe('explore command', () => {
test('command file exists', () => {
const p = path.join(__dirname, '..', 'commands', 'gsd', 'explore.md');
assert.ok(fs.existsSync(p), 'commands/gsd/explore.md should exist');
const p = path.join(__dirname, '..', 'commands', 'msd', 'explore.md');
assert.ok(fs.existsSync(p), 'commands/msd/explore.md should exist');
});
test('command file has required frontmatter', () => {
const p = path.join(__dirname, '..', 'commands', 'gsd', 'explore.md');
const p = path.join(__dirname, '..', 'commands', 'msd', 'explore.md');
const content = fs.readFileSync(p, 'utf-8');
assert.ok(content.includes('name: gsd:explore'), 'Command must have name frontmatter');
assert.ok(content.includes('name: msd:explore'), 'Command must have name frontmatter');
assert.ok(content.includes('description:'), 'Command must have description frontmatter');
assert.ok(content.includes('allowed-tools:'), 'Command must have allowed-tools frontmatter');
});
test('workflow file exists', () => {
const p = path.join(__dirname, '..', 'gsd-core', 'workflows', 'explore.md');
const p = path.join(__dirname, '..', 'msd-core', 'workflows', 'explore.md');
assert.ok(fs.existsSync(p), 'workflows/explore.md should exist');
});
test('workflow references questioning.md and domain-probes.md', () => {
const p = path.join(__dirname, '..', 'gsd-core', 'workflows', 'explore.md');
const p = path.join(__dirname, '..', 'msd-core', 'workflows', 'explore.md');
const content = fs.readFileSync(p, 'utf-8');
assert.ok(content.includes('questioning.md'), 'Workflow must reference questioning.md');
assert.ok(content.includes('domain-probes.md'), 'Workflow must reference domain-probes.md');
});
test('workflow documents all 6 output types', () => {
const p = path.join(__dirname, '..', 'gsd-core', 'workflows', 'explore.md');
const p = path.join(__dirname, '..', 'msd-core', 'workflows', 'explore.md');
const content = fs.readFileSync(p, 'utf-8');
assert.ok(content.includes('Note'), 'Workflow must document Note output type');
assert.ok(content.includes('Todo'), 'Workflow must document Todo output type');
@@ -46,13 +46,13 @@ describe('explore command', () => {
});
test('workflow enforces one question at a time principle', () => {
const p = path.join(__dirname, '..', 'gsd-core', 'workflows', 'explore.md');
const p = path.join(__dirname, '..', 'msd-core', 'workflows', 'explore.md');
const content = fs.readFileSync(p, 'utf-8');
assert.ok(content.includes('one question at a time'), 'Workflow must mention "one question at a time" principle');
});
test('workflow requires user confirmation before writing artifacts', () => {
const p = path.join(__dirname, '..', 'gsd-core', 'workflows', 'explore.md');
const p = path.join(__dirname, '..', 'msd-core', 'workflows', 'explore.md');
const content = fs.readFileSync(p, 'utf-8');
assert.ok(
content.includes('explicit user selection') || content.includes('Never write artifacts without'),
@@ -61,13 +61,13 @@ describe('explore command', () => {
});
test('workflow respects commit_docs config', () => {
const p = path.join(__dirname, '..', 'gsd-core', 'workflows', 'explore.md');
const p = path.join(__dirname, '..', 'msd-core', 'workflows', 'explore.md');
const content = fs.readFileSync(p, 'utf-8');
assert.ok(content.includes('commit_docs'), 'Workflow must respect commit_docs configuration');
});
test('command references the workflow via execution_context', () => {
const p = path.join(__dirname, '..', 'commands', 'gsd', 'explore.md');
const p = path.join(__dirname, '..', 'commands', 'msd', 'explore.md');
const content = fs.readFileSync(p, 'utf-8');
assert.ok(
content.includes('workflows/explore.md'),
@@ -77,14 +77,14 @@ describe('explore command', () => {
});
// Enhancement #2229 — three-way claim disposition (admit / refute / abstain) in the
// /gsd-explore Step 3 research pass. The research pass is pure prompt orchestration (it
// spawns gsd-phase-researcher and folds prose back), so the disposition contract lives in
// /msd-explore Step 3 research pass. The research pass is pure prompt orchestration (it
// spawns msd-phase-researcher and folds prose back), so the disposition contract lives in
// the workflow text itself — asserting the text asserts the deployed contract (the
// source-text-is-the-product exemption at the top of this file). This mirrors the #1154
// honest-verifier abstention PATTERN (never a silent pass; abstain-and-flag), not the
// verify-time probe-core code path (which sits on the verifier↔predicate rail, ADR-857).
describe('explore research-pass claim disposition (#2229)', () => {
const workflowPath = path.join(__dirname, '..', 'gsd-core', 'workflows', 'explore.md');
const workflowPath = path.join(__dirname, '..', 'msd-core', 'workflows', 'explore.md');
const readWorkflow = () => fs.readFileSync(workflowPath, 'utf-8');
test('#2543 B1: ledger discipline is stated WITHIN the Step-3 disposition region, not merely somewhere in the file', () => {
@@ -117,7 +117,7 @@ describe('explore research-pass claim disposition (#2229)', () => {
test('#2543 M1: the researcher agent is taught the disposition enum, so admit is reachable', () => {
// The admit arm only fires if the spawned researcher actually emits
// [admit/refute/abstain] tags. explore.md's spawn prompt asks for them, but
// gsd-phase-researcher is a SHARED agent carrying its own [VERIFIED]/[CITED]/
// msd-phase-researcher is a SHARED agent carrying its own [VERIFIED]/[CITED]/
// [ASSUMED] contract — if it never learned the disposition enum it follows its
// own template, every finding returns untagged, and the three-way disposition
// degenerates to all-abstain. Assert BOTH ends of the contract (the spawn
@@ -126,19 +126,19 @@ describe('explore research-pass claim disposition (#2229)', () => {
const explore = readWorkflow();
const spawn = explore.slice(
explore.indexOf('Agent('),
explore.indexOf('subagent_type="gsd-phase-researcher"'),
explore.indexOf('subagent_type="msd-phase-researcher"'),
);
for (const tag of ['[admit:', '[refute:', '[abstain:']) {
assert.ok(spawn.includes(tag), `the spawn prompt must ask the researcher for ${tag} …] tags`);
}
const agent = fs.readFileSync(
path.join(__dirname, '..', 'agents', 'gsd-phase-researcher.md'),
path.join(__dirname, '..', 'agents', 'msd-phase-researcher.md'),
'utf-8',
);
assert.match(
agent,
/claim-disposition mode/i,
'gsd-phase-researcher.md must document the claim-disposition mode; without it the shared agent ' +
'msd-phase-researcher.md must document the claim-disposition mode; without it the shared agent ' +
'follows its own [VERIFIED]/[CITED]/[ASSUMED] template and the admit arm never fires (#2543 M1)',
);
for (const tag of ['[admit:', '[refute:', '[abstain:']) {
@@ -146,12 +146,12 @@ describe('explore research-pass claim disposition (#2229)', () => {
}
});
test('#2543 M4: the ledger-reason enum is identical across every copy in explore.md, CONTEXT.md, and agents/gsd-phase-researcher.md', () => {
test('#2543 M4: the ledger-reason enum is identical across every copy in explore.md, CONTEXT.md, and agents/msd-phase-researcher.md', () => {
// The prior extractor used text.match() with no /g — it only ever inspected the
// FIRST copy, so a second explore.md copy (or the CONTEXT.md copy) could drift
// unnoticed. Use matchAll so every occurrence is checked, not just one.
//
// A fourth copy lives in agents/gsd-phase-researcher.md (~line 190) and was NOT
// A fourth copy lives in agents/msd-phase-researcher.md (~line 190) and was NOT
// scanned here, even though this exact class of defect — an enum duplicated
// across surfaces with no coupling between them — is why this test exists in the
// first place: a third copy (in CONTEXT.md) silently drifted earlier in this
@@ -175,7 +175,7 @@ describe('explore research-pass claim disposition (#2229)', () => {
const exploreCopies = extractAll(readWorkflow(), 'explore.md');
// Measured: explore.md currently carries 2 copies (the Step-3 share template and
// the Step-4 carry-forward instruction), CONTEXT.md carries a 3rd, and
// agents/gsd-phase-researcher.md carries a 4th. Assert >=2 in explore.md so a
// agents/msd-phase-researcher.md carries a 4th. Assert >=2 in explore.md so a
// future removal of either copy is caught, without hardcoding a count this test
// can't independently justify.
assert.ok(
@@ -201,13 +201,13 @@ describe('explore research-pass claim disposition (#2229)', () => {
);
const agentCopies = extractAll(
fs.readFileSync(path.join(__dirname, '..', 'agents', 'gsd-phase-researcher.md'), 'utf-8'),
'agents/gsd-phase-researcher.md',
fs.readFileSync(path.join(__dirname, '..', 'agents', 'msd-phase-researcher.md'), 'utf-8'),
'agents/msd-phase-researcher.md',
);
assert.deepStrictEqual(
agentCopies[0],
exploreCopies[0],
'the ledger-reason enum in agents/gsd-phase-researcher.md has drifted from explore.md/CONTEXT.md; keep all copies identical (#2543 M4)',
'the ledger-reason enum in agents/msd-phase-researcher.md has drifted from explore.md/CONTEXT.md; keep all copies identical (#2543 M4)',
);
// Total-copy floor across all three files so deleting a copy anywhere is also
@@ -215,7 +215,7 @@ describe('explore research-pass claim disposition (#2229)', () => {
const totalCopies = exploreCopies.length + contextCopies.length + agentCopies.length;
assert.ok(
totalCopies >= 4,
`expected at least 4 total ledger-reason enum copies across explore.md, CONTEXT.md, and agents/gsd-phase-researcher.md; found ${totalCopies}`,
`expected at least 4 total ledger-reason enum copies across explore.md, CONTEXT.md, and agents/msd-phase-researcher.md; found ${totalCopies}`,
);
});
@@ -238,22 +238,22 @@ describe('explore research-pass claim disposition (#2229)', () => {
const content = readWorkflow();
assert.match(
content,
/resolve-model\s+gsd-phase-researcher\s+--pick\s+tier/,
/resolve-model\s+msd-phase-researcher\s+--pick\s+tier/,
'the tier floor needs the resolved tier as its trigger; without a ' +
'`resolve-model … --pick tier` binding the guard has no operative input'
);
assert.match(
content,
/resolve-model\s+gsd-phase-researcher\s+--pick\s+model/,
/resolve-model\s+msd-phase-researcher\s+--pick\s+model/,
'the spawn must bind the researcher model per model-profile-resolution.md'
);
});
test('tier-floor guard: the Agent() spawn passes the bound model', () => {
const content = readWorkflow();
const spawn = content.slice(content.indexOf('Agent('), content.indexOf('subagent_type="gsd-phase-researcher"'));
const spawn = content.slice(content.indexOf('Agent('), content.indexOf('subagent_type="msd-phase-researcher"'));
assert.match(
spawn + content.slice(content.indexOf('subagent_type="gsd-phase-researcher"'), content.indexOf('subagent_type="gsd-phase-researcher"') + 200),
spawn + content.slice(content.indexOf('subagent_type="msd-phase-researcher"'), content.indexOf('subagent_type="msd-phase-researcher"') + 200),
/model="\{RESEARCHER_MODEL\}"/,
'omitting model= makes the agent inherit the orchestrator model rather than ' +
'the catalog-resolved tier, which is what left the floor unenforceable'
@@ -304,7 +304,7 @@ describe('explore research-pass claim disposition (#2229)', () => {
assert.match(clause, /\bRESEARCHER_TIER\b/,
'the floor must reference RESEARCHER_TIER — the single signal now, replacing RESEARCHER_PROFILE');
assert.match(clause, /RESEARCHER_TIER[^.]*\bhaiku\b/,
'the floor must name `haiku` as the budget tier for gsd-phase-researcher');
'the floor must name `haiku` as the budget tier for msd-phase-researcher');
});
test('tier-floor guard: an unreadable tier (unknown/inherit/empty) is also floored', () => {
@@ -377,7 +377,7 @@ describe('explore research-pass claim disposition (#2229)', () => {
// disagreeing source — wrong version, adjacent subject, secondary/derivative —
// trigger a refute instead of an abstain.
const explore = readWorkflow();
const spawn = explore.slice(explore.indexOf('Agent('), explore.indexOf('subagent_type="gsd-phase-researcher"'));
const spawn = explore.slice(explore.indexOf('Agent('), explore.indexOf('subagent_type="msd-phase-researcher"'));
assert.match(
spawn,
/\[refute:[^\]]*\]\s*\([^)]*authoritative[^)]*\)/i,
@@ -385,20 +385,20 @@ describe('explore research-pass claim disposition (#2229)', () => {
);
});
test('#2543 B2: the research pass reaches a gsd_run bootstrapped ahead of Step 3', () => {
test('#2543 B2: the research pass reaches a msd_run bootstrapped ahead of Step 3', () => {
// The tier floor abstains EVERY claim when both resolve-model probes come back
// empty because gsd_run is undefined. The launcher preamble now lives once,
// empty because msd_run is undefined. The launcher preamble now lives once,
// unconditionally, at the end of Step 1 (not re-inlined per bash block) — so this
// only needs to confirm the bootstrap precedes the probe, not that it is duplicated
// into the Step-3 fence.
const explore = readWorkflow();
const preamble = explore.indexOf('_GSD_SHIM_NAME="gsd-tools.cjs"');
const probe = explore.indexOf('resolve-model gsd-phase-researcher --pick tier');
assert.notStrictEqual(preamble, -1, 'the gsd_run bootstrap preamble must exist in the file');
const preamble = explore.indexOf('_MSD_SHIM_NAME="msd-tools.cjs"');
const probe = explore.indexOf('resolve-model msd-phase-researcher --pick tier');
assert.notStrictEqual(preamble, -1, 'the msd_run bootstrap preamble must exist in the file');
assert.notStrictEqual(probe, -1, 'the research pass must call resolve-model to arm the tier floor');
assert.ok(
preamble < probe,
'gsd_run must be bootstrapped before the tier-floor probe runs, otherwise both probes ' +
'msd_run must be bootstrapped before the tier-floor probe runs, otherwise both probes ' +
'return empty and the tier floor abstains every claim (#2543 B2)'
);
});
@@ -432,7 +432,7 @@ describe('explore research-pass claim disposition (#2229)', () => {
assert.match(
region,
/untrusted-input-boundary/,
'Step 4 must reference @gsd-core/references/untrusted-input-boundary.md when quoting research text into a durable file'
'Step 4 must reference @msd-core/references/untrusted-input-boundary.md when quoting research text into a durable file'
);
assert.match(
region,
@@ -462,24 +462,24 @@ describe('explore research-pass claim disposition (#2229)', () => {
test('the launcher preamble is bootstrapped once, unconditionally, ahead of Step 3', () => {
const explore = readWorkflow();
const marker = '_GSD_SHIM_NAME="gsd-tools.cjs"';
const marker = '_MSD_SHIM_NAME="msd-tools.cjs"';
const firstMarker = explore.indexOf(marker);
const lastMarker = explore.lastIndexOf(marker);
assert.notStrictEqual(firstMarker, -1, 'the canonical preamble marker must exist');
assert.strictEqual(firstMarker, lastMarker, 'the preamble must be inlined exactly once in the file');
const firstGsdRun = explore.indexOf('gsd_run');
assert.notStrictEqual(firstGsdRun, -1, 'gsd_run must be used somewhere in the file');
const firstMsdRun = explore.indexOf('msd_run');
assert.notStrictEqual(firstMsdRun, -1, 'msd_run must be used somewhere in the file');
assert.ok(
firstMarker < firstGsdRun,
'the preamble that DEFINES gsd_run must appear before the first USE of gsd_run anywhere in the file'
firstMarker < firstMsdRun,
'the preamble that DEFINES msd_run must appear before the first USE of msd_run anywhere in the file'
);
const step3 = explore.indexOf('## Step 3');
assert.notStrictEqual(step3, -1, 'Step 3 heading must exist');
// Must sit in Step 1, not inside Step 3's optional research-offer branch:
// declining the research offer must not leave Step 5's commit call unbootstrapped,
// since gsd_run is only ever defined at this one call site.
// since msd_run is only ever defined at this one call site.
assert.ok(
firstMarker < step3,
'the launcher preamble must be bootstrapped before Step 3, not gated behind the optional research offer'
@@ -488,15 +488,15 @@ describe('explore research-pass claim disposition (#2229)', () => {
});
describe('explore seeds: the plant-seed contract (#4648)', () => {
const workflowPath = path.join(__dirname, '..', 'gsd-core', 'workflows', 'explore.md');
const workflowPath = path.join(__dirname, '..', 'msd-core', 'workflows', 'explore.md');
const workflow = () => fs.readFileSync(workflowPath, 'utf-8');
test('step 5 delegates seeds to the plant-seed workflow instead of hand-writing a file', () => {
// allow-test-rule: source-text-is-the-product (#4648) — explore.md text is the deployed contract
const content = workflow();
assert.ok(
content.includes('/gsd:capture --seed'),
'explore step 5 must delegate seeds via /gsd:capture --seed — the only command surface routing to the plant-seed workflow (#4648)',
content.includes('/msd:capture --seed'),
'explore step 5 must delegate seeds via /msd:capture --seed — the only command surface routing to the plant-seed workflow (#4648)',
);
assert.ok(
!content.includes('trigger_condition'),
@@ -525,7 +525,7 @@ describe('explore seeds: the plant-seed contract (#4648)', () => {
test('the plant-seed workflow still defines the canonical contract the delegation relies on', () => {
const plantSeed = fs.readFileSync(
path.join(__dirname, '..', 'gsd-core', 'workflows', 'plant-seed.md'),
path.join(__dirname, '..', 'msd-core', 'workflows', 'plant-seed.md'),
'utf-8',
);
assert.ok(plantSeed.includes('SEED-'), 'plant-seed mints SEED- ids');