Commit Graph
360 Commits
Author SHA1 Message Date
Quintine bcabaaf596 Enable native Fremen Cunning with original Nexus components 2026-10-11 18:56:20 +11:00
Quintine 7571ffb2ef Correct superseded multi-pile and HMS scope guidance 2026-10-11 17:30:55 +11:00
Quintine 18693b3207 Resume native Intrusion after final-flight Semuta response 2026-10-11 17:25:26 +11:00
Quintine 9efa17b2b7 Offer Semuta before native Black Market replacement draws 2026-10-11 17:03:04 +11:00
Quintine d1ba8e0c7e Activate approved normal Mentat and document Emperor gift ruling 2026-10-11 16:46:17 +11:00
Quintine eb63967b5c Connect owned Sandmaster stronghold pile allocation 2026-10-09 05:24:33 +11:00
Quintine 0040ed1921 Connect owned Sandmaster destination pile choices 2026-10-09 04:51:12 +11:00
Quintine 24863480cb Connect owned Sandmaster ground pile selection 2026-10-09 03:54:00 +11:00
Quintine 5544b69d7e Use proxy-free runtime for built local serving 2026-10-09 03:30:27 +11:00
Quintine a1517ec949 Connect owned multi-pile battle skill choices 2026-10-09 03:14:14 +11:00
Quintine f2fd274502 Repair deterministic Occupy test transitions and card staging 2026-10-09 02:53:09 +11:00
Quintine 38b1ba3419 Allow provisional Kulon and Ornithopter coexistence 2026-10-09 02:46:41 +11:00
Quintine 5bfcd2dfbf Record remaining intermittent prototype test flakes 2026-10-09 02:37:01 +11:00
Quintine 048c8e60ff Resolve the high-threshold revival deployment question provisionally 2026-10-09 02:12:58 +11:00
Quintine 504681db82 Resume gated preserved captures under the new Basic occupation and Occupy prototypes 2026-10-09 01:56:38 +11:00
Quintine 5e2a320512 Repair inherited stale rule guards and two minimal-legal bot gaps 2026-10-09 01:49:39 +11:00
Quintine b892967eb3 Connect provisional Basic current-sole Homeworld benefits and repair stale rule guards 2026-10-09 01:26:20 +11:00
Quintine 66e061ccca Connect Richese final-cache and provisional full-hand acquisition 2026-10-08 20:29:45 +11:00
Quintine 451ecc950c Connect provisional late-paid Recruits accounting 2026-10-08 19:31:42 +11:00
Quintine be8703dc51 Connect printed Diplomat defenses and Ecaz Tanked Duke Cunning 2026-10-08 19:05:08 +11:00
Quintine 039fe4e87f Connect Sandmaster collection to physical Ambassador relocation 2026-10-08 17:23:43 +11:00
Quintine 7cef1a3412 Connect Advanced allied reserve transit and legal departure 2026-10-08 16:58:21 +11:00
Quintine 869412bebd Connect Advanced Auditor repeated revival and provisional native cycles 2026-10-08 16:51:05 +11:00
Quintine 85729f9819 Connect provisional Advanced Richese mixed battles and exchanges 2026-10-08 16:46:48 +11:00
Quintine 4ed6beb33a Apply supplied Advanced Ixian Technology Richese-lot exclusion 2026-10-08 16:35:13 +11:00
Quintine 0315917987 Connect supplied Advanced Fremen Ecaz two-sietch victory allowance 2026-10-08 16:26:49 +11:00
Quintine d438d923a3 Connect Advanced Ecaz and Moritani special Karama first versions 2026-10-08 11:29:08 +11:00
Quintine 59a406830c Connect source-ordered Advanced Ecaz new-ally Duke grant 2026-10-08 10:14:08 +11:00
Quintine 5e293f567a Align Basic faction guidance with connected rule prototypes 2026-10-08 09:48:55 +11:00
Quintine f29f14128f Connect provisional Basic full-hand Nullentropy Box exchange 2026-10-08 09:30:34 +11:00
Quintine 8d55b8f3f7 Connect provisional Basic Guild and Karama allied No-Field prices 2026-10-08 09:15:48 +11:00
Quintine 2ede6b55ea Connect provisional Basic mixed Richese No-Field battles 2026-10-08 09:02:10 +11:00
Quintine d3a09a95fe Connect Basic allied reserve shipment and provisional departure policy 2026-10-08 08:53:44 +11:00
Quintine fbbfabb404 Remove the superseded Guild Secret Ally native-return preview block 2026-10-08 08:36:53 +11:00
Quintine 2d0f20b69c Connect the Basic Ecaz new-ally Duke loan 2026-10-08 08:30:38 +11:00
Quintine c28e24b5fa Prioritize Basic faction prototypes and connect three missing rule paths 2026-10-08 08:23:20 +11:00
Quintine f36632accc Count the Advanced CHOAM Auditor in the expected Traitor deck
tools/sample-custody.ts built its expected Traitor deck from the printed
leaders only, but Advanced CHOAM adds its printed extra Auditor disc during
setup, so every fresh Advanced all-expansion sample failed at setup with
'physical traitor custody'. The expectation now includes the Auditor for
Advanced CHOAM seats; the resumed saved positions were unaffected because the
resume path recomputes the inventory from the game.

With the fix a fresh --profile combined-homeworld-nexus --rules both --players
all run completes 2/4 (both Advanced). The two Basic samples stop at phase 6
on 'Odd-force Basic Occupy awaits the preserved publisher casualty-rounding
ruling', one of the three other unresolved questions recorded in the capture
resumption note, not on the five implemented rulings.

tests/sample-custody.test.ts (11 cases) and the faction-games suite pass;
types and lint are green.
2026-10-07 22:39:43 +11:00
Quintine 7fa737f690 Record the preserved-capture resumption under the five rulings
All 123 preserved failed-*.json captures were resumed in place with
tools/faction-games.ts --resume (same saved position, seed and physical
custody; no reset, no fresh re-run). 102 of the 116 that produced a report
now complete; seven collided on duplicate basenames and were re-run with
unique output directories.

- The low-Tupile CHOAM opening-income ruling unblocked all 23 captures that
  stopped at response choamCharity, across the mixed/single/paired/native
  Homeworld+Nexus profiles and the occupation choam-6-basic capture.
- The exhausted-cache count ruling unblocked all three captures that stopped
  at decision richeseBlackMarket (seeds 20265033, 20273010 and the paired E3
  discovery variant).
- Nine of the thirteen preserved homeworld-occupation captures now complete.
- Suk/Kwisatz, Guild Secret Ally return and Sandmaster relocation changed no
  capture outcome.

The 14 remaining captures are gated on three other unresolved questions (the
competing-occupier/native-repopulation occupation lifecycle, the Homeworld
high-threshold revival-deployment timing and the odd-force Basic Ecaz Occupy
casualty rounding), not on the five implemented rulings. No guard was
weakened and no capture was force-completed.
2026-10-07 22:33:13 +11:00
Quintine 7e3bec2721 Implement the five 7 October pending rule rulings
The user answered five recorded questions; each ruling is indexed in
RULE_DECISIONS.md and implemented with a focused regression.

- CHOAM opening income counts as a qualifying collection, so low-population
  Tupile adds its bank increment under the Inflation multiplier. The engine
  guard is removed and the projection/notice expose the added bonus.
- An exhausted Richese cache is legal and restores one ordinary lot; the
  canceled/prevented compulsory cache auction branch restores the reduction
  before the ordinary pool runs and the cache offer is skipped when no cache
  lot can run. The pure continuation quote mirrors the count.
- Suk-rescued casualties count toward Advanced Atreides' seven Kwisatz
  Haderach losses: the battle-loss counter gains the full dialed allocation in
  both rescue paths, and the earlier Suk availability restriction is removed.
- The Guild Nexus Secret Ally reserve return overrides the Arrakis-to-native-
  Homeworld restriction for the holder's own reserves and deposits through the
  shared native-reserve pipeline (generalized from the revival deposit).
- Interior passengers count as entering the territories a relocated Ixian HMS
  points into, so Sandmaster collects there before the native collection.

Full offline suite 7804/7804, types and lint pass. Historical evidence and
superseded test expectations are updated to the ruled behaviour; preserved
combined Homeworld/Nexus, occupation and Richese captures are unblocked but
not re-run here. No existing game, seat or saved state was changed.
2026-10-07 21:56:17 +11:00
Quintine e493bcf58e Report database size and make four genuine suites reproducible
Operations now report the SQLite database size and page count, read through
PRAGMA page_count/page_size in the same authority-checked batch as the
lifecycle counters with non-numeric values clamped to zero; the page renders
both and states that free disk space is still unknown.

replaceMoritaniAssassinationTraitors draws the first distinct physical Traitor
Card from the reserve instead of the reserve's first entry, because the face-up
set-aside card can still sit in that list: re-drawing it produced a receipt
whose replacement equalled the revealed card, which the assassination integrity
check rejects mid-Mentat. With no distinct card left the step is blocked with an
explicit reason instead of committing an invalid receipt.

Four tests were made reproducible after measuring their real failure rates,
because a suite that fails for random reasons cannot act as a checkpoint gate:
the Discovery typed Spice Blow test now removes other cards for the same
territory so one blow deposits the printed amount (0/20 after, ~20% before); the
Discovery E2 skills deal is pinned with the new shared
tests/deterministic-random.ts helper so a Lasgun-shield explosion cannot
pre-empt its skill consumer (0/12 after, ~20% before); the Ecaz Occupy Ix/CHOAM
policy check accepts any legal continuation and still asserts the phase it
reaches (0/30 after, ~10% before); and the mixed-E3 Moritani Cunning test keeps
the random storm off red_chasm's single sector (0/25 after, ~20% before).

Offline suite 7,801/7,801 with typecheck and lint clean. No game, seat, saved
state or deployment changes.
2026-10-07 19:55:43 +11:00
Quintine 8bea4c1a0c Record administrator failed attempts without storing credentials
Rejected administrator authentication and authorization attempts are now
recorded durably in a new additive admin_attempts table with a fixed reason
(invalid_key_format, unknown_or_disabled_key, missing_session,
unknown_or_expired_session, role_denied), the attempt kind, the attempted role
and an already-known account id. No key, key hash, session token, session hash,
request body, origin, address or user agent is stored, and the
unknown/disabled distinction is deliberately collapsed so the lookup cannot
become an account-enumeration oracle.

GET /api/admin/operations?attempts=1 returns seven-day per-reason counters plus
the twenty most recent attempts, newest first, to a live owner only, with
no-store and the same query guard as the other reads. The operations page adds
"List failed attempts" with the counters and the bounded sample, truncating each
account id to eight characters. Recording is best-effort inside the rejection
path, so a rejected request keeps its own answer even when the table is
unavailable, and the history never locks out, disables or revokes anything by
itself.

Evidence: tests/admin-attempts.test.ts asserts every recorded reason, the
kind/role/account fields, that successful sign-ins and privileged reads record
nothing, that no credential text appears anywhere in the page, the reporting
window, the twenty-row bound and the owner-only recheck after demotion, and that
a dropped attempts table leaves the original rejection answer unchanged. The
anonymous HTTP boundary denies ?attempts=1, and the panel was verified in the
real browser against a genuine recorded rejection. The shared AdminError moved
to db/admin-error.ts so the recorder and the access module no longer form a
value-import cycle. Offline suite 7,801/7,801 with typecheck and lint clean. No
game, seat, saved state or deployment changes.
2026-10-07 19:11:45 +11:00
Quintine 3bebc68cd5 Compose the Sneak Attack arrival with the Bene Gesserit reactions
A positive Moritani Sneak Attack now resolves its committed Terror entry first —
placing the reserve forces and accruing the Heighliners token — and then offers
the Bene Gesserit reactions under the same adopted shipment classification used
for ordinary off-planet arrivals: an eligible Advanced Intrusion choice when
Bene Gesserit fighters stand in the destination, carrying the free
spiritual-advisor follow-up, and the advisor shipment itself when the intrusion
is declined, with its existing territory, storm and occupancy validation. A
zero-force resolution still opens none of them, and the last "Sneak Attack
combined with Bene Gesserit arrival reactions" guard is removed rather than left
as a duplicate check.

This selected order is an implementation interpretation, not a located ruling;
the source note, the pending-interpretation registry, the component inventory,
the player reference and the status log record it. Evidence:
tests/moritani-force-leader.test.ts asserts the post-entry Intrusion offer and
the full decline -> advisor decision -> placement chain with nothing left
pending; the former gated-interaction pin was replaced by the composed
behaviour. Offline suite 7,798/7,798 with typecheck and lint clean, plus the
reference guide tests 10/10. No game, seat, saved state or deployment changes.
2026-10-07 18:53:19 +11:00
Quintine 972b781d0a Adopt the Sneak Attack shipment classification for Heighliners
A positive Moritani Sneak Attack in Shipment and Movement now accrues the
Heighliners token once for its owner through the same techIncome helper as an
ordinary off-planet arrival. The token still enforces its working phase, its
printed Guild exception and one accrual per turn, and a zero-force resolution
accrues nothing; the previous phase-5 guard is removed rather than duplicated.

This is an explicitly adopted implementation interpretation, not a retrieved
publisher ruling: the printed verb is "Send", and classifying the expressly
off-planet reserve transfer as a shipment is the supported reading already
recorded in the source note. Bene Gesserit spiritual-advisor accompaniment and
Intrusion stay gated because their ordering inherits the unresolved
arrival-timing boundary; a Spice Blow worm-ride Sneak Attack stays outside the
token's working phase.

Evidence: tests/moritani-force-leader.test.ts asserts the accrual, the
once-per-turn guard, the unchanged zero-force resolution and the altered-sector
rejection; the former unsupported-classification pin was replaced by the
adopted behaviour rather than re-pinned. The component inventory, the source
note, the pending-interpretation registry, the player reference and the status
log record the reduced boundary. Offline suite 7,797/7,797 with typecheck and
lint clean. No game, seat, saved state or deployment changes.
2026-10-07 18:40:19 +11:00
Quintine 0e1a442dca Wire the Tleilaxu Ambassador force return
The last unimplemented Ambassador effect is now reachable. A placed Tleilaxu
token gives its beneficiary — the Ecaz owner or its ally — a private
ecazAmbassador decision at the new revival stage: one to four physical counters
return from the Tanks to reserves at zero cost, quoted by the existing
game/tleilaxu-ambassador-forces.ts, which also enforces the shared
Fedaykin/Sardaukar one-per-turn counter and keeps Ixian cyborgs uncapped.

The player view projects the maximum, Tanks and elite inventory and current
elite usage to the beneficiary only; the entry control offers a per-count
button and an explicit "Return no forces" decline; all four AI profiles choose
a legal return from the decision owner's own view or decline when the Tanks are
empty. Player-facing coverage text now lists Tleilaxu.

Kept gated exactly as recorded: the printed leader alternative, ordinary
force/free/leader allowance accounting around this independent grant,
dead-twice eligibility, and Tleilaxu free-income repeat scope. No ordinary
revival allowance, price, phase or income path changes.

Evidence: tests/tleilaxu-ambassador-engine.test.ts drives a genuine arrival into
a placed token and asserts the beneficiary-only projection, the typed return
with unchanged spice, the shared elite limit, malformed/over-maximum rejection
with immutability, the ordinary-only return, the decline path and the rendered
control. The four-profile ecaz-entry-bots loop now covers tleilaxu, and the
former unsupported-effect and copy-list pins were updated to the supported
behaviour rather than re-pinned. Offline suite 7,797/7,797 with typecheck and
lint clean. No game, seat, saved state or deployment changes.
2026-10-07 18:28:57 +11:00
Quintine 07c20ae806 Diagnose stalled administrator decisions from the operations page
Add an owner-only, read-only sample of at most ten live rooms whose public
pending interaction — decision, response, Truthtrance or phase opening — has
been idle longest, with the room code, idle duration, interaction kind, turn
and phase. GET /api/admin/operations?stalled=1 repeats live owner authority,
answers no-store, rejects any other query combination and repairs nothing;
paused, closed, removed and archived rooms are excluded and no private game
content is selected. The aggregate sample adds stalledRooms and
oldestStalledChange for the same predicate.

Owner-only unit coverage asserts the counters, the oldest stalled write, the
bounded oldest-first order, every exclusion boundary, idle arithmetic, the
absence of private content and the owner recheck after demotion. The anonymous
HTTP boundary denies the new read, and the full HTTP integration suite passes
55/55 against a local build of this revision. The panel was verified in the
real browser against six hours of genuine idle rooms, which caught and fixed a
missing threshold field in the response.

No game, seat, saved state, deployment, public start or played-save conversion
changes.
2026-10-07 17:51:08 +11:00
Quintine e05a205a47 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.
2026-10-07 17:24:23 +11:00
Quintine 45e6084424 Record mixed E3 Nexus composition scope and receipts 2026-10-07 15:17:01 +11:00
Quintine 48b2755088 Compose original mixed E3 and three-family Nexus 2026-10-07 15:16:37 +11:00
Quintine 6935b8650d Record exact mixed Nexus container verification receipt 2026-10-07 14:20:50 +11:00
Quintine 05ab2c92b0 Compose original mixed and paired Nexus optional modules 2026-10-07 14:12:47 +11:00