Files
msd-core/tests/plan-phase-mvp-flag.test.cjs
Jakub Zych a9a7a328e6 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.
2026-10-06 01:47:40 +02:00

84 lines
3.8 KiB
JavaScript

/**
* plan-phase workflow — --mvp flag parsing and MVP_MODE resolution
* Contract test: verifies the workflow markdown documents the agreed
* resolution order (CLI flag → roadmap mode → config → default false).
*/
const { test, describe, beforeEach, afterEach } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('fs');
const path = require('path');
const { runMsdTools, createTempProject, cleanup } = require('./helpers.cjs');
const WORKFLOW = path.join(__dirname, '..', 'msd-core', 'workflows', 'plan-phase.md');
function parseWorkflowContract(content) {
const lines = content.split(/\r?\n/).map(line => line.trim());
const argExtractionLine = lines.find(line => line.includes('Extract from $ARGUMENTS:')) || '';
const hasMvpModeVariable = lines.some(line => line.includes('MVP_MODE'));
const hasWorkflowConfigRead = lines.some(line => line.includes('workflow.mvp_mode'));
const hasRoadmapModeRead = lines.some(line => line.includes('phase.mvp-mode') || line.includes('roadmap'));
const hasSkeletonReference = lines.some(line => line.includes('SKELETON.md'));
const hasWalkingSkeletonLabel = lines.some(line => line.toLowerCase().includes('walking skeleton'));
const plannerLines = lines.filter(line => line.includes('planner') || line.includes('msd-planner'));
const plannerUsesMvpMode = plannerLines.some(line => line.includes('MVP_MODE')) || lines.some(line => line.includes('MVP_MODE') && line.includes('planner'));
return {
argExtractionLine,
hasMvpModeVariable,
hasWorkflowConfigRead,
hasRoadmapModeRead,
hasSkeletonReference,
hasWalkingSkeletonLabel,
plannerUsesMvpMode,
};
}
describe('plan-phase workflow — --mvp flag', () => {
const contract = parseWorkflowContract(fs.readFileSync(WORKFLOW, 'utf-8'));
test('argument list documents --mvp flag', () => {
assert.ok(contract.argExtractionLine.length > 0, 'Step 2 arg-extraction line not found');
assert.ok(contract.argExtractionLine.includes('--mvp'), 'argument list must mention --mvp');
});
test('workflow defines MVP_MODE resolution block', () => {
assert.ok(contract.hasMvpModeVariable, 'workflow must declare MVP_MODE');
assert.ok(contract.hasWorkflowConfigRead, 'must read workflow.mvp_mode config');
assert.ok(contract.hasRoadmapModeRead, 'must consult phase mode from roadmap/phase.mvp-mode');
});
test('Walking Skeleton gate references new-project + Phase 1', () => {
assert.ok(contract.hasSkeletonReference, 'workflow must mention SKELETON.md');
assert.ok(contract.hasWalkingSkeletonLabel, 'workflow must label the gate as Walking Skeleton');
});
test('planner spawn passes MVP_MODE to msd-planner', () => {
assert.ok(contract.plannerUsesMvpMode, 'workflow must wire MVP_MODE into the planner subagent prompt');
});
});
describe('plan-phase --mvp — resolution chain integration', () => {
let tmpDir;
beforeEach(() => { tmpDir = createTempProject(); });
afterEach(() => { cleanup(tmpDir); });
test('roadmap.get-phase reports mode=mvp when set in roadmap', () => {
fs.writeFileSync(
path.join(tmpDir, '.planning', 'ROADMAP.md'),
`# Roadmap\n\n## v1.0.0\n\n### Phase 1: Auth\n**Goal:** Users can log in\n**Mode:** mvp\n`
);
const result = runMsdTools('roadmap get-phase 1 --pick mode', tmpDir);
assert.ok(result.success);
assert.strictEqual(result.output.trim(), 'mvp');
});
test('config-get workflow.mvp_mode default is empty/unset', () => {
const result = runMsdTools('config-get workflow.mvp_mode', tmpDir);
// Either success with empty output OR a non-zero exit; both are fine.
// Real assertion: the key isn't accidentally set to "true" in tmp project.
if (result.success) {
assert.notStrictEqual(result.output.trim(), 'true');
}
});
});