Keep forced Silent bids indistinguishable in notices
This commit is contained in:
1 parent
b64c657c1d
commit
4690200f59
6 files changed
+41
-7
No files matched your search
@@ -20,6 +20,13 @@ open mode gates.
|
||||
Keep identified Basic-function gaps ahead of Advanced and wider interactions.
|
||||
Prototype labels and final acceptance gates remain.
|
||||
|
||||
**Silent automatic submission notice — 27 October.**
|
||||
A full hand's forced Silent submission now uses the same public text as a
|
||||
manual sealed bid and a neutral animation tag, instead of announcing the
|
||||
reason for a forced zero. Public hand counts can still allow inference. The
|
||||
existing native reveal and automatic settlement remain unchanged. Five focused
|
||||
files pass 54/54; type/lint passed before the intervening test-only CI fix.
|
||||
|
||||
**Richese Silent Truthtrance bid — 27 October. Prototyped / Partial.**
|
||||
The event-bound Richese question also supports one sealed Silent submission.
|
||||
Yes requires a qualifying bid; No permits zero or a lower bid. Feasibility uses
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# Dune implementation status
|
||||
|
||||
## 27 October 2026 — Silent automatic notice
|
||||
|
||||
Use the same public text for forced and manual sealed submissions, and a
|
||||
neutral automatic tag, so the notice itself does not identify a full hand or a
|
||||
zero bid. Public hand counts can still permit inference. Basic/Advanced cases
|
||||
compare real manual and forced events while retaining sealed views, promise
|
||||
receipts and conserved physical cards; the full-hand setup is controlled.
|
||||
Five focused files pass 54/54; type/lint passed before the intervening test-only
|
||||
CI fix. Private reports are `20261027-silent-neutral-notice-proof-v1/` and
|
||||
`20261027-silent-neutral-notice-proof-v2/`. No browser or deployment result is claimed.
|
||||
|
||||
## 27 October 2026 — Richese Silent bid Truthtrance
|
||||
|
||||
Extend the current public-event bid question to a single sealed Silent
|
||||
|
||||
@@ -9,7 +9,8 @@ The answer and guide use only the respondent's actual available funds and aid,
|
||||
not other sealed amounts. All eligible submissions retain native escrow and
|
||||
reveal simultaneously in original tie order; only the winner pays. When a hand
|
||||
becomes full, the native automatic zero releases an impossible Yes or completes
|
||||
No. Its public text and action tag do not announce the amount before reveal.
|
||||
No. Its public text matches a manual sealed submission and its action tag is neutral. Public hand counts can still allow inference of a forced zero. Five focused
|
||||
files pass 54/54; type/lint passed before the intervening test-only CI fix.
|
||||
|
||||
The [GF9 November 2020 FAQ p8](https://www.gf9games.com/dune/wp-content/uploads/2020/11/Dune-FAQ-Nov-2020.pdf#page=8)
|
||||
supports action commitments while possible, but does not supply this specific
|
||||
|
||||
+4
-2
@@ -18581,8 +18581,10 @@ function finishAutomaticDecision(g: Game): boolean {
|
||||
const player = getPlayer(g, full);
|
||||
log(
|
||||
g,
|
||||
`${player.name} automatically ${lot.method === 'silent' ? 'submitted a sealed bid' : 'passed'} because their hand became full before bidding.`,
|
||||
{ faction: player.faction, name: lot.method === 'silent' ? 'Full hand: sealed submission' : 'Full hand: no bid' },
|
||||
lot.method === 'silent'
|
||||
? `${player.name} submitted a sealed bid; its amount remains concealed until every eligible bidder submits.`
|
||||
: `${player.name} automatically passed because their hand became full before bidding.`,
|
||||
{ faction: player.faction, name: lot.method === 'silent' ? 'Sealed bid' : 'Full hand: no bid' },
|
||||
);
|
||||
if (lot.method === 'silent' && g.richeseAuction.outcome)
|
||||
log(
|
||||
|
||||
@@ -325,7 +325,7 @@ void test('restored full hands automatically submit zero or remove an unbid cach
|
||||
assert.equal(g.players[0].spice, 22);
|
||||
assert.equal(g.players[0].hand.length, 4);
|
||||
assert.ok(
|
||||
g.log.some((entry) => entry.text.includes('automatically submitted a sealed bid')),
|
||||
g.log.some((entry) => entry.text.includes('submitted a sealed bid; its amount remains concealed')),
|
||||
);
|
||||
let unbid = cache();
|
||||
for (const id of ['h', 'e', 'r']) unbid = bid(unbid, id, 0);
|
||||
|
||||
@@ -113,6 +113,15 @@ for (const advanced of [false, true]) for (const answer of ['yes','no'] as const
|
||||
}
|
||||
assert.deepEqual(inventory(harmed),f.originalCards);
|
||||
assert.equal(Object.hasOwn(harmed.richeseAuction!.sealed,f.target),false);
|
||||
// Compare the automatic notice to an actual manual submission from the
|
||||
// same public game state. The original Yes can bid 4; No can submit zero.
|
||||
const manualBefore = bound.log.at(-1)?.seq ?? 0;
|
||||
const manual = act(bound,f.target,{type:'richeseBid',event:f.lot,
|
||||
amount:answer === 'yes' ? 4 : 0,allyPayment:0});
|
||||
const manualNotice = manual.log.find(entry => entry.seq > manualBefore &&
|
||||
entry.text.includes('submitted a sealed bid')); assert.ok(manualNotice);
|
||||
assert.equal(viewGame(manual,f.owner).richeseAuction?.revealedBids,null);
|
||||
assert.deepEqual(inventory(manual),f.originalCards);
|
||||
const beforeSequence = harmed.log.at(-1)?.seq ?? 0;
|
||||
const settled = normalizeAutomaticGame(harmed);
|
||||
const receipt = settled.richeseBidPromises!.find(row => row.player === f.target); assert.ok(receipt);
|
||||
@@ -123,9 +132,13 @@ for (const advanced of [false, true]) for (const answer of ['yes','no'] as const
|
||||
assert.equal(observer.ownBid,null); assert.equal(observer.revealedBids,null);
|
||||
assert.ok(observer.submitted.includes(f.target));
|
||||
const fresh = settled.log.filter(entry => entry.seq > beforeSequence);
|
||||
assert.ok(fresh.some(entry => entry.text.includes('submitted a sealed bid')));
|
||||
assert.ok(fresh.every(entry => !/revealed together|zero|0 spice|no bid/i.test(`${entry.text} ${entry.automatic?.name ?? ''}`)),
|
||||
'Automatic public notices must not disclose the sealed zero before reveal');
|
||||
const automaticNotice = fresh.find(entry => entry.text.includes('submitted a sealed bid')); assert.ok(automaticNotice);
|
||||
assert.equal(automaticNotice.text,manualNotice.text,
|
||||
'Forced and manual submissions use the same public notice before reveal');
|
||||
assert.ok(!automaticNotice.automatic || automaticNotice.automatic.name === 'Sealed bid',
|
||||
'An optional automatic-action tag must use a neutral name');
|
||||
assert.ok(fresh.every(entry => !/revealed together|zero|0 spice|no bid|full hand|hand became full/i.test(`${entry.text} ${entry.automatic?.name ?? ''}`)),
|
||||
'Automatic public notices and tags must not directly disclose the forced-zero reason before reveal');
|
||||
assert.deepEqual(inventory(settled),f.originalCards);
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user