---
title: The Tidal Archive world
date: 2026-06-19
status: implemented
tags: [world-design, the-tidal-archive, displacement, discard-memory, deck-control, core-effect]
modules: [core-engine, world-data, game-view, themes]
related: [.lore/reference/worlds/authoring/theme-authoring.md, src/game/assets/themes/the-tidal-archive/CATACLYSM.md]
req-prefix: TIDAL
---

# The Tidal Archive world

The Tidal Archive is a floating turquoise-and-gold archive where memory is indexed by place. The Walker's passage breaks that index: buildings drift away from their histories, roads connect to yesterday, and every route begins converging on the remembered moment when the player followed the Walker.

Threat verb: **displace**. The world attacks card location: hand, discard, draw pile, world deck, and the top of each deck. The player survives by remembering where useful cards went, choosing which hazards to repeat, and controlling what the tide returns next.

The signature rule is **Tidal Memory**: at the end of each turn, the Archive recalls one player discard to the top of the player deck. Unlike ordinary discard pressure, a discarded card is not gone; it has become a place the tide can revisit.

## Ratified decisions (2026-06-20)

Found during a cross-plan review and folded into the requirements below (trail: `.lore/work/plans/the-tidal-archive.md` § Review corrections):

- **`Hidden` → `Obstructed`** everywhere. The engine has no `Hidden` keyword (`KeywordName = "Obstructed" | "Creature" | "Slow" | "Spore" | "Concealed"`). REQ-TIDAL-22/29/30/31 now read `Obstructed`.
- **A creature snatches so `Brace` works** (REQ-TIDAL-26/34). `Anchor the Memory` grants `Brace`, which only absorbs `ForceDestroy` snatches; nothing produced one. `Chained Books Rising` now uses `ForceDestroy` instead of `Damage`. (`ForceDestroy` removes cards from hand outright, not to discard, so it does not feed Tidal Memory.)
- **`ReturnWorldCards` is not used on world auto-hooks** (REQ-TIDAL-32). It is inert there (auto-hooks never supply the player selection it reads). `Bridge to Yesterday`'s `onCleared` is re-expressed as a top-deck recurrence. (`Waterproof Notes`' player-played `ReturnWorldCards` is unaffected.)
- **Tool-fetch gives a boon choice, not a fixed multi-card grant** (REQ-TIDAL-30). `Drowned Index` `onCleared` runs `OfferBoon` over the reward kit instead of `Sequence[GainCard ×2]`.
- **Vocabulary** (REQ-TIDAL-19): adds `ForceDestroy` and `OfferBoon`, both existing engine effects.

## World Contract

<div id="REQ-TIDAL-1"></div>

**REQ-TIDAL-1:** The world id must be `the-tidal-archive` everywhere: `cards.json`, `meta.ts`, `theme.ts`, `index.ts`, registry entry, `VisualTheme.worldId`, asset keys, and asset binding imports.

<div id="REQ-TIDAL-2"></div>

**REQ-TIDAL-2:** Theme assets must live under `src/game/assets/themes/the-tidal-archive/`. The existing base assets are canonical and must be wired, not regenerated by default:

- `the-tidal-archive-reality.webp`
- `intrusion-overlay.webp`
- `the-tidal-archive-cardfront.webp`

<div id="REQ-TIDAL-3"></div>

**REQ-TIDAL-3:** *(DEFERRED — follow-up art pass; tracked in `.lore/work/issues/the-tidal-archive-card-insets.md`.)* The implementation must add one inset asset per Tidal card under `src/game/assets/themes/the-tidal-archive/insets/`, use a `tidal-inset-*` key namespace, and register every referenced inset key in `src/game/worlds/assetBindings.ts`. Cards ship with no `insetKey` until the art lands; the base assets (reality/intrusion/cardfront/music) are wired and tests pass without insets.

<div id="REQ-TIDAL-4"></div>

**REQ-TIDAL-4:** The world must register through the existing `WorldDataBundle` and `worldDataRegistry` pattern. Do not add one-off theme selection, world building, or manifest code when registry derivation can carry the world.

## Narrative And Identity

<div id="REQ-TIDAL-5"></div>

**REQ-TIDAL-5:** The three-beat fiction is: ordinary floating archive with coral bridges and indexed districts, Walker passage unmoors memory from place, the Door opens where all maps and recalled locations converge on the Walker's footprint.

<div id="REQ-TIDAL-6"></div>

**REQ-TIDAL-6:** The Walker, `Summon Door`, and `Door` remain shared starter templates. Tidal data must not redefine any of them.

<div id="REQ-TIDAL-7"></div>

**REQ-TIDAL-7:** The exclusive signature verb is `displace`: move actual cards between discard, draw, hand, and world deck zones, with special pressure on the top of decks. No other world may use Tidal-only recall effects without a new design decision.

<div id="REQ-TIDAL-8"></div>

**REQ-TIDAL-8:** The catastrophe identity must appear in the passive rule, hazards, reward cards, deck composition, display/help copy, visual theme, intrusion overlay, cardfront, and card insets. The world is not "water damage"; it is "the order of places has broken."

## Core Slice: Player Discard Recall

<div id="REQ-TIDAL-9"></div>

**REQ-TIDAL-9:** Add a core effect for moving existing player cards from `playerDiscard` to the top of `playerDraw`, preserving card id, template id, modified state, exhaust state, frozen state if present, and any instance metadata. This must not mint a new copy.

<div id="REQ-TIDAL-10"></div>

**REQ-TIDAL-10:** The player-selected form must support Tidal reward cards. Initial shape:

```typescript
{ kind: "ReturnPlayerDiscardToTop", min: number, max: number }
```

When played from a player card, it targets cards currently in `playerDiscard`. Selected cards are removed from discard and placed on top of `playerDraw` in player-selected order.

<div id="REQ-TIDAL-11"></div>

**REQ-TIDAL-11:** The automatic form must support hazards and world passives. Initial shape:

```typescript
{
  kind: "RecallPlayerDiscard";
  count?: number;
  policy?: "latest" | "random" | "lowestCost" | "highestCost" | "panicFirst";
}
```

The default is `{ count: 1, policy: "latest" }`. `panicFirst` recalls `Panic` if one exists, then falls back to latest. `random` must use the deterministic run RNG and emit enough event data for replay verification.

<div id="REQ-TIDAL-12"></div>

**REQ-TIDAL-12:** Both recall effects must emit `PlayerDiscardRecalled` with recalled card ids, template ids, source policy or `playerSelected`, and destination `playerDrawTop`.

<div id="REQ-TIDAL-13"></div>

**REQ-TIDAL-13:** Recall effects must be safe no-ops when `playerDiscard` is empty. They must not block playability unless their `min` requires selection and not enough legal discard targets exist.

<div id="REQ-TIDAL-14"></div>

**REQ-TIDAL-14:** The renderer and selection model must support targeting cards in `playerDiscard` for `ReturnPlayerDiscardToTop`. The UI may use a compact discard chooser overlay, but it must show card name, cost, inset, and whether the card is modified or exhausted.

<div id="REQ-TIDAL-15"></div>

**REQ-TIDAL-15:** Add a per-world end-turn passive hook that can run after player hand discard and before turn-start draw/refill. Tidal sets this hook to `RecallPlayerDiscard { policy: "latest" }`.

<div id="REQ-TIDAL-16"></div>

**REQ-TIDAL-16:** The passive hook must be authored in world data, not hard-coded by scene code. Initial source shape may be `onEndOfTurnPassive?: CardEffect` or an equivalent field on `RawCardSource`/`WorldData`, with default `{ "kind": "None" }`.

<div id="REQ-TIDAL-17"></div>

**REQ-TIDAL-17:** End-turn ordering for Tidal must be deterministic: world `onEndOfTurn` hooks resolve, unretained player cards are discarded, the Tidal Memory passive recalls one card from `playerDiscard` to the top of `playerDraw`, then normal turn-start logic refills the hand. This lets the tide return a card discarded by the just-ended turn.

<div id="REQ-TIDAL-18"></div>

**REQ-TIDAL-18:** Non-Tidal worlds must behave exactly as before unless they explicitly set a world end-turn passive. The new hook defaults to `None` and must not emit events in other worlds.

## Core Slice: Existing Effects And Vocabulary

<div id="REQ-TIDAL-19"></div>

**REQ-TIDAL-19:** Tidal cards must use existing effect names where they already cover the behavior: `DiscardThenDraw`, `Draw`, `ReturnWorldCards` (player-played cards only — inert on world auto-hooks), `AddCard`, `AddWorldCardToDeck`, `AddThreatToWorldDeck`, `GainCard`, `OfferBoon`, `Sequence`, `Modal`, `Damage`, `ForceDestroy`, `DestroySelf`, `Brace`, and `None`.

<div id="REQ-TIDAL-20"></div>

**REQ-TIDAL-20:** The spec must not resurrect stale aliases from the cataclysm note. In current code, `AddWorldCardToDeck` replaces the old `AddWorldCardToTop` wording by setting `bTop: true`, and `AddCard` with `dest: "playerDrawTop"` covers top-deck card minting.

<div id="REQ-TIDAL-21"></div>

**REQ-TIDAL-21:** `worldThreatTemplateByWorldId` must map `the-tidal-archive` to `The Same Footprint` so `AddThreatToWorldDeck` repeats the Tidal signature threat.

<div id="REQ-TIDAL-22"></div>

**REQ-TIDAL-22:** No new keyword is required for Tidal. The world may use only valid existing keywords: `Obstructed`, `Creature`, and `Slow` where appropriate. `Spore` remains Overgrown-only in data, and `Concealed` remains Fog-only in data.

## Reward Card Recipe

The following numbers are initial tuning. Costs, counts, and exact progress values may change during playtest as long as the roles remain intact.

<div id="REQ-TIDAL-23"></div>

**REQ-TIDAL-23:** `Mark the Shelf` must be a player reward card that returns a chosen card from `playerDiscard` to the top of `playerDraw`. Initial effect: `ReturnPlayerDiscardToTop min 1 max 1`. Its role is deliberate recall and top-deck setup.

<div id="REQ-TIDAL-24"></div>

**REQ-TIDAL-24:** `Cross-Reference` must be a player reward card using the existing discard/draw target flow. Initial effect: `DiscardThenDraw player 2`. Its role is to turn the discard pile into planned future material under Tidal Memory.

<div id="REQ-TIDAL-25"></div>

**REQ-TIDAL-25:** `Waterproof Notes` must be a player reward card that trades present tempo for a known future hazard. Initial effect: `Sequence` of `DealProgress base 3` then `ReturnWorldCards min 0 max 1`. If `ReturnWorldCards` returns a card to a shuffled deck rather than the top, this card still satisfies the role by deliberately revisiting a known problem later.

<div id="REQ-TIDAL-26"></div>

**REQ-TIDAL-26:** `Anchor the Memory` must be an exhaust player reward that protects against displacement pressure using existing `Brace` until a broader protection mechanic exists. Initial effect: `Sequence` of `Brace amount 1` then `Draw player 1`; `exhaust: true`. Its copy and help text must describe it as anchoring the next snatch or forced loss, not as a universal immunity. The snatch it anchors is supplied by `Chained Books Rising`'s `ForceDestroy` (REQ-TIDAL-34); without that source `Brace` would be inert.

<div id="REQ-TIDAL-27"></div>

**REQ-TIDAL-27:** `Shelf Map` must be a player reward card that gives low progress plus controlled recall. Initial effect: `Sequence` of `DealProgress base 1` then `ReturnPlayerDiscardToTop min 0 max 1`. Its role is flexible navigation rather than raw damage.

<div id="REQ-TIDAL-28"></div>

**REQ-TIDAL-28:** Tidal reward cards must not duplicate another world's reward identity. Their shared identity is manipulating real discard and deck order; they must not claim Light, Heat, Spore scaling, freeze/thaw, or overgrown pruning as their primary value.

## World Card Recipe

<div id="REQ-TIDAL-29"></div>

**REQ-TIDAL-29:** `Wandering Stacks` must be an act-1 ambient hazard. Initial shape: cost 2, `Obstructed`, discardable, `onEndOfTurn: RecallPlayerDiscard latest`, `onCleared: None`, `onDiscarded: None`. It teaches that player discard can return.

<div id="REQ-TIDAL-30"></div>

**REQ-TIDAL-30:** `Drowned Index` must be an act-1/2 tool-fetch hazard. Initial shape: cost 4, `Obstructed`, discardable, `onCleared: OfferBoon { setId: "tidal-boons", offeredCount: 3, chooseCount: 1 }` (offers three of the reward kit, player keeps one), `onEndOfTurn: None`, `onDiscarded: None`. It is the visible way the player learns the reward kit. *(Ratified 2026-06-20: was `Sequence[GainCard ×2]` granting `Mark the Shelf` and `Cross-Reference`, which floods the deck across the card's copies; the boon set is a single source shared with the hazards' fixed `GainCard` grants.)*

<div id="REQ-TIDAL-31"></div>

**REQ-TIDAL-31:** `Misfiled Century` must be an act-2 recurrence hazard. Initial shape: cost 3, `Obstructed`, discardable, `onEndOfTurn: AddThreatToWorldDeck`, `onCleared: None`, `onDiscarded: Damage 1`. It makes the top of the world deck a threat.

<div id="REQ-TIDAL-32"></div>

**REQ-TIDAL-32:** `Bridge to Yesterday` must be an act-2 choice hazard. Initial shape: cost 3, discardable, `onCleared: AddWorldCardToDeck { template: "Misfiled Century", bTop: true }`, `onDiscarded: Damage 2`, `onEndOfTurn: None`. Clearing it is not pure upside: it revisits a known recurrence hazard. *(Ratified 2026-06-20: was `onCleared: ReturnWorldCards`, which is inert on a world auto-hook — auto-hooks never supply the player selection it reads — so the original "player chooses which world card to revisit" intent could not run; re-expressed as a fixed top-deck.)*

<div id="REQ-TIDAL-33"></div>

**REQ-TIDAL-33:** `Borrowed Catastrophe` must be an act-2/3 hazard that imports another disaster without importing another world's exclusive mechanics. Initial shape: cost 4, `Slow`, discardable, `onEndOfTurn: AddWorldCardToDeck { template: "Misfiled Century", bTop: true }`, `onDiscarded: Damage 2`, `onCleared: GainCard "Waterproof Notes"`.

<div id="REQ-TIDAL-34"></div>

**REQ-TIDAL-34:** `Chained Books Rising` must be an act-2/3 pressure hazard, and as a `Creature` it snatches a card from hand rather than dealing HP damage. Initial shape: cost 4, `Creature`, discardable, `onEndOfTurn: Sequence` of `ForceDestroy 1` and `RecallPlayerDiscard lowestCost`, `onDiscarded: RecallPlayerDiscard latest`, `onCleared: GainCard "Anchor the Memory"`. *(Ratified 2026-06-20: `onEndOfTurn` `Damage 1` → `ForceDestroy 1` so the `Brace` from `Anchor the Memory` (REQ-TIDAL-26) has a snatch to absorb; matches the `bird-building` creature-snatch language.)*

<div id="REQ-TIDAL-35"></div>

**REQ-TIDAL-35:** `The Same Footprint` must be the act-3 signature threat. Initial shape: cost 6, `Slow`, non-discardable or high-penalty discardable after playtest, `onEndOfTurn: Sequence` of `RecallPlayerDiscard panicFirst` and `AddThreatToWorldDeck`, `onCleared: GainCard "Shelf Map"`, `onDiscarded: Damage 3` if discardable. It makes all routes lead back to the Walker.

<div id="REQ-TIDAL-36"></div>

**REQ-TIDAL-36:** Every Tidal world card must define `onDiscarded`, `onCleared`, `onPartialClear`, and `onEndOfTurn`. Use `{ "kind": "None" }` for unused hooks.

<div id="REQ-TIDAL-37"></div>

**REQ-TIDAL-37:** At least one early hazard must be harmless or low-damage when discarded, and at least one mid-game hazard must make clearing versus discarding a real choice. The player must never be soft-locked by unbounded recall with no discard or clear valve before the reward kit appears.

## Deck Composition

<div id="REQ-TIDAL-38"></div>

**REQ-TIDAL-38:** The deck must have exactly three acts. Act 1 teaches individual displacement; Act 2 introduces world-deck recurrence and clear/discard sequencing; Act 3 peaks top-deck control and converges on the Walker.

<div id="REQ-TIDAL-39"></div>

**REQ-TIDAL-39:** Initial act composition should be:

| Act | Cards |
| --- | --- |
| Act 1 - Misfiled Shores | `Wandering Stacks` x3, `Drowned Index` x2, `Bridge to Yesterday` x1 |
| Act 2 - Borrowed Histories | `Misfiled Century` x3, `Bridge to Yesterday` x2, `Borrowed Catastrophe` x2, `Drowned Index` x1 |
| Act 3 - The Convergence | `Chained Books Rising` x2, `Borrowed Catastrophe` x2, `The Same Footprint` x1, `Misfiled Century` x1, `The Walker` x1 |

Counts are tuning values; act roles and the fixed Walker closer are not.

<div id="REQ-TIDAL-40"></div>

**REQ-TIDAL-40:** Act 3 must always end with exactly one `{ "templateId": "The Walker", "count": 1 }`.

<div id="REQ-TIDAL-41"></div>

**REQ-TIDAL-41:** The world must not introduce deck-pollution junk by default. Tidal may weaponize existing player discard, including `Panic`, but its core pressure is location/order rather than adding a new junk template.

## Visual Theme

<div id="REQ-TIDAL-42"></div>

**REQ-TIDAL-42:** The visual keynote is sea-glass green and aged archive gold disrupted by the Walker's impossible violet. Suggested values: intrusion hue around `#7657ff`, door glow tint matching violet, cool return/displacement accents in turquoise, warm danger accents in coral red.

<div id="REQ-TIDAL-43"></div>

**REQ-TIDAL-43:** The reality backdrop must remain the floating archive: turquoise water, gold-lit stacks, coral bridges, map tables, catalog marks, and calm architectural order.

<div id="REQ-TIDAL-44"></div>

**REQ-TIDAL-44:** The intrusion overlay must show the Unmooring around the perimeter while preserving central play readability: broken coral bridges curling into loops, translucent displaced buildings, chained books rising from water, index routes bending toward one footprint, and violet corruption overtaking sea-glass/coral colors.

<div id="REQ-TIDAL-45"></div>

**REQ-TIDAL-45:** The cardfront must read as archive material under tidal stress: vellum, water-stained catalog cards, gold index lines, coral cracks, and a subtle violet route mark. Runtime text must remain readable at card scale.

<div id="REQ-TIDAL-46"></div>

**REQ-TIDAL-46:** *(DEFERRED — follow-up art pass; tracked in `.lore/work/issues/the-tidal-archive-card-insets.md`.)* Card insets must make displacement legible. Hazards should show places out of order, maps pointing to wrong districts, books chained to water, and repeated footprints. Reward insets should show deliberate indexing, marked shelves, waterproof notes, and anchored memories. The discard chooser renders an empty inset slot until the art lands.

## Display And Help

<div id="REQ-TIDAL-47"></div>

**REQ-TIDAL-47:** `meta.ts` display copy must describe the place-vs-disaster contrast: an archive that remembers by location, now shuffled so every place recalls the Walker's path.

<div id="REQ-TIDAL-48"></div>

**REQ-TIDAL-48:** Help text must fit the existing world help budget and cover: Tidal Memory returns one discard to the top of the player deck each turn, hazards can change which cards return or what the world deck repeats, and Tidal rewards let the player set up the top of their deck deliberately.

<div id="REQ-TIDAL-49"></div>

**REQ-TIDAL-49:** If the world select layout cannot display a seventh world cleanly, Tidal registration may remain data-ready but hidden from normal selection until the layout supports it. `buildWorld("the-tidal-archive")` and `selectTheme("the-tidal-archive")` must still work in tests.

## Documentation

<div id="REQ-TIDAL-50"></div>

**REQ-TIDAL-50:** `.lore/reference/worlds/authoring/theme-authoring.md` must be updated when this world is implemented: add Tidal to the signature verb table, add the new recall effects to the current effect vocabulary, and document that `the-tidal-archive` owns discard/deck-order recall as its exclusive reward space.

<div id="REQ-TIDAL-51"></div>

**REQ-TIDAL-51:** Any implementation plan derived from this spec must split the work into at least three reviewable slices: core recall/passive hook, world data and registration, and assets/presentation/help.

## Tests And Validation

<div id="REQ-TIDAL-52"></div>

**REQ-TIDAL-52:** Core tests must cover `ReturnPlayerDiscardToTop`: selecting a card from `playerDiscard`, preserving card instance identity, ordering multiple selected cards on top of `playerDraw`, event emission, playability failure when `min` cannot be satisfied, and no-op behavior for optional zero-selection.

<div id="REQ-TIDAL-53"></div>

**REQ-TIDAL-53:** Core tests must cover `RecallPlayerDiscard`: each policy, empty discard no-op, deterministic `random` behavior, `panicFirst` fallback, event emission, and preservation of recalled card instance data.

<div id="REQ-TIDAL-54"></div>

**REQ-TIDAL-54:** Engine tests must cover Tidal Memory ordering: a player card discarded at end turn can be recalled by the passive and then drawn during the same transition into the next turn.

<div id="REQ-TIDAL-55"></div>

**REQ-TIDAL-55:** World data tests must verify no duplicate template ids, all Tidal world cards define all required hooks, all keywords are valid, Act 3 ends with `The Walker`, the Tidal bundle is in `worldDataRegistry`, and `buildWorld("the-tidal-archive")` succeeds.

<div id="REQ-TIDAL-56"></div>

**REQ-TIDAL-56:** Asset validation must verify every Tidal `worldCardfrontKey`, backdrop key, display background key, and intrusion key has a matching manifest binding and loads without falling back to starter art. *(The `insetKey` clause is DEFERRED with REQ-TIDAL-3 — no `insetKey` is referenced yet, so `referencedAssetKeys(bundle)` returns only the base keys and validation passes without inset bindings; tracked in `.lore/work/issues/the-tidal-archive-card-insets.md`.)*

<div id="REQ-TIDAL-57"></div>

**REQ-TIDAL-57:** Presentation tests must cover the discard chooser or equivalent UI for `ReturnPlayerDiscardToTop`, plus effect glyph/description text for both recall effects.

<div id="REQ-TIDAL-58"></div>

**REQ-TIDAL-58:** Replay or deterministic-session tests must cover at least one seeded Tidal run segment where a hazard recalls from discard, the passive recalls after hand discard, and a reward card chooses a discard to top-deck. The event stream must replay to the same state.

## AI Validation

An AI implementing this spec should verify completion by running or observing:

1. `bun test` passes.
2. A targeted core test run for recall, end-turn ordering, effect descriptions, and selection legality passes.
3. A targeted world-data test confirms `buildWorld("the-tidal-archive")`, registry inclusion, unique template ids, valid hooks, valid keywords, and Walker closer.
4. Asset validation confirms all `tidal-inset-*` keys and base Tidal image keys are registered and preloadable.
5. A local game smoke test can select or directly start `the-tidal-archive`, clear `Drowned Index`, choose `Mark the Shelf` from the boon offer, play it from a non-empty discard pile, and observe the chosen card appear on top of the player deck.
6. A seeded replay test proves the same Tidal Memory and hazard recall events produce the same final state across two runs.
