fix: resume campaign progress safely

This commit is contained in:
2026-07-29 01:13:57 +09:00
parent 90de2a3559
commit 6f2b6e42a4
31 changed files with 9354 additions and 148 deletions

View File

@@ -101,7 +101,71 @@ try {
'Replaying the exact same victory report must not duplicate gold or items.'
);
campaign.completeCampaignAftermath(scenario.id);
const aftermathReading =
campaign.setCampaignStoryCheckpoint({
version: 1,
sequenceId:
'settlement-aftermath-fixture',
beatId: 'settlement-aftermath-fixture',
pageIndex: 0
});
const aftermathReference = {
sequenceId:
aftermathReading.storyCheckpoint.sequenceId,
revision:
aftermathReading.storyCheckpoint.revision
};
const aftermathHandoff =
campaign.markCampaignStoryHandoff(
aftermathReference.sequenceId,
aftermathReference.revision
);
const beforeMismatchedAftermath =
JSON.stringify(aftermathHandoff);
const staleAftermath =
campaign.completeCampaignStoryHandoffAftermath(
scenario.id,
{
...aftermathReference,
revision:
aftermathReference.revision + 1
}
);
assert.equal(
JSON.stringify(staleAftermath),
beforeMismatchedAftermath,
'A stale handoff reference must consume neither the pending aftermath nor its story checkpoint.'
);
const wrongBattleAftermath =
campaign.completeCampaignStoryHandoffAftermath(
'second-battle-yellow-turban-pursuit',
aftermathReference
);
assert.equal(
JSON.stringify(wrongBattleAftermath),
beforeMismatchedAftermath,
'A mismatched battle must consume neither half of an aftermath handoff.'
);
const completedAftermath =
campaign.completeCampaignStoryHandoffAftermath(
scenario.id,
aftermathReference
);
assert.equal(
completedAftermath.pendingAftermathBattleId,
undefined,
'An exact aftermath handoff must retire the pending settlement.'
);
assert.equal(
completedAftermath.storyCheckpoint,
undefined,
'An exact aftermath handoff must retire its story checkpoint atomically.'
);
assert.equal(
completedAftermath.storyCheckpointRevision,
aftermathReference.revision + 1,
'An exact aftermath handoff must invalidate its consumed revision.'
);
campaign.setActiveCampVisitId(
'first-pursuit-scout-tent'
);