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:
@@ -3,11 +3,11 @@
|
||||
/**
|
||||
* Behavioral tests for codex-agent-toml.cjs (#3243, ADR-2313 Phase 3).
|
||||
*
|
||||
* Module: gsd-core/bin/lib/codex-agent-toml.cjs
|
||||
* Module: msd-core/bin/lib/codex-agent-toml.cjs
|
||||
* Exports: PARSE_REASON, parseCodexAgentToml, renderCodexAgentToml,
|
||||
* stripModel, stripReasoningEffort
|
||||
*
|
||||
* Spec: .gsd/phase/feat-3243-codex-toml-sync/{40-design,50-test-matrix}.md
|
||||
* Spec: .msd/phase/feat-3243-codex-toml-sync/{40-design,50-test-matrix}.md
|
||||
* Row numbers below (# A<N>) map 1:1 to 50-test-matrix.md's "A — the IR" table.
|
||||
*
|
||||
* Every fixture is hand-authored against the real `generateCodexAgentToml`
|
||||
@@ -26,7 +26,7 @@ const {
|
||||
renderCodexAgentToml,
|
||||
stripModel,
|
||||
stripReasoningEffort,
|
||||
} = require('../gsd-core/bin/lib/codex-agent-toml.cjs');
|
||||
} = require('../msd-core/bin/lib/codex-agent-toml.cjs');
|
||||
|
||||
// Row 18a's CRLF fixture (and A12 here) is derived at test runtime, never read
|
||||
// from a committed file: `.gitattributes` (`* text=auto eol=lf`, repo-wide) would
|
||||
@@ -39,75 +39,75 @@ function toCrlf(lfContent) {
|
||||
|
||||
// ─── A1-A13 fixtures (hand-authored, #2371) ───────────────────────────────────
|
||||
|
||||
const A1_FULL = 'name = "gsd-planner"\n' +
|
||||
'description = "Plans phases for GSD milestones"\n' +
|
||||
const A1_FULL = 'name = "msd-planner"\n' +
|
||||
'description = "Plans phases for MSD milestones"\n' +
|
||||
'model = "gpt-5.6-sol"\n' +
|
||||
'model_reasoning_effort = "high"\n' +
|
||||
"developer_instructions = '''\n" +
|
||||
'Plan the next phase.\n' +
|
||||
"'''\n";
|
||||
|
||||
const A2_NO_HEADER_FIELDS = 'name = "gsd-plain"\n' +
|
||||
const A2_NO_HEADER_FIELDS = 'name = "msd-plain"\n' +
|
||||
'description = "No model, no effort"\n' +
|
||||
"developer_instructions = '''\n" +
|
||||
'Just work.\n' +
|
||||
"'''\n";
|
||||
|
||||
const A3_DOUBLE_QUOTED_KEY = 'name = "gsd-quoted-double"\n' +
|
||||
const A3_DOUBLE_QUOTED_KEY = 'name = "msd-quoted-double"\n' +
|
||||
'"model" = "sonnet"\n' +
|
||||
"developer_instructions = '''\n" +
|
||||
'Work.\n' +
|
||||
"'''\n";
|
||||
|
||||
const A3_SINGLE_QUOTED_KEY = "name = \"gsd-quoted-single\"\n" +
|
||||
const A3_SINGLE_QUOTED_KEY = "name = \"msd-quoted-single\"\n" +
|
||||
"'model' = \"sonnet\"\n" +
|
||||
"developer_instructions = '''\n" +
|
||||
'Work.\n' +
|
||||
"'''\n";
|
||||
|
||||
const A4_VERBOSITY_ONLY = 'name = "gsd-light"\n' +
|
||||
const A4_VERBOSITY_ONLY = 'name = "msd-light"\n' +
|
||||
'model_verbosity = "low"\n' +
|
||||
"developer_instructions = '''\n" +
|
||||
'Work fast.\n' +
|
||||
"'''\n";
|
||||
|
||||
const A5_MODEL_INSIDE_BLOCK = 'name = "gsd-planner"\n' +
|
||||
const A5_MODEL_INSIDE_BLOCK = 'name = "msd-planner"\n' +
|
||||
"developer_instructions = '''\n" +
|
||||
'When picking a plan, remember: model = "sonnet" is just prose here.\n' +
|
||||
"'''\n";
|
||||
|
||||
const A6_MODEL_AFTER_BLOCK = 'name = "gsd-reordered"\n' +
|
||||
const A6_MODEL_AFTER_BLOCK = 'name = "msd-reordered"\n' +
|
||||
"developer_instructions = '''\n" +
|
||||
'Work.\n' +
|
||||
"'''\n" +
|
||||
'model = "sonnet"\n';
|
||||
|
||||
const A7_DECOY_MARKER_IN_DESCRIPTION = 'name = "gsd-decoy-marker"\n' +
|
||||
const A7_DECOY_MARKER_IN_DESCRIPTION = 'name = "msd-decoy-marker"\n' +
|
||||
'description = "mentions developer_instructions = \'\'\' as an example string"\n' +
|
||||
'model = "sonnet"\n' +
|
||||
"developer_instructions = '''\n" +
|
||||
'Work.\n' +
|
||||
"'''\n";
|
||||
|
||||
const A8_SAME_LINE_BLOCK = 'name = "gsd-terse"\n' +
|
||||
const A8_SAME_LINE_BLOCK = 'name = "msd-terse"\n' +
|
||||
"developer_instructions = '''one line block'''\n";
|
||||
|
||||
const A9_UNTERMINATED = 'name = "gsd-broken"\n' +
|
||||
const A9_UNTERMINATED = 'name = "msd-broken"\n' +
|
||||
"developer_instructions = '''\n" +
|
||||
'This block never closes.\n';
|
||||
|
||||
const A10_NO_BLOCK_AT_ALL = 'name = "gsd-noblock"\n' +
|
||||
const A10_NO_BLOCK_AT_ALL = 'name = "msd-noblock"\n' +
|
||||
'description = "no prompt block on this agent"\n' +
|
||||
'"model" = "sonnet"\n';
|
||||
|
||||
const A11_COMMENTED_PIN = 'name = "gsd-reviewer"\n' +
|
||||
const A11_COMMENTED_PIN = 'name = "msd-reviewer"\n' +
|
||||
'# model = "sonnet"\n' +
|
||||
"developer_instructions = '''\n" +
|
||||
'Review.\n' +
|
||||
"'''\n";
|
||||
|
||||
const A12_CRLF_SOURCE = toCrlf(
|
||||
'name = "gsd-scribe"\n' +
|
||||
'name = "msd-scribe"\n' +
|
||||
'model = "sonnet"\n' +
|
||||
"developer_instructions = '''\n" +
|
||||
'Write a changelog entry.\n' +
|
||||
@@ -115,7 +115,7 @@ const A12_CRLF_SOURCE = toCrlf(
|
||||
);
|
||||
|
||||
const A13_BOM_SOURCE = String.fromCharCode(0xfeff) +
|
||||
'name = "gsd-archivist"\n' +
|
||||
'name = "msd-archivist"\n' +
|
||||
'model = "sonnet"\n' +
|
||||
"developer_instructions = '''\n" +
|
||||
'Archive.\n' +
|
||||
@@ -259,8 +259,8 @@ describe('A15/A16: round-trip after stripModel / stripReasoningEffort', () => {
|
||||
assert.equal(result.ok, true);
|
||||
const stripped = stripModel(result.doc);
|
||||
const rendered = renderCodexAgentToml(stripped);
|
||||
const expected = 'name = "gsd-planner"\n' +
|
||||
'description = "Plans phases for GSD milestones"\n' +
|
||||
const expected = 'name = "msd-planner"\n' +
|
||||
'description = "Plans phases for MSD milestones"\n' +
|
||||
'model_reasoning_effort = "high"\n' +
|
||||
"developer_instructions = '''\n" +
|
||||
'Plan the next phase.\n' +
|
||||
@@ -275,8 +275,8 @@ describe('A15/A16: round-trip after stripModel / stripReasoningEffort', () => {
|
||||
assert.equal(result.ok, true);
|
||||
const stripped = stripReasoningEffort(result.doc);
|
||||
const rendered = renderCodexAgentToml(stripped);
|
||||
const expected = 'name = "gsd-planner"\n' +
|
||||
'description = "Plans phases for GSD milestones"\n' +
|
||||
const expected = 'name = "msd-planner"\n' +
|
||||
'description = "Plans phases for MSD milestones"\n' +
|
||||
'model = "gpt-5.6-sol"\n' +
|
||||
"developer_instructions = '''\n" +
|
||||
'Plan the next phase.\n' +
|
||||
@@ -311,25 +311,25 @@ describe('A15/A16: round-trip after stripModel / stripReasoningEffort', () => {
|
||||
// shipped untested. These fixtures are hand-authored (never emitted by
|
||||
// `generateCodexAgentToml`), per CONTRIBUTING's fixture-provenance rule.
|
||||
|
||||
const A18_MIXED_EOL = 'name = "gsd-mixed"\r\n' +
|
||||
const A18_MIXED_EOL = 'name = "msd-mixed"\r\n' +
|
||||
'model = "sonnet"\n' +
|
||||
'description = "mixed line endings"\r\n' +
|
||||
"developer_instructions = '''\n" +
|
||||
'Work.\r\n' +
|
||||
"'''\n";
|
||||
|
||||
const A20_LONE_CR = 'name = "gsd-oldmac"\r' +
|
||||
const A20_LONE_CR = 'name = "msd-oldmac"\r' +
|
||||
'model = "sonnet"\n' +
|
||||
"developer_instructions = '''\n" +
|
||||
'Work.\n' +
|
||||
"'''\n";
|
||||
|
||||
const A21_NO_TRAILING_AFTER_BLOCK = 'name = "gsd-terse2"\n' +
|
||||
const A21_NO_TRAILING_AFTER_BLOCK = 'name = "msd-terse2"\n' +
|
||||
"developer_instructions = '''\n" +
|
||||
'Work.\n' +
|
||||
"'''"; // no trailing newline at all — last line is the block's closing '''
|
||||
|
||||
const A22_MULTI_TRAILING_NEWLINES = 'name = "gsd-multi"\n' +
|
||||
const A22_MULTI_TRAILING_NEWLINES = 'name = "msd-multi"\n' +
|
||||
'model = "sonnet"\n' +
|
||||
"developer_instructions = '''\n" +
|
||||
'Work.\n' +
|
||||
@@ -358,7 +358,7 @@ describe('A18-A24 (BLOCKER regression): mixed/edge line-ending round-trip', () =
|
||||
assert.equal(result.ok, true);
|
||||
const stripped = stripModel(result.doc);
|
||||
const rendered = renderCodexAgentToml(stripped);
|
||||
const expected = 'name = "gsd-mixed"\r\n' +
|
||||
const expected = 'name = "msd-mixed"\r\n' +
|
||||
'description = "mixed line endings"\r\n' +
|
||||
"developer_instructions = '''\n" +
|
||||
'Work.\r\n' +
|
||||
@@ -424,15 +424,15 @@ describe('A18-A24 (BLOCKER regression): mixed/edge line-ending round-trip', () =
|
||||
|
||||
describe('A25-A28 (regression, B17): removeLine preserves trailing-newline status', () => {
|
||||
test('A25 (red pre-fix): strip a model line that is the file\'s last line, no trailing newline — still no trailing newline', () => {
|
||||
const source = 'name = "gsd-bare"\nmodel = "sonnet"'; // no trailing \n; model is the last line
|
||||
const source = 'name = "msd-bare"\nmodel = "sonnet"'; // no trailing \n; model is the last line
|
||||
const result = parseCodexAgentToml(source);
|
||||
assert.equal(result.ok, true);
|
||||
assert.equal(result.doc.trailingNewline, false);
|
||||
const rendered = renderCodexAgentToml(stripModel(result.doc));
|
||||
// Pre-fix: removeLine kept the PREVIOUS line's terminator ('\n') instead
|
||||
// of the removed line's own ('') — rendered came back as
|
||||
// 'name = "gsd-bare"\n', a trailing newline the source never had.
|
||||
assert.equal(rendered, 'name = "gsd-bare"', 'the file must still have no trailing newline');
|
||||
// 'name = "msd-bare"\n', a trailing newline the source never had.
|
||||
assert.equal(rendered, 'name = "msd-bare"', 'the file must still have no trailing newline');
|
||||
});
|
||||
|
||||
test('A26 (red pre-fix): strip a model line that is the file\'s last line, WITH a trailing newline — still exactly one trailing newline', () => {
|
||||
@@ -443,17 +443,17 @@ describe('A25-A28 (regression, B17): removeLine preserves trailing-newline statu
|
||||
// the removed line's terminator onto it would silently change the
|
||||
// survivor's own ending, which is exactly the class of defect the
|
||||
// mixed-EOL round-trip guarantee (A14) exists to prevent.
|
||||
const source = 'name = "gsd-bare"\r\nmodel = "sonnet"\n'; // name: CRLF: model (last): LF
|
||||
const source = 'name = "msd-bare"\r\nmodel = "sonnet"\n'; // name: CRLF: model (last): LF
|
||||
const result = parseCodexAgentToml(source);
|
||||
assert.equal(result.ok, true);
|
||||
assert.equal(result.doc.trailingNewline, true);
|
||||
const rendered = renderCodexAgentToml(stripModel(result.doc));
|
||||
// Pre-fix (style-inheriting variant): rendered came back as
|
||||
// 'name = "gsd-bare"\n' — the removed line's own LF terminator, which
|
||||
// 'name = "msd-bare"\n' — the removed line's own LF terminator, which
|
||||
// silently changed the survivor's ending from CRLF to LF. Correct: the
|
||||
// survivor keeps its OWN CRLF terminator unchanged; the file still ends
|
||||
// with exactly one trailing newline, in the survivor's original style.
|
||||
assert.equal(rendered, 'name = "gsd-bare"\r\n', 'exactly one trailing newline must survive, on the new last line, in ITS OWN style');
|
||||
assert.equal(rendered, 'name = "msd-bare"\r\n', 'exactly one trailing newline must survive, on the new last line, in ITS OWN style');
|
||||
});
|
||||
|
||||
test('A27: strip the only line in a file — empty result', () => {
|
||||
@@ -472,7 +472,7 @@ describe('A25-A28 (regression, B17): removeLine preserves trailing-newline statu
|
||||
});
|
||||
|
||||
test('A28 (red pre-fix, row B7 shape): stale model plus its orphaned effort, effort is the last line, no trailing newline — both counts correct', () => {
|
||||
const source = 'name = "gsd-stale"\nmodel = "opus"\nmodel_reasoning_effort = "medium"'; // no trailing \n
|
||||
const source = 'name = "msd-stale"\nmodel = "opus"\nmodel_reasoning_effort = "medium"'; // no trailing \n
|
||||
const result = parseCodexAgentToml(source);
|
||||
assert.equal(result.ok, true);
|
||||
assert.equal(result.doc.trailingNewline, false);
|
||||
@@ -483,9 +483,9 @@ describe('A25-A28 (regression, B17): removeLine preserves trailing-newline statu
|
||||
const afterBoth = stripReasoningEffort(afterModel);
|
||||
// Pre-fix: the second removal (now-last-line) kept the intermediate
|
||||
// survivor's terminator instead of the removed effort line's own,
|
||||
// rendering 'name = "gsd-stale"\n' — a trailing newline the source
|
||||
// rendering 'name = "msd-stale"\n' — a trailing newline the source
|
||||
// never had.
|
||||
assert.equal(renderCodexAgentToml(afterBoth), 'name = "gsd-stale"', 'both lines gone AND no invented trailing newline');
|
||||
assert.equal(renderCodexAgentToml(afterBoth), 'name = "msd-stale"', 'both lines gone AND no invented trailing newline');
|
||||
assert.equal(afterBoth.model, null);
|
||||
assert.equal(afterBoth.reasoningEffort, null);
|
||||
});
|
||||
@@ -497,7 +497,7 @@ describe('A25-A28 (regression, B17): removeLine preserves trailing-newline statu
|
||||
// of the second removal (survivor 'name' is CRLF-terminated, the
|
||||
// removed effort line is LF-terminated) so a style-inheriting bug and
|
||||
// the correct emptiness-inheriting behavior render DIFFERENT bytes.
|
||||
const source = 'name = "gsd-stale"\r\nmodel = "opus"\nmodel_reasoning_effort = "medium"\n';
|
||||
const source = 'name = "msd-stale"\r\nmodel = "opus"\nmodel_reasoning_effort = "medium"\n';
|
||||
const result = parseCodexAgentToml(source);
|
||||
assert.equal(result.ok, true);
|
||||
assert.equal(result.doc.trailingNewline, true);
|
||||
@@ -508,11 +508,11 @@ describe('A25-A28 (regression, B17): removeLine preserves trailing-newline statu
|
||||
assert.deepEqual(afterModel.terminators, ['\r\n', '\n']);
|
||||
const afterBoth = stripReasoningEffort(afterModel);
|
||||
// If the bug were still present (inheriting the removed effort line's
|
||||
// OWN '\n'), this would render 'name = "gsd-stale"\n' — silently
|
||||
// OWN '\n'), this would render 'name = "msd-stale"\n' — silently
|
||||
// downgrading the survivor's CRLF to LF. Correct: the survivor's own
|
||||
// '\r\n' is unchanged; the file still ends with exactly one trailing
|
||||
// newline.
|
||||
assert.equal(renderCodexAgentToml(afterBoth), 'name = "gsd-stale"\r\n', 'survivor keeps its OWN terminator; no invented/altered line ending');
|
||||
assert.equal(renderCodexAgentToml(afterBoth), 'name = "msd-stale"\r\n', 'survivor keeps its OWN terminator; no invented/altered line ending');
|
||||
assert.equal(afterBoth.model, null);
|
||||
assert.equal(afterBoth.reasoningEffort, null);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user