fix: harden campaign resume UX and flow verification
This commit is contained in:
63
scripts/verify-flow-segment-data.mjs
Normal file
63
scripts/verify-flow-segment-data.mjs
Normal file
@@ -0,0 +1,63 @@
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { readCampaignFlowSegments } from './campaign-flow-segments.mjs';
|
||||
|
||||
const { routes, segments, manifestHash } = await readCampaignFlowSegments();
|
||||
const flowSource = await readFile(new URL('./verify-flow.mjs', import.meta.url), 'utf8');
|
||||
const packageJson = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8'));
|
||||
|
||||
assert(segments.length === 12, `Expected 12 campaign flow segments, received ${segments.length}.`);
|
||||
assert(routes.length === 66, `Expected 66 campaign battle routes, received ${routes.length}.`);
|
||||
assert(/^[a-f0-9]{64}$/.test(manifestHash), `Expected a SHA-256 flow manifest hash, received ${manifestHash}.`);
|
||||
|
||||
const flattenedBattleIds = segments.flatMap(({ battleIds }) => battleIds);
|
||||
assert(
|
||||
JSON.stringify(flattenedBattleIds) === JSON.stringify(routes.map(({ battleId }) => battleId)),
|
||||
'Campaign flow segments must preserve the canonical 66-battle route order.'
|
||||
);
|
||||
|
||||
const specialCheckpointSteps = {
|
||||
'hanzhong-shuhan': 'shu-han-foundation-camp',
|
||||
'yiling-baidi': 'baidi-entrustment-camp',
|
||||
nanzhong: 'northern-campaign-prep-camp',
|
||||
northern: 'ending-complete'
|
||||
};
|
||||
|
||||
for (const segment of segments) {
|
||||
assert(segment.index === segments.indexOf(segment), `Flow segment ${segment.id} has an invalid index.`);
|
||||
assert(
|
||||
countOccurrences(flowSource, `shouldRunFlowSegment('${segment.id}')`) === 1,
|
||||
`Flow segment ${segment.id} must have exactly one executable body boundary.`
|
||||
);
|
||||
assert(
|
||||
countOccurrences(flowSource, `completeFlowSegment(page, '${segment.id}')`) === 1,
|
||||
`Flow segment ${segment.id} must have exactly one completion checkpoint.`
|
||||
);
|
||||
const specialStep = specialCheckpointSteps[segment.id];
|
||||
if (specialStep) {
|
||||
assert(
|
||||
segment.checkpointStep === specialStep,
|
||||
`Flow segment ${segment.id} must end at ${specialStep}, received ${segment.checkpointStep}.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
assert(
|
||||
packageJson.scripts?.['verify:flow'] === 'node scripts/verify-flow-segments.mjs',
|
||||
'The default verify:flow command must use the segmented orchestrator.'
|
||||
);
|
||||
assert(
|
||||
packageJson.scripts?.['verify:flow:monolith'] === 'node scripts/verify-flow.mjs',
|
||||
'The legacy monolith flow command must remain available for comparison.'
|
||||
);
|
||||
|
||||
console.log(`Verified ${segments.length} campaign flow segments across ${routes.length} ordered battles (${manifestHash.slice(0, 12)}).`);
|
||||
|
||||
function countOccurrences(source, needle) {
|
||||
return source.split(needle).length - 1;
|
||||
}
|
||||
|
||||
function assert(condition, message) {
|
||||
if (!condition) {
|
||||
throw new Error(message);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user