+ Your Harkonnen inspection · Turn {record.turn}
+
+ {record.kind === 'draw'
+ ? `Cards you took and inspected from ${target?.name ?? 'the other player'} during Bidding.`
+ : `Cards in your hand before the automatic return to ${target?.name ?? 'the other player'} during Bidding.`}
+ {' '}This is a record of what you saw then. These cards may have changed hands since.
+
+
+ {record.cards.map(card => (
+ -
+ {card.name}
+
+
+
+ ))}
+
+
+ );
+}
diff --git a/db/rooms.ts b/db/rooms.ts
index 3b94c22a..5ad35440 100644
--- a/db/rooms.ts
+++ b/db/rooms.ts
@@ -486,6 +486,7 @@ export function needsAutomaticRoomRecovery(
state.decision?.kind === 'ecazAmbassador' ||
state.decision?.kind === 'homeworldShipmentGuild' ||
state.decision?.kind === 'fullPlanRead' ||
+ state.decision?.kind === 'handExchange' ||
state.decision?.kind === 'auctionPayment'
);
}
diff --git a/docs/CURRENT_STATUS.md b/docs/CURRENT_STATUS.md
index f1245f39..1b626462 100644
--- a/docs/CURRENT_STATUS.md
+++ b/docs/CURRENT_STATUS.md
@@ -6,23 +6,21 @@ gated.** Prototypes do not open completion or publication gates.
## Current checkpoint and work
-Latest delivered checkpoint: `7136c8d`, [Truthtrance physical-force questions](TRUTHTRANCE_FORCE_FACTS.md).
-Types, lint, **5,122 offline tests** and the production build passed; six
-complete Basic/Advanced samples had no rejected actions across 1,551 actions
-and 39 JSON restores. Browser compound questions, AI responses, mobile controls
-and exact human private-answer refresh were checked. All 1,584 prior rooms and
-3,352 seats remained intact; one QA room/seat brought the baseline to 1,585 rooms
-and 3,353 human seats. Full visual acceptance remains open.
+Latest delivered checkpoint: `a3bc0ac`, [completed-action feedback](ACTION_FEEDBACK.md).
+Types, lint, **5,137 offline tests** and the production build passed. Two complete
+Basic/Advanced samples had no rejected actions across 821 actions and 21 JSON
+restores. Browser burst notices, local interaction, muted updates and exact refresh
+were checked. All 1,585 prior rooms and 3,353 seats remained intact; one QA
+room/seat brought the baseline to 1,586 rooms and 3,354 human seats. Full visual
+acceptance remains open.
-Current work connects [completed-action feedback](ACTION_FEEDBACK.md) for core
-movement, shipment, revival, collection and battle results. Existing cosmetic
-notices coalesce bursts into at most three visible/pending notices, with complete
-chronicle details retained; hidden pages clear and silently consume feedback.
-
-A bounded follow-up candidate is the forced Harkonnen special-Karama return
-when every held card must go back. Automatic settlement must preserve a private
-saved record of the randomly inspected cards and the original interruption.
-This is unfinished; larger hands must keep their real return choice.
+Current work connects the [forced Harkonnen special-Karama return](HARKONNEN_EXCHANGE.md)
+when every held card must go back. Automatic settlement preserves a private saved
+record of the inspected cards and the original interruption. Larger hands keep
+their real return choice; legacy records identify held cards without inventing
+which were originally drawn. The server also schedules older saved exchanges for
+automatic recovery while preserving real choices. Independent review is complete;
+final source-bound checks and browser evidence accompany the Git checkpoint.
The [Sandmaster/HMS source comparison](SANDMASTER_MOVEMENT.md#21-september-native-hms-relocation-eligibility)
found no official clarification that passengers remaining in the interior
diff --git a/docs/HARKONNEN_EXCHANGE.md b/docs/HARKONNEN_EXCHANGE.md
new file mode 100644
index 00000000..b59e349d
--- /dev/null
+++ b/docs/HARKONNEN_EXCHANGE.md
@@ -0,0 +1,74 @@
+# Harkonnen special-Karama inspection and forced returns
+
+The existing Advanced development power draws one through four random, unseen
+cards from another player during Bidding. Harkonnen spends its Karama and
+once-per-game use, inspects the combined hand, and returns the same number of
+cards. Newly drawn cards may be returned. Larger hands keep their real choice.
+
+When the combined hand contains exactly the number owed, every held card must
+return. The engine completes that return automatically and emits a house-colored
+notice explaining the lack of a choice. A manual return also announces the
+completed exchange. The table's existing cosmetic toggle,
+reduced-motion behavior and short notice queue apply.
+
+## Private saved observation
+
+**Your Harkonnen inspection** below the board retains the actual randomly drawn
+cards, including their readable rules and enlarged inspectors. It identifies the
+target and turn and describes historical knowledge: the cards may have changed
+hands since. Only Harkonnen's owning seat receives this record. Allies, the target
+and other seats receive no inspection record or suspended private auction data.
+
+The copied card descriptions are observations, outside physical card custody.
+They persist through ordinary returns, later card movement and JSON recovery.
+An internal integrity receipt binds the original card faces and provenance;
+changed history is rejected before disclosure. The receipt is not projected.
+Existing forced-return saves without a recorded draw retain a truthful snapshot
+of the cards held before returning them; the interface does not claim these were
+all originally drawn from the target. Legacy exchanges with a real choice keep
+their selector without inventing prior knowledge.
+
+Both manual and automatic returns use the same settlement, restore the suspended
+decision/response and keep the existing auction funding recovery. Higher-priority
+interruptions finish first. Restoring a completed exchange must never redraw,
+repeat the return, spend a second Karama or consume the power twice.
+
+## Authority and limits
+
+This composes the existing contract recorded under **Emperor and Harkonnen
+special Karama checkpoint** in [implementation history](IMPLEMENTATION_STATUS.md):
+GF9 base rules page 14; November 2020 FAQ page 3 (phase and once-per-game limit)
+and page 6 (blind draw, inspection, equal return and temporary hand limits).
+Automatic resolution of a uniquely determined action follows the user's explicit
+interface requirement. Persisting information already inspected does not reveal
+the target's current hand.
+
+The existing recovery when an exchange removes the only Karama backing an
+unfunded auction bid remains provisional. This checkpoint does not resolve that
+ruling or certify all timing and expansion combinations. Advanced and publication
+gates remain closed.
+
+## Verification scope
+
+Focused engine tests cover forced and real choices, saved interruption priority,
+legacy observations, private projection, rejected-action immutability, physical
+custody and minimal legal AI continuation. An authenticated in-memory SQL test
+races two real special-card actions, accepts one, reloads every seat and rejects
+stale replay without changing the inspection or cards. It also races two restored
+legacy continuations through the production recovery scheduler: one return is
+saved with no new random draw. Genuine choices remain waiting without writes.
+Component tests distinguish
+drawn cards from legacy held-card history and exclude non-owner output.
+
+Required checks and browser evidence are recorded in the private source-bound
+checkpoint report. These checks establish bounded behavior, not full Advanced
+acceptance or AI difficulty calibration.
+
+Browser QA used genuine Advanced setup in a new isolated development room,
+then conserved Bidding positions. Playing the real special-Karama control drew
+and returned four cards with no return prompt; bidding stayed available. The
+private history and enlarged Shield inspector survived refresh, which retained
+the exact saved row hash. At a 390-pixel viewport, the 339-pixel history panel
+fit within the 375-pixel document without horizontal overflow; each inspector
+button was 44 pixels high. The viewport was reset. Screenshot capture timed out,
+so these interaction and DOM checks do not establish full visual acceptance.
diff --git a/docs/IMPLEMENTATION_STATUS.md b/docs/IMPLEMENTATION_STATUS.md
index 4628f810..3820dfcb 100644
--- a/docs/IMPLEMENTATION_STATUS.md
+++ b/docs/IMPLEMENTATION_STATUS.md
@@ -1,5 +1,14 @@
# Dune implementation status
+## 21 September 2026 — Harkonnen forced exchange return
+
+Special-Karama exchanges now return automatically when the entire combined hand
+is owed. A private saved inspection retains the actual drawn card faces; legacy
+forced saves describe their held-card observation without inventing draw origin.
+Real choices remain interactive. Shared settlement preserves suspended responses,
+auction recovery and physical custody. See [scope and evidence](HARKONNEN_EXCHANGE.md).
+The existing unfunded-bid ruling and Advanced/publication gates remain open.
+
## 21 September 2026 — Completed-action feedback
Core committed movement, shipping, revival, collection and battle results now
diff --git a/docs/RULE_DECISIONS.md b/docs/RULE_DECISIONS.md
index ad5be40d..97faad67 100644
--- a/docs/RULE_DECISIONS.md
+++ b/docs/RULE_DECISIONS.md
@@ -6,6 +6,7 @@ Updated 14 September 2026. This is the authoritative navigation index for existi
| Topic | Decision to preserve | Detailed authority and evidence |
| --- | --- | --- |
+| Harkonnen special-Karama forced return | Return automatically only when the combined hand equals the count owed. Keep actual drawn-card observations owner-private after settlement; legacy forced saves describe held-card history without inventing draw provenance. Existing provisional auction-payment recovery and mode gates remain. | [Contract and limits](HARKONNEN_EXCHANGE.md) |
| Basic Moritani / Leader Skills | Ordinary Terror death returns the assigned skill once; own revival offers the existing private optional replacement. Sabotage does not take skills, alliances do not transfer assignments, and mandatory Planetologist/Diplomat disposal excludes those cards from ally retention. This is composition of existing contracts, not a new ruling or resolution of unfinished skill effects. Advanced and other roster/module combinations remain gated. | [Integration contract](MORITANI_LEADER_SKILLS.md) |
| Ecaz Loyalty | Before initial Traitor dealing, randomly set aside one native Ecaz card face up permanently. No Karama effect; no change to its leader disc. Resolving after existing pre-Traitor setup is an explicit sequencing composition. Older dealt saves are not retrofitted; combined Skills/assassination rosters remain gated. | [Official sources and runtime](ECAZ_LOYALTY.md) |
| Sapho battle order | First/last reorders remaining Battle-phase choosers at clean boundaries. Phase priority persists through aftermath; actual legal pairs determine eligibility. Separating the chooser from physical attacker/tie advantage is an explicit implementation interpretation of the card's distinct alternatives, not a dedicated FAQ ruling. Last does not prevent others from choosing the holder as an opponent. | [Runtime scope and source interpretation](SAPHO_BATTLE_ORDER.md) |
diff --git a/game/engine.ts b/game/engine.ts
index 18869002..9e795af8 100644
--- a/game/engine.ts
+++ b/game/engine.ts
@@ -1496,6 +1496,16 @@ export type Game = {
response: ResponseWindow | null;
decision: Decision | null;
} | null;
+ /** Private knowledge copies, never an additional physical card zone. */
+ harkonnenExchangeInspection?: {
+ owner: string;
+ target: string;
+ turn: number;
+ phase: 3;
+ kind: 'draw' | 'return';
+ cards: Card[];
+ signature: string;
+ };
/** Purchase is already committed; only the Emperor's receipt remains pending. */
pendingRichesePurchaseIncome?: {
owner: string;
@@ -8776,10 +8786,128 @@ function recordFullPlanInspection(g: Game, owner: string) {
{ faction: p.faction, name: 'Full plan inspection' },
);
}
+function harkonnenInspectionSignature(
+ inspection: Omit