Allow group actions after settled Truthtrance
Verify and publish checkpoint container / container (push) Canceled after 0s

This commit is contained in:
Quintine committed 2026-10-29 00:12:09 +11:00
1 parent 9cc659602c
commit 420943b890
8 files changed
+135 -5

No files matched your search

+13
View File
@@ -104,6 +104,19 @@ void test('each donor share of a leading group bid remains locked until outbid',
assert.equal(spice(game), 32);
});
void test('fulfilled and released bid promises leave group bid funding usable', () => {
for (const history of ['settled', 'prior-turn'] as const) {
const initial = fixture();
initial.phaseBidPromises = [{event:`bid-${history}`, player:'d', asker:'a',
turn:history === 'prior-turn' ? initial.turn - 1 : initial.turn,
minimum:1, answer:true, ...(history === 'settled' ? {fulfilled:true} : {released:true})}];
const game = act(pledge(initial), 'a', groupBid);
assert.equal(game.auction?.bidder, 'a');
assert.deepEqual(game.auction?.coalitionContributions, groupBid.coalitionContributions);
assert.deepEqual(game.phaseBidPromises, initial.phaseBidPromises);
}
});
void test('only the bidder sees the combined group payment, without raw donor allocations', () => {
const game = act(pledge(fixture()), 'a', groupBid);
const own = viewGame(game, 'a').auction; assert.ok(own);
+39
View File
@@ -65,6 +65,45 @@ void test('native pair expands only after three separate group approvals', () =>
assert.deepEqual(game.ready, []);
});
void test('fulfilled and released Truthtrance records do not prevent group Nexus negotiation', () => {
for (const history of ['settled', 'prior-turn'] as const) {
const game = originalPair();
// Stage only the public history; pair, proposal and answers are real actions.
game.bribePromises = [{event: `bribe-${history}`, player:'d', asker:'a',
turn:history === 'prior-turn' ? game.turn - 1 : game.turn,
recipient:'c', minimum:1, answer:true, progress:history === 'settled' ? 1 : 0,
...(history === 'settled' ? {fulfilled:true} : {released:true})}];
game.alliancePromises = [{event:`alliance-${history}`, source:'old-nexus',
player:'d', asker:'a', turn:game.turn - 1, partner:'c', answer:false, fulfilled:true}];
assert.ok(viewGame(game, 'a').coalitionNexus, 'Old answers do not hide the group controls.');
let formed = propose(game);
formed = answer(formed, 'b'); formed = answer(formed, 'c');
assert.deepEqual(coalitionOf(formed.players, formed.coalitionState, 'a')!.members, ['a','b','c']);
assert.deepEqual(formed.bribePromises, game.bribePromises);
assert.deepEqual(formed.alliancePromises, game.alliancePromises);
}
});
void test('an unresolved prior-turn Truthtrance record still blocks group Nexus', () => {
const game = originalPair();
game.bribePromises = [{event:'unreconciled-bribe', player:'d', asker:'a', turn:game.turn - 1,
recipient:'c', minimum:1, answer:true, progress:0}];
assert.equal(viewGame(game, 'a').coalitionNexus, null);
const pair = coalitionOf(game.players, game.coalitionState, 'a')!;
rejected(game, 'a', {type:'coalitionPropose', groupId:pair.id, entrant:'c',
expectedRevision:game.coalitionState!.revision});
});
void test('a current unanswered group-incompatible Truthtrance commitment still blocks group Nexus', () => {
const game = originalPair();
game.bribePromises = [{event:'live-bribe', player:'d', asker:'a', turn:game.turn,
recipient:'c', minimum:1, answer:true, progress:0}];
assert.equal(viewGame(game, 'a').coalitionNexus, null);
const pair = coalitionOf(game.players, game.coalitionState, 'a')!;
rejected(game, 'a', {type:'coalitionPropose', groupId:pair.id, entrant:'c',
expectedRevision:game.coalitionState!.revision});
});
void test('any participant may decline and the original pair remains unchanged', () => {
const original = originalPair();
const pending = propose(original);
+48
View File
@@ -101,6 +101,54 @@ void test('two allies fund one ordinary shipment with donor-specific settlement
assert.equal(spiceIncludingEscrow(game), originalSpice);
});
void test('fulfilled and released Truthtrance records leave group shipment funding usable', () => {
for (const history of ['settled', 'prior-turn'] as const) {
const initial = fixture();
initial.bribePromises = [{event:`bribe-${history}`, player:'d', asker:'a',
turn:history === 'prior-turn' ? initial.turn - 1 : initial.turn,
recipient:'c', minimum:1, answer:true, progress:history === 'settled' ? 1 : 0,
...(history === 'settled' ? {fulfilled:true} : {released:true})}];
let game = pledge(initial);
assert.equal(viewGame(game, 'a').coalitionFunding?.incoming.length, 2);
game = finishResponses(send(game, 'a', shipment));
assert.equal(game.players[0].forces['imperial_basin:9'], 3);
assert.equal(remaining(game, 'b'), 1);
assert.equal(remaining(game, 'c'), 1);
assert.deepEqual(game.bribePromises, initial.bribePromises);
conservedForces(game);
}
});
void test('an unreconciled prior-turn commitment blocks group shipment funding', () => {
const game = fixture();
game.bribePromises = [{event:'unreconciled-bribe', player:'d', asker:'a', turn:game.turn - 1,
recipient:'c', minimum:1, answer:true, progress:0}];
assert.equal(viewGame(game, 'a').coalitionFunding, null);
const before = structuredClone(game);
assert.throws(() => send(game, 'b', {type:'coalitionPledge', recipient:'a', amount:4}));
assert.deepEqual(game, before);
});
void test('a live No bribe-expression commitment blocks group shipment funding', () => {
const game = fixture();
game.bribeExpressionPromises = [{event:'live-expression-no', player:'d', asker:'a',
turn:game.turn, claim:{kind:'payment', recipient:'c', minimum:1}, answer:false, progress:[]}];
assert.equal(viewGame(game, 'a').coalitionFunding, null);
const before = structuredClone(game);
assert.throws(() => send(game, 'b', {type:'coalitionPledge', recipient:'a', amount:4}));
assert.deepEqual(game, before);
});
void test('a current unsupported Truthtrance commitment still blocks group shipment funding', () => {
const game = fixture();
game.bribePromises = [{event:'live-bribe', player:'d', asker:'a', turn:game.turn,
recipient:'c', minimum:1, answer:true, progress:0}];
assert.equal(viewGame(game, 'a').coalitionFunding, null);
const before = structuredClone(game);
assert.throws(() => send(game, 'b', {type:'coalitionPledge', recipient:'a', amount:4}));
assert.deepEqual(game, before);
});
void test('fake or insufficient donor contributions reject without payment or arrival', () => {
const game = pledge(fixture());
for (const contributions of [