Compose the deferred Terror arrival and green the mixed E3 programmes

Queue a committed Terror entry whose arrival also opened its own
interaction — Guild income, a Bene Gesserit fighter Intrusion or advisor
choice, or Fremen storm protection — in the additive
Game.pendingArrivalReaction list, and open the oldest queued entry from
settleAutomaticContinuations once nothing is pending. Payment, force
transfer and the original movement never replay; a Terror entry already in
flight and every Ambassador combination still reject.

Both withdrawn mixed E3 programme pairs are green: Moritani 9/9 and Ecaz
14/14, stable across 20 consecutive full-file runs. Their recorded resume
constraints became real fixture repairs, and the two restored consumer
omissions were corrected against the engine rather than re-pinned.

Repair pre-existing failures inherited at 45e6084 against current engine
behavior: stale Discovery and module gates in the native skills, Ix and
expansion-faction prototypes, the advanced Moritani skill boundary, the
Richese Nexus betrayal sale-credit expectation, one incidental gate
message and one flaky Collection-readiness assertion that reproduced at
HEAD.

Offline suite 7,793/7,793 with typecheck and lint clean. No game, seat,
saved-state, deployment, public-start or played-save conversion changes.
This commit is contained in:
Quintine committed 2026-10-07 17:24:23 +11:00
1 parent 45e6084424
commit e05a205a47
30 files changed
+2467 -117

No files matched your search

+18 -8
View File
@@ -420,7 +420,7 @@ void test('all four bots respect the projected count cap for both Ambassador rou
}
});
void test('movement preflight permits the low two-force Intrusion arrival and keeps unsupported three-force ordering immutable', () => {
void test('movement preflight commits each Intrusion arrival and defers its Terror entry behind the pending Intrusion', () => {
for (const reserves of [7, 8]) {
const g = fixture(reserves, 'emperor', true);
const bg = newPlayer('b', 'Bene Gesserit', 'beneGesserit');
@@ -444,13 +444,23 @@ void test('movement preflight permits the low two-force Intrusion arrival and ke
assert.equal(result.pendingTerrorEntry ?? null, null);
assert.equal(player(result, 'e').forces['arrakeen:10'], 2);
homeworldGameIntegrity(result);
} else reject(g, 'e', move, /Terror combined/);
reject(
g,
'e',
{ ...move, forces: { 'imperial_basin:10': 3 } },
/Terror combined/,
);
} else {
const result = applyAction(g, 'e', move);
assert.equal(result.decision?.kind, 'intrusion');
assert.equal(result.pendingArrivalReaction?.[0]?.amount, 2,
'The committed entry waits for the Intrusion choice.');
assert.equal(result.pendingTerrorEntry ?? null, null);
assert.equal(player(result, 'e').forces['arrakeen:10'], 2);
assert.equal(player(result, 'e').forces['imperial_basin:10'], 1);
homeworldGameIntegrity(result);
}
const three = applyAction(g, 'e', { ...move, forces: { 'imperial_basin:10': 3 } });
assert.equal(three.decision?.kind, 'intrusion');
assert.equal(three.pendingArrivalReaction?.[0]?.amount, 3,
'The whole committed group is one deferred entry.');
assert.equal(three.pendingTerrorEntry ?? null, null);
assert.equal(player(three, 'e').forces['arrakeen:10'], 3);
homeworldGameIntegrity(three);
}
});