fix(simulation): store candidateStateId in theaterResults to enable Phase 3 merge (#2374)

* fix(simulation): store candidateStateId in theaterResults to enable Phase 3 merge

applySimulationMerge looks up paths by candidateStateId but theaterResults
only stored theaterId ("theater-1"). The map lookup always returned undefined,
silently no-oping all simulationAdjustment writes.

Fix: write candidateStateId alongside theaterId in theaterResults, and key
the simByTheater map by candidateStateId with theaterId as fallback.

* fix(e2e): add missing Earthquake fields to map-harness test fixture

* Revert "fix(e2e): add missing Earthquake fields to map-harness test fixture"

This reverts commit 69d8930b88.

* test(simulation): add T13 to cover positional theaterId vs candidateStateId mismatch
This commit is contained in:
Elie Habib
2026-03-27 21:01:29 +04:00
committed by GitHub
parent da18fd3fb6
commit a99eb5a023
2 changed files with 25 additions and 1 deletions

View File

@@ -6446,6 +6446,29 @@ describe('phase 3 simulation re-ingestion — applySimulationMerge', () => {
assert.equal(simulationEvidence.theaterCount, 1);
assert.ok(Array.isArray(simulationEvidence.adjustments));
});
it('T13: candidateStateId-keyed lookup works when theaterId is a positional ID (production scenario)', () => {
// Regression test: before the fix, theaterResults only stored theaterId="theater-1"
// and the map lookup by candidateStateId="state-eca8696a31" always returned undefined.
const candidateStateId = 'state-eca8696a31';
const path = makeExpandedPath(candidateStateId, 0.52); // routeFacilityKey='Red Sea' from fixture
const evaluation = makeEval('completed', [path]);
const simOutcome = {
runId: 'sim-run-002',
isCurrentRun: true,
theaterResults: [{
theaterId: 'theater-1', // positional — diverges from candidateStateId
candidateStateId, // production fix: stored alongside theaterId
topPaths: [],
invalidators: ['Red Sea reopened after ceasefire agreement'],
stabilizers: [],
}],
};
const candidatePackets = [{ candidateStateId, routeFacilityKey: 'Red Sea', commodityKey: 'crude_oil', topBucketId: 'energy', topChannel: 'energy_supply_shock' }];
const { simulationEvidence } = applySimulationMerge(evaluation, simOutcome, candidatePackets, { generatedAt: Date.now(), impactExpansionCandidates: candidatePackets }, null);
assert.equal(simulationEvidence.pathsDemoted, 1, 'path should be demoted via candidateStateId lookup');
assert.equal(simulationEvidence.adjustments.length, 1);
});
});
describe('phase 3 simulation re-ingestion — matching helpers', () => {