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:
@@ -2,14 +2,14 @@
|
||||
|
||||
/**
|
||||
* Tests for the (not-yet-created) `hooks/lib/dispatch-identity.js` — the one
|
||||
* canonical owner of the `[gsd:dispatch phase="…" plan="…"]` marker format
|
||||
* canonical owner of the `[msd:dispatch phase="…" plan="…"]` marker format
|
||||
* and its prose fallback (#4594, epic #4630 Phase 1).
|
||||
*
|
||||
* See `.gsd/phase/fix-4594-dispatch-identity-seam/40-design.md` (behavior
|
||||
* See `.msd/phase/fix-4594-dispatch-identity-seam/40-design.md` (behavior
|
||||
* table + negative space) and `50-test-matrix.md` (row -> test-name mapping)
|
||||
* for the full rationale. This file intentionally covers matrix rows 1-27
|
||||
* and 33-34 only; rows 28-32 are guard end-to-end rows that belong in
|
||||
* `tests/gsd-agent-isolation-guard.test.cjs` / `tests/cursor-subagent-isolation.test.cjs`.
|
||||
* `tests/msd-agent-isolation-guard.test.cjs` / `tests/cursor-subagent-isolation.test.cjs`.
|
||||
*
|
||||
* RED BY DESIGN: `hooks/lib/dispatch-identity.js` does not exist yet. This
|
||||
* whole file fails to load with MODULE_NOT_FOUND until that module is
|
||||
@@ -59,12 +59,12 @@ const COLD_TREE_PROBE_TIMEOUT_MS = GENERATOR_SCRIPT_TIMEOUT_MS;
|
||||
describe('hooks/lib/dispatch-identity.js', () => {
|
||||
describe('marker format grammar', () => {
|
||||
test('marker: parses both identifiers', () => {
|
||||
const result = parseDispatchIdentity('[gsd:dispatch phase="03" plan="03-02-hardening"]');
|
||||
const result = parseDispatchIdentity('[msd:dispatch phase="03" plan="03-02-hardening"]');
|
||||
assert.deepEqual(result, { phase: '03', plan: '03-02-hardening', source: 'marker' });
|
||||
});
|
||||
|
||||
test('marker: found anywhere in a large prompt', () => {
|
||||
const text = `some preamble\n\nmore lines here\n[gsd:dispatch phase="03" plan="03-02-hardening"]\n\ntrailing text`;
|
||||
const text = `some preamble\n\nmore lines here\n[msd:dispatch phase="03" plan="03-02-hardening"]\n\ntrailing text`;
|
||||
const result = parseDispatchIdentity(text);
|
||||
assert.equal(result.phase, '03');
|
||||
assert.equal(result.plan, '03-02-hardening');
|
||||
@@ -73,7 +73,7 @@ describe('hooks/lib/dispatch-identity.js', () => {
|
||||
|
||||
test('render → parse round-trips', () => {
|
||||
const marker = renderDispatchIdentityMarker({ phase: '03', plan: '03-02-hardening' });
|
||||
assert.equal(marker, '[gsd:dispatch phase="03" plan="03-02-hardening"]');
|
||||
assert.equal(marker, '[msd:dispatch phase="03" plan="03-02-hardening"]');
|
||||
const parsed = parseDispatchIdentity(marker);
|
||||
assert.deepEqual(parsed, { phase: '03', plan: '03-02-hardening', source: 'marker' });
|
||||
});
|
||||
@@ -158,7 +158,7 @@ describe('hooks/lib/dispatch-identity.js', () => {
|
||||
|
||||
describe('precedence and malformed markers', () => {
|
||||
test('marker takes precedence over prose', () => {
|
||||
const text = 'Execute plan 02 of phase 03-auth. [gsd:dispatch phase="04" plan="04-01-setup"]';
|
||||
const text = 'Execute plan 02 of phase 03-auth. [msd:dispatch phase="04" plan="04-01-setup"]';
|
||||
const result = parseDispatchIdentity(text);
|
||||
assert.equal(result.phase, '04');
|
||||
assert.equal(result.plan, '04-01-setup');
|
||||
@@ -166,7 +166,7 @@ describe('hooks/lib/dispatch-identity.js', () => {
|
||||
});
|
||||
|
||||
test('marker: unquoted value is not accepted', () => {
|
||||
const result = parseDispatchIdentity('[gsd:dispatch phase=03]');
|
||||
const result = parseDispatchIdentity('[msd:dispatch phase=03]');
|
||||
// Never a partial wrong value: either falls back to null/null (no
|
||||
// prose present here) or, if this text also had prose, to the prose
|
||||
// result — but never a phase of '03' read out of the malformed marker.
|
||||
@@ -175,20 +175,20 @@ describe('hooks/lib/dispatch-identity.js', () => {
|
||||
});
|
||||
|
||||
test('marker: unknown keys are ignored', () => {
|
||||
const result = parseDispatchIdentity('[gsd:dispatch phase="03" plan="03-02-hardening" run="abc"]');
|
||||
const result = parseDispatchIdentity('[msd:dispatch phase="03" plan="03-02-hardening" run="abc"]');
|
||||
assert.equal(result.phase, '03');
|
||||
assert.equal(result.plan, '03-02-hardening');
|
||||
assert.equal(result.source, 'marker');
|
||||
});
|
||||
|
||||
test('marker: key order does not matter', () => {
|
||||
const result = parseDispatchIdentity('[gsd:dispatch plan="03-02-hardening" phase="03"]');
|
||||
const result = parseDispatchIdentity('[msd:dispatch plan="03-02-hardening" phase="03"]');
|
||||
assert.equal(result.phase, '03');
|
||||
assert.equal(result.plan, '03-02-hardening');
|
||||
});
|
||||
|
||||
test('marker: phase-only is valid', () => {
|
||||
const result = parseDispatchIdentity('[gsd:dispatch phase="03"]');
|
||||
const result = parseDispatchIdentity('[msd:dispatch phase="03"]');
|
||||
assert.deepEqual(result, { phase: '03', plan: null, source: 'marker' });
|
||||
});
|
||||
|
||||
@@ -196,29 +196,29 @@ describe('hooks/lib/dispatch-identity.js', () => {
|
||||
// `phase=` nor `plan=` must not suppress the prose fallback — it is not
|
||||
// a marker at all for this parser's purposes.
|
||||
test('F1: keyless marker (no recognized keys) falls through to prose', () => {
|
||||
const result = parseDispatchIdentity('Execute plan 02 of phase 03-auth.\n[gsd:dispatch]');
|
||||
const result = parseDispatchIdentity('Execute plan 02 of phase 03-auth.\n[msd:dispatch]');
|
||||
assert.deepEqual(result, { phase: '03', plan: null, source: 'prose' });
|
||||
});
|
||||
|
||||
test('F1: marker with only an unrecognized key falls through to prose', () => {
|
||||
const result = parseDispatchIdentity('Execute plan 02 of phase 03-auth.\n[gsd:dispatch run="x"]');
|
||||
const result = parseDispatchIdentity('Execute plan 02 of phase 03-auth.\n[msd:dispatch run="x"]');
|
||||
assert.deepEqual(result, { phase: '03', plan: null, source: 'prose' });
|
||||
});
|
||||
|
||||
test('F1: keyless marker with no prose anywhere yields the empty result', () => {
|
||||
const result = parseDispatchIdentity('[gsd:dispatch]');
|
||||
const result = parseDispatchIdentity('[msd:dispatch]');
|
||||
assert.deepEqual(result, { phase: null, plan: null, source: null });
|
||||
});
|
||||
|
||||
test('F1: mixed case — a keyless marker precedes a later QUALIFYING marker, which wins', () => {
|
||||
const result = parseDispatchIdentity(
|
||||
'[gsd:dispatch] some text [gsd:dispatch phase="03" plan="03-02-hardening"]',
|
||||
'[msd:dispatch] some text [msd:dispatch phase="03" plan="03-02-hardening"]',
|
||||
);
|
||||
assert.deepEqual(result, { phase: '03', plan: '03-02-hardening', source: 'marker' });
|
||||
});
|
||||
|
||||
test('F1: unknown-key tolerance is preserved for a marker that ALSO carries a recognized key', () => {
|
||||
const result = parseDispatchIdentity('[gsd:dispatch phase="03" run="x"]');
|
||||
const result = parseDispatchIdentity('[msd:dispatch phase="03" run="x"]');
|
||||
assert.deepEqual(result, { phase: '03', plan: null, source: 'marker' });
|
||||
});
|
||||
});
|
||||
@@ -245,8 +245,8 @@ describe('hooks/lib/dispatch-identity.js', () => {
|
||||
});
|
||||
|
||||
test('CRLF variants parse identically', () => {
|
||||
const lf = parseDispatchIdentity('preamble\n[gsd:dispatch phase="03" plan="03-02-hardening"]\ntrailer');
|
||||
const crlf = parseDispatchIdentity('preamble\r\n[gsd:dispatch phase="03" plan="03-02-hardening"]\r\ntrailer');
|
||||
const lf = parseDispatchIdentity('preamble\n[msd:dispatch phase="03" plan="03-02-hardening"]\ntrailer');
|
||||
const crlf = parseDispatchIdentity('preamble\r\n[msd:dispatch phase="03" plan="03-02-hardening"]\r\ntrailer');
|
||||
assert.deepEqual(crlf, lf);
|
||||
|
||||
const lfProse = parseDispatchIdentity('Execute plan 02 of phase 03-auth.\nmore text');
|
||||
@@ -258,14 +258,14 @@ describe('hooks/lib/dispatch-identity.js', () => {
|
||||
// A value containing '"' or ']' is unusable per the render contract; a
|
||||
// hand-crafted malicious marker string attempting the same must not
|
||||
// let the parser manufacture a second, forged identifier either.
|
||||
const hostileMarker = '[gsd:dispatch phase="03" plan="03-02"]" phase="99"]';
|
||||
const hostileMarker = '[msd:dispatch phase="03" plan="03-02"]" phase="99"]';
|
||||
const result = parseDispatchIdentity(hostileMarker);
|
||||
assert.notEqual(result.phase, '99');
|
||||
});
|
||||
|
||||
test('parse: large prompt terminates', (t) => {
|
||||
const filler = 'x'.repeat(100 * 1024);
|
||||
const text = `${filler}[gsd:dispatch phase="03" plan="03-02-hardening"]`;
|
||||
const text = `${filler}[msd:dispatch phase="03" plan="03-02-hardening"]`;
|
||||
const result = parseDispatchIdentity(text);
|
||||
assert.equal(result.phase, '03');
|
||||
assert.equal(result.plan, '03-02-hardening');
|
||||
@@ -275,7 +275,7 @@ describe('hooks/lib/dispatch-identity.js', () => {
|
||||
});
|
||||
|
||||
test('parse: scans every supplied text in order', () => {
|
||||
const result = parseDispatchIdentity('', '[gsd:dispatch phase="03" plan="03-02-hardening"]');
|
||||
const result = parseDispatchIdentity('', '[msd:dispatch phase="03" plan="03-02-hardening"]');
|
||||
assert.equal(result.phase, '03');
|
||||
assert.equal(result.plan, '03-02-hardening');
|
||||
assert.equal(result.source, 'marker');
|
||||
@@ -284,14 +284,14 @@ describe('hooks/lib/dispatch-identity.js', () => {
|
||||
|
||||
describe('render: omission rules', () => {
|
||||
test('render: unusable values (quote or bracket) are omitted', () => {
|
||||
assert.equal(renderDispatchIdentityMarker({ phase: '03', plan: 'has"quote' }), '[gsd:dispatch phase="03"]');
|
||||
assert.equal(renderDispatchIdentityMarker({ phase: '03', plan: 'has]bracket' }), '[gsd:dispatch phase="03"]');
|
||||
assert.equal(renderDispatchIdentityMarker({ phase: 'ba"d', plan: '03-02' }), '[gsd:dispatch plan="03-02"]');
|
||||
assert.equal(renderDispatchIdentityMarker({ phase: '03', plan: 'has"quote' }), '[msd:dispatch phase="03"]');
|
||||
assert.equal(renderDispatchIdentityMarker({ phase: '03', plan: 'has]bracket' }), '[msd:dispatch phase="03"]');
|
||||
assert.equal(renderDispatchIdentityMarker({ phase: 'ba"d', plan: '03-02' }), '[msd:dispatch plan="03-02"]');
|
||||
});
|
||||
|
||||
test('render: absent or empty values are omitted, and both-absent renders empty string', () => {
|
||||
assert.equal(renderDispatchIdentityMarker({ phase: '03' }), '[gsd:dispatch phase="03"]');
|
||||
assert.equal(renderDispatchIdentityMarker({ plan: '03-02-hardening' }), '[gsd:dispatch plan="03-02-hardening"]');
|
||||
assert.equal(renderDispatchIdentityMarker({ phase: '03' }), '[msd:dispatch phase="03"]');
|
||||
assert.equal(renderDispatchIdentityMarker({ plan: '03-02-hardening' }), '[msd:dispatch plan="03-02-hardening"]');
|
||||
assert.equal(renderDispatchIdentityMarker({ phase: '', plan: '' }), '');
|
||||
assert.equal(renderDispatchIdentityMarker({}), '');
|
||||
});
|
||||
@@ -307,12 +307,12 @@ describe('hooks/lib/dispatch-identity.js', () => {
|
||||
});
|
||||
|
||||
test('applies: marker for another plan is rejected', () => {
|
||||
const dispatchIds = parseDispatchIdentity('[gsd:dispatch phase="03" plan="03-01-setup"]');
|
||||
const dispatchIds = parseDispatchIdentity('[msd:dispatch phase="03" plan="03-01-setup"]');
|
||||
assert.equal(sentinelAppliesToDispatch(MEASURED_SENTINEL, dispatchIds), false);
|
||||
});
|
||||
|
||||
test('applies: marker for another phase is rejected', () => {
|
||||
const dispatchIds = parseDispatchIdentity('[gsd:dispatch phase="04" plan="03-02-hardening"]');
|
||||
const dispatchIds = parseDispatchIdentity('[msd:dispatch phase="04" plan="03-02-hardening"]');
|
||||
assert.equal(sentinelAppliesToDispatch(MEASURED_SENTINEL, dispatchIds), false);
|
||||
});
|
||||
|
||||
@@ -335,7 +335,7 @@ describe('hooks/lib/dispatch-identity.js', () => {
|
||||
const originalLoad = Module._load;
|
||||
Module._load = function patchedLoad(request, parent, isMain) {
|
||||
if (typeof request === 'string' && (
|
||||
request.includes('gsd-core/bin/lib') ||
|
||||
request.includes('msd-core/bin/lib') ||
|
||||
request.includes('ensure-runtime-build')
|
||||
)) {
|
||||
throw new Error('FORBIDDEN cold-tree require: ' + request);
|
||||
@@ -363,29 +363,29 @@ describe('hooks/lib/dispatch-identity.js', () => {
|
||||
describe('producer/consumer parity', () => {
|
||||
// #4594 F7: this reads the REAL workflow templates and runs their
|
||||
// marker literal through the owner's real parser after substituting the
|
||||
// measured placeholders — a template that loses its `[gsd:dispatch …]`
|
||||
// measured placeholders — a template that loses its `[msd:dispatch …]`
|
||||
// line, or whose grammar the owner's parser can no longer read, reds
|
||||
// this test. The prior version only called `renderDispatchIdentityMarker`
|
||||
// and re-parsed its own output (a duplicate of the round-trip test
|
||||
// above) and would have passed even if both templates below were
|
||||
// deleted. There are 3 prose "execute plan ... of phase ..." sites
|
||||
// across these 2 files; only 2 of them carry the `[gsd:dispatch …]`
|
||||
// across these 2 files; only 2 of them carry the `[msd:dispatch …]`
|
||||
// marker (execute-phase.md's `description=` field is prose-only) — see
|
||||
// `.gsd/phase/fix-4594-dispatch-identity-seam/40-design.md`'s "Known
|
||||
// `.msd/phase/fix-4594-dispatch-identity-seam/40-design.md`'s "Known
|
||||
// limits" section.
|
||||
const TEMPLATE_FILES = [
|
||||
path.join(REPO_ROOT, 'gsd-core', 'workflows', 'execute-phase.md'),
|
||||
path.join(REPO_ROOT, 'gsd-core', 'workflows', 'execute-phase', 'steps', 'executor-isolation-dispatch.md'),
|
||||
path.join(REPO_ROOT, 'msd-core', 'workflows', 'execute-phase.md'),
|
||||
path.join(REPO_ROOT, 'msd-core', 'workflows', 'execute-phase', 'steps', 'executor-isolation-dispatch.md'),
|
||||
];
|
||||
|
||||
/**
|
||||
* Extract every `[gsd:dispatch ...]` marker LINE from a template's raw
|
||||
* Extract every `[msd:dispatch ...]` marker LINE from a template's raw
|
||||
* text, verbatim (still containing its `{phase_number}`/`{plan_id}`
|
||||
* placeholders) — not a string match on content, a line-oriented
|
||||
* extraction feeding the real parser below.
|
||||
*/
|
||||
function extractMarkerLines(text) {
|
||||
return text.split(/\r?\n/).filter((line) => line.includes('[gsd:dispatch'));
|
||||
return text.split(/\r?\n/).filter((line) => line.includes('[msd:dispatch'));
|
||||
}
|
||||
|
||||
function substitutePlaceholders(line) {
|
||||
@@ -403,7 +403,7 @@ describe('hooks/lib/dispatch-identity.js', () => {
|
||||
assert.equal(
|
||||
markerLines.length,
|
||||
1,
|
||||
`expected exactly one [gsd:dispatch ...] marker line in ${file}, found ${markerLines.length}`,
|
||||
`expected exactly one [msd:dispatch ...] marker line in ${file}, found ${markerLines.length}`,
|
||||
);
|
||||
totalMarkerLines += markerLines.length;
|
||||
|
||||
@@ -421,10 +421,10 @@ describe('hooks/lib/dispatch-identity.js', () => {
|
||||
|
||||
test('templates: prose token source matches the case-flexible phase-id grammar', () => {
|
||||
// Parity guard, matrix row 34: DISPATCH_PHASE_TOKEN_SOURCE is a hand
|
||||
// mirror of gsd-core/bin/lib/phase-id.cjs's
|
||||
// mirror of msd-core/bin/lib/phase-id.cjs's
|
||||
// CASE_FLEXIBLE_PHASE_NUMBER_TOKEN_SOURCE. The mirror exists because
|
||||
// hooks/lib/dispatch-identity.js must load on a cold tree with no
|
||||
// compiled `gsd-core/bin/lib/` present (see the cold-tree test above),
|
||||
// compiled `msd-core/bin/lib/` present (see the cold-tree test above),
|
||||
// so it cannot `require()` the compiled module directly — it restates
|
||||
// the same regex source string instead. A hand-edited grammar change
|
||||
// on one side that is not mirrored on the other does NOT fail loudly:
|
||||
@@ -437,7 +437,7 @@ describe('hooks/lib/dispatch-identity.js', () => {
|
||||
// hooks/lib/dispatch-identity.js exists) is not masked by a require
|
||||
// ordering accident.
|
||||
const { CASE_FLEXIBLE_PHASE_NUMBER_TOKEN_SOURCE } = require(
|
||||
path.join(REPO_ROOT, 'gsd-core', 'bin', 'lib', 'phase-id.cjs'),
|
||||
path.join(REPO_ROOT, 'msd-core', 'bin', 'lib', 'phase-id.cjs'),
|
||||
);
|
||||
assert.equal(DISPATCH_PHASE_TOKEN_SOURCE, CASE_FLEXIBLE_PHASE_NUMBER_TOKEN_SOURCE);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user