Add verified Truthtrance hand inventory questions

Players can ask total-hand and primary-role card-count comparisons using the
existing count controls and compound facts. Component presentation shares the
same default-role classification, including canonical Richese cards, Ix alternate
uses, and Ecaz slot-only specials. Only the respondent receives the verified
aggregate answer; current facts do not impose future custody promises.

Eight new tests cover all 60 catalog cards, real engine actions, malformed input,
private worlds, all four bots, JSON continuation, and a legal custody transfer.
Expanded production-room SQLite cases cover restored total/category/compound
facts, suspended auction state, and one winning concurrent answer/discard.
Independent review's two copy issues were fixed before broad verification.

Validation: types, lint and 4,200 offline tests passed; production build passed;
40 HTTP tests passed. One stable broad run (check 123036 ms, build 6505 ms,
integration 23467 ms). Browser room LC3E55GY verified combined role counts,
total hand size, invalid-input feedback and refresh at 390px phone width.
All 33 pre-integration rooms preserved unchanged; HTTP checks added 30 rooms.
No complete-mode, full-game or publication gate opened.

Private report: 20260913-hand-inventory-final/report.json
Source fingerprint: c6a69a9e69941cdd1e5734d92afedbf10d31fda36c91d26ca7e15f4fb7c59b18
Efficiency pilot milestone 3: aggregate counter 58,695,053 to 59,144,653 at
completed verification = 449,600 tokens, including context/coordination overhead.
Two bounded workhorse-model helpers, reused UI and SQLite fixtures, one browser
room. Counter is not monetary cost and this differently sized batch does not
establish a savings percentage. Final Git/push overhead follows this sample.
This commit is contained in:
Quintine committed 2026-09-13 11:29:05 +10:00
1 parent 32791ed5e2
commit 7454456755
14 files changed
+980 -151

No files matched your search

+26 -12
View File
@@ -62,7 +62,9 @@ export function Truthtrance({
]);
const factId = useId();
const invalidSpice = (fact: TruthFact) =>
(fact.kind === 'spice' || fact.kind === 'handCount') &&
(fact.kind === 'spice' ||
fact.kind === 'handCount' ||
fact.kind === 'handInventory') &&
(!Number.isSafeInteger(fact.value) || fact.value < 0);
const invalidFact = clauses
.slice(0, join === 'single' ? 1 : 2)
@@ -357,9 +359,10 @@ export function Truthtrance({
<p className="notice">
Automatic enforcement currently supports the active
player’s unused shipment in base Basic games and base
Advanced games without Guild or optional modules. Select that player and finish pending
decisions first. Earlier questions and other rules
configurations remain unfinished.
Advanced games without Guild or optional modules. Select
that player and finish pending decisions first. Earlier
questions and other rules configurations remain
unfinished.
</p>
)}
<p className="notice">
@@ -442,16 +445,23 @@ export function Truthtrance({
compare: 'gte',
value: 2,
}
: e.target.value === 'spice'
: e.target.value === 'handInventory'
? {
kind: 'spice',
kind: 'handInventory',
category: 'all',
compare: 'gte',
value: 6,
}
: {
kind: 'traitor',
leader: g.allLeaders[0].id,
value: 2,
}
: e.target.value === 'spice'
? {
kind: 'spice',
compare: 'gte',
value: 6,
}
: {
kind: 'traitor',
leader: g.allLeaders[0].id,
}
: old,
),
)
@@ -461,6 +471,9 @@ export function Truthtrance({
<option value="handCount">
Number of a named card
</option>
<option value="handInventory">
Hand size or primary card role
</option>
<option value="traitor">Selected a traitor</option>
<option value="spice">
Current personal spice
@@ -487,7 +500,8 @@ export function Truthtrance({
))}
</select>
</label>
) : c.kind === 'handCount' ? (
) : c.kind === 'handCount' ||
c.kind === 'handInventory' ? (
<CardCountFields
value={c}
onChange={(next) =>