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:
@@ -1,5 +1,5 @@
|
||||
// allow-test-rule: source-text-is-the-product see #2568
|
||||
// agents/gsd-debug-session-manager.md is executed instruction text: the orchestrator
|
||||
// agents/msd-debug-session-manager.md is executed instruction text: the orchestrator
|
||||
// follows it verbatim, so WHERE the commit step sits relative to the terminal vs
|
||||
// non-terminal summary shapes IS the contract. The commit_docs gate it relies on is
|
||||
// real code and is exercised behaviorally through the CLI below.
|
||||
@@ -9,11 +9,11 @@ const { test } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const { runGsdTools, createTempGitProject, cleanup } = require('./helpers.cjs');
|
||||
const { runMsdTools, createTempGitProject, cleanup } = require('./helpers.cjs');
|
||||
|
||||
const ROOT = path.resolve(__dirname, '..');
|
||||
const MANAGER = path.join(ROOT, 'agents', 'gsd-debug-session-manager.md');
|
||||
const DEBUGGER = path.join(ROOT, 'agents', 'gsd-debugger.md');
|
||||
const MANAGER = path.join(ROOT, 'agents', 'msd-debug-session-manager.md');
|
||||
const DEBUGGER = path.join(ROOT, 'agents', 'msd-debugger.md');
|
||||
|
||||
const manager = () => fs.readFileSync(MANAGER, 'utf8');
|
||||
|
||||
@@ -31,26 +31,26 @@ test('#2568: the manager commits the session doc before a terminal summary', ()
|
||||
// manager-driven path ever consults commit_docs.
|
||||
assert.match(
|
||||
body,
|
||||
/gsd_run query commit/,
|
||||
/msd_run query commit/,
|
||||
'the manager owns the terminal path and must commit the session doc via the CLI — ' +
|
||||
'the step existed only in gsd-debugger.md, which does not reach the end of a ' +
|
||||
'the step existed only in msd-debugger.md, which does not reach the end of a ' +
|
||||
'manager-driven session (#2568)',
|
||||
);
|
||||
|
||||
// Resolved and abandoned shapes each need their own doc committed.
|
||||
assert.match(
|
||||
body,
|
||||
/gsd_run query commit[^\n]*resolved/,
|
||||
/msd_run query commit[^\n]*resolved/,
|
||||
'the resolved session doc (.planning/debug/resolved/{slug}.md) must be committed',
|
||||
);
|
||||
assert.match(
|
||||
body,
|
||||
/gsd_run query commit[^\n]*(debug_file_path|checkpoint)/,
|
||||
/msd_run query commit[^\n]*(debug_file_path|checkpoint)/,
|
||||
'the abandoned/checkpoint session doc must be committed',
|
||||
);
|
||||
|
||||
// Ordering: the commit instruction must PRECEDE the terminal summary it guards.
|
||||
const firstCommit = offsetOf(body, 'gsd_run query commit', 'commit step');
|
||||
const firstCommit = offsetOf(body, 'msd_run query commit', 'commit step');
|
||||
const terminal = offsetOf(body, '## DEBUG SESSION COMPLETE', 'terminal summary');
|
||||
assert.ok(
|
||||
firstCommit < terminal,
|
||||
@@ -82,7 +82,7 @@ test('#2568: the manager must NOT commit on the non-terminal CONTINUE_REQUIRED p
|
||||
// Structural: the commit block must sit after the CONTINUE_REQUIRED fence, so an
|
||||
// orchestrator taking the early-return path never reaches it.
|
||||
const continueFence = offsetOf(body, '## CONTINUE_REQUIRED', 'CONTINUE_REQUIRED shape');
|
||||
const firstCommit = offsetOf(body, 'gsd_run query commit', 'commit step');
|
||||
const firstCommit = offsetOf(body, 'msd_run query commit', 'commit step');
|
||||
assert.ok(
|
||||
firstCommit > continueFence,
|
||||
'the commit step must come after the CONTINUE_REQUIRED early-return block, not before it',
|
||||
@@ -132,7 +132,7 @@ test('#2568: the fix does not touch agent frontmatter', () => {
|
||||
const end = body.indexOf('\n---', 4);
|
||||
assert.ok(end > 0, 'frontmatter terminates');
|
||||
const fm = body.slice(0, end);
|
||||
assert.match(fm, /^name:\s*gsd-debug-session-manager$/m, 'name key intact');
|
||||
assert.match(fm, /^name:\s*msd-debug-session-manager$/m, 'name key intact');
|
||||
assert.doesNotMatch(fm, /commit/i, 'the commit instruction must live in the body, not frontmatter');
|
||||
});
|
||||
|
||||
@@ -143,14 +143,14 @@ test('#2568: the debugger keeps its own commit step for the single-spawn path',
|
||||
const body = fs.readFileSync(DEBUGGER, 'utf8');
|
||||
assert.match(
|
||||
body,
|
||||
/gsd_run query commit[^\n]*resolved/,
|
||||
'gsd-debugger.md must retain its own doc-commit step',
|
||||
/msd_run query commit[^\n]*resolved/,
|
||||
'msd-debugger.md must retain its own doc-commit step',
|
||||
);
|
||||
});
|
||||
|
||||
test('#2568: every token substituted into a commit command is a declared session parameter', () => {
|
||||
// The first cut of this fix pasted `{debug_dir}` straight from the issue's suggested
|
||||
// patch. That variable is real in gsd-core/workflows/debug.md — the ORCHESTRATOR
|
||||
// patch. That variable is real in msd-core/workflows/debug.md — the ORCHESTRATOR
|
||||
// receives it from init JSON — but this agent never does: <session_parameters>
|
||||
// declares only slug, debug_file_path, symptoms_prefilled, tdd_mode, goal and
|
||||
// specialist_dispatch_enabled. An unbound token makes --files resolve to a
|
||||
@@ -163,7 +163,7 @@ test('#2568: every token substituted into a commit command is a declared session
|
||||
const declared = new Set([...block.matchAll(/^- `([a-z_]+)`/gm)].map((m) => m[1]));
|
||||
assert.ok(declared.size >= 5, `precondition: session parameters parsed, got ${declared.size}`);
|
||||
|
||||
const commitLines = [...body.matchAll(/gsd_run query commit[^\n]*/g)].map((m) => m[0]);
|
||||
const commitLines = [...body.matchAll(/msd_run query commit[^\n]*/g)].map((m) => m[0]);
|
||||
assert.ok(commitLines.length >= 2, `expected the resolved + checkpoint commits, got ${commitLines.length}`);
|
||||
|
||||
for (const line of commitLines) {
|
||||
@@ -178,29 +178,29 @@ test('#2568: every token substituted into a commit command is a declared session
|
||||
});
|
||||
|
||||
test('#2568: the commit call is covered by the single canonical preamble', () => {
|
||||
// The repo invariant (tests/…B-agents…) is that each agent .md using gsd_run carries
|
||||
// EXACTLY ONE canonical preamble, placed before the first gsd_run call — the runtime
|
||||
// The repo invariant (tests/…B-agents…) is that each agent .md using msd_run carries
|
||||
// EXACTLY ONE canonical preamble, placed before the first msd_run call — the runtime
|
||||
// establishes it once. An earlier cut of this fix pasted a second preamble into the
|
||||
// commit block on the theory that shell state does not persist; that broke the
|
||||
// invariant and five suites with it. The correct property is coverage, not locality.
|
||||
const body = manager();
|
||||
const preambles = body.match(/^\s*_GSD_SHIM_NAME=/gm) || [];
|
||||
const preambles = body.match(/^\s*_MSD_SHIM_NAME=/gm) || [];
|
||||
assert.equal(
|
||||
preambles.length,
|
||||
1,
|
||||
`exactly one canonical gsd_run preamble per agent file, got ${preambles.length}`,
|
||||
`exactly one canonical msd_run preamble per agent file, got ${preambles.length}`,
|
||||
);
|
||||
const preambleAt = body.search(/^\s*_GSD_SHIM_NAME=/m);
|
||||
const commitAt = body.indexOf('gsd_run query commit');
|
||||
const preambleAt = body.search(/^\s*_MSD_SHIM_NAME=/m);
|
||||
const commitAt = body.indexOf('msd_run query commit');
|
||||
assert.notEqual(commitAt, -1, 'precondition: the commit call exists');
|
||||
assert.ok(
|
||||
preambleAt < commitAt,
|
||||
'the canonical preamble must precede the commit call that relies on gsd_run',
|
||||
'the canonical preamble must precede the commit call that relies on msd_run',
|
||||
);
|
||||
});
|
||||
|
||||
test('#2568: the in-session fix commit is idempotent', () => {
|
||||
// gsd-debugger.md's archive_session already commits the fix on the confirmed-checkpoint
|
||||
// msd-debugger.md's archive_session already commits the fix on the confirmed-checkpoint
|
||||
// path, which is the standard find_and_fix flow. A bare `git commit` with nothing
|
||||
// staged exits non-zero and would abort this step before the summary is returned.
|
||||
const body = manager();
|
||||
@@ -230,11 +230,11 @@ function writeConfig(dir, extra) {
|
||||
}
|
||||
|
||||
test('#2568: query commit honors commit_docs true', () => {
|
||||
const dir = createTempGitProject('gsd-2568-on-');
|
||||
const dir = createTempGitProject('msd-2568-on-');
|
||||
try {
|
||||
writeConfig(dir, { commit_docs: true });
|
||||
const rel = seedDoc(dir);
|
||||
const res = runGsdTools(['query', 'commit', 'docs(debug): resolve demo session', '--files', rel], dir);
|
||||
const res = runMsdTools(['query', 'commit', 'docs(debug): resolve demo session', '--files', rel], dir);
|
||||
assert.ok(res.success, `commit failed: ${res.error}`);
|
||||
const parsed = JSON.parse(res.output);
|
||||
assert.equal(parsed.committed, true, `expected a commit, got ${res.output}`);
|
||||
@@ -247,11 +247,11 @@ test('#2568: query commit no-ops when commit_docs is false', () => {
|
||||
// This is the load-bearing assumption: the manager calls the CLI unconditionally
|
||||
// and correctness follows from the gate, rather than the agent re-implementing a
|
||||
// config check it could get wrong.
|
||||
const dir = createTempGitProject('gsd-2568-off-');
|
||||
const dir = createTempGitProject('msd-2568-off-');
|
||||
try {
|
||||
writeConfig(dir, { commit_docs: false });
|
||||
const rel = seedDoc(dir);
|
||||
const res = runGsdTools(['query', 'commit', 'docs(debug): resolve demo session', '--files', rel], dir);
|
||||
const res = runMsdTools(['query', 'commit', 'docs(debug): resolve demo session', '--files', rel], dir);
|
||||
assert.ok(res.success, `commit invocation failed: ${res.error}`);
|
||||
const parsed = JSON.parse(res.output);
|
||||
assert.equal(parsed.committed, false, 'must not commit when commit_docs is false');
|
||||
@@ -263,11 +263,11 @@ test('#2568: query commit no-ops when commit_docs is false', () => {
|
||||
});
|
||||
|
||||
test('#2568: query commit behavior with commit_docs absent is explicit, not assumed', () => {
|
||||
const dir = createTempGitProject('gsd-2568-default-');
|
||||
const dir = createTempGitProject('msd-2568-default-');
|
||||
try {
|
||||
writeConfig(dir, {});
|
||||
const rel = seedDoc(dir);
|
||||
const res = runGsdTools(['query', 'commit', 'docs(debug): resolve demo session', '--files', rel], dir);
|
||||
const res = runMsdTools(['query', 'commit', 'docs(debug): resolve demo session', '--files', rel], dir);
|
||||
assert.ok(res.success, `commit invocation failed: ${res.error}`);
|
||||
const parsed = JSON.parse(res.output);
|
||||
// Pin whatever the shipped default resolves to, so a silent change to
|
||||
|
||||
Reference in New Issue
Block a user