@storylet-studio/runtime 0.8.2 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.cjs +149 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +56 -20
- package/dist/index.d.ts +56 -20
- package/dist/index.js +155 -29
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/engine.ts","../src/prng.ts","../src/describe.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// The reference runtime: an Engine is the world + flow manager, and ALL play\n// happens on a Flow handle (design/flows.md; the shape is Patter's, adopted\n// deliberately so a host driving both engines holds two objects with the\n// same grammar). The dealing semantics of design/storylets-schema.md\n// section 3 run per flow, implemented exactly and held to the conformance\n// corpus.\n//\n// The flow model, in one place:\n// - an Engine owns the bundle, every lookup built from it, the SHARED\n// property partitions and the @world resolver; a Flow owns its own\n// PRNG, per-box clocks, cooldowns, board, claims, play history and the\n// per-flow property partitions. Flows meet only through shared state.\n// - sharing is a per-property `shared` flag on the declaration (never a\n// scope token): @story defaults shared; box, deck, hand and tag\n// properties default per-flow. Every name is shared XOR per-flow, so a\n// read is a union of two bags and a write routes by name.\n// - every property bag lives in ONE ScopeRegistry per game (the\n// one-registry model): the game hands the engine its registry\n// (EngineOptions.registry) or the engine makes its own and acts as its\n// own game. The shared @story registers under `story`, every other bag\n// under a key starting `storylets/`, which no expression can name.\n// saveGame() carries what is NOT a property, plus the registry's values\n// only when the engine made the registry itself.\n// - @world is the game's: a resolver it binds (EngineOptions.world, never\n// saved), a scope it registers in its registry, or, for a standalone\n// engine, a self-backed bag the registry stores and saves.\n// - there is no default flow and no ambient current flow: openFlow(id) is\n// the only way in, an existing id is REPLACED (the old flow closes),\n// and a closed flow's handle is INERT - every verb throws (Patter's\n// stale-handle rule).\n// - engine.getProperty serves world.* and shared refs only; a ref that\n// resolves per-flow throws, naming the fix (Patter's teaching rule).\n//\n// Key dealing contracts, unchanged from round 2 (all per flow now):\n// - two verbs: deal(hand) claims, peek(box, criteria) just looks; you can\n// never play a card you only peeked (3.1, look/use rule)\n// - availability order: deck gate -> cooldown -> tags -> hand condition ->\n// card condition -> claims (3.1)\n// - claims are physical WITHIN a flow: a card sits in at most `copies`\n// hands of that flow's board at once, at most once in any one hand; the\n// ledger is derived from the board contents (3.5)\n// - a SHARED card (its deck's flag, or its own overriding it) is scarce\n// across flows too: at most `sharedCopies` hands anywhere, counted over\n// every live flow's board, and a shared `redraw: \"never\"` is spent for\n// everyone the first time anyone plays it. A finite redraw deliberately\n// stays per flow - a cooldown is an absolute turn of a per-flow clock, so\n// there is nothing shared to compare it against (design/shared-scarcity.md)\n// - the reserved home group inverts the wildcard: a homed card is\n// available only to an ask binding its home (2.4)\n// - ranking: priority desc -> specificity desc (box toggle) -> seeded\n// shuffle of each maximal tie run (3.2)\n// - one PRNG per flow: expression random(), tie shuffles and the batch\n// deal's hand-order shuffle all advance it; state lives in the save (3.3)\n// - each box has its own turn counter PER FLOW; cooldowns are absolute\n// next-eligible turns of the card's box's clock, set at play time from\n// the post-advance turn; \"never\" is MAX_SAFE_INTEGER, not Infinity (3.4)\n// - @hand composes bound-tag props -> hand props -> chosen tags/criteria\n// (by group name), later shadowing earlier; writes route back to their\n// source; criteria names cannot be written (3.6)\n// - outcome availability is never snapshotted: outcomes() and play()\n// evaluate gates against current state (3.1, 3.7)\n// - a trace event fires after the state it reports has landed, so a\n// handler reading the flow inside it sees the effect (the Live Link's\n// board snapshot depends on this; the shared fixture pins it)\n// ---------------------------------------------------------------------------\n\nimport { deserialiseAst, evaluate } from \"@wildwinter/expr\";\nimport type { EvalContext, ExprNode, ScalarValue, ScopeResolver } from \"@wildwinter/expr\";\nimport { matchedSpecificity } from \"@wildwinter/expr-specificity\";\nimport { storyletsDialect, NEVER_PLAYED } from \"@storylet-studio/dialect\";\n\n/** The play-history indexes' key for one (group, tag) pair.\n *\n * A UNIT SEPARATOR (U+001F) joins them: ids are letters, digits and\n * underscores, so a control character cannot occur in one and two different\n * pairs can never collide into one key the way a \".\" or \":\" join could. NUL\n * would say the same thing and was the first choice, but GDScript will not\n * carry one in a string - it substitutes U+FFFD and warns on every parse - and\n * the four runtimes keep the same spelling. */\nconst tagKey = (groupId: string, tagId: string): string => `${groupId}\\u001f${tagId}`;\n\nimport type { StoryletsHost } from \"@storylet-studio/dialect\";\nimport {\n PLACE_GROUP, ambiguousValueAddressMessage, effectiveGameId, isHoleRef, parseHoleRef, valueAddresses,\n} from \"@storylet-studio/model\";\nimport type {\n Box, Bundle, BundleContent, Card, Deck, Expression, FlowSave, Hand, HandTemplate,\n LoadEviction, LoadProperty, LoadReport, PlayRecord, PropertyBag, PropertyDecl, PropsPartition,\n SaveEnvelope, SaveEnvelopeV1, Tag, TagGroup,\n} from \"@storylet-studio/model\";\nimport { SAVE_SCHEMA, SAVE_SCHEMA_V1 } from \"@storylet-studio/model\";\nimport { PropertyBag as StateBag, ScopeRegistry } from \"@wildwinter/scoperegistry\";\nimport type { PropertyRow, ScopeDeclaration } from \"@wildwinter/scoperegistry\";\nimport { makePrng, shuffleInPlace } from \"./prng.js\";\nimport type { Prng } from \"./prng.js\";\n\nexport interface EngineOptions {\n /** Default seed for each flow's PRNG; override per flow in openFlow\n * (cross-runtime determinism, schema 3.3). Default 0. */\n seed?: number;\n /** Retain each flow's event log for introspection - the game-engine seam\n * (schema 5): every trace event, sequence-stamped and turn-stamped where\n * the event has a box context. `true` keeps the default 1000 entries\n * (oldest dropped first). Off by default; subscribeTrace stays the\n * zero-retention stream. */\n log?: boolean | { cap?: number };\n /**\n * The host's resolver for @world - the values the game owns and the\n * story reads (and, where `set` is offered, writes). Engine-level, shared\n * by all flows, never saved: the game keeps these values. Omit it and a\n * standalone engine self-backs @world from the declared defaults, as a\n * property its registry stores and saves. A game running several engines\n * registers @world in its registry itself instead.\n */\n world?: ScopeResolver;\n /**\n * The game's registry: ONE per game, holding every engine's properties\n * except those the game keeps itself, saved once. Given one, the engine\n * registers its own scopes in it (@story under `story`, every other bag\n * under a key starting `storylets/`, and @world if `world` is passed),\n * reads every other scope from it, and `saveGame()` leaves the property\n * values to the game. @world is then the game's to register: owned if the\n * registry should store it, foreign if the game keeps it. Omit it and the\n * engine makes its own registry and acts as its own game: it self-backs\n * @world, and `saveGame()` carries the registry's values too.\n */\n registry?: ScopeRegistry;\n /**\n * Diagnostics hook (opt-in, dev tooling only): fired when `openFlow` REPLACES\n * a flow that still had cards dealt, with the flow id and how many. The\n * behaviour is unchanged - replacing is deliberate and the same in Patter -\n * this only makes it observable, because the case it catches is a host\n * calling `openFlow` straight after `loadGame` to \"re-take\" its handle and\n * silently discarding the hand the save just restored (`getFlow` is the\n * call). Zero cost when unset; leave it unset in shipped games.\n */\n onReplacedFlow?: (id: string, dealt: number) => void;\n}\n\nexport interface OpenFlowOptions {\n /** Seed for this flow's PRNG (defaults to the engine's `seed`). */\n seed?: number;\n /**\n * Open this flow AS IT WAS: a blob from `saveFlow`, applied to the freshly\n * opened (or replaced) flow before the handle comes back\n * (design/engine-server.md 4.1).\n *\n * An option on `openFlow` rather than a `Flow.restore` verb on purpose:\n * restoring INTO a running flow is the trap hosts keep falling into\n * (openFlow REPLACES), and \"open this flow as it was\" is one act. Drift is\n * tolerated exactly as `loadGame` tolerates it, with one addition, because\n * this restore lands in a LIVE engine: a shared card whose world copies are\n * all held by the OTHER open flows is not put back, and is reported as\n * `claimed-elsewhere`. Ask `previewFlowRestore` first to see that coming.\n */\n restore?: FlowSave;\n /** Handed the `restore`'s LoadReport as it happens - the same report\n * `previewFlowRestore` returns for the same blob. Ignored without\n * `restore`; the report has nowhere else to go, since `openFlow` returns\n * the handle. */\n onRestoreReport?: (report: LoadReport) => void;\n}\n\n/** A card view in a dealt hand or a peeked list. Carries NO outcome\n * availability - ask `outcomes()` for current truth (schema 5). */\nexport interface DealtCard {\n id: string;\n gameId: string;\n title?: string;\n purpose?: string;\n fields?: Record<string, ScalarValue>;\n}\n\nexport interface OutcomeView {\n id: string;\n gameId: string;\n title?: string;\n purpose?: string;\n /** The outcome's fields, exactly as the bundle carries them: game data\n * declared by the box's `outcomeFields`, never read by the engine. */\n fields?: Record<string, ScalarValue>;\n /** Evaluated against CURRENT state at the moment of the ask. */\n available: boolean;\n}\n\n/** What a peek returns: the top of the stock, looked at and put back.\n * The engine has no pick policy (Reboot 2.1). */\nexport interface RankedList {\n box: string;\n cards: DealtCard[];\n}\n\nexport interface PlayOptions {\n /** Turn advance override; default settings.playAdvancesTurns, or 0 when the\n * card's box is timed (design/engine-server.md 4.8). */\n advanceTurns?: number;\n}\n\n// --- the trace (schema 5): the deal/play log for tooling ----------------------\n\n/** Why a card did or did not make an ask, in availability order (schema 3.1). */\nexport type TraceVerdict =\n | \"dealt\" // in the hand / the returned list\n | \"capped\" // eligible, ranked below the size cap\n | \"cooldown\" // schema 3.1 step 1\n | \"deck-gate\" // step 2\n | \"tags\" // step 3 (incl. the home group's inverted default)\n | \"condition\" // steps 4-5 (a failing or erroring condition)\n | \"priority\" // a priority expression errored or was not a number\n | \"claimed\" // step 6: no free copy on YOUR board\n | \"claimed-elsewhere\" // step 6: another flow holds the world's copies\n | \"taken\"; // a shared redraw:never was spent, by anyone, for everyone\n\n/** One event on the deal/play log - \"why did Ambush at the ford get dealt\n * here?\" is answered by the ask event's per-card verdicts and keys. The\n * verb is the event type, so a peek is distinguishable from a deal when\n * reading a run back.\n *\n * IDENTITY IS BY GAMEID throughout (design/engine-server.md 4.4). It was\n * mixed until then: `deal.hand` and `peek.box` were gameIds while\n * `evict.hand`, `play.card` and every `cards[].id` were internal ids, so\n * every consumer outside the engine - the Board, the four examiners, the\n * Live Link, a wire a kiosk reads - mapped one to the other itself. */\nexport type TraceEvent =\n | {\n type: \"deal\";\n /** Hand gameId. */\n hand: string;\n /** `id` is the card's GAMEID (design/engine-server.md 4.4). */\n cards: { id: string; verdict: TraceVerdict; priority?: number; specificity?: number }[];\n }\n | {\n type: \"peek\";\n /** Box gameId. */\n box: string;\n criteria: Record<string, string>;\n /** `id` is the card's GAMEID (design/engine-server.md 4.4). */\n cards: { id: string; verdict: TraceVerdict; priority?: number; specificity?: number }[];\n }\n /** Hand and card gameIds. A card the build no longer has (`vanished`) has\n * no gameId left and is named by the id the board carried. */\n | { type: \"evict\"; hand: string; card: string; reason: TraceVerdict | \"hand-condition\" | \"vanished\" }\n /** Card and outcome gameIds; `outcome` is \"\" for a card with no outcomes,\n * played with none. */\n | { type: \"play\"; card: string; outcome: string; turn: number }\n /** One landed outcome change; `path` is the resolved store location, in the\n * address grammar `getProperty` takes - the owner segment is its gameId (a\n * routed @hand write shows where it actually went, schema 3.6). `prev`\n * is the value it replaced, so a log can read \"0 -> 1\". */\n | { type: \"write\"; target: string; path: string; value: ScalarValue; prev?: ScalarValue }\n /** An explicit clock advance via advanceTurns (schema 3.4); `turn` is the\n * box's new value. Plays stamp their own turn on the play event. */\n | { type: \"turns\"; box: string; turn: number }\n /** An expression eval error: never a silent pass (schema 3.1), always a\n * visible diagnostic. */\n | { type: \"diagnostic\"; where: string; message: string };\n\nexport type TraceHandler = (event: TraceEvent) => void;\n/** The engine-level tap: every flow's events, tagged with the flow id -\n * the tools' one stream. */\nexport type EngineTraceHandler = (flow: string, event: TraceEvent) => void;\n\n/** A retained log entry: the trace event plus its place in flow time.\n * `seq` orders the whole flow (monotonic; survives clearLog). `turn` is\n * the clock of the box the event happened in when it fired (peek: the box;\n * deal/evict: the hand's box; play and its writes: the played card's box,\n * stamped together with the play's own turn). Diagnostics carry no turn. */\nexport type LogEntry = TraceEvent & { seq: number; turn?: number };\n\n/** One entry on the ENGINE's log: the same event, plus the flow it happened\n * in. A run is several flows over shared state, so \"what happened in this\n * run\" is only answerable in one ordered stream, and only if each line says\n * who. The flow's own log stays flow-local and unchanged. */\nexport type EngineLogEntry = LogEntry & { flow: string };\n\n// --- internals ---------------------------------------------------------------\n\ninterface CardEntry {\n card: Card<Expression>;\n deck: Deck<Expression>;\n box: Box<Expression>;\n}\n\n/** Is this card scarce across flows (design/shared-scarcity.md)? The deck says\n * what the pile is for and the card may override it, the same inheritance a\n * property has with its scope default. Hoist the deck's flag out of a card\n * loop and pass the answer down: the ask runs this per card per deal. */\nconst cardIsShared = (card: Card<Expression>, deckShared: boolean): boolean =>\n card.shared ?? deckShared;\n\n/** How many hands ACROSS EVERY FLOW may hold this at once. Defaults to\n * `copies`, so the common case writes one number and only \"five in the world,\n * one to a customer\" needs both. Meaningless on an unshared card, and the\n * compiler warns when one sets it. */\nconst sharedCap = (card: Card<Expression>): number => card.sharedCopies ?? card.copies ?? 1;\n\ntype HandSource = { kind: \"value\"; id: string } | { kind: \"hand\"; id: string } | { kind: \"criteria\" };\n\n/** The composed @hand for one ask: the read bag, plus where each name\n * routes on write (schema 3.6). */\ninterface HandEnv {\n bag: PropertyBag;\n sources: Map<string, HandSource>;\n /** tag group id -> bound tag id (home included, its \"tag\" a hand id). */\n boundTags: Map<string, string>;\n}\n\n/** One ask, resolved: a deal (hand present, condition from its template or\n * rule) or a peek (criteria only, no condition - schema 3.1). */\ninterface AskDescriptor {\n box: Box<Expression>;\n hand?: Hand<Expression>;\n condition?: Expression;\n /** tag group id -> tag id, everything the ask binds (fixed + chosen +\n * criteria; for deals also home -> the hand's own id). */\n boundTags: Map<string, string>;\n /** Chosen tags / criteria surfaced into @hand by group gameId, the tag's\n * gameId as the value (schema 3.6). */\n askNames: Record<string, string>;\n}\n\n/** The owner label on everything this engine registers: named in a clash\n * error and carried on the registry's examiner rows. */\nconst OWNER = \"Storylet Engine\";\n\n/** Identity: storylets property names are case-significant as authored. */\nconst identity = (n: string): string => n;\n\n/** The registry keys this engine's bags live under. An id is escaped (`%` and\n * `/`) so no two keys can meet. Every runtime writes the same keys: they are\n * in the save. Owners are keyed by INTERNAL id, as the save always was, so a\n * save survives a rename. */\nconst esc = (id: string): string => id.replace(/%/g, \"%25\").replace(/\\//g, \"%2F\");\nconst unesc = (id: string): string => id.replace(/%2F/g, \"/\").replace(/%25/g, \"%\");\nconst sharedKey = (kind: OwnedScope, id: string): string => `storylets/${kind}/${esc(id)}`;\nconst flowPrefix = (flowId: string): string => `storylets/flow/${esc(flowId)}/`;\nconst flowKey = (flowId: string, kind: FlaggedScope, id?: string): string =>\n kind === \"story\" ? `${flowPrefix(flowId)}story` : `${flowPrefix(flowId)}${kind}/${esc(id!)}`;\n\n/** A registry section's values: registry key -> name -> value. */\ntype Sections = Record<string, PropertyBag>;\n\nconst emptyPartitionValues = (): PropsPartition => ({ story: {}, box: {}, deck: {}, hand: {}, value: {} });\n\n/** Sort a registry save's sections back into partitions, for the load walk:\n * the shared ones, each flow's (only the flows the save restores; the rest\n * are dropped), and everything that is not this engine's, passed through. */\nfunction partitionsFromSections(sections: Sections, flowIds: Set<string>): {\n shared: PropsPartition; flows: Map<string, PropsPartition>; rest: Sections;\n} {\n const shared = emptyPartitionValues();\n const flows = new Map<string, PropsPartition>();\n const rest: Sections = {};\n const flowOf = (escaped: string): PropsPartition | undefined => {\n const id = unesc(escaped);\n if (!flowIds.has(id)) return undefined;\n let p = flows.get(id);\n if (!p) { p = emptyPartitionValues(); flows.set(id, p); }\n return p;\n };\n for (const [key, values] of Object.entries(sections)) {\n let m: RegExpExecArray | null;\n if (key === \"story\") shared.story = values;\n else if ((m = /^storylets\\/(box|deck|hand|value)\\/([^/]+)$/.exec(key))) shared[m[1] as OwnedScope][unesc(m[2]!)] = values;\n else if ((m = /^storylets\\/flow\\/([^/]+)\\/story$/.exec(key))) { const p = flowOf(m[1]!); if (p) p.story = values; }\n else if ((m = /^storylets\\/flow\\/([^/]+)\\/(box|deck|hand|value)\\/([^/]+)$/.exec(key))) {\n const p = flowOf(m[1]!); if (p) p[m[2] as OwnedScope][unesc(m[3]!)] = values;\n } else if (!key.startsWith(\"storylets/\")) rest[key] = values;\n }\n return { shared, flows, rest };\n}\n\n/** A cleaned partition as registry sections, keyed the way its bags register.\n * Empty sections are left out: they would load nothing, and a section for a\n * bag that never registers would wait in the registry for ever. */\nfunction sectionsOf(p: PropsPartition, keyOf: (kind: FlaggedScope, id?: string) => string, out: Sections): void {\n if (Object.keys(p.story).length > 0) out[keyOf(\"story\")] = p.story;\n for (const kind of [\"box\", \"deck\", \"hand\", \"value\"] as const) {\n for (const [id, values] of Object.entries(p[kind])) if (Object.keys(values).length > 0) out[keyOf(kind, id)] = values;\n }\n}\n\n// Stores are shared-kernel bags (@wildwinter/scoperegistry, the properties\n// implementer Patter shares): identity normalisation because storylets\n// property names are case-significant as authored.\n// `pathPrefix` carries its own separator, so a bag composes its rows' addresses itself\n// (`story.gold`, `deck.tavern.drawn`) instead of every caller pasting a prefix onto a row.\nconst bagFromDecls = (decls: PropertyDecl[], pathPrefix: string): StateBag =>\n new StateBag(decls, { normalise: (n) => n, pathPrefix });\n\n// Truthiness for a bare condition. Booleans and numbers as you would expect;\n// a string passes when non-empty and a flag list when non-empty, matching\n// JavaScript's own coercion for those two.\n//\n// Until 2026-09-01 this admitted ONLY booleans and numbers, and Patterplay's\n// `truthy` admitted strings and lists as well. That was drift from writing the\n// two engines at different times, not a considered difference: the two share a\n// property registry, so the same value read from the same registry answered a\n// condition differently depending on which engine asked. expr-specificity calls\n// truthiness host-bound, and it is, but \"host-bound\" is licence for a host to\n// choose, not licence for two hosts in one family to disagree by accident.\nfunction conditionPasses(v: ScalarValue): boolean {\n if (typeof v === \"boolean\") return v;\n if (typeof v === \"number\") return v !== 0;\n if (typeof v === \"string\") return v !== \"\";\n return v.length > 0; // string[] (flags)\n}\n\n// PropertyView is gone. It was the shared PropertyRow plus a `path`, and `path` moved onto\n// that row on 2026-09-02 - so the name was a synonym, and a synonym for a shared type is how\n// the two families drifted in the first place: the same row called PropertyView here,\n// ScopePropertyRow next to it, PropertyRow in the kernel. listProperties() returns PropertyRow.\n\n/** One kernel bag with its store path prefix (story / box.<gameId> / deck.<gameId>\n * / hand.<gameId> / value.<gameId>): the state logger's mount surface\n * (design/engine-runtimes.md 3.4 - the logger builds on the PropertyBag\n * audit hook, so it needs the bags themselves, not just their rows).\n * The Engine lists the shared bags, a Flow its own; the @world container\n * is the host's bag and the host mounts it itself. loadGame() replaces\n * every bag, so re-enumerate after a load. */\nexport interface BagMount {\n prefix: string;\n bag: StateBag;\n}\n\n/** One box on the enumeration surface (examiners, hosts): identity plus\n * its clock (per flow). */\nexport interface BoxView {\n id: string;\n gameId: string;\n title?: string;\n turn: number;\n}\n\n/** The sharing default per scope (design/flows.md, the old system's rule):\n * @story is the playthrough family's globals, shared; the narrower scopes\n * are geographic, per-flow, so \"this flow's danger in the docks\" stays\n * expressible. A declaration's `shared` flag overrides. */\nconst SCOPE_DEFAULT_SHARED = { story: true, box: false, deck: false, hand: false, value: false } as const;\ntype FlaggedScope = keyof typeof SCOPE_DEFAULT_SHARED;\n\nconst isShared = (scope: FlaggedScope, d: PropertyDecl): boolean => d.shared ?? SCOPE_DEFAULT_SHARED[scope];\nconst sharedHalf = (scope: FlaggedScope, decls: PropertyDecl[]): PropertyDecl[] =>\n decls.filter((d) => isShared(scope, d));\nconst flowHalf = (scope: FlaggedScope, decls: PropertyDecl[]): PropertyDecl[] =>\n decls.filter((d) => !isShared(scope, d));\n\n/** One side's five declaration lists, keyed by owner id where the scope has\n * owners. The bags are built from these; so is the load report's answer to\n * \"what does this build declare that the save does not carry\". */\ninterface DeclSet {\n story: PropertyDecl[];\n box: Map<string, PropertyDecl[]>;\n deck: Map<string, PropertyDecl[]>;\n hand: Map<string, PropertyDecl[]>;\n value: Map<string, PropertyDecl[]>;\n}\n\n/** The four owned property scopes: the ones whose address carries an owner\n * segment. `story` has no owner and `world` is the host's. */\ntype OwnedScope = \"box\" | \"deck\" | \"hand\" | \"value\";\nconst OWNED_SCOPES = [\"box\", \"deck\", \"hand\", \"value\"] as const;\n\n/** The owner segment of a property address, both ways round\n * (design/engine-server.md 4.4).\n *\n * `gameId` is the segment the ADDRESS uses; `id` is the internal id everything\n * inside the engine is keyed by - the bags, the save envelope, the ladders.\n * Both maps are built in bundle order and a repeated gameId does NOT\n * overwrite the first.\n *\n * Box, deck, hand and card gameIds are unique bundle-wide, so for three of the\n * four scopes the segment is simply the gameId. A TAG's is unique only within\n * its group, and a group's only within its box, so two boxes may each name a\n * tag \"docks\": the value scope's segment is box-qualified,\n * `value.<boxGameId>/<tagGameId>.<name>`, wherever a gameId repeats, and the\n * short form is REFUSED there rather than resolved to the first in bundle\n * order. `valueAddresses` in the model is the one definition of that rule -\n * the Board draws these addresses from the bundle while the engine builds them\n * from this index, and the two have to agree - and `repeated` is what it\n * found, so a refusal can name the candidates.\n *\n * Two GROUPS in one box naming the same tag is the case the box qualifier\n * cannot separate, and it is closing at the source rather than here (question\n * 16, ruled 2026-09-06): the compiler warns that a tag gameId must be unique\n * within its box, and refuses it from the next release. Until then the first\n * in bundle order answers, as it always did.\n */\ninterface OwnerIndex {\n gameId: Map<string, string>; // internal id -> owner segment\n id: Map<string, string>; // owner segment -> internal id (first in bundle order wins)\n repeated: Map<string, string[]>; // an ambiguous short form -> the qualified candidates\n}\n\ntype OwnerIndexes = Record<OwnedScope, OwnerIndex>;\n\nconst emptyOwnerIndexes = (): OwnerIndexes => ({\n box: { gameId: new Map(), id: new Map(), repeated: new Map() },\n deck: { gameId: new Map(), id: new Map(), repeated: new Map() },\n hand: { gameId: new Map(), id: new Map(), repeated: new Map() },\n value: { gameId: new Map(), id: new Map(), repeated: new Map() },\n});\n\nconst indexOwner = (index: OwnerIndex, entity: { id: string; gameId?: string; title?: string }): void => {\n const gameId = effectiveGameId(entity);\n index.gameId.set(entity.id, gameId);\n if (!index.id.has(gameId)) index.id.set(gameId, entity.id);\n};\n\n/** The value scope's index, whole: the segments to print, the segments to\n * accept, and the gameIds that need qualifying. Built from the bundle rather\n * than tag by tag, because whether a tag's own gameId is enough is a question\n * about the OTHER boxes. */\nconst indexValueOwners = (index: OwnerIndex, bundle: Bundle): void => {\n const addresses = valueAddresses(bundle);\n for (const [id, segment] of addresses.print) index.gameId.set(id, segment);\n for (const [segment, id] of addresses.accept) index.id.set(segment, id);\n for (const [gameId, candidates] of addresses.repeated) index.repeated.set(gameId, candidates);\n};\n\n/** One side's five stores (shared on the engine, per-flow on each flow). */\ninterface Partition {\n story: StateBag;\n box: Map<string, StateBag>;\n deck: Map<string, StateBag>;\n hand: Map<string, StateBag>;\n value: Map<string, StateBag>;\n}\n\ntype PartitionKind = keyof Partition;\n\n/** Everything a Flow shares with its Engine: the bundle-derived lookups\n * (immutable), the shared stores (replaced wholesale by loadGame/reset),\n * and the seams. One object, held by both classes - the two are one\n * machine in two lifetimes. */\ninterface Internals {\n bundle: Bundle;\n logCap?: number;\n cardsById: Map<string, CardEntry>;\n cardsByGameId: Map<string, CardEntry>;\n boxesByGameId: Map<string, Box<Expression>>;\n boxesById: Map<string, Box<Expression>>;\n handsById: Map<string, { hand: Hand<Expression>; box: Box<Expression> }>;\n handsByGameId: Map<string, { hand: Hand<Expression>; box: Box<Expression> }>;\n /** The owner segment of a property address, both ways round (4.4). */\n owners: OwnerIndexes;\n templatesById: Map<string, HandTemplate<Expression>>;\n groupsById: Map<string, { group: TagGroup; box: Box<Expression> }>;\n requiredGroups: Set<string>;\n nodeCache: WeakMap<Expression, ExprNode>;\n ladders: {\n world: Map<string, readonly string[]>;\n story: Map<string, readonly string[]>;\n box: Map<string, Map<string, readonly string[]>>;\n deck: Map<string, Map<string, readonly string[]>>;\n value: Map<string, Map<string, readonly string[]>>;\n hand: Map<string, Map<string, readonly string[]>>;\n };\n hasQualities: boolean;\n /** Does ANY deck or card in the bundle opt into shared scarcity? False for\n * the overwhelming majority of projects, and when it is false the two\n * claim-ledger walks in dealing are skipped entirely. Same idea as\n * `hasQualities` above: a bundle that does not use a feature must not pay\n * for it. */\n hasShared: boolean;\n /** The per-flow halves of every declaration list, precomputed once: each\n * new flow builds its bags from these. */\n flowDecls: DeclSet;\n /** The shared halves, the same way. Not used to build anything - the shared\n * bags are built straight from the bundle - but a load report has to say\n * what the shared side WOULD hold without building a bag, which is what\n * makes previewLoad pure. */\n sharedDecls: DeclSet;\n /** The shared stores, registered in the registry for the engine's life.\n * Reseeded in place by reset and by a load that carries values. */\n shared: Partition;\n /** The game's one registry (or the engine's own, when it is standalone). */\n registry: ScopeRegistry;\n /** True when the engine made the registry: `saveGame()` then carries its values. */\n ownsRegistry: boolean;\n /** True when the engine self-backed @world (standalone, no resolver bound). */\n selfWorld: boolean;\n /** Every OTHER scope in the registry, as an eval context sees it (instance\n * keys left out), rebuilt only when the registry's set of scopes moves. */\n registryView: () => { scopes: EvalContext[\"scopes\"]; qualities: EvalContext[\"qualities\"] };\n /** @world, read through the registry by name (the scope's own normalisation),\n * so a @world the game registered folded to lower case still answers the\n * names as authored. */\n worldResolver: ScopeResolver;\n /** The @world WRITE seam. `host` says the caller is the GAME's own surface -\n * setProperty, the coverage harness, the CLI's --set - which the shared\n * kernel lets past a `writable: false` (scoperegistry 0.6.0): that flag is\n * the story's promise, not the game's. The story's refusal is the\n * worldReadOnly table below, consulted before this seam is reached. A BOUND\n * resolver is opaque - it takes a name and a value and keeps whatever rule\n * the game has - so the flag only ever reaches the self-backed bag.\n * Undefined when @world cannot be written at all (a resolver bound with no\n * `set`). */\n worldSet?: (name: string, value: ScalarValue, host?: boolean) => void;\n /** @world names declared `writable: false`: the story's promise, kept at\n * runtime as the compiler keeps it at publish (Reboot.md 10). */\n worldReadOnly: Set<string>;\n /** `turn` is the box clock the event happened on, where the caller knows it\n * - the same stamp the flow's own log carries. Unity and Unreal passed it\n * from the start; JS and Godot dropped it, so their examiners printed \"[-]\"\n * on every deal, peek, evict and write line while the other two printed the\n * real turn. Four runtimes, two different run logs (2026-08-29). */\n emitEngine: (flow: string, event: TraceEvent, turn?: number) => void;\n engineTracing: () => boolean;\n}\n\nconst handDeclsOf = (internals: Internals, hand: Hand<Expression>): PropertyDecl[] => {\n if (hand.template !== undefined) {\n return internals.templatesById.get(hand.template)?.properties\n ?? internals.bundle.boxes.flatMap((b) => b.handTemplates).find((t) => t.id === hand.template)?.properties\n ?? [];\n }\n return hand.properties ?? [];\n};\n\n/**\n * One owned property's ADDRESS, owner segment and all: `box.village.mood`.\n *\n * The stores, the save envelope and the ladders stay keyed by internal id -\n * a save must survive a rename, which is the whole reason ids exist - so this\n * is the one place the two vocabularies meet, and it is a formatter, never a\n * lookup key. An owner the build no longer has (a save that outlived an edit)\n * keeps the id it arrived with: there is no gameId left to give it, which is\n * the rule a load report's evictions have always used.\n */\nconst addressOf = (internals: Internals, kind: OwnedScope, id: string): string =>\n `${kind}.${internals.owners[kind].gameId.get(id) ?? id}`;\n\n/**\n * Resolve a property address's owner segment to the internal id the stores are\n * keyed by. `legacy` says the caller used the pre-4.4 form - an internal id\n * where a gameId belongs - which resolves for THIS release and earns a\n * diagnostic; the next lockstep release refuses it, in every scope including\n * `value`, which had the one reprieve until it gained an address of its own.\n * `ambiguous` is a short-form value address two boxes answer to: the caller\n * REFUSES it, listing those candidates. Undefined when the segment names no\n * owner at all, which is the caller's \"no <kind> store\" error.\n */\ntype OwnerLookup = { id: string; legacy: boolean } | { ambiguous: string[] };\n\nconst resolveOwner = (internals: Internals, kind: OwnedScope, segment: string): OwnerLookup | undefined => {\n // Checked before the lookup, because the short form is deliberately NOT in\n // the accept map when it is ambiguous: silently picking the first tag in\n // bundle order is the bug this removes.\n const candidates = internals.owners[kind].repeated.get(segment);\n if (candidates !== undefined) return { ambiguous: candidates };\n const byGameId = internals.owners[kind].id.get(segment);\n if (byGameId !== undefined) return { id: byGameId, legacy: false };\n // A gameId that equals its id took the branch above, so anything reaching\n // here and known as an id is genuinely the old spelling.\n if (internals.owners[kind].gameId.has(segment)) return { id: segment, legacy: true };\n return undefined;\n};\n\n/** Resolve or throw: the two refusals every property address shares, in one\n * place, so the engine's surface and a flow's answer alike. */\nconst ownerOrThrow = (internals: Internals, kind: OwnedScope, segment: string, name: string): { id: string; legacy: boolean } => {\n const owner = resolveOwner(internals, kind, segment);\n if (owner === undefined) throw new Error(`no ${kind} store \"${segment}\"`);\n if (\"ambiguous\" in owner) throw new Error(ambiguousValueAddressMessage(segment, name, owner.ambiguous));\n return owner;\n};\n\n/** What a legacy address is told. It NAMES the address to move to, because\n * \"that form is deprecated\" without the replacement leaves a host grepping a\n * bundle for ids it never chose. */\nconst legacyAddressMessage = (internals: Internals, kind: OwnedScope, segment: string, name: string): string =>\n `\"${kind}.${segment}.${name}\" names the ${kind} by its internal id; write \"${addressOf(internals, kind, segment)}.${name}\". `\n + `The internal-id form is refused after the next release.`;\n\n/** Build one side of the partition from the bundle. The bags are KEYED by\n * internal id and ADDRESSED by gameId; see addressOf. */\nconst buildPartition = (internals: Internals, half: (scope: FlaggedScope, decls: PropertyDecl[]) => PropertyDecl[]): Partition => {\n const b = internals.bundle;\n const at = (kind: OwnedScope, id: string): string => `${addressOf(internals, kind, id)}.`;\n return {\n story: bagFromDecls(half(\"story\", b.story.properties), \"story.\"),\n box: new Map(b.boxes.map((box) => [box.id, bagFromDecls(half(\"box\", box.properties), at(\"box\", box.id))])),\n deck: new Map(b.boxes.flatMap((box) => box.decks.map(\n (deck): [string, StateBag] => [deck.id, bagFromDecls(half(\"deck\", deck.properties), at(\"deck\", deck.id))]))),\n // A template instance inherits the template's property declarations;\n // a standalone hand declares its own (schema 2.6).\n hand: new Map(b.boxes.flatMap((box) => box.hands.map(\n (hand): [string, StateBag] => [hand.id, bagFromDecls(half(\"hand\", handDeclsOf(internals, hand)), at(\"hand\", hand.id))]))),\n value: new Map(b.boxes.flatMap((box) => box.tagGroups.flatMap((group) => group.tags.map(\n (tag): [string, StateBag] => [tag.id, bagFromDecls(half(\"value\", tag.properties ?? []), at(\"value\", tag.id))])))),\n };\n};\n\nconst partitionValues = (p: Partition): PropsPartition => ({\n story: p.story.values,\n box: Object.fromEntries([...p.box].map(([id, bag]) => [id, bag.values])),\n deck: Object.fromEntries([...p.deck].map(([id, bag]) => [id, bag.values])),\n hand: Object.fromEntries([...p.hand].map(([id, bag]) => [id, bag.values])),\n value: Object.fromEntries([...p.value].map(([id, bag]) => [id, bag.values])),\n});\n\nconst loadPartition = (p: Partition, values: PropsPartition | undefined): void => {\n // Fresh defaults are already in the bags; the saved values land over\n // them: orphaned keys (deleted entities, re-flagged properties) drop;\n // newly declared properties keep defaults.\n p.story.load(values?.story ?? {});\n for (const kind of [\"box\", \"deck\", \"hand\", \"value\"] as const) {\n for (const [id, bag] of Object.entries(values?.[kind] ?? {})) {\n p[kind].get(id)?.load(bag);\n }\n }\n};\n\n// --- the load report (design/engine-server.md 4.9) ---------------------------\n//\n// One walk, two entry points. `previewLoad` runs it and returns the report;\n// `loadGame` runs it, returns the same report and then applies the CLEANED\n// blob the walk produced. Two implementations of \"what does this save cost\"\n// would drift the first time one of them was fixed, so there is one, and the\n// apply half consumes its output rather than repeating its decisions.\n\n/** The report under construction: unsorted, until finishReport orders it. */\ninterface ReportDraft {\n evicted: LoadEviction[];\n droppedCooldowns: { flow: string; card: string }[];\n droppedSpent: string[];\n droppedProperties: LoadProperty[];\n defaultedProperties: LoadProperty[];\n retypedProperties: LoadProperty[];\n}\n\nconst emptyDraft = (): ReportDraft => ({\n evicted: [], droppedCooldowns: [], droppedSpent: [],\n droppedProperties: [], defaultedProperties: [], retypedProperties: [],\n});\n\n/** The sort key separator: a UNIT SEPARATOR, as the play-history indexes use,\n * because it cannot occur in an id, a gameId or a property name. */\nconst SORT_SEP = \"\\u001f\";\n\nconst byKey = <T>(items: T[], key: (item: T) => string): T[] =>\n [...items].map((item) => ({ item, k: key(item) }))\n .sort((a, b) => (a.k < b.k ? -1 : a.k > b.k ? 1 : 0))\n .map((e) => e.item);\n\nconst propKey = (p: LoadProperty): string => `${p.flow ?? \"\"}${SORT_SEP}${p.path}`;\n\n/**\n * Does a saved value still fit its declaration?\n *\n * The type first, then the declaration's own vocabulary: an enum value or a\n * quality stage the edit struck out is still a string of the right type and\n * still no longer a legal value, and a condition comparing against the ladder\n * would answer nonsense about it. A declaration with no vocabulary (`values` /\n * `stages` absent) constrains nothing, so anything of the right type fits.\n */\nfunction valueFits(decl: PropertyDecl, value: ScalarValue): boolean {\n switch (decl.type) {\n case \"boolean\": return typeof value === \"boolean\";\n case \"number\": return typeof value === \"number\";\n case \"string\": return typeof value === \"string\";\n case \"enum\":\n return typeof value === \"string\" && (decl.values === undefined || decl.values.includes(value));\n case \"quality\":\n return typeof value === \"string\" && (decl.stages === undefined || decl.stages.includes(value));\n case \"flags\":\n return Array.isArray(value) && (decl.values === undefined || value.every((f) => decl.values!.includes(f)));\n default: return true;\n }\n}\n\n/** Walk one bag's worth of saved values against one bag's worth of\n * declarations: report the orphans, the newcomers and the misfits, and\n * return the values that survive. */\nfunction walkScope(\n decls: PropertyDecl[] | undefined,\n saved: PropertyBag | undefined,\n path: (name: string) => string,\n flow: string | undefined,\n draft: ReportDraft,\n): PropertyBag {\n const at = (name: string): LoadProperty =>\n ({ ...(flow !== undefined ? { flow } : {}), path: path(name) });\n const byName = new Map((decls ?? []).map((d) => [d.name, d]));\n const values = saved ?? {};\n const clean: PropertyBag = {};\n for (const [name, value] of Object.entries(values)) {\n const decl = byName.get(name);\n if (decl === undefined) { draft.droppedProperties.push(at(name)); continue; }\n if (!valueFits(decl, value)) { draft.retypedProperties.push(at(name)); continue; }\n clean[name] = value;\n }\n for (const decl of decls ?? []) {\n if (!(decl.name in values)) draft.defaultedProperties.push(at(decl.name));\n }\n return clean;\n}\n\n/** The same walk over all five scopes of one partition. An owner the save\n * carries and the build no longer has drops whole (its bag is gone, so its\n * values have nowhere to land); an owner the build has and the save lacks\n * keeps every default. */\nfunction walkPartition(\n internals: Internals,\n decls: DeclSet,\n values: PropsPartition | undefined,\n flow: string | undefined,\n draft: ReportDraft,\n): PropsPartition {\n const out: PropsPartition = {\n story: walkScope(decls.story, values?.story, (n) => `story.${n}`, flow, draft),\n box: {}, deck: {}, hand: {}, value: {},\n };\n for (const kind of [\"box\", \"deck\", \"hand\", \"value\"] as const) {\n const savedKind = values?.[kind] ?? {};\n const ids = [...new Set([...decls[kind].keys(), ...Object.keys(savedKind)])].sort();\n for (const id of ids) {\n // The report's `path` is exactly what listProperties() prints and what\n // setProperty takes: one grammar, so an operator reading a hot-swap\n // report can paste the address straight back in (4.4).\n const owner = addressOf(internals, kind, id);\n out[kind][id] = walkScope(decls[kind].get(id), savedKind[id],\n (n) => `${owner}.${n}`, flow, draft);\n }\n }\n return out;\n}\n\n/** Order the draft and answer the identity questions. `saved` is the content\n * block the save carries; for a single-flow restore there is none, so the\n * caller passes the bundle's own and no drift is reported. */\nfunction finishReport(bundle: BundleContent, saved: BundleContent, flows: string[], draft: ReportDraft): LoadReport {\n const drift = saved.version !== bundle.version || saved.hash !== bundle.hash;\n const evicted = byKey(draft.evicted, (e) => [e.flow, e.hand, e.card, e.reason].join(SORT_SEP));\n const droppedCooldowns = byKey(draft.droppedCooldowns, (c) => `${c.flow}${SORT_SEP}${c.card}`);\n const droppedSpent = [...draft.droppedSpent].sort();\n const droppedProperties = byKey(draft.droppedProperties, propKey);\n const defaultedProperties = byKey(draft.defaultedProperties, propKey);\n const retypedProperties = byKey(draft.retypedProperties, propKey);\n return {\n // `flows` is what the load restores, not something it had to change, so\n // it never makes a report inexact.\n exact: !drift && evicted.length === 0 && droppedCooldowns.length === 0 && droppedSpent.length === 0\n && droppedProperties.length === 0 && defaultedProperties.length === 0 && retypedProperties.length === 0,\n project: bundle.project,\n version: { saved: saved.version, bundle: bundle.version },\n hash: { saved: saved.hash, bundle: bundle.hash },\n flows,\n evicted, droppedCooldowns, droppedSpent,\n droppedProperties, defaultedProperties, retypedProperties,\n };\n}\n\n// --- the Engine ---------------------------------------------------------------\n\nexport class Engine {\n private readonly internals: Internals;\n private readonly seed: number;\n private readonly onReplacedFlow: EngineOptions[\"onReplacedFlow\"];\n private readonly flowsById = new Map<string, Flow>();\n private readonly engineTraceHandlers = new Set<EngineTraceHandler>();\n /** The host's @world binding, if the engine was built with one: it\n * outlives reset/loadGame (the host's container is the host's). The\n * self-backed resolver is rebuilt instead. */\n private readonly hostWorld?: ScopeResolver;\n\n /** The options this engine was built with: hotSwap builds its replacement from them. */\n private readonly creationOptions: EngineOptions;\n /** How to register each shared scope again, in registration order: a failed\n * hotSwap puts this engine back exactly as it was. */\n private readonly sharedMounts: Array<{ key: string; mount: () => void }> = [];\n\n constructor(bundle: Bundle, opts: EngineOptions = {}) {\n this.creationOptions = opts;\n this.seed = opts.seed ?? 0;\n this.onReplacedFlow = opts.onReplacedFlow;\n if (opts.world !== undefined) this.hostWorld = opts.world;\n const internals: Internals = {\n bundle,\n ...(opts.log ? { logCap: typeof opts.log === \"object\" ? (opts.log.cap ?? 1000) : 1000 } : {}),\n cardsById: new Map(), cardsByGameId: new Map(),\n boxesByGameId: new Map(), boxesById: new Map(),\n handsById: new Map(), handsByGameId: new Map(),\n owners: emptyOwnerIndexes(),\n templatesById: new Map(), groupsById: new Map(),\n requiredGroups: new Set(),\n nodeCache: new WeakMap(),\n ladders: { world: new Map(), story: new Map(), box: new Map(), deck: new Map(), value: new Map(), hand: new Map() },\n hasQualities: false,\n hasShared: false,\n flowDecls: { story: [], box: new Map(), deck: new Map(), hand: new Map(), value: new Map() },\n sharedDecls: { story: [], box: new Map(), deck: new Map(), hand: new Map(), value: new Map() },\n shared: undefined as unknown as Partition,\n registry: opts.registry ?? new ScopeRegistry(),\n ownsRegistry: opts.registry === undefined,\n selfWorld: false,\n registryView: () => view(),\n worldResolver: undefined as unknown as ScopeResolver,\n worldReadOnly: new Set<string>(),\n emitEngine: (flow, event, turn) => {\n if (this.internals.logCap !== undefined) {\n this.engineLog.push({ ...event, flow, seq: this.engineSeq++, ...(turn !== undefined ? { turn } : {}) });\n if (this.engineLog.length > this.internals.logCap) {\n this.engineLog.splice(0, this.engineLog.length - this.internals.logCap);\n }\n }\n for (const h of this.engineTraceHandlers) h(flow, event);\n },\n engineTracing: () => this.engineTraceHandlers.size > 0,\n };\n this.internals = internals;\n let viewRevision = -1;\n let viewCache: ReturnType<Internals[\"registryView\"]> = { scopes: {}, qualities: undefined };\n const view = (): ReturnType<Internals[\"registryView\"]> => {\n const reg = internals.registry;\n if (reg.revision !== viewRevision) {\n const ctx = reg.toEvalContext();\n const scopes: EvalContext[\"scopes\"] = {};\n // An instance key (`storylets/deck/x`, another engine's) is no expression token.\n for (const [k, v] of Object.entries(ctx.scopes)) if (!k.includes(\"/\")) scopes[k] = v;\n viewCache = { scopes, qualities: ctx.qualities };\n viewRevision = reg.revision;\n }\n return viewCache;\n };\n\n // The value scope's segments come off the whole bundle at once (a tag\n // gameId is only unique within its group), so they are built before the\n // walk rather than tag by tag inside it.\n indexValueOwners(internals.owners.value, bundle);\n\n for (const box of bundle.boxes) {\n internals.boxesById.set(box.id, box);\n internals.boxesByGameId.set(effectiveGameId(box), box);\n indexOwner(internals.owners.box, box);\n for (const group of box.tagGroups) {\n internals.groupsById.set(group.id, { group, box });\n if (group.required === true) internals.requiredGroups.add(group.id);\n }\n for (const deck of box.decks) {\n indexOwner(internals.owners.deck, deck);\n if (deck.shared === true) internals.hasShared = true;\n for (const card of deck.cards) {\n const entry = { card, deck, box };\n internals.cardsById.set(card.id, entry);\n internals.cardsByGameId.set(effectiveGameId(card), entry);\n if (card.shared === true) internals.hasShared = true;\n }\n }\n for (const template of box.handTemplates) {\n internals.templatesById.set(template.id, template);\n }\n for (const hand of box.hands) {\n internals.handsById.set(hand.id, { hand, box });\n internals.handsByGameId.set(effectiveGameId(hand), { hand, box });\n indexOwner(internals.owners.hand, hand);\n }\n }\n this.initLadders();\n\n // Both halves, precomputed once (a bundle's declarations never change):\n // each openFlow builds its bags from the per-flow half, and a load report\n // asks either half what it declares without building anything at all.\n const declSet = (half: (scope: FlaggedScope, decls: PropertyDecl[]) => PropertyDecl[]): DeclSet => ({\n story: half(\"story\", bundle.story.properties),\n box: new Map(bundle.boxes.map((box) => [box.id, half(\"box\", box.properties)])),\n deck: new Map(bundle.boxes.flatMap((box) => box.decks.map(\n (deck): [string, PropertyDecl[]] => [deck.id, half(\"deck\", deck.properties)]))),\n hand: new Map(bundle.boxes.flatMap((box) => box.hands.map(\n (hand): [string, PropertyDecl[]] => [hand.id, half(\"hand\", handDeclsOf(internals, hand))]))),\n value: new Map(bundle.boxes.flatMap((box) => box.tagGroups.flatMap((group) => group.tags.map(\n (tag): [string, PropertyDecl[]] => [tag.id, half(\"value\", tag.properties ?? [])])))),\n });\n internals.flowDecls = declSet(flowHalf);\n internals.sharedDecls = declSet(sharedHalf);\n\n this.initShared(this.hostWorld);\n }\n\n /** Build the shared stores, register them and @world, and set up the @world\n * seam. Once, for the engine's life: reset and loads reseed the bags in\n * place, so the registry never sees them come and go. */\n private initShared(hostWorld?: ScopeResolver): void {\n const internals = this.internals;\n const reg = internals.registry;\n const worldDecls = internals.bundle.world.properties as unknown as ScopeDeclaration[];\n internals.shared = buildPartition(internals, sharedHalf);\n internals.worldReadOnly = new Set(internals.bundle.world.properties.filter((d) => d.writable === false).map((d) => d.name));\n const registered: string[] = [];\n // Register now, and remember how, so a failed hotSwap can register again.\n const mount = (key: string, register: () => void): void => {\n register();\n registered.push(key);\n this.sharedMounts.push({ key, mount: register });\n };\n try {\n // `story` is this engine's token whether or not the bundle declares a shared\n // @story property: registering it is what makes a clash show at once.\n const story = internals.shared.story;\n mount(\"story\", () => { reg.mountOwned(\"story\", story, { owner: OWNER }); }); // claims values the game loaded first\n for (const kind of OWNED_SCOPES) {\n for (const [id, bag] of internals.shared[kind]) {\n if (bag.declarations().length === 0) continue; // holds nothing: not registered\n mount(sharedKey(kind, id), () => { reg.mountOwned(sharedKey(kind, id), bag, { owner: OWNER }); });\n }\n }\n if (hostWorld !== undefined) {\n // The game keeps these values: an external scope, never saved.\n mount(\"world\", () => { reg.defineForeign(\"world\", hostWorld, worldDecls, { normalise: identity, owner: OWNER }); });\n } else if (internals.ownsRegistry && !reg.has(\"world\")) {\n // Standalone: self-backed from the declared defaults, DECLARATIONS AND\n // ALL, as a property the registry stores and SAVES (only a resolver the\n // game binds is external). The bag keeps `writable: false` so an\n // examiner still reads it there, and the kernel lets a `{ host: true }`\n // write past it, which is what the game's own surface passes.\n reg.defineOwned(\"world\", worldDecls, { normalise: identity, pathPrefix: \"world.\", owner: OWNER });\n const worldBag = reg.ownedBag(\"world\");\n registered.push(\"world\");\n this.sharedMounts.push({ key: \"world\", mount: () => { reg.mountOwned(\"world\", worldBag, { owner: OWNER }); } });\n internals.selfWorld = true;\n }\n // Given the game's registry and no resolver, @world is the game's to\n // register: this engine registers nothing for it.\n } catch (e) {\n for (const k of registered) reg.remove(k, { keep: true }); // a clash leaves the game's registry as it was\n throw e;\n }\n internals.worldResolver = {\n get: (n) => reg.get(\"world\", n),\n set: (n, v) => { reg.set(\"world\", n, v); },\n };\n if (hostWorld !== undefined) {\n // A bound resolver is opaque: it keeps whatever rule the game has, so the\n // story's `writable: false` is kept by worldReadOnly before this seam.\n internals.worldSet = hostWorld.set !== undefined ? (n, v): void => { reg.set(\"world\", n, v, { host: true }); } : undefined;\n } else {\n internals.worldSet = (n, v, host): void => { reg.set(\"world\", n, v, host === true ? { host: true } : undefined); };\n }\n }\n\n /** Every shared bag back to its declared defaults, in place (the registry\n * keeps them registered), the self-backed @world included. */\n private reseedShared(): void {\n const { shared, sharedDecls, registry } = this.internals;\n shared.story.reseed(sharedDecls.story as unknown as ScopeDeclaration[]);\n for (const kind of OWNED_SCOPES) {\n for (const [id, bag] of shared[kind]) bag.reseed((sharedDecls[kind].get(id) ?? []) as unknown as ScopeDeclaration[]);\n }\n if (this.internals.selfWorld) {\n registry.reseedOwned(\"world\", this.internals.bundle.world.properties as unknown as ScopeDeclaration[]);\n }\n }\n\n /** Quality ladders by scope for the eval channel (design/quality.md):\n * world/story keyed by name; box/deck/value keyed by owner id then name.\n * Built once - a bundle's declarations never change. Ladders are\n * declaration-level, so the sharing flag does not touch them. */\n private initLadders(): void {\n const internals = this.internals;\n const grab = (decls: PropertyDecl[] | undefined): Map<string, readonly string[]> => {\n const m = new Map<string, readonly string[]>();\n for (const d of decls ?? []) if (d.type === \"quality\" && d.stages !== undefined) m.set(d.name, d.stages);\n return m;\n };\n const b = internals.bundle;\n internals.ladders.world = grab(b.world.properties);\n internals.ladders.story = grab(b.story.properties);\n for (const box of b.boxes) {\n internals.ladders.box.set(box.id, grab(box.properties));\n for (const deck of box.decks) internals.ladders.deck.set(deck.id, grab(deck.properties));\n for (const group of box.tagGroups) {\n for (const tag of group.tags) internals.ladders.value.set(tag.id, grab(tag.properties));\n }\n for (const hand of box.hands) internals.ladders.hand.set(hand.id, grab(handDeclsOf(internals, hand)));\n }\n const any = (m: Map<string, Map<string, readonly string[]>>): boolean =>\n [...m.values()].some((x) => x.size > 0);\n internals.hasQualities = internals.ladders.world.size > 0 || internals.ladders.story.size > 0\n || any(internals.ladders.box) || any(internals.ladders.deck)\n || any(internals.ladders.value) || any(internals.ladders.hand);\n }\n\n // --- flow management (Patter's surface, name for name) ----------------------\n\n /** Open (or REPLACE) the named flow. An existing id's flow is closed\n * first - re-opening a name is a reset of that name's whole per-flow\n * state; shared state is untouched. There is no default flow: \"main\" is\n * a caller convention, not an engine rule. */\n openFlow(id: string, opts: OpenFlowOptions = {}): Flow {\n return this.open(id, opts, false);\n }\n\n /** openFlow, and loadGame's rebuild. `claim` says the new flow's bags take\n * the values the registry holds for them (a load); a fresh open is a reset\n * of that name, so anything waiting for it is discarded first. */\n private open(id: string, opts: OpenFlowOptions, claim: boolean): Flow {\n this.assertExternalScopes();\n // The world's claims as they stand WITHOUT this name, taken before the\n // replace: a resume competes with the other flows, never with the flow it\n // is replacing (which is about to release everything it holds).\n const otherClaims = opts.restore !== undefined ? this.sharedClaimsExcept(id) : undefined;\n // Replacing an existing id KEEPS its place in the order. `close()` would\n // drop the key, and a JS Map re-inserts a deleted key at the END, so\n // openFlow(\"a\"); openFlow(\"b\"); openFlow(\"a\") listed [b, a] here and\n // [a, b] on all three ports - a different `flows()` order and, since\n // `saveGame` keys its flows in that order, a different `.storyletsave`\n // byte stream for the same run (2026-08-29). markClosed without dropFlow\n // is the difference: the old handle goes inert, the slot stays put.\n const existing = this.flowsById.get(id);\n if (existing) {\n // Say so BEFORE the old flow goes inert, while its board is still readable.\n const dealt = existing.heldCardIds().length;\n if (dealt > 0) this.onReplacedFlow?.(id, dealt);\n existing.markClosed();\n }\n if (!claim) this.internals.registry.discardParked(flowPrefix(id));\n const flow = new Flow(this, this.internals, id, opts.seed ?? this.seed);\n this.flowsById.set(id, flow);\n if (opts.restore !== undefined) {\n const draft = emptyDraft();\n // Cloned: a caller holding one blob may resume two flows from it, and\n // an aliased playLog would then grow in both.\n const clean = this.planFlowRestore(id, structuredClone(opts.restore), otherClaims, draft);\n flow.restore(clean);\n const content = this.internals.bundle.content;\n opts.onRestoreReport?.(finishReport(content, content, [id], draft));\n }\n return flow;\n }\n\n getFlow(id: string): Flow | undefined {\n return this.flowsById.get(id);\n }\n\n /** Every live flow, open order. */\n flows(): Flow[] {\n return [...this.flowsById.values()];\n }\n\n /** Close the named flow: its handle goes INERT (every verb throws). A\n * dropped-but-held flow must not keep writing shared state (Patter's\n * stale-handle lesson). Unknown ids are a quiet no-op, like closing a\n * closed door. */\n closeFlow(id: string): void {\n const flow = this.flowsById.get(id);\n if (!flow) return;\n this.flowsById.delete(id);\n flow.markClosed();\n }\n\n /** @internal - Flow.close() routes here so both doors agree. */\n dropFlow(id: string, flow: Flow): void {\n if (this.flowsById.get(id) === flow) this.flowsById.delete(id);\n }\n\n /** Close every flow and reseed the shared state to its defaults (the\n * self-backed @world included; a host-bound @world is the host's and is\n * not touched). */\n reset(): void {\n this.dropRun(false);\n this.reseedShared();\n // Values loaded for bags nobody has claimed yet are the old run's too: a\n // flow opened after the reset must not pick them up. Other engines' stay.\n this.internals.registry.discardParked(\"storylets/\");\n }\n\n /** End the run: clear the log, close every flow, forget spent cards. Each\n * flow's bags leave the registry; `keepFlows` names the flows whose values\n * are kept there for the flow that replaces them (a load into the game's\n * registry). */\n private dropRun(keepFlows: Set<string> | false): void {\n // The log is a run-lifetime utility and is not saved; a reset is a new run.\n // All three ports cleared it here and the reference did not, so `reset()`\n // (and `loadGame`) left the previous run's entries in place with `seq`\n // continuing across the boundary - while the same call on Godot, Unity or\n // Unreal returned an empty log (2026-08-29).\n this.engineLog = [];\n for (const [id, flow] of this.flowsById) {\n flow.releaseBags(keepFlows !== false && keepFlows.has(id));\n flow.markClosed();\n }\n this.flowsById.clear();\n this.spent.clear();\n }\n\n // --- shared scarcity (design/shared-scarcity.md) -----------------------------\n\n /** Cards a shared `redraw: \"never\"` has taken out of the world, by card id.\n * The claim ledger is DERIVED from live boards and so needs no storage;\n * this one is durable, so it rides the save's shared half. */\n private spent = new Set<string>();\n\n /** @internal */\n isTaken(cardId: string): boolean {\n return this.spent.has(cardId);\n }\n\n /** @internal */\n markTaken(cardId: string): void {\n this.spent.add(cardId);\n }\n\n // --- the run's log (design/shared-scarcity.md 8.2) ---------------------------\n\n /** Every flow's events in one ordered stream, each tagged with its flow.\n * Opt in with the same `log` option the flow logs use; capped the same way.\n *\n * This exists because a flow's own log cannot answer the question a run\n * raises: when a story action in ANOTHER flow moves shared state, your\n * flow's log says nothing and your value simply changes. Reading a run\n * needs one stream that says who did what, and merging the per-flow logs by\n * hand is a thing every host would otherwise have to write. */\n private engineLog: EngineLogEntry[] = [];\n private engineSeq = 0;\n\n log(): readonly EngineLogEntry[] {\n return this.engineLog;\n }\n\n clearLog(): void {\n this.engineLog = [];\n }\n\n /** @internal - shared claims across every LIVE flow, card id -> holders.\n * Derived, which is what makes closeFlow and the openFlow replace release\n * what a flow was holding: its board leaves the map with it. */\n sharedClaims(): Map<string, number> {\n const counts = new Map<string, number>();\n for (const flow of this.flowsById.values()) {\n for (const id of flow.heldCardIds()) counts.set(id, (counts.get(id) ?? 0) + 1);\n }\n return counts;\n }\n\n /** The same ledger with one name left out: what the REST of the world\n * holds, which is the question a resume under that name has to ask. */\n private sharedClaimsExcept(id: string): Map<string, number> {\n const counts = new Map<string, number>();\n for (const [flowId, flow] of this.flowsById) {\n if (flowId === id) continue;\n for (const cardId of flow.heldCardIds()) counts.set(cardId, (counts.get(cardId) ?? 0) + 1);\n }\n return counts;\n }\n\n // --- engine-level state access ----------------------------------------------\n\n /**\n * Read shared state by path: \"world.x\", \"story.gold\" (when shared),\n * \"box.village.heat\" (when shared) - the owner segment is its GAMEID\n * (design/engine-server.md 4.4). A ref that resolves PER-FLOW throws,\n * naming the fix - silently answering with some flow's copy (or a junk\n * default) was the bug Patter's engine.getProperty guard exists to stop.\n */\n getProperty(path: string): ScalarValue {\n const found = this.resolveShared(path);\n const value = found.kind === \"world\" ? this.internals.worldResolver.get(found.name)\n : found.kind === \"scope\" ? this.internals.registry.get(found.token, found.name)\n : found.bag.get(found.name);\n if (value === undefined) throw new Error(`no property at \"${path}\"`);\n return value;\n }\n\n setProperty(path: string, value: ScalarValue): void {\n const found = this.resolveShared(path);\n if (found.kind === \"world\") {\n if (!this.internals.worldSet) {\n throw new Error(`@world is read-only here: the host bound no write`);\n }\n this.internals.worldSet(found.name, value, true);\n return;\n }\n if (found.kind === \"scope\") {\n this.internals.registry.set(found.token, found.name, value, { host: true });\n return;\n }\n // A host write: silent under the firing rule (no subscriber feedback\n // loop), but visible to the bag's audit hook - and a HOST write, so a\n // `writable: false` does not refuse it. That flag is the story's promise\n // about its own outcomes; this is the game speaking, in any scope.\n found.bag.set(found.name, value, { silent: true, reason: \"host setProperty\", host: true });\n }\n\n private resolveShared(path: string):\n | { kind: \"world\"; name: string }\n | { kind: \"scope\"; token: string; name: string }\n | { kind: \"bag\"; bag: StateBag; name: string } {\n const parts = path.split(\".\");\n const perFlow = (): never => {\n throw new Error(`\"${path}\" is per-flow state - read it on a Flow, not the Engine`);\n };\n if (parts.length === 2 && parts[0] === \"world\") return { kind: \"world\", name: parts[1]! };\n // Another engine's game-wide scope (`patter.gold`): every engine reads every scope.\n if (parts.length === 2 && parts[0] !== \"story\" && this.internals.registry.has(parts[0]!)) {\n return { kind: \"scope\", token: parts[0]!, name: parts[1]! };\n }\n if (parts.length === 2 && parts[0] === \"story\") {\n const name = parts[1]!;\n if (this.internals.shared.story.get(name) !== undefined) return { kind: \"bag\", bag: this.internals.shared.story, name };\n if (this.internals.flowDecls.story.some((d) => d.name === name)) perFlow();\n throw new Error(`no property at \"${path}\"`);\n }\n if (parts.length === 3 && (parts[0] === \"box\" || parts[0] === \"deck\" || parts[0] === \"hand\" || parts[0] === \"value\")) {\n const kind = parts[0] as OwnedScope;\n const [, segment, name] = parts as unknown as [string, string, string];\n const owner = ownerOrThrow(this.internals, kind, segment, name);\n if (owner.legacy) this.diagnose(legacyAddressMessage(this.internals, kind, segment, name));\n const id = owner.id;\n const bag = this.internals.shared[kind].get(id);\n if (bag !== undefined && bag.get(name) !== undefined) return { kind: \"bag\", bag, name };\n if (this.internals.flowDecls[kind].get(id)?.some((d) => d.name === name)) perFlow();\n if (bag === undefined && !this.internals.flowDecls[kind].has(id)) throw new Error(`no ${kind} store \"${segment}\"`);\n throw new Error(`no property at \"${path}\"`);\n }\n throw new Error(`bad property path \"${path}\"`);\n }\n\n /** The engine's own surface has no flow, so an engine-level diagnostic\n * carries the empty flow id - the same way a LoadReport's shared half\n * carries no flow. It reaches the run log and the engine tap; there is\n * nowhere else for it to go, and it fires only on a legacy address. */\n private diagnose(message: string): void {\n this.internals.emitEngine(\"\", { type: \"diagnostic\", where: \"property address\", message });\n }\n\n /** Content that names another engine's scope (`@patter.visits`) runs only\n * where that engine is on this registry: without it every read would answer\n * false and every write fail, so the flow is refused as it opens, before\n * anything changes. By then a game has built all of its engines, whatever\n * order it built them in. The same message on every runtime. */\n private assertExternalScopes(): void {\n for (const token of this.internals.bundle.externalScopes ?? []) {\n if (!this.internals.registry.has(token)) {\n throw new Error(`this content names @${token}, which no engine on this registry registered: `\n + `give every engine the game's one registry`);\n }\n }\n }\n\n /** The shared surface as examiner rows: @world (read through the\n * resolver) then the shared partitions. Per-flow rows live on each Flow. */\n listProperties(): PropertyRow[] {\n const out: PropertyRow[] = [];\n for (const d of this.internals.bundle.world.properties) {\n const value = this.internals.worldResolver.get(d.name);\n out.push({\n path: `world.${d.name}`, name: d.name, type: d.type,\n value: value ?? d.default, default: d.default,\n ...(d.values !== undefined ? { values: d.values } : {}),\n ...(d.stages !== undefined ? { stages: d.stages } : {}),\n // @world is FOREIGN - a host resolver backs it - so writability is whether that\n // resolver can be written at all AND what the declaration says, which is the\n // shared registry's own rule for a foreign scope (its foreignWritable). The\n // `as PropertyView` cast this replaced was hiding the field's absence: the row\n // type has always required it, and these rows shipped without one.\n //\n // A row is where `writable: false` is meant to SHOW (Reboot.md 10): it tells a\n // state panel this is the game's value, not the story's. It does not stop the\n // panel editing it - the host's setProperty passes `{ host: true }`.\n writable: this.internals.worldSet !== undefined && !this.internals.worldReadOnly.has(d.name),\n });\n }\n // The bag composes its rows' addresses from its own pathPrefix, so the prefix here is\n // only the caller's label for the mount; the row arrives already addressed.\n const add = (_prefix: string, bag: StateBag): void => {\n for (const row of bag.rows()) out.push(row);\n };\n add(\"story\", this.internals.shared.story);\n for (const kind of OWNED_SCOPES) {\n for (const [id, bag] of this.internals.shared[kind]) add(addressOf(this.internals, kind, id), bag);\n }\n return out;\n }\n\n /** The SHARED kernel bags with their store path prefixes (the state\n * logger's mount surface). The @world container is the host's own bag -\n * the host mounts it itself. */\n listBags(): BagMount[] {\n const mounts: BagMount[] = [{ prefix: \"story\", bag: this.internals.shared.story }];\n for (const kind of [\"box\", \"deck\", \"hand\", \"value\"] as const) {\n for (const [id, bag] of this.internals.shared[kind]) mounts.push({ prefix: addressOf(this.internals, kind, id), bag });\n }\n return mounts;\n }\n\n /** Every flow's trace, one stream, each event tagged with its flow id. */\n subscribeTrace(handler: EngineTraceHandler): () => void {\n this.engineTraceHandlers.add(handler);\n return () => this.engineTraceHandlers.delete(handler);\n }\n\n // --- persistence (schema 4) -------------------------------------------------\n\n /**\n * Live bundle refresh: rebuild on an edited bundle with the whole run carried\n * over, and return the replacement with the report its load produced.\n *\n * Standalone, that is a save and a load into a new engine, and this one is left\n * untouched (discard it). With the game's registry the two cannot both hold the\n * same keys, so this engine is spent afterwards (its flows closed, the\n * replacement holding everything on the same registry): it carries its\n * own values into the snapshot, steps out of the registry, and the replacement\n * loads them the way a standalone save loads: so the report covers the\n * properties the edit dropped, defaulted, or retyped, and a dropped property\n * is dropped rather than kept. Values the game loaded that were still waiting\n * for a flow of this engine carry across as they were, and nothing belonging\n * to any other engine is touched. A save for another project is refused before\n * anything moves; if the rebuild fails for any other reason, this engine takes\n * its registrations back and is left exactly as it was.\n */\n hotSwap(bundle: Bundle, opts: EngineOptions = {}): { engine: Engine; report: LoadReport } {\n if (bundle.content.project !== this.internals.bundle.content.project) {\n throw new Error(`save is for project \"${this.internals.bundle.content.project}\", bundle is \"${bundle.content.project}\"`);\n }\n const options: EngineOptions = { ...this.creationOptions, ...opts };\n const snapshot = this.saveGame();\n const reg = this.internals.registry;\n if (this.internals.ownsRegistry) {\n // Its own registry: a save and a load into a new engine, as it always was,\n // and this engine is left untouched.\n const next = new Engine(bundle, { ...options, registry: undefined });\n return { engine: next, report: next.loadGame(snapshot) };\n }\n // This engine's own values, registered or still waiting for a flow.\n const mine: Record<string, Record<string, ScalarValue>> = {};\n for (const [key, values] of Object.entries(reg.save())) {\n if (key === \"story\" || key.startsWith(\"storylets/\")) mine[key] = values;\n }\n const registeredKeys = new Set([\n ...this.sharedMounts.map((m) => m.key),\n ...[...this.flowsById.values()].flatMap((f) => f.registeredKeys()),\n ]);\n const waiting = Object.fromEntries(Object.entries(mine).filter(([key]) => !registeredKeys.has(key)));\n // Step out of the registry. The bags keep their values, so stepping back in is exact.\n for (const { key } of this.sharedMounts) if (reg.has(key)) reg.remove(key);\n for (const flow of this.flowsById.values()) flow.releaseBags(false);\n let next: Engine | undefined;\n try {\n next = new Engine(bundle, { ...options, registry: reg });\n const report = next.loadGame({ ...snapshot, registry: mine });\n // Values that were waiting for a flow wait on, for the replacement's flow of that name.\n const stillWaiting = Object.fromEntries(Object.entries(waiting).filter(([key]) => !reg.has(key)));\n if (Object.keys(stillWaiting).length > 0) reg.load(stillWaiting, { keepParked: true });\n this.dropRun(false);\n return { engine: next, report };\n } catch (e) {\n // Back as it was. The replacement's registrations go; a constructor that\n // failed part way parked what it had claimed, so this engine's keys are\n // cleared of anything waiting, registered again, and its own values laid\n // back over them (the waiting ones parked again).\n next?.dropRun(false);\n for (const { key } of next?.sharedMounts ?? []) if (reg.has(key)) reg.remove(key);\n reg.discardParked(\"storylets/\");\n for (const { mount } of this.sharedMounts) mount();\n for (const flow of this.flowsById.values()) flow.mountBags();\n // `story` may have claimed what the failed replacement parked there: back to\n // its declarations, then this engine's own values over it.\n this.reseedShared();\n reg.load(mine, { keepParked: true });\n throw e;\n }\n }\n\n /** The whole engine's NON-property state, one envelope: the spent cards\n * once, then every live flow (board, clocks, cooldowns, PRNG, play log)\n * keyed by its id. The property values are the registry's: a standalone\n * engine (one that made its own registry) carries them here under\n * `registry`, self-backed @world included; a game that passed a registry\n * saves it once itself, beside each engine's envelope. */\n saveGame(): SaveEnvelope {\n return structuredClone({\n schema: SAVE_SCHEMA,\n content: this.internals.bundle.content,\n ...(this.internals.ownsRegistry ? { registry: this.internals.registry.save() } : {}),\n shared: { spent: [...this.spent].sort() },\n flows: Object.fromEntries([...this.flowsById].map(([id, flow]) => [id, flow.snapshot(false)])),\n });\n }\n\n /** ONE flow's blob, to park a visit that is walking away: the same shape\n * the envelope carries per flow, and the same shape `openFlow`'s `restore`\n * option takes back (design/engine-server.md 4.1). Saving the whole\n * envelope to park one of four hundred players is wrong in cost and in\n * meaning. Throws for a name that is not open - a closed flow has nothing\n * left to save. */\n saveFlow(id: string): FlowSave {\n const flow = this.flowsById.get(id);\n if (!flow) throw new Error(`unknown flow \"${id}\"`);\n // Parked whole, properties included: a parked flow's bags leave the\n // registry when it closes, so its values have to travel with it.\n return structuredClone(flow.snapshot(true));\n }\n\n /** What `loadGame(envelope)` would do that is not a plain restore, without\n * doing any of it (design/engine-server.md 4.9). Pure: nothing on this\n * engine moves. A project mismatch is refused here exactly as `loadGame`\n * refuses it - it is the one thing neither call will tolerate. */\n previewLoad(envelope: SaveEnvelope | SaveEnvelopeV1): LoadReport {\n this.assertSameProject(envelope);\n return this.planLoad(envelope).report;\n }\n\n /** What `openFlow(id, { restore: saved })` would do to a flow of that name,\n * without doing it: the same report shape, since a visit parked under one\n * build and resumed under the next raises the same questions. Pure. */\n previewFlowRestore(id: string, saved: FlowSave): LoadReport {\n const draft = emptyDraft();\n this.planFlowRestore(id, saved, this.sharedClaimsExcept(id), draft);\n const content = this.internals.bundle.content;\n return finishReport(content, content, [id], draft);\n }\n\n /** Restore: shared state once, then every flow REBUILT from its blob.\n * Handles held from before the load are closed and inert (Patter's\n * rule); take fresh ones from getFlow()/flows().\n *\n * Property values come from the registry. An envelope that carries them\n * (a standalone engine's, or a version 1 envelope) has them walked, cleaned,\n * and moved into the registry here, over fresh defaults. Otherwise the game\n * loads its registry itself, before or after this call: each flow's bags\n * are handed back to the registry with their values, and the restored\n * flows claim them. The report then covers only what this envelope holds;\n * the registry's own load rule applies to the values.\n *\n * Returns the report `previewLoad` would have given for this envelope: the\n * drift tolerance that makes a load forgiving is what hides its cost, so\n * the cost comes back with the load whether or not anybody looked first. */\n loadGame(envelope: SaveEnvelope | SaveEnvelopeV1): LoadReport {\n this.assertSameProject(envelope);\n this.assertExternalScopes();\n const plan = this.planLoad(structuredClone(envelope));\n const reg = this.internals.registry;\n if (plan.sections !== undefined) {\n // The envelope carries the values: every bag of this engine back to its\n // defaults, then the cleaned values over them.\n this.reset();\n // The engine's own registry takes the save wholesale. A game's registry may\n // hold values the game loaded for other engines, still waiting: add to\n // those, never replace them.\n if (this.internals.ownsRegistry) reg.load(plan.sections);\n else reg.load(plan.sections, { keepParked: true });\n } else {\n this.dropRun(new Set(plan.flows.map(([id]) => id)));\n }\n for (const id of plan.spent) this.spent.add(id);\n for (const [id, clean] of plan.flows) this.open(id, {}, true).restore(clean);\n return plan.report;\n }\n\n private assertSameProject(envelope: SaveEnvelope | SaveEnvelopeV1): void {\n if (envelope.content.project !== this.internals.bundle.content.project) {\n throw new Error(`save is for project \"${envelope.content.project}\", bundle is \"${this.internals.bundle.content.project}\"`);\n }\n }\n\n /** The whole-envelope walk: the report, and the cleaned state the apply\n * half writes. Nothing here touches the engine, which is what lets\n * previewLoad and loadGame share it. */\n private planLoad(envelope: SaveEnvelope | SaveEnvelopeV1): {\n report: LoadReport;\n /** The cleaned property values to move into the registry, when the\n * envelope carries any. */\n sections?: Sections;\n spent: string[];\n flows: [string, FlowSave][];\n } {\n const schema = (envelope as { schema?: unknown }).schema;\n if (schema !== SAVE_SCHEMA && schema !== SAVE_SCHEMA_V1) throw new Error(`unsupported save schema: ${String(schema)}`);\n const draft = emptyDraft();\n // Where the property values are, if this envelope has them: a version 1\n // envelope's partitions, or a standalone engine's registry sections.\n const flowIds = new Set(Object.keys(envelope.flows ?? {}));\n let moved: { shared: PropsPartition; flows: Map<string, PropsPartition>; rest: Sections } | undefined;\n if (envelope.schema === SAVE_SCHEMA_V1) {\n moved = {\n shared: envelope.shared?.props ?? emptyPartitionValues(),\n flows: new Map(Object.entries(envelope.flows ?? {}).map(([id, f]) => [id, f.props ?? emptyPartitionValues()])),\n rest: {},\n };\n } else if (envelope.registry !== undefined) {\n moved = partitionsFromSections(envelope.registry, flowIds);\n }\n const shared = moved !== undefined\n ? walkPartition(this.internals, this.internals.sharedDecls, moved.shared, undefined, draft)\n : undefined;\n const spent: string[] = [];\n for (const cardId of envelope.shared?.spent ?? []) {\n if (this.internals.cardsById.has(cardId)) spent.push(cardId);\n else draft.droppedSpent.push(cardId);\n }\n const flows: [string, FlowSave][] = [];\n const sections: Sections | undefined = moved !== undefined ? { ...moved.rest } : undefined;\n if (sections !== undefined && shared !== undefined) {\n sectionsOf(shared, (kind, id) => (kind === \"story\" ? \"story\" : sharedKey(kind, id!)), sections);\n }\n for (const [id, saved] of Object.entries(envelope.flows ?? {})) {\n const withProps: FlowSave = moved !== undefined\n ? { ...saved, props: moved.flows.get(id) ?? emptyPartitionValues() }\n : { ...saved };\n const clean = this.planFlowRestore(id, withProps, undefined, draft);\n if (sections !== undefined && clean.props !== undefined) {\n // The flow's values go into the registry, where its bags claim them; the\n // restored flow itself carries none.\n sectionsOf(clean.props, (kind, owner) => flowKey(id, kind, owner), sections);\n delete clean.props;\n }\n flows.push([id, clean]);\n }\n return {\n report: finishReport(this.internals.bundle.content, envelope.content, flows.map(([id]) => id), draft),\n ...(sections !== undefined ? { sections } : {}),\n spent, flows,\n };\n }\n\n /** One flow's walk. `otherClaims` is the rest of the world's shared ledger\n * and is present only for a SINGLE-flow restore into a live engine: a\n * whole-envelope load rebuilds every flow from one consistent moment, so\n * there is nobody else to compete with. */\n private planFlowRestore(\n id: string,\n saved: FlowSave,\n otherClaims: Map<string, number> | undefined,\n draft: ReportDraft,\n ): FlowSave {\n const internals = this.internals;\n // A flow blob without properties (a version 2 envelope's: the registry has\n // them) has nothing to walk.\n const props = saved.props !== undefined ? walkPartition(internals, internals.flowDecls, saved.props, id, draft) : undefined;\n\n const cooldowns: Record<string, number> = {};\n for (const [cardId, turn] of Object.entries(saved.cooldowns ?? {})) {\n if (internals.cardsById.has(cardId)) cooldowns[cardId] = turn;\n else draft.droppedCooldowns.push({ flow: id, card: cardId });\n }\n\n // A deleted entity has no gameId left, so it is named by the id the save\n // carries; everything the build still knows is named by its gameId.\n const cardName = (cardId: string): string => {\n const entry = internals.cardsById.get(cardId);\n return entry ? effectiveGameId(entry.card) : cardId;\n };\n const board: Record<string, string[]> = {};\n const restored = new Map<string, number>();\n for (const [handId, ids] of Object.entries(saved.board ?? {})) {\n const known = internals.handsById.get(handId);\n if (known === undefined) {\n for (const cardId of ids) {\n draft.evicted.push({ flow: id, hand: handId, card: cardName(cardId), reason: \"hand-vanished\" });\n }\n continue;\n }\n const hand = effectiveGameId(known.hand);\n const kept: string[] = [];\n for (const cardId of ids) {\n const entry = internals.cardsById.get(cardId);\n if (entry === undefined) {\n draft.evicted.push({ flow: id, hand, card: cardId, reason: \"vanished\" });\n continue;\n }\n if (otherClaims !== undefined && cardIsShared(entry.card, entry.deck.shared ?? false)) {\n const held = (otherClaims.get(cardId) ?? 0) + (restored.get(cardId) ?? 0);\n if (held >= sharedCap(entry.card)) {\n draft.evicted.push({ flow: id, hand, card: effectiveGameId(entry.card), reason: \"claimed-elsewhere\" });\n continue;\n }\n restored.set(cardId, (restored.get(cardId) ?? 0) + 1);\n }\n kept.push(cardId);\n }\n board[handId] = kept;\n }\n\n return {\n ...(props !== undefined ? { props } : {}),\n turns: saved.turns ?? {},\n prng: saved.prng,\n cooldowns,\n board,\n playLog: saved.playLog ?? [],\n };\n }\n}\n\n// --- the Flow -----------------------------------------------------------------\n\nexport class Flow {\n readonly id: string;\n private readonly engine: Engine;\n private readonly internals: Internals;\n private closed = false;\n\n private prng: Prng;\n /** Per-box turn counters, keyed by box id (schema 3.4) - per flow. */\n private turnCounts = new Map<string, number>();\n private cooldowns: Record<string, number> = {};\n /** The board: hand contents (card ids, dealt order), keyed by hand id. */\n private boardContents = new Map<string, string[]>();\n private playLog: PlayRecord[] = [];\n // --- play-history indexes -------------------------------------------------\n // The four play-history host functions used to SCAN playLog on every call,\n // and they are called once per candidate card per ask, so dealing was\n // O(candidates x playLog): a shipped game got measurably slower the longer\n // somebody played it, which is the failure mode nobody meets in testing.\n // Measured before the change, 2000 cards: a box with no history condition\n // held flat at 0.3ms while `count_played` went 0.8ms -> 27.9ms as the log\n // reached 4000 plays.\n //\n // These are a pure summary of `playLog`, maintained where it is appended and\n // rebuilt where it is replaced, so they cannot drift from it. They are NOT\n // saved: `playLog` is the record, this is a derivation, and rebuilding on\n // load keeps the save format untouched.\n //\n // The tag keys are the played card's OWN (groupId, tagId) pairs, which is\n // what makes the box-local rule survive: a group name resolves inside the\n // ASKING box, so a card in another box carries different ids and cannot\n // match, exactly as the per-record `inTag` check used to decide.\n private playCount = new Map<string, number>();\n private lastPlayOf = new Map<string, PlayRecord>();\n private tagPlayCount = new Map<string, number>();\n private lastPlayInTag = new Map<string, PlayRecord>();\n /** The per-flow property partitions (the not-shared halves), each bag\n * that declares something registered under this flow's keys. */\n private stores: Partition;\n private readonly registered: string[] = [];\n /** This flow's bags that declare something, under their registry keys. */\n private readonly bagKeys: Array<[string, StateBag]> = [];\n\n private traceHandlers = new Set<TraceHandler>();\n private logEntries: LogEntry[] = [];\n private logSeq = 0;\n\n /** Merged read view per scope, built once (bags are stable for the\n * flow's life): the flow's own bag first, the shared bag behind it.\n * Names are disjoint (shared XOR per-flow by declaration), so \"first\"\n * is routing, not shadowing. */\n private readonly storyReader: ScopeResolver;\n private readonly boxReaders = new Map<string, ScopeResolver>();\n private readonly deckReaders = new Map<string, ScopeResolver>();\n\n /** @internal - built by Engine.openFlow / Engine.loadGame only. */\n constructor(engine: Engine, internals: Internals, id: string, seed: number) {\n this.engine = engine;\n this.internals = internals;\n this.id = id;\n this.prng = makePrng(seed);\n this.stores = buildPartition(internals, flowHalf);\n // Register the bags: each claims whatever the registry holds for its key (a\n // load); openFlow discarded that first for a fresh flow.\n const put = (key: string, bag: StateBag): void => {\n if (bag.declarations().length === 0) return; // holds nothing: not registered\n this.bagKeys.push([key, bag]);\n };\n put(flowKey(id, \"story\"), this.stores.story);\n for (const kind of OWNED_SCOPES) for (const [owner, bag] of this.stores[kind]) put(flowKey(id, kind, owner), bag);\n this.mountBags();\n for (const box of internals.bundle.boxes) {\n this.turnCounts.set(box.id, 0);\n for (const hand of box.hands) this.boardContents.set(hand.id, []);\n }\n const pair = (own: StateBag | undefined, shared: StateBag | undefined): ScopeResolver => ({\n get: (n) => own?.get(n) ?? shared?.get(n),\n });\n // `internals.shared` is reassigned wholesale by loadGame/reset, but a\n // load rebuilds every Flow too, so a live flow's readers and the\n // shared partition are always the same generation.\n this.storyReader = pair(this.stores.story, internals.shared.story);\n for (const box of internals.bundle.boxes) {\n this.boxReaders.set(box.id, pair(this.stores.box.get(box.id), internals.shared.box.get(box.id)));\n for (const deck of box.decks) {\n this.deckReaders.set(deck.id, pair(this.stores.deck.get(deck.id), internals.shared.deck.get(deck.id)));\n }\n }\n }\n\n // --- lifetime ----------------------------------------------------------------\n\n get isClosed(): boolean {\n return this.closed;\n }\n\n /** Close this flow: the handle goes inert, every verb throws. */\n close(): void {\n if (this.closed) return;\n this.engine.dropFlow(this.id, this);\n this.markClosed();\n }\n\n /** @internal */\n markClosed(): void {\n this.releaseBags(false);\n this.closed = true;\n }\n\n /** @internal - take this flow's bags out of the registry; with `keep`, their\n * values wait there for the flow that replaces this one (a load into the\n * game's registry). Idempotent. */\n releaseBags(keep: boolean): void {\n for (const key of this.registered) this.internals.registry.remove(key, { keep });\n this.registered.length = 0;\n }\n\n /** @internal - the registry keys this flow holds right now. */\n registeredKeys(): string[] {\n return [...this.registered];\n }\n\n /** @internal - register this flow's bags (again): at construction, and when a\n * failed hotSwap hands them back. Each claims what the registry holds for it. */\n mountBags(): void {\n for (const [key, bag] of this.bagKeys) {\n this.internals.registry.mountOwned(key, bag, { owner: OWNER });\n this.registered.push(key);\n }\n }\n\n private assertOpen(): void {\n if (this.closed) throw new Error(`flow \"${this.id}\" is closed`);\n }\n\n /** A box's current turn (schema 3.4), on THIS flow's clock. */\n turn(boxRef: string): number {\n this.assertOpen();\n const box = this.internals.boxesByGameId.get(boxRef) ?? this.internals.boxesById.get(boxRef);\n if (!box) throw new Error(`unknown box \"${boxRef}\"`);\n return this.turnCounts.get(box.id) ?? 0;\n }\n\n /** Subscribe to this flow's deal/play trace (schema 5). Returns the\n * unsubscribe. With no subscribers anywhere the flow does no trace work. */\n subscribeTrace(handler: TraceHandler): () => void {\n this.traceHandlers.add(handler);\n return () => this.traceHandlers.delete(handler);\n }\n\n private get tracing(): boolean {\n return this.traceHandlers.size > 0 || this.internals.logCap !== undefined || this.internals.engineTracing();\n }\n\n private emit(event: TraceEvent, turn?: number): void {\n if (this.internals.logCap !== undefined) {\n this.logEntries.push({ ...event, seq: this.logSeq++, ...(turn !== undefined ? { turn } : {}) });\n if (this.logEntries.length > this.internals.logCap) this.logEntries.splice(0, this.logEntries.length - this.internals.logCap);\n }\n for (const handler of this.traceHandlers) handler(event);\n this.internals.emitEngine(this.id, event, turn);\n }\n\n /** The retained flow log (opt-in via the Engine's `log`), oldest first,\n * capped. The introspection seam for hosts and tools; the durable play\n * history in a save stays `playLog` (schema 4) - the log is a\n * flow-lifetime utility and is NOT saved. */\n log(): readonly LogEntry[] {\n return this.logEntries;\n }\n\n /** Empty the retained log; `seq` keeps counting, so ordering across a\n * clear stays meaningful. */\n clearLog(): void {\n this.logEntries = [];\n }\n\n // --- expression plumbing ----------------------------------------------------\n\n private node(expr: Expression): ExprNode {\n let node = this.internals.nodeCache.get(expr);\n if (!node) {\n node = deserialiseAst(expr.ast);\n this.internals.nodeCache.set(expr, node);\n }\n return node;\n }\n\n /** Tag group names are box-scoped: two boxes may name a group the same way\n * (schema 1 - boxes namespace their groups), so a name is only ever\n * resolved inside the box being asked, never bundle-wide. Ids are\n * project-unique and accepted here too, still confined to the box. */\n private groupInBox(box: Box<Expression>, ref: string): TagGroup | undefined {\n return box.tagGroups.find((g) => effectiveGameId(g) === ref)\n ?? box.tagGroups.find((g) => g.id === ref);\n }\n\n /** Fold one play into the indexes. O(the card's tags), not O(the log). */\n private indexPlay(record: PlayRecord): void {\n this.playCount.set(record.card, (this.playCount.get(record.card) ?? 0) + 1);\n this.lastPlayOf.set(record.card, record);\n const entry = this.internals.cardsByGameId.get(record.card);\n if (!entry) return;\n for (const [groupId, tagIds] of Object.entries(entry.card.tags ?? {})) {\n for (const tagId of tagIds) {\n const key = tagKey(groupId, tagId);\n this.tagPlayCount.set(key, (this.tagPlayCount.get(key) ?? 0) + 1);\n this.lastPlayInTag.set(key, record);\n }\n }\n }\n\n /** Rebuild the indexes from the log. Called wherever `playLog` is REPLACED\n * rather than appended to, which is `restore` alone. */\n private rebuildPlayIndex(): void {\n this.playCount.clear();\n this.lastPlayOf.clear();\n this.tagPlayCount.clear();\n this.lastPlayInTag.clear();\n for (const record of this.playLog) this.indexPlay(record);\n }\n\n /** `box` is the box whose ask is being evaluated: the play-history\n * functions take a bare group name, so it resolves there (a card's tags\n * reference its own box's group, which keeps the counts box-local).\n * History is THIS flow's: countPlayed answers \"have I done this\". */\n /** One host per box, built once.\n *\n * The closures below read `this.playCount`, `this.turnCounts` and the rest\n * LIVE, so a cached host answers with current state - which is what makes\n * caching safe rather than a snapshot bug. Unreal did this from the start\n * (`hostsByBox_`, built at flow construction) and the other three rebuilt a\n * host, and its closures, on every `evalCtx` call: once per deck per ask,\n * and once per surviving card in the eviction pass. Structural divergence\n * in one port AND the allocation the audit flagged, so the other three\n * copied it (2026-08-29). Lazy rather than eager, so a bundle's unvisited\n * boxes cost nothing. */\n private hostsByBox = new Map<string, StoryletsHost>();\n\n private host(box: Box<Expression>): StoryletsHost {\n const cached = this.hostsByBox.get(box.id);\n if (cached !== undefined) return cached;\n const made = this.makeHost(box);\n this.hostsByBox.set(box.id, made);\n return made;\n }\n\n private makeHost(box: Box<Expression>): StoryletsHost {\n /** A group NAME and tag name resolved in THIS box, as the index's key.\n * Resolved once per call now, where `inTag` used to resolve it again for\n * every record in the log. Undefined when either name is unknown here,\n * which is the old per-record `false` and answers \"never\". */\n const keyOf = (group: string, tag: string): string | undefined => {\n const found = this.groupInBox(box, group);\n const t = found?.tags.find((v) => v.gameId === tag);\n return found && t ? tagKey(found.id, t.id) : undefined;\n };\n /** Turns-since is measured on the played card's box's clock (3.4). */\n const since = (record: PlayRecord): number => {\n const entry = this.internals.cardsByGameId.get(record.card);\n if (!entry) return NEVER_PLAYED;\n return (this.turnCounts.get(entry.box.id) ?? 0) - record.turn;\n };\n return {\n nextRandom: () => this.prng.next(),\n countPlayed: (card) => this.playCount.get(card) ?? 0,\n turnsSincePlayed: (card) => {\n const last = this.lastPlayOf.get(card);\n return last ? since(last) : NEVER_PLAYED;\n },\n countPlayedIn: (group, tag) => {\n const key = keyOf(group, tag);\n return key === undefined ? 0 : this.tagPlayCount.get(key) ?? 0;\n },\n turnsSincePlayedIn: (group, tag) => {\n const key = keyOf(group, tag);\n const last = key === undefined ? undefined : this.lastPlayInTag.get(key);\n return last ? since(last) : NEVER_PLAYED;\n },\n };\n }\n\n /** The evaluation environment (schema 3.1/6.2): @box/@deck resolve to the\n * card under evaluation; in hand-condition contexts @deck is an empty bag,\n * so any reference is an eval error (missing-policy throw). Every scope\n * is the flow's MERGED view - its own copies over the shared values,\n * names disjoint - and @world reads through the engine's resolver. */\n private evalCtx(box: Box<Expression>, deck: Deck<Expression> | undefined, handEnv: HandEnv): EvalContext {\n const others = this.internals.registryView();\n return {\n scopes: {\n // Every other engine's game-wide scope first (every engine reads every\n // scope); this engine's own tokens are its merged views, over the top.\n ...others.scopes,\n world: this.internals.worldResolver,\n story: this.storyReader,\n box: this.boxReaders.get(box.id) ?? {},\n deck: deck ? this.deckReaders.get(deck.id) ?? {} : {},\n hand: handEnv.bag,\n },\n host: this.host(box) as unknown as Record<string, unknown>,\n // The quality channel, answering for THIS ask's box and deck. Only wired\n // when a quality exists, so a bundle without one evaluates byte-\n // identically to before the feature.\n ...(this.internals.hasQualities || others.qualities !== undefined ? {\n qualities: (scope: string, name: string): readonly string[] | undefined =>\n scope === \"world\" ? this.internals.ladders.world.get(name) ?? others.qualities?.(scope, name)\n : scope === \"story\" ? this.internals.ladders.story.get(name)\n : scope === \"box\" ? this.internals.ladders.box.get(box.id)?.get(name)\n : scope === \"deck\" && deck ? this.internals.ladders.deck.get(deck.id)?.get(name)\n // @hand is composed, so the ladder belongs to whatever supplied the\n // value THIS ask: the bound tag, or the asking hand. `sources` is\n // already the map that answers that, because write-back needs it.\n : scope === \"hand\" ? this.handLadder(handEnv, name)\n : others.qualities?.(scope, name),\n } : {}),\n };\n }\n\n /** The ladder behind one composed @hand name, or undefined when the name is\n * not a quality (or came from criteria, which are tag NAMES, never state). */\n private handLadder(handEnv: HandEnv, name: string): readonly string[] | undefined {\n const source = handEnv.sources.get(name);\n if (!source) return undefined;\n return source.kind === \"value\" ? this.internals.ladders.value.get(source.id)?.get(name)\n : source.kind === \"hand\" ? this.internals.ladders.hand.get(source.id)?.get(name)\n : undefined;\n }\n\n private eval(expr: Expression, ctx: EvalContext): ScalarValue {\n return evaluate(this.node(expr), ctx, storyletsDialect);\n }\n\n private passes(expr: Expression | undefined, ctx: EvalContext, where?: string): boolean {\n if (!expr) return true;\n try {\n return conditionPasses(this.eval(expr, ctx));\n } catch (e) {\n // An eval error is never a silent pass: the card/deck is unavailable\n // (schema 3.1), and the trace surfaces the diagnostic.\n if (this.tracing) {\n this.emit({ type: \"diagnostic\", where: where ?? \"condition\", message: e instanceof Error ? e.message : String(e) });\n }\n return false;\n }\n }\n\n // --- resolving asks (schema 2.6 + 3.6) -----------------------------------------\n\n private tagByGameId(group: TagGroup, gameId: string): Tag | undefined {\n return group.tags.find((t) => t.gameId === gameId);\n }\n\n /** A deal's ask: the hand's template bindings + chosen tags, or its rule's\n * bindings, plus the implicit home binding (schema 2.4). */\n private askForHand(hand: Hand<Expression>, box: Box<Expression>): AskDescriptor {\n const boundTags = new Map<string, string>();\n const askNames: Record<string, string> = {};\n let condition: Expression | undefined;\n if (hand.template !== undefined) {\n const template = this.internals.templatesById.get(hand.template);\n if (!template) throw new Error(`hand \"${effectiveGameId(hand)}\": unknown template \"${hand.template}\"`);\n for (const [groupId, tagId] of Object.entries(template.bindings ?? {})) {\n boundTags.set(groupId, tagId);\n }\n for (const [groupId, tagId] of Object.entries(hand.chosen ?? {})) {\n // A hole filled from a property rather than with a tag: resolve it\n // now, before tag composition (4.6, the hand that moves).\n if (isHoleRef(tagId)) {\n this.fillHoleFromProperty(hand, groupId, tagId, boundTags, askNames);\n continue;\n }\n boundTags.set(groupId, tagId);\n const found = this.internals.groupsById.get(groupId);\n const tag = found?.group.tags.find((t) => t.id === tagId);\n if (found && tag) askNames[effectiveGameId(found.group)] = effectiveGameId(tag);\n }\n condition = template.condition;\n } else {\n for (const [groupId, tagId] of Object.entries(hand.rule?.bindings ?? {})) {\n if (isHoleRef(tagId)) {\n this.fillHoleFromProperty(hand, groupId, tagId, boundTags, askNames);\n continue;\n }\n boundTags.set(groupId, tagId);\n // ...and name it, exactly as the template branch above does: a card\n // reading @hand.<group> must not care HOW the group got bound\n // (design/hand-typing.md, the residues).\n const found = this.internals.groupsById.get(groupId);\n const tag = found?.group.tags.find((t) => t.id === tagId);\n if (found && tag) askNames[effectiveGameId(found.group)] = effectiveGameId(tag);\n }\n condition = hand.rule?.condition;\n }\n boundTags.set(PLACE_GROUP, hand.id);\n this.bindStateGroups(box, boundTags, askNames);\n return { box, hand, ...(condition !== undefined ? { condition } : {}), boundTags, askNames };\n }\n\n /** A peek's ask: raw criteria ({group gameId: tag gameId}), bindings only,\n * no condition slot (schema 3.1; the boundary, Reboot 4). */\n private askForPeek(box: Box<Expression>, criteria: Record<string, string>): AskDescriptor {\n const boundTags = new Map<string, string>();\n const askNames: Record<string, string> = {};\n for (const [groupRef, tagRef] of Object.entries(criteria)) {\n if (groupRef === PLACE_GROUP) {\n const hand = this.internals.handsByGameId.get(tagRef) ?? this.internals.handsById.get(tagRef);\n if (!hand) throw new Error(`peek: unknown hand \"${tagRef}\" in home criteria`);\n boundTags.set(PLACE_GROUP, hand.hand.id);\n continue;\n }\n const found = this.groupInBox(box, groupRef);\n if (!found) {\n throw new Error(`peek: unknown tag group \"${groupRef}\" in box \"${effectiveGameId(box)}\"`);\n }\n const tag = this.tagByGameId(found, tagRef) ?? found.tags.find((t) => t.id === tagRef);\n if (!tag) throw new Error(`peek: unknown tag \"${tagRef}\" in group \"${effectiveGameId(found)}\"`);\n boundTags.set(found.id, tag.id);\n askNames[effectiveGameId(found)] = effectiveGameId(tag);\n }\n this.bindStateGroups(box, boundTags, askNames);\n return { box, boundTags, askNames };\n }\n\n /**\n * Fill one hole from the property its value names: the hand that moves\n * (design/engine-server.md 4.6).\n *\n * The semantics are `bindStateGroups`' below, word for word, applied per\n * HOLE instead of per group: resolved at ask time, and a value naming no tag\n * leaves the hole UNBOUND (a wildcard) with a diagnostic rather than dealing\n * a silently empty hand. What is added is the `@hand` scope - the asking\n * hand's OWN declared state, read here from the flow's merged view (the\n * shared half under the flow's own, so a `shared: true` declaration moves\n * the hole for every flow and a per-flow one moves it for this flow alone).\n *\n * Read BEFORE tag composition, which is the whole reason it is safe: the\n * @hand bag a card sees is built from the bound tags, so resolving a hole\n * from it would be circular. A hand's own declarations are not, so they are.\n */\n private fillHoleFromProperty(\n hand: Hand<Expression>, groupId: string, ref: string,\n boundTags: Map<string, string>, askNames: Record<string, string>,\n ): void {\n const found = this.internals.groupsById.get(groupId);\n const groupName = found ? effectiveGameId(found.group) : groupId;\n const where = `hand ${effectiveGameId(hand)}, tag group ${groupName}`;\n const parsed = parseHoleRef(ref);\n if (!parsed) {\n this.emit({ type: \"diagnostic\", where, message: `\"${ref}\" is not a @hand, @world or @story property reference` });\n return;\n }\n if (!found) {\n this.emit({ type: \"diagnostic\", where, message: `\"${ref}\" fills a tag group that is not in this box` });\n return;\n }\n let value: ScalarValue | undefined;\n if (parsed.scope === \"hand\") {\n value = this.valuesOf(\"hand\", hand.id)[parsed.name];\n } else {\n try {\n value = this.getProperty(`${parsed.scope}.${parsed.name}`);\n } catch {\n value = undefined;\n }\n }\n if (value === undefined) {\n this.emit({ type: \"diagnostic\", where, message: `\"${ref}\" names a property that is not declared` });\n return;\n }\n const wanted = typeof value === \"string\" ? value : String(value);\n const tag = found.group.tags.find((t) => effectiveGameId(t) === wanted);\n if (!tag) {\n this.emit({ type: \"diagnostic\", where, message: `${ref} is \"${wanted}\", which is not one of the tags of \"${groupName}\"` });\n return;\n }\n boundTags.set(groupId, tag.id);\n askNames[groupName] = effectiveGameId(tag);\n }\n\n /**\n * Bind every `boundBy` group in the box from the property it names.\n *\n * The gap this closes: only a hand could bind a group, and `deal` takes no\n * criteria, so an axis driven by state (an act, a chapter) had nowhere to\n * gate. Runs AFTER the hand's own bindings and never overwrites one: an\n * explicit binding is a deliberate act and beats a default.\n *\n * A value naming no tag in the group leaves the group UNBOUND rather than\n * matching nothing. Unbound is a wildcard, so the ask still deals; a silent\n * empty hand would look like content that does not exist, and the diagnostic\n * is what says otherwise.\n */\n private bindStateGroups(box: Box<Expression>, boundTags: Map<string, string>, askNames: Record<string, string>): void {\n for (const group of box.tagGroups) {\n if (group.boundBy === undefined || boundTags.has(group.id)) continue;\n const ref = /^@(world|story)\\.([a-z][a-z0-9_-]*)$/.exec(group.boundBy);\n if (!ref) {\n this.emit({ type: \"diagnostic\", where: `tag group ${effectiveGameId(group)}`, message: `boundBy \"${group.boundBy}\" is not a @world or @story property reference` });\n continue;\n }\n let value: ScalarValue | undefined;\n try {\n value = this.getProperty(`${ref[1]}.${ref[2]}`);\n } catch {\n this.emit({ type: \"diagnostic\", where: `tag group ${effectiveGameId(group)}`, message: `boundBy \"${group.boundBy}\" names a property that is not declared` });\n continue;\n }\n const wanted = typeof value === \"string\" ? value : String(value);\n const tag = group.tags.find((t) => effectiveGameId(t) === wanted);\n if (!tag) {\n this.emit({ type: \"diagnostic\", where: `tag group ${effectiveGameId(group)}`, message: `${group.boundBy} is \"${wanted}\", which is not one of its tags` });\n continue;\n }\n boundTags.set(group.id, tag.id);\n askNames[effectiveGameId(group)] = effectiveGameId(tag);\n }\n }\n\n // --- @hand composition (schema 3.6) -------------------------------------------\n\n /** A store's full value view for one owner: the shared half under the\n * flow's half. Names are disjoint, so the spread is routing, not\n * shadowing. */\n private valuesOf(kind: Exclude<PartitionKind, \"story\">, id: string): PropertyBag {\n return {\n ...(this.internals.shared[kind].get(id)?.values ?? {}),\n ...(this.stores[kind].get(id)?.values ?? {}),\n };\n }\n\n private buildHandEnv(ask: AskDescriptor): HandEnv {\n const bag: PropertyBag = {};\n const sources = new Map<string, HandSource>();\n\n // 1. Tag properties of every bound tag (home binds a hand, not a tag).\n for (const [groupId, tagId] of ask.boundTags) {\n if (groupId === PLACE_GROUP) continue;\n for (const [name, value] of Object.entries(this.valuesOf(\"value\", tagId))) {\n bag[name] = value;\n sources.set(name, { kind: \"value\", id: tagId });\n }\n }\n // 2. Hand properties, when the ask is a deal.\n if (ask.hand) {\n for (const [name, value] of Object.entries(this.valuesOf(\"hand\", ask.hand.id))) {\n bag[name] = value;\n sources.set(name, { kind: \"hand\", id: ask.hand.id });\n }\n }\n // 3. Chosen tags / criteria, by group name (the tag's gameId as value).\n for (const [name, value] of Object.entries(ask.askNames)) {\n bag[name] = value;\n sources.set(name, { kind: \"criteria\" });\n }\n return { bag, sources, boundTags: ask.boundTags };\n }\n\n // --- the ask (schema 3.1 + 3.2) ------------------------------------------------\n\n /** The claims ledger, derived from THIS flow's board: card id -> holding\n * hands (schema 3.5). Claims are per flow - another flow holding the\n * card is another playthrough, not a rival hand. */\n private claims(): Map<string, number> {\n const counts = new Map<string, number>();\n for (const contents of this.boardContents.values()) {\n for (const id of contents) counts.set(id, (counts.get(id) ?? 0) + 1);\n }\n return counts;\n }\n\n /** @internal - every card id on THIS flow's board, one entry per holding\n * hand. The engine sums these across live flows for the shared ledger. */\n heldCardIds(): string[] {\n return [...this.boardContents.values()].flat();\n }\n\n private copiesOf(card: Card<Expression>): number {\n return card.copies ?? 1;\n }\n\n /** The claims step (schema 3.1 step 6) for one card, as a verdict or null\n * for \"available\". Two caps apply to a shared card and they are different\n * statements, so they get different verdicts: `copies` is your own board\n * filling up, `sharedCopies` is somebody else already holding it, and a\n * participant told \"claimed\" about a card sitting on another person's\n * table would read it as an engine fault (design/shared-scarcity 9.3.1).\n *\n * `mine` counts this flow's holdings, `world` every live flow's. */\n private claimVerdict(\n card: Card<Expression>,\n shared: boolean,\n mine: Map<string, number>,\n world: Map<string, number>,\n ): \"claimed\" | \"claimed-elsewhere\" | null {\n const id = card.id;\n if ((mine.get(id) ?? 0) >= this.copiesOf(card)) return \"claimed\";\n if (shared && (world.get(id) ?? 0) >= sharedCap(card)) return \"claimed-elsewhere\";\n return null;\n }\n\n /** Tag matching (schema 3.1 step 3): for every bound group the card lists\n * the bound tag or omits the group (wildcard); the home group inverts -\n * a homed card requires a matching home binding (schema 2.4). */\n private tagsMatch(card: Card<Expression>, boundTags: Map<string, string>): boolean {\n const home = card.tags?.[PLACE_GROUP];\n if (home !== undefined && home.length > 0) {\n const bound = boundTags.get(PLACE_GROUP);\n if (bound === undefined || !home.includes(bound)) return false;\n }\n for (const [groupId, tagId] of boundTags) {\n if (groupId === PLACE_GROUP) continue;\n const tags = card.tags?.[groupId];\n if (tags === undefined) {\n // Omission is a wildcard unless the group says otherwise. A required\n // group inverts it, which is what `place` has always done per card.\n if (this.internals.requiredGroups.has(groupId)) return false;\n continue;\n }\n if (!tags.includes(tagId)) return false;\n }\n return true;\n }\n\n /** Run one ask: availability filter then ranking. `claimed` decides the\n * claims step (step 6) per card, returning the verdict that refused it or\n * null for available. `trace` (when a subscriber exists) collects the\n * per-card verdicts. */\n private runAsk(\n ask: AskDescriptor,\n claimed: (card: Card<Expression>, shared: boolean) => \"claimed\" | \"claimed-elsewhere\" | null,\n trace?: { id: string; verdict: TraceVerdict; priority?: number; specificity?: number }[],\n ): { ordered: CardEntry[]; handEnv: HandEnv } {\n const { box } = ask;\n const handEnv = this.buildHandEnv(ask);\n // Identity on the trace is by gameId (4.4), so the helper takes the CARD\n // rather than an id: every call site had one in hand, and taking the id\n // was the whole of how the two vocabularies got mixed.\n const verdict = (card: Card<Expression>, v: TraceVerdict): void => {\n trace?.push({ id: effectiveGameId(card), verdict: v });\n };\n\n // The hand's condition: ask-constant, evaluated once (schema 3.1 step 4).\n if (!this.passes(ask.condition, this.evalCtx(box, undefined, handEnv), `hand ${ask.hand ? effectiveGameId(ask.hand) : \"\"} condition`)) {\n return { ordered: [], handEnv };\n }\n\n // Deck gates: evaluated once per ask, in deck (id) order (schema 2.5).\n const gateOk = new Map<string, boolean>();\n for (const deck of box.decks) {\n gateOk.set(deck.id, this.passes(deck.condition, this.evalCtx(box, deck, handEnv), `deck ${deck.gameId} gate`));\n }\n\n const turn = this.turnCounts.get(box.id) ?? 0;\n const scored: { entry: CardEntry; priority: number; spec: number }[] = [];\n for (const deck of box.decks) {\n // ONE context per deck, not per card. It is built from box, deck and\n // handEnv, none of which vary inside this loop, and a condition is a\n // read-only gate (schema 3.1), so nothing can write through it and make\n // sharing visible. Rebuilding it per card cost an EvalContext, a scopes\n // map and five bag wrappers each time: about half the garbage a peek over\n // a large box produced (port-review-2026-08.md, measured).\n const deckCtx = this.evalCtx(box, deck, handEnv);\n const deckShared = deck.shared ?? false;\n for (const card of deck.cards) {\n const shared = cardIsShared(card, deckShared);\n if (!gateOk.get(deck.id)) {\n verdict(card, \"deck-gate\");\n continue;\n }\n // Taken out of the world by somebody's shared one-shot. Checked\n // before the flow's own clock, because \"cooldown\" would point the\n // reader at a turn counter that has nothing to do with it.\n if (shared && this.engine.isTaken(card.id)) {\n verdict(card, \"taken\");\n continue;\n }\n if ((this.cooldowns[card.id] ?? 0) > turn) {\n verdict(card, \"cooldown\");\n continue;\n }\n if (!this.tagsMatch(card, handEnv.boundTags)) {\n verdict(card, \"tags\");\n continue;\n }\n // The label is only read when an eval THROWS and only when tracing, so\n // building it per card was pure waste on the path that matters. Built\n // when tracing is on, where the cost is already accepted.\n if (card.condition && !this.passes(card.condition, deckCtx,\n this.tracing ? `card ${card.gameId} condition` : undefined)) {\n verdict(card, \"condition\");\n continue;\n }\n const refused = claimed(card, shared); // claims, last (schema 3.1 step 6)\n if (refused) {\n verdict(card, refused);\n continue;\n }\n\n let priority: number;\n if (typeof card.priority === \"number\") {\n priority = card.priority;\n } else {\n try {\n const v = this.eval(card.priority, deckCtx);\n if (typeof v !== \"number\") {\n verdict(card, \"priority\");\n continue;\n }\n priority = v;\n } catch (e) {\n if (this.tracing) {\n this.emit({ type: \"diagnostic\", where: `card ${card.gameId} priority`, message: e instanceof Error ? e.message : String(e) });\n }\n verdict(card, \"priority\");\n continue;\n }\n }\n let spec = 0;\n if (box.ranking.specificity && card.condition) {\n const node = this.node(card.condition);\n spec = matchedSpecificity(node, (n) => {\n try {\n return conditionPasses(evaluate(n, deckCtx, storyletsDialect));\n } catch {\n return false;\n }\n });\n }\n scored.push({ entry: { card, deck, box }, priority, spec });\n }\n }\n\n scored.sort((a, b) => b.priority - a.priority || b.spec - a.spec); // stable\n // Seeded shuffle of each maximal tie run; runs of 1 consume no draws.\n let i = 0;\n while (i < scored.length) {\n let j = i + 1;\n while (j < scored.length\n && scored[j]!.priority === scored[i]!.priority\n && scored[j]!.spec === scored[i]!.spec) j++;\n if (j - i > 1) {\n const run = scored.slice(i, j);\n shuffleInPlace(run, this.prng);\n // Written back element by element, as all three ports do. It used to be\n // `scored.splice(i, j - i, ...run)`, which SPREADS one argument per\n // element: with every card at the default priority 0 the tie run is the\n // whole list, and a box of 150 000 such cards threw `RangeError:\n // Maximum call stack size exceeded` rather than dealing. Far-fetched\n // for one box, but it was a crash where the ports had no limit, and the\n // reference is supposed to be the thing they are transliterated from.\n for (let k = 0; k < run.length; k++) scored[i + k] = run[k]!;\n }\n i = j;\n }\n for (const s of scored) {\n trace?.push({ id: effectiveGameId(s.entry.card), verdict: \"dealt\", priority: s.priority, specificity: s.spec });\n }\n return { ordered: scored.map((s) => s.entry), handEnv };\n }\n\n /** Flip eligible-but-not-taken trace entries to \"capped\". `taken` is keyed\n * by GAMEID, as the trace rows are (4.4): the two must move together or\n * every dealt card silently reads as capped. */\n private capTrace(\n trace: { id: string; verdict: TraceVerdict; priority?: number; specificity?: number }[],\n taken: ReadonlySet<string>,\n ): void {\n for (const entry of trace) {\n if (entry.verdict === \"dealt\" && !taken.has(entry.id)) entry.verdict = \"capped\";\n }\n }\n\n private view(entry: CardEntry): DealtCard {\n const { card } = entry;\n return {\n id: card.id,\n gameId: effectiveGameId(card),\n ...(card.title !== undefined ? { title: card.title } : {}),\n ...(card.purpose !== undefined ? { purpose: card.purpose } : {}),\n ...(card.fields !== undefined ? { fields: card.fields } : {}),\n };\n }\n\n private handCapacity(hand: Hand<Expression>): number {\n if (hand.slots !== undefined) return hand.slots;\n const declared = hand.template !== undefined\n ? this.internals.templatesById.get(hand.template)?.slots\n : hand.rule?.slots;\n return declared === undefined || declared === \"unbounded\" ? Infinity : declared;\n }\n\n private resolveHand(ref: string): { hand: Hand<Expression>; box: Box<Expression> } {\n const found = this.internals.handsByGameId.get(ref) ?? this.internals.handsById.get(ref);\n if (!found) throw new Error(`unknown hand \"${ref}\"`);\n return found;\n }\n\n // --- host surface (schema 5) ---------------------------------------------------\n\n /** Look at the top of the stock through raw tag criteria (schema 3.1):\n * claims respected, nothing registered, nothing left behind but the\n * trace line. You can never play a card you only peeked. */\n peek(boxRef: string, criteria: Record<string, string> = {}, n?: number): RankedList {\n this.assertOpen();\n const box = this.internals.boxesByGameId.get(boxRef) ?? this.internals.boxesById.get(boxRef);\n if (!box) throw new Error(`unknown box \"${boxRef}\"`);\n const ask = this.askForPeek(box, criteria);\n const claimCounts = this.claims();\n // Skipped outright when the bundle shares nothing, which is most bundles:\n // the ledger walks every live flow's whole board, and an empty map answers\n // every question the same way a computed one would.\n const worldClaims = this.internals.hasShared ? this.engine.sharedClaims() : new Map<string, number>();\n const trace = this.tracing ? [] : undefined;\n const { ordered } = this.runAsk(ask, (card, shared) => this.claimVerdict(card, shared, claimCounts, worldClaims), trace);\n // CLAMPED. `slice(0, -1)` drops the last card and returns the rest, so a\n // negative n answered with almost the whole list here while every port\n // returned nothing (2026-08-29).\n const listed = n === undefined ? ordered : ordered.slice(0, Math.max(n, 0));\n if (trace) {\n this.capTrace(trace, new Set(listed.map((e) => effectiveGameId(e.card))));\n this.emit({ type: \"peek\", box: effectiveGameId(box), criteria, cards: trace }, this.turnCounts.get(box.id) ?? 0);\n }\n return { box: effectiveGameId(box), cards: listed.map((e) => this.view(e)) };\n }\n\n /** Refresh one hand (schema 3.5); returns its new shape. */\n deal(handRef: string): DealtCard[] {\n this.assertOpen();\n const { hand } = this.resolveHand(handRef);\n return this.dealMany([handRef])[effectiveGameId(hand)] ?? [];\n }\n\n /** Re-deal several / all hands (schema 3.5): seeded hand-order shuffle\n * (fairness), evict, seed the ledger from survivors, fill in order.\n * Returns the dealt slice - the new contents of exactly the hands this\n * call dealt, keyed by hand gameId (board() stays the whole-board read). */\n dealMany(handRefs?: string[]): Record<string, DealtCard[]> {\n this.assertOpen();\n const dealt = (handRefs ?? [...this.internals.handsById.keys()].sort())\n .map((ref) => this.resolveHand(ref));\n shuffleInPlace(dealt, this.prng);\n\n // Eviction first: drop dealt cards no longer available to their hand\n // (minus the claims check against their own seat).\n for (const { hand, box } of dealt) {\n const ask = this.askForHand(hand, box);\n const handEnv = this.buildHandEnv(ask);\n const conditionOk = this.passes(ask.condition, this.evalCtx(box, undefined, handEnv));\n const gateOk = new Map<string, boolean>();\n for (const deck of box.decks) {\n gateOk.set(deck.id, this.passes(deck.condition, this.evalCtx(box, deck, handEnv)));\n }\n const turn = this.turnCounts.get(box.id) ?? 0;\n // Trace events fire after the state they report has landed (a handler\n // reading the board sees the eviction), so they are collected here and\n // emitted once the survivors are set.\n const evicted: { card: string; reason: Extract<TraceEvent, { type: \"evict\" }>[\"reason\"] }[] = [];\n // The card is named by gameId (4.4). A card the build no longer has -\n // the `vanished` branch below - has no gameId left, so it is named by\n // the id the board carries, which is the rule a load report has always\n // used for the same reason.\n const evict = (cardId: string, reason: Extract<TraceEvent, { type: \"evict\" }>[\"reason\"]): false => {\n const known = this.internals.cardsById.get(cardId);\n evicted.push({ card: known ? effectiveGameId(known.card) : cardId, reason });\n return false;\n };\n const survivors = (this.boardContents.get(hand.id) ?? []).filter((cardId) => {\n if (!conditionOk) return evict(cardId, \"hand-condition\");\n const entry = this.internals.cardsById.get(cardId);\n if (!entry) return evict(cardId, \"vanished\"); // edited content: dropped\n if (!gateOk.get(entry.deck.id)) return evict(cardId, \"deck-gate\");\n if ((this.cooldowns[cardId] ?? 0) > turn) return evict(cardId, \"cooldown\");\n if (!this.tagsMatch(entry.card, handEnv.boundTags)) return evict(cardId, \"tags\");\n if (!this.passes(entry.card.condition, this.evalCtx(box, entry.deck, handEnv), `card ${entry.card.gameId} condition`)) {\n return evict(cardId, \"condition\");\n }\n return true;\n });\n this.boardContents.set(hand.id, survivors);\n if (this.tracing) {\n for (const e of evicted) this.emit({ type: \"evict\", hand: effectiveGameId(hand), card: e.card, reason: e.reason }, turn);\n }\n }\n\n const claimCounts = this.claims();\n // The world ledger is taken once for the whole batch and kept in step with\n // the local one below, so two hands in the SAME deal cannot both take the\n // last shared copy. Skipped outright when the bundle shares nothing (most\n // bundles): an empty map answers every question the same way.\n const worldClaims = this.internals.hasShared ? this.engine.sharedClaims() : new Map<string, number>();\n for (const { hand, box } of dealt) {\n const contents = this.boardContents.get(hand.id) ?? [];\n const free = this.handCapacity(hand) - contents.length;\n if (free <= 0) continue;\n const ask = this.askForHand(hand, box);\n const own = new Set(contents);\n const trace = this.tracing ? [] : undefined;\n // At most once in any one hand; at most `copies` hands here, and at most\n // `sharedCopies` hands anywhere (schema 3.5, shared-scarcity 5).\n const { ordered } = this.runAsk(ask,\n (card, shared) => (own.has(card.id) ? \"claimed\" : this.claimVerdict(card, shared, claimCounts, worldClaims)), trace);\n const taking = ordered.slice(0, free);\n const added = taking.map((e) => e.card.id);\n this.boardContents.set(hand.id, [...contents, ...added]);\n for (const id of added) {\n claimCounts.set(id, (claimCounts.get(id) ?? 0) + 1);\n worldClaims.set(id, (worldClaims.get(id) ?? 0) + 1);\n }\n // Emitted after the hand is set: a handler reading board() sees the deal.\n if (trace) {\n this.capTrace(trace, new Set(taking.map((e) => effectiveGameId(e.card))));\n this.emit({ type: \"deal\", hand: effectiveGameId(hand), cards: trace }, this.turnCounts.get(box.id) ?? 0);\n }\n }\n\n return Object.fromEntries(dealt.map(({ hand }) => [\n effectiveGameId(hand),\n (this.boardContents.get(hand.id) ?? []).map((id) => this.view(this.internals.cardsById.get(id)!)),\n ]));\n }\n\n /** The board: current hand contents, in dealt order, keyed by hand gameId\n * (schema 5). Read it for what is out; peek the stock for what could\n * come.\n *\n * `boxRef` (a box gameId or id) narrows the read to that box's hands, in\n * the same shape and the same order: \"give me the barks hands\" is a\n * common host query, and boxes are how a game separates its storylet\n * systems, so the grouping belongs here rather than in every host. An\n * unknown box throws, as it does on turn() and peek(). */\n board(boxRef?: string): Record<string, DealtCard[]> {\n this.assertOpen();\n let keep: string | undefined;\n if (boxRef !== undefined) {\n const box = this.internals.boxesByGameId.get(boxRef) ?? this.internals.boxesById.get(boxRef);\n if (!box) throw new Error(`unknown box \"${boxRef}\"`);\n keep = box.id;\n }\n return Object.fromEntries([...this.boardContents.entries()]\n .filter(([handId]) => keep === undefined || this.internals.handsById.get(handId)!.box.id === keep)\n .map(([handId, ids]) => [\n effectiveGameId(this.internals.handsById.get(handId)!.hand),\n ids.map((id) => this.view(this.internals.cardsById.get(id)!)),\n ]));\n }\n\n /** Resolve a played/inspected card within a hand on the board. */\n private resolveDealt(cardId: string, handRef: string): { entry: CardEntry; ask: AskDescriptor } {\n const entry = this.internals.cardsById.get(cardId) ?? this.internals.cardsByGameId.get(cardId);\n if (!entry) throw new Error(`unknown card \"${cardId}\"`);\n const { hand, box } = this.resolveHand(handRef);\n if (!(this.boardContents.get(hand.id) ?? []).includes(entry.card.id)) {\n throw new Error(`card \"${effectiveGameId(entry.card)}\" is not dealt to hand \"${effectiveGameId(hand)}\"`);\n }\n return { entry, ask: this.askForHand(hand, box) };\n }\n\n /** Outcome availability, evaluated against CURRENT state on every ask\n * (schema 3.1/5) - never a deal-time snapshot. */\n outcomes(cardId: string, from: string): OutcomeView[] {\n this.assertOpen();\n const { entry, ask } = this.resolveDealt(cardId, from);\n const ctx = this.evalCtx(entry.box, entry.deck, this.buildHandEnv(ask));\n return entry.card.outcomes.map((o) => ({\n id: o.id,\n gameId: effectiveGameId(o),\n ...(o.title !== undefined ? { title: o.title } : {}),\n ...(o.purpose !== undefined ? { purpose: o.purpose } : {}),\n ...(o.fields !== undefined ? { fields: o.fields } : {}),\n available: this.passes(o.condition, ctx),\n }));\n }\n\n /** Apply an outcome (schema 3.7): the card must sit in a hand on the\n * board (you never play a card from inside the deck). Throws before any\n * mutation on a gated-shut outcome or a bad write target.\n *\n * A card with NO outcomes is played with none, named as \"\" (the\n * no-outcome-play brief, 2026-09-14): a masthead, a notice, a codex entry,\n * whose play means \"shown\". It is everything a play is except the writes:\n * the play log and the history functions count it, the box's turn moves by\n * the usual rule, the redraw rests it and it leaves its hand. \"\" is the one\n * spelling in all four runtimes, because a Blueprint pin cannot be absent.\n * Only the empty-for-empty case is new: \"\" on a card that has outcomes is\n * refused, and a named outcome on a card with none is refused as before. */\n play(cardId: string, outcomeGameId: string, from: string, opts: PlayOptions = {}): void {\n this.assertOpen();\n const { entry, ask } = this.resolveDealt(cardId, from);\n const bare = outcomeGameId === \"\";\n if (bare && entry.card.outcomes.length > 0) {\n throw new Error(`card \"${effectiveGameId(entry.card)}\" has outcomes (${entry.card.outcomes.map((o) => effectiveGameId(o)).join(\", \")}); name the one played`);\n }\n const outcome = bare ? undefined : entry.card.outcomes.find((o) => effectiveGameId(o) === outcomeGameId);\n if (!bare && !outcome) throw new Error(`card \"${effectiveGameId(entry.card)}\" has no outcome \"${outcomeGameId}\"`);\n\n const handEnv = this.buildHandEnv(ask);\n const ctx = this.evalCtx(entry.box, entry.deck, handEnv);\n if (outcome && !this.passes(outcome.condition, ctx)) {\n throw new Error(`outcome \"${outcomeGameId}\" on \"${effectiveGameId(entry.card)}\" is gated shut`);\n }\n\n // The played card's box's clock advances (schema 3.4); computed up\n // front so the play and its writes log as one action, one turn stamp.\n //\n // A TIMED box (design/engine-server.md 4.8) defaults to advancing\n // NOTHING: its clock is time, the host ticks it, and a play is not a\n // tick. A call that names `advanceTurns` still gets what it asked for,\n // in either kind of box, because the call says otherwise. This is the\n // whole of `turn`'s effect on the engine: the seconds are never read.\n const perPlay = entry.box.turn !== undefined ? 0 : this.internals.bundle.settings.playAdvancesTurns;\n const newTurn = (this.turnCounts.get(entry.box.id) ?? 0) + (opts.advanceTurns ?? perPlay);\n\n // Every right-hand side evaluates against PRE-play state, then all\n // writes land (schema 3.7).\n const writes: { target: string; value: ScalarValue }[] = [];\n for (const [target, expr] of Object.entries(outcome?.changes ?? {})) {\n writes.push({ target, value: this.eval(expr, ctx) });\n }\n for (const { target, value } of writes) {\n const { path, prev } = this.applyWrite(target, value, entry, handEnv);\n if (this.tracing) this.emit({ type: \"write\", target, path, value, ...(prev !== undefined ? { prev } : {}) }, newTurn);\n }\n\n const outcomeId = outcome ? effectiveGameId(outcome) : \"\";\n const record: PlayRecord = { card: effectiveGameId(entry.card), outcome: outcomeId, turn: newTurn };\n this.playLog.push(record);\n this.indexPlay(record);\n if (entry.card.redraw === \"never\") {\n // A shared one-shot leaves the world rather than this flow: the engine\n // holds it, so every flow is refused. A finite redraw deliberately does\n // NOT share, whatever the deck says - a cooldown is an absolute turn of\n // this flow's box clock, and there is no shared clock to compare it\n // against (design/shared-scarcity.md 9.3.2).\n if (cardIsShared(entry.card, entry.deck.shared ?? false)) this.engine.markTaken(entry.card.id);\n else this.cooldowns[entry.card.id] = Number.MAX_SAFE_INTEGER;\n } else if (typeof entry.card.redraw === \"number\") {\n this.cooldowns[entry.card.id] = newTurn + entry.card.redraw;\n }\n // The card leaves its hand, releasing its claim (schema 3.5/3.7).\n const handId = ask.hand!.id;\n this.boardContents.set(handId,\n (this.boardContents.get(handId) ?? []).filter((id) => id !== entry.card.id));\n this.turnCounts.set(entry.box.id, newTurn);\n // Emitted last: a handler reading the board and the clock sees the play.\n if (this.tracing) this.emit({ type: \"play\", card: effectiveGameId(entry.card), outcome: outcomeId, turn: newTurn }, newTurn);\n }\n\n /** One owned property's address, owner segment and all (4.4). */\n private address(kind: OwnedScope, id: string): string {\n return addressOf(this.internals, kind, id);\n }\n\n /** Land one change in whichever partition declares the name: the flow's\n * bag when the property is per-flow, the shared bag when it is shared -\n * the union/partition invariant made executable. */\n private landIn(kind: Exclude<PartitionKind, \"story\"> | \"story\", id: string | undefined, name: string, value: ScalarValue, path: string): { path: string; prev?: ScalarValue } {\n const own = kind === \"story\" ? this.stores.story : id !== undefined ? this.stores[kind].get(id) : undefined;\n const shared = kind === \"story\" ? this.internals.shared.story : id !== undefined ? this.internals.shared[kind].get(id) : undefined;\n const bag = own !== undefined && own.get(name) !== undefined ? own\n : shared !== undefined && shared.get(name) !== undefined ? shared\n : undefined;\n if (bag === undefined) throw new Error(`no property at \"${path}\"`);\n // An engine write: the bag's subscribers fire (the firing rule).\n const change = bag.set(name, value);\n return { path, ...(change.prev !== undefined ? { prev: change.prev } : {}) };\n }\n\n /** Land one change; returns the resolved store path (for the trace) and\n * the value it replaced (for the log's \"0 -> 1\" reading). */\n private applyWrite(target: string, value: ScalarValue, entry: CardEntry, handEnv: HandEnv): { path: string; prev?: ScalarValue } {\n const match = /^@([a-z]+)\\.([A-Za-z_][A-Za-z0-9_-]*)$/.exec(target);\n if (!match) throw new Error(`bad change target \"${target}\"`);\n const [, scope, name] = match as unknown as [string, string, string];\n switch (scope) {\n case \"world\": {\n const worldSet = this.internals.worldSet;\n if (!worldSet) throw new Error(`@world.${name} cannot be written: the host bound @world read-only`);\n // The story's own promise, kept HERE and only here, because here is where\n // the story does the writing: the table is consulted before the seam, so\n // an outcome never reaches the bag (which would let a host write past it)\n // nor a bound resolver (which cannot tell the two apart). The host's\n // setProperty is its own path and never asks. Patter's runtime refuses the\n // same write through the shared kernel, so both read one way.\n if (this.internals.worldReadOnly.has(name)) throw new Error(`'@world.${name}' is read-only (writable: false)`);\n const prev = this.internals.worldResolver.get(name);\n worldSet(name, value);\n return { path: `world.${name}`, ...(prev !== undefined ? { prev } : {}) };\n }\n case \"story\": return this.landIn(\"story\", undefined, name, value, `story.${name}`);\n case \"box\": return this.landIn(\"box\", entry.box.id, name, value, `${this.address(\"box\", entry.box.id)}.${name}`);\n case \"deck\": return this.landIn(\"deck\", entry.deck.id, name, value, `${this.address(\"deck\", entry.deck.id)}.${name}`);\n case \"hand\": {\n // Write-back routing (schema 3.6): the composed name remembers its\n // source store; writes to criteria/chosen-tag names are errors.\n const source = handEnv.sources.get(name);\n if (!source) throw new Error(`@hand.${name} is not composed in this ask`);\n if (source.kind === \"criteria\") throw new Error(`@hand.${name} is a chosen tag / criteria name and cannot be written`);\n return this.landIn(source.kind, source.id, name, value, `${this.address(source.kind, source.id)}.${name}`);\n }\n default: {\n // Another engine's game-wide scope (`@patter.x`): the family's shared\n // vocabulary lets a card write it, and the registry keeps that engine's\n // rules (a read-only property is refused). A story write, so no host flag.\n if (this.internals.registry.has(scope)) {\n const prev = this.internals.registry.get(scope, name);\n this.internals.registry.set(scope, name, value);\n return { path: `${scope}.${name}`, ...(prev !== undefined ? { prev } : {}) };\n }\n if (this.internals.bundle.externalScopes?.includes(scope)) {\n throw new Error(`@${scope}.${name} cannot be written: no engine on this registry registered @${scope}`);\n }\n throw new Error(`bad change target scope \"@${scope}\"`);\n }\n }\n }\n\n /** Advance one box's clock (schema 3.4): a turn is one draw-from-stock\n * session for that box, on THIS flow's clock. */\n advanceTurns(boxRef: string, n = 1): void {\n this.assertOpen();\n const box = this.internals.boxesByGameId.get(boxRef) ?? this.internals.boxesById.get(boxRef);\n if (!box) throw new Error(`unknown box \"${boxRef}\"`);\n const next = (this.turnCounts.get(box.id) ?? 0) + n;\n this.turnCounts.set(box.id, next);\n if (this.tracing) this.emit({ type: \"turns\", box: effectiveGameId(box), turn: next }, next);\n }\n\n // --- state access (host surface + test tooling) ---------------------------------\n\n /** Every box, bundle order: identity + this flow's clock (the enumeration\n * surface examiners key their turns sections on; parity member). */\n listBoxes(): BoxView[] {\n this.assertOpen();\n return this.internals.bundle.boxes.map((b) => ({\n id: b.id,\n gameId: effectiveGameId(b),\n ...(b.title !== undefined ? { title: b.title } : {}),\n turn: this.turnCounts.get(b.id) ?? 0,\n }));\n }\n\n /** THIS flow's kernel bags with their store path prefixes (the state\n * logger's mount surface; parity member). The shared bags are the\n * Engine's listBags; the flows are rebuilt by loadGame, so consumers\n * re-enumerate after a load. */\n listBags(): BagMount[] {\n this.assertOpen();\n const mounts: BagMount[] = [{ prefix: \"story\", bag: this.stores.story }];\n for (const kind of [\"box\", \"deck\", \"hand\", \"value\"] as const) {\n for (const [id, bag] of this.stores[kind]) mounts.push({ prefix: addressOf(this.internals, kind, id), bag });\n }\n return mounts;\n }\n\n /** The flow's FULL merged view as examiner rows (the property examiner /\n * editor surface, parity across all runtimes): @world read through the\n * resolver, then per scope the shared values and this flow's own.\n * Bundle order: world, story, then per-box / per-deck / per-hand /\n * per-tag stores. */\n listProperties(): PropertyRow[] {\n this.assertOpen();\n const out: PropertyRow[] = [];\n for (const d of this.internals.bundle.world.properties) {\n const value = this.internals.worldResolver.get(d.name);\n out.push({\n path: `world.${d.name}`, name: d.name, type: d.type,\n value: value ?? d.default, default: d.default,\n ...(d.values !== undefined ? { values: d.values } : {}),\n ...(d.stages !== undefined ? { stages: d.stages } : {}),\n // @world is FOREIGN - a host resolver backs it - so writability is whether that\n // resolver can be written at all AND what the declaration says, which is the\n // shared registry's own rule for a foreign scope (its foreignWritable). The\n // `as PropertyView` cast this replaced was hiding the field's absence: the row\n // type has always required it, and these rows shipped without one.\n //\n // A row is where `writable: false` is meant to SHOW (Reboot.md 10): it tells a\n // state panel this is the game's value, not the story's. It does not stop the\n // panel editing it - the host's setProperty passes `{ host: true }`.\n writable: this.internals.worldSet !== undefined && !this.internals.worldReadOnly.has(d.name),\n });\n }\n const add = (_prefix: string, shared: StateBag | undefined, own: StateBag | undefined): void => {\n for (const bag of [shared, own]) {\n if (bag === undefined) continue;\n for (const row of bag.rows()) out.push(row);\n }\n };\n add(\"story\", this.internals.shared.story, this.stores.story);\n for (const kind of OWNED_SCOPES) {\n const ids = new Set([...this.internals.shared[kind].keys(), ...this.stores[kind].keys()]);\n for (const id of ids) {\n add(addressOf(this.internals, kind, id), this.internals.shared[kind].get(id), this.stores[kind].get(id));\n }\n }\n return out;\n }\n\n /** Read by path: \"world.x\", \"story.gold\", \"value.docks.danger\",\n * \"box.village.heat\", \"deck.wares.n\", \"hand.the-elder.zone\" - the flow's\n * merged view, routed by the declaration's sharing.\n *\n * The owner segment is the entity's GAMEID, the name it is called by\n * everywhere else (4.4). Its internal id is accepted for this release and\n * earns a `diagnostic` naming the address to move to; the next lockstep\n * release refuses it. */\n getProperty(path: string): ScalarValue {\n this.assertOpen();\n const found = this.resolvePath(path);\n const value = found.kind === \"world\" ? this.internals.worldResolver.get(found.name)\n : found.kind === \"scope\" ? this.internals.registry.get(found.token, found.name)\n : found.own?.get(found.name) ?? found.shared?.get(found.name);\n if (value === undefined) throw new Error(`no property at \"${path}\"`);\n return value;\n }\n\n setProperty(path: string, value: ScalarValue): void {\n this.assertOpen();\n const found = this.resolvePath(path);\n if (found.kind === \"world\") {\n if (!this.internals.worldSet) throw new Error(`@world is read-only here: the host bound no write`);\n this.internals.worldSet(found.name, value, true);\n return;\n }\n if (found.kind === \"scope\") {\n this.internals.registry.set(found.token, found.name, value, { host: true });\n return;\n }\n const bag = found.own !== undefined && found.own.get(found.name) !== undefined ? found.own\n : found.shared !== undefined && found.shared.get(found.name) !== undefined ? found.shared\n : undefined;\n if (bag === undefined) throw new Error(`no property at \"${path}\"`);\n // A host write: silent under the firing rule (no subscriber feedback\n // loop), visible to the bag's audit hook, and flagged HOST so a\n // `writable: false` does not refuse the game its own value.\n bag.set(found.name, value, { silent: true, reason: \"host setProperty\", host: true });\n }\n\n private resolvePath(path: string):\n | { kind: \"world\"; name: string }\n | { kind: \"scope\"; token: string; name: string }\n | { kind: \"bag\"; own?: StateBag; shared?: StateBag; name: string } {\n const parts = path.split(\".\");\n if (parts.length === 2 && parts[0] === \"world\") return { kind: \"world\", name: parts[1]! };\n if (parts.length === 2 && parts[0] !== \"story\" && this.internals.registry.has(parts[0]!)) {\n return { kind: \"scope\", token: parts[0]!, name: parts[1]! };\n }\n if (parts.length === 2 && parts[0] === \"story\") {\n return { kind: \"bag\", own: this.stores.story, shared: this.internals.shared.story, name: parts[1]! };\n }\n if (parts.length === 3 && (parts[0] === \"box\" || parts[0] === \"deck\" || parts[0] === \"hand\" || parts[0] === \"value\")) {\n const kind = parts[0] as OwnedScope;\n const [, segment, name] = parts as unknown as [string, string, string];\n const owner = ownerOrThrow(this.internals, kind, segment, name);\n if (owner.legacy && this.tracing) {\n this.emit({ type: \"diagnostic\", where: \"property address\", message: legacyAddressMessage(this.internals, kind, segment, name) });\n }\n const own = this.stores[kind].get(owner.id);\n const shared = this.internals.shared[kind].get(owner.id);\n if (own === undefined && shared === undefined) throw new Error(`no ${kind} store \"${segment}\"`);\n return { kind: \"bag\", ...(own !== undefined ? { own } : {}), ...(shared !== undefined ? { shared } : {}), name };\n }\n throw new Error(`bad property path \"${path}\"`);\n }\n\n // --- persistence (schema 4) -------------------------------------------------\n\n /** @internal - this flow's blob: inside the engine's envelope without its\n * properties (the registry has them), or parked whole by saveFlow. */\n snapshot(withProps: boolean): FlowSave {\n return {\n ...(withProps ? { props: partitionValues(this.stores) } : {}),\n turns: Object.fromEntries(this.turnCounts),\n prng: this.prng.state(),\n cooldowns: this.cooldowns,\n board: Object.fromEntries(this.boardContents),\n playLog: this.playLog,\n };\n }\n\n /** @internal - restore a freshly opened flow from its blob (loadGame).\n * Orphaned keys (deleted entities) drop; new declarations keep defaults. */\n restore(saved: FlowSave): void {\n if (saved.props !== undefined) loadPartition(this.stores, saved.props);\n this.turnCounts = new Map(this.internals.bundle.boxes.map((b) => [b.id, 0]));\n for (const [boxId, turn] of Object.entries(saved.turns ?? {})) {\n if (this.turnCounts.has(boxId)) this.turnCounts.set(boxId, turn);\n }\n this.prng = makePrng(saved.prng);\n this.cooldowns = saved.cooldowns ?? {};\n this.playLog = saved.playLog ?? [];\n this.rebuildPlayIndex();\n this.boardContents = new Map(Object.entries(saved.board ?? {})\n .filter(([handId]) => this.internals.handsById.has(handId))\n .map(([handId, ids]) => [handId, ids.filter((id) => this.internals.cardsById.has(id))]));\n for (const handId of this.internals.handsById.keys()) {\n if (!this.boardContents.has(handId)) this.boardContents.set(handId, []);\n }\n }\n}\n","// The contractual PRNG now lives in @wildwinter/expr, the package both product\n// families already depend on: mulberry32 is a fixed published algorithm that\n// neither family owns, and it existed thirteen times across the two of them.\n//\n// This file stays as a re-export so nothing that imports `./prng.js` has to\n// move, and so the runtime's public surface is unchanged.\n// toUint32 is deliberately NOT re-exported: it is the seed-coercion detail a\n// PORT has to reproduce, not something a game author calls, and widening this\n// runtime's public surface by accident is how a sample stops being the answer\n// to \"how do I use this\". Import it from @wildwinter/expr if you need it.\nexport { makePrng, shuffleInPlace } from \"@wildwinter/expr\";\nexport type { Prng } from \"@wildwinter/expr\";\n","// ---------------------------------------------------------------------------\n// describeBundle - the bundle inspector's runtime half (design/engine-runtimes.md\n// section 2, piece 6).\n//\n// A BUNDLE-level API, deliberately NOT a session method: it answers the\n// integrator's question - \"I dropped a .storyletsc into my project, what may\n// my game code call?\" - from the imported asset alone, with no session, no\n// state and no game running. That makes the boundary rule (design 4) visible:\n// hands are what deal() takes, tag groups + tags are what peek() criteria are\n// drawn from, declared properties are what expressions read and a host may\n// set. Card lists are deliberately absent: cards are the engine's business,\n// counts are the orientation an integrator needs.\n//\n// Everything is in bundle order, so the description is deterministic and two\n// runtimes render the same rows in the same sequence. The property scopes are\n// the static twin of session.listProperties(): the same stores, in the same\n// order, before anything is instantiated (a hand instance carries its\n// template's declarations, exactly as the session's hand bags do).\n// ---------------------------------------------------------------------------\n\nimport { effectiveGameId, isHoleRef } from \"@storylet-studio/model\";\nimport type {\n Box, Bundle, Expression, Hand, PropertyDecl, PropertyType, ScalarValue,\n} from \"@storylet-studio/model\";\n\n/** What bundle this is: the staleness/identity triple plus the schema tag. */\nexport interface BundleIdentity {\n /** The bundle schema tag (\"storylets/bundle@0\"). */\n schema: string;\n /** content.project - the project name a save must agree with. */\n project: string;\n /** content.version - the authored bundle version. */\n version: string;\n /** content.hash - hash32 over the canonical source shards (schema 2.8). */\n hash: string;\n /** \"full\" | \"stripped\": whether authoring metadata (titles) survived. */\n metadata: string;\n}\n\n/** One hole this hand fills from a property rather than with a tag: the hand\n * MOVES when that property is written (design/engine-server.md 4.6). `group`\n * is the tag group's gameId, `from` the reference exactly as authored. */\nexport interface MovableHole {\n group: string;\n from: string;\n}\n\n/** One hand: the deal() surface. `gameId` is the name deal() is called with. */\nexport interface HandSummary {\n gameId: string;\n title?: string;\n /** The owning box's gameId (peek's first argument for the same stock). */\n box: string;\n /** The effective slot cap: the hand's override, else its template's or\n * rule's, else \"unbounded\". */\n slots: number | \"unbounded\";\n /** The hand template's gameId; absent for a standalone (inline-rule) hand. */\n template?: string;\n /**\n * The holes filled from a property, in bundle order. Absent when the hand\n * has none, which is the ordinary case.\n *\n * Reported because it is the one thing about a hand an integrator cannot see\n * from its name: a movable hole means writing that property MOVES the hand,\n * so it is the difference between a fixed kiosk and a performer who walks\n * about. `setProperty` is the whole verb; there is no other.\n */\n movable?: MovableHole[];\n}\n\n/** One tag group and its tags, by gameId: the peek() criteria surface (a\n * criteria entry is `{ [group gameId]: tag gameId }`). */\nexport interface TagGroupSummary {\n gameId: string;\n tags: string[];\n}\n\n/** One box: identity, its ranking policy, its tag groups, and counts. */\nexport interface BoxSummary {\n gameId: string;\n title?: string;\n /** The only per-box ranking policy (Reboot 2.2). */\n ranking: { specificity: boolean };\n /** Present on a TIMED box (design/engine-server.md 4.8): how long one of\n * its turns lasts. An integrator reading a bundle needs it to know which\n * boxes their host must tick, and how often. Absent is the ordinary box. */\n turn?: { seconds: number };\n /** How many cards in this box are DURABLE (design/engine-server.md 4.2):\n * their `redraw: \"never\"` spend outlives the run, and a server has to lift\n * and restore it. A count rather than a list, like every other number here:\n * an integrator needs to know whether this box has any such cards at all,\n * and which ones is the authoring tool's question. Absent when there are\n * none, which is the ordinary bundle. */\n durableCards?: number;\n tagGroups: TagGroupSummary[];\n counts: {\n decks: number;\n cards: number;\n hands: number;\n templates: number;\n tagGroups: number;\n };\n}\n\n/** One declared property: what expressions read and what a host may set. */\nexport interface PropertySummary {\n name: string;\n type: PropertyType;\n default: ScalarValue;\n /** Enum / flags options, where declared. */\n values?: string[];\n /** Declared DURABLE (design/engine-server.md 4.2): the value survives a run,\n * and a server lifts and restores it across one. The engine never reads it;\n * it is reported because it is the difference between a value an integrator\n * may reset and one somebody is going to expect back. Absent = run-scoped. */\n durable?: true;\n purpose?: string;\n}\n\n/** The scope a declaration block belongs to. `tag` declarations compose into\n * @hand for any ask that binds the tag (schema 3.6). */\nexport type PropertyScopeKind = \"world\" | \"story\" | \"box\" | \"deck\" | \"hand\" | \"tag\";\n\n/** One scope's declared properties. `owner` is the owning entity's gameId\n * (empty for world / story); `box` names its box; `group` names a tag's\n * group. */\nexport interface PropertyScopeSummary {\n scope: PropertyScopeKind;\n owner: string;\n box?: string;\n group?: string;\n properties: PropertySummary[];\n}\n\n/**\n * One map the bundle was asked to carry (design/graphical-views.md 2).\n *\n * Counts rather than the geometry itself, which is the same judgement the rest\n * of this file makes: an inspector answers \"what is in here\", and a host that\n * wants the polygons reads `bundle.maps` directly. Reported because a bundle\n * that silently carried a map would fail the promise this API exists for.\n */\nexport interface MapSummary {\n /** The owning box, by gameId. */\n box: string;\n /** The tag group this is a map of, by gameId. */\n group: string;\n zones: number;\n backgrounds: number;\n /** Placed hands standing on this map (design/engine-server.md 4.3): where the\n * kiosks are, in a bundle that carries geometry at all. */\n sites: number;\n}\n\n/** What a bundle offers a host, read from the asset alone. */\nexport interface BundleDescription {\n identity: BundleIdentity;\n /** Orientation, not inventory: no card lists (Reboot 2.1). */\n totals: {\n boxes: number;\n decks: number;\n cards: number;\n hands: number;\n templates: number;\n tagGroups: number;\n };\n boxes: BoxSummary[];\n /** Every hand in the bundle, box by box: the deal() surface. */\n hands: HandSummary[];\n /** world, story, then per box: the box, its decks, its hands, its tags.\n * Scopes that declare nothing are omitted (world and story always show,\n * so their absence reads as \"this bundle declares none\"). */\n properties: PropertyScopeSummary[];\n /** Maps carried as inert payload, when the build asked for them. Empty is\n * the normal state and means the bundle has no geometry in it. */\n maps: MapSummary[];\n}\n\nconst summarise = (decls: PropertyDecl[]): PropertySummary[] =>\n decls.map((d) => ({\n name: d.name,\n type: d.type,\n default: d.default,\n ...(d.values !== undefined ? { values: d.values } : {}),\n ...(d.durable === true ? { durable: true as const } : {}),\n ...(d.purpose !== undefined ? { purpose: d.purpose } : {}),\n }));\n\n/** How many cards in a box are durable: the card's own flag, else its deck's\n * (design/engine-server.md 4.2, the same inheritance `shared` has). */\nconst durableCardCount = (box: Box<Expression>): number =>\n box.decks.reduce((n, deck) =>\n n + deck.cards.filter((card) => (card.durable ?? deck.durable) === true).length, 0);\n\n/** A hand's declared @hand state: a template instance inherits its template's\n * declarations, a standalone hand declares its own (schema 2.6) - the same\n * rule the session's hand bags are built on. */\nconst handDecls = (hand: Hand<Expression>, box: Box<Expression>): PropertyDecl[] => {\n if (hand.template !== undefined) {\n return box.handTemplates.find((t) => t.id === hand.template)?.properties ?? [];\n }\n return hand.properties ?? [];\n};\n\n/** The hand's movable holes, in the bundle's own key order: every `chosen` /\n * rule-binding value that is a property reference rather than a tag (4.6).\n * A group id the bundle does not carry is skipped rather than reported under\n * its raw id: the description speaks gameIds throughout. */\nconst movableHoles = (hand: Hand<Expression>, box: Box<Expression>): MovableHole[] => {\n const filled = hand.template !== undefined ? hand.chosen : hand.rule?.bindings;\n const out: MovableHole[] = [];\n for (const [groupId, value] of Object.entries(filled ?? {})) {\n if (!isHoleRef(value)) continue;\n const group = box.tagGroups.find((g) => g.id === groupId);\n if (group === undefined) continue;\n out.push({ group: effectiveGameId(group), from: value });\n }\n return out;\n};\n\n/** The effective slot cap, resolved the way the session resolves capacity. */\nconst handSlots = (hand: Hand<Expression>, box: Box<Expression>): number | \"unbounded\" => {\n if (hand.slots !== undefined) return hand.slots;\n const declared = hand.template !== undefined\n ? box.handTemplates.find((t) => t.id === hand.template)?.slots\n : hand.rule?.slots;\n return declared === undefined ? \"unbounded\" : declared;\n};\n\n/** Describe a compiled bundle: the callable surface of an imported asset, no\n * session required (design/engine-runtimes.md 2, piece 6). Bundle order\n * throughout; the same shape every runtime returns. */\nexport function describeBundle(bundle: Bundle): BundleDescription {\n const boxes: BoxSummary[] = [];\n const hands: HandSummary[] = [];\n const properties: PropertyScopeSummary[] = [\n { scope: \"world\", owner: \"\", properties: summarise(bundle.world.properties) },\n { scope: \"story\", owner: \"\", properties: summarise(bundle.story.properties) },\n ];\n const totals = { boxes: 0, decks: 0, cards: 0, hands: 0, templates: 0, tagGroups: 0 };\n\n for (const box of bundle.boxes) {\n const boxGameId = effectiveGameId(box);\n const cards = box.decks.reduce((n, deck) => n + deck.cards.length, 0);\n boxes.push({\n gameId: boxGameId,\n ...(box.title !== undefined ? { title: box.title } : {}),\n ranking: { specificity: box.ranking.specificity },\n ...(box.turn !== undefined ? { turn: { seconds: box.turn.seconds } } : {}),\n ...(durableCardCount(box) > 0 ? { durableCards: durableCardCount(box) } : {}),\n tagGroups: box.tagGroups.map((group) => ({\n gameId: effectiveGameId(group),\n tags: group.tags.map((tag) => effectiveGameId(tag)),\n })),\n counts: {\n decks: box.decks.length,\n cards,\n hands: box.hands.length,\n templates: box.handTemplates.length,\n tagGroups: box.tagGroups.length,\n },\n });\n totals.boxes += 1;\n totals.decks += box.decks.length;\n totals.cards += cards;\n totals.hands += box.hands.length;\n totals.templates += box.handTemplates.length;\n totals.tagGroups += box.tagGroups.length;\n\n for (const hand of box.hands) {\n const template = hand.template !== undefined\n ? box.handTemplates.find((t) => t.id === hand.template)\n : undefined;\n const movable = movableHoles(hand, box);\n hands.push({\n gameId: effectiveGameId(hand),\n ...(hand.title !== undefined ? { title: hand.title } : {}),\n box: boxGameId,\n slots: handSlots(hand, box),\n ...(template !== undefined ? { template: effectiveGameId(template) } : {}),\n ...(movable.length > 0 ? { movable } : {}),\n });\n }\n\n // The property scopes, in the session's store order: box, decks, hands,\n // tags. Empty declaration blocks are dropped (nothing to read or set).\n const push = (scope: PropertyScopeKind, owner: string, decls: PropertyDecl[], group?: string): void => {\n if (decls.length === 0) return;\n properties.push({\n scope, owner, box: boxGameId, ...(group !== undefined ? { group } : {}),\n properties: summarise(decls),\n });\n };\n push(\"box\", boxGameId, box.properties);\n for (const deck of box.decks) push(\"deck\", effectiveGameId(deck), deck.properties);\n for (const hand of box.hands) push(\"hand\", effectiveGameId(hand), handDecls(hand, box));\n for (const group of box.tagGroups) {\n for (const tag of group.tags) {\n push(\"tag\", effectiveGameId(tag), tag.properties ?? [], effectiveGameId(group));\n }\n }\n }\n\n return {\n identity: {\n schema: bundle.schema,\n project: bundle.content.project,\n version: bundle.content.version,\n hash: bundle.content.hash,\n metadata: bundle.metadata,\n },\n totals,\n boxes,\n hands,\n properties,\n maps: (bundle.maps ?? []).map((map) => ({\n box: map.box,\n group: map.group,\n zones: map.zones.length,\n backgrounds: map.backgrounds?.length ?? 0,\n sites: map.sites?.length ?? 0,\n })),\n };\n}\n"],"mappings":"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","names":["next","effectiveGameId","isHoleRef"]}
|
|
1
|
+
{"version":3,"sources":["../src/engine.ts","../src/prng.ts","../src/describe.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// The reference runtime: an Engine is the world + flow manager, and ALL play\n// happens on a Flow handle (design/flows.md; the shape is Patter's, adopted\n// deliberately so a host driving both engines holds two objects with the\n// same grammar). The dealing semantics of design/storylets-schema.md\n// section 3 run per flow, implemented exactly and held to the conformance\n// corpus.\n//\n// The flow model, in one place:\n// - an Engine owns the bundle, every lookup built from it, the SHARED\n// property partitions and the @world resolver; a Flow owns its own\n// PRNG, per-box clocks, cooldowns, board, claims, play history and the\n// per-flow property partitions. Flows meet only through shared state.\n// - sharing is a per-property `shared` flag on the declaration (never a\n// scope token): @story defaults shared; box, deck, hand and tag\n// properties default per-flow. Every name is shared XOR per-flow, so a\n// read is a union of two bags and a write routes by name.\n// - every property bag lives in ONE ScopeRegistry per game (the\n// one-registry model): the game hands the engine its registry\n// (EngineOptions.registry) or the engine makes its own and acts as its\n// own game. The shared @story registers under `story`, every other bag\n// under a key starting `storylets/`, which no expression can name.\n// saveGame() carries what is NOT a property, plus the registry's values\n// only when the engine made the registry itself.\n// - @world is the game's: a resolver it binds (EngineOptions.world, never\n// saved), a scope it registers in its registry, or, for a standalone\n// engine, a self-backed bag the registry stores and saves.\n// - there is no default flow and no ambient current flow: openFlow(id) is\n// the only way in, an existing id is REPLACED (the old flow closes),\n// and a closed flow's handle is INERT - every verb throws (Patter's\n// stale-handle rule).\n// - engine.getProperty serves world.* and shared refs only; a ref that\n// resolves per-flow throws, naming the fix (Patter's teaching rule).\n// - the PROJECT MAP (design/project-map-contract.md 3) is one zone group\n// above the boxes, in `bundle.map.group` and in no box's `tagGroups`. A\n// box that opts in (`usesMap`) sees its name beside its own groups', so\n// its hands bind zones and its cards are tagged with them by id exactly\n// as with a box group. Each zone is ONE value bag, keyed by the tag's id\n// like any tag's, so a zone property is one value whichever box's hand\n// is dealt to it; the `shared` flag still decides per-flow against one\n// for the engine. What the boxes on a map do NOT share: a hand deals only\n// from its own box's decks, and play history stays the asking box's\n// (D7). A bundle that breaks the map's rules is refused at construction\n// (3.8) rather than half-played.\n//\n// Key dealing contracts, unchanged from round 2 (all per flow now):\n// - two verbs: deal(hand) claims, peek(box, criteria) just looks; you can\n// never play a card you only peeked (3.1, look/use rule)\n// - availability order: deck gate -> cooldown -> tags -> hand condition ->\n// card condition -> claims (3.1)\n// - claims are physical WITHIN a flow: a card sits in at most `copies`\n// hands of that flow's board at once, at most once in any one hand; the\n// ledger is derived from the board contents (3.5)\n// - a SHARED card (its deck's flag, or its own overriding it) is scarce\n// across flows too: at most `sharedCopies` hands anywhere, counted over\n// every live flow's board, and a shared `redraw: \"never\"` is spent for\n// everyone the first time anyone plays it. A finite redraw deliberately\n// stays per flow - a cooldown is an absolute turn of a per-flow clock, so\n// there is nothing shared to compare it against (design/shared-scarcity.md)\n// - the reserved home group inverts the wildcard: a homed card is\n// available only to an ask binding its home (2.4)\n// - ranking: priority desc -> specificity desc (box toggle) -> seeded\n// shuffle of each maximal tie run (3.2)\n// - one PRNG per flow: expression random(), tie shuffles and the batch\n// deal's hand-order shuffle all advance it; state lives in the save (3.3)\n// - each box has its own turn counter PER FLOW; cooldowns are absolute\n// next-eligible turns of the card's box's clock, set at play time from\n// the post-advance turn; \"never\" is MAX_SAFE_INTEGER, not Infinity (3.4)\n// - @hand composes bound-tag props -> hand props -> chosen tags/criteria\n// (by group name), later shadowing earlier; writes route back to their\n// source; criteria names cannot be written (3.6)\n// - outcome availability is never snapshotted: outcomes() and play()\n// evaluate gates against current state (3.1, 3.7)\n// - a trace event fires after the state it reports has landed, so a\n// handler reading the flow inside it sees the effect (the Live Link's\n// board snapshot depends on this; the shared fixture pins it)\n// ---------------------------------------------------------------------------\n\nimport { deserialiseAst, evaluate } from \"@wildwinter/expr\";\nimport type { EvalContext, ExprNode, ScalarValue, ScopeResolver } from \"@wildwinter/expr\";\nimport { matchedSpecificity } from \"@wildwinter/expr-specificity\";\nimport { storyletsDialect, NEVER_PLAYED } from \"@storylet-studio/dialect\";\n\n/** The play-history indexes' key for one (box, group, tag) triple.\n *\n * The BOX is in it because play history is box-specific (design/project-map-\n * contract.md 3.7, D7, ruled 2026-10-01): `count_played_in` asks about the\n * asking box's own plays. A box group was already box-unique, so its key never\n * needed the box; a project-map zone is one tag every opted-in box tags its\n * cards with, and without the box a play of a newspaper at the quay in one box\n * would count as an encounter at the quay in another.\n *\n * A UNIT SEPARATOR (U+001F) joins them: ids are letters, digits and\n * underscores, so a control character cannot occur in one and two different\n * triples can never collide into one key the way a \".\" or \":\" join could. NUL\n * would say the same thing and was the first choice, but GDScript will not\n * carry one in a string - it substitutes U+FFFD and warns on every parse - and\n * the four runtimes keep the same spelling. */\nconst tagKey = (boxId: string, groupId: string, tagId: string): string =>\n `${boxId}\\u001f${groupId}\\u001f${tagId}`;\n\nimport type { StoryletsHost } from \"@storylet-studio/dialect\";\nimport {\n BUNDLE_SCHEMAS, PLACE_GROUP, allTagGroups, ambiguousValueAddressMessage, effectiveGameId, groupsOfBox,\n isHoleRef, parseHoleRef, valueAddresses, zoneQualifiedValueAddressMessage,\n} from \"@storylet-studio/model\";\nimport type {\n Box, Bundle, BundleContent, Card, Deck, Expression, FlowSave, Hand, HandTemplate,\n LoadEviction, LoadProperty, LoadReport, PlayRecord, PropertyBag, PropertyDecl, PropsPartition,\n SaveEnvelope, SaveEnvelopeV1, Tag, TagGroup,\n} from \"@storylet-studio/model\";\nimport { SAVE_SCHEMA, SAVE_SCHEMA_V1 } from \"@storylet-studio/model\";\nimport { PropertyBag as StateBag, ScopeRegistry } from \"@wildwinter/scoperegistry\";\nimport type { PropertyRow, ScopeDeclaration } from \"@wildwinter/scoperegistry\";\nimport { makePrng, shuffleInPlace } from \"./prng.js\";\nimport type { Prng } from \"./prng.js\";\n\nexport interface EngineOptions {\n /** Default seed for each flow's PRNG; override per flow in openFlow\n * (cross-runtime determinism, schema 3.3). Default 0. */\n seed?: number;\n /** Retain each flow's event log for introspection - the game-engine seam\n * (schema 5): every trace event, sequence-stamped and turn-stamped where\n * the event has a box context. `true` keeps the default 1000 entries\n * (oldest dropped first). Off by default; subscribeTrace stays the\n * zero-retention stream. */\n log?: boolean | { cap?: number };\n /**\n * The host's resolver for @world - the values the game owns and the\n * story reads (and, where `set` is offered, writes). Engine-level, shared\n * by all flows, never saved: the game keeps these values. Omit it and a\n * standalone engine self-backs @world from the declared defaults, as a\n * property its registry stores and saves. A game running several engines\n * registers @world in its registry itself instead.\n */\n world?: ScopeResolver;\n /**\n * The game's registry: ONE per game, holding every engine's properties\n * except those the game keeps itself, saved once. Given one, the engine\n * registers its own scopes in it (@story under `story`, every other bag\n * under a key starting `storylets/`, and @world if `world` is passed),\n * reads every other scope from it, and `saveGame()` leaves the property\n * values to the game. @world is then the game's to register: owned if the\n * registry should store it, foreign if the game keeps it. Omit it and the\n * engine makes its own registry and acts as its own game: it self-backs\n * @world, and `saveGame()` carries the registry's values too.\n */\n registry?: ScopeRegistry;\n /**\n * Diagnostics hook (opt-in, dev tooling only): fired when `openFlow` REPLACES\n * a flow that still had cards dealt, with the flow id and how many. The\n * behaviour is unchanged - replacing is deliberate and the same in Patter -\n * this only makes it observable, because the case it catches is a host\n * calling `openFlow` straight after `loadGame` to \"re-take\" its handle and\n * silently discarding the hand the save just restored (`getFlow` is the\n * call). Zero cost when unset; leave it unset in shipped games.\n */\n onReplacedFlow?: (id: string, dealt: number) => void;\n}\n\nexport interface OpenFlowOptions {\n /** Seed for this flow's PRNG (defaults to the engine's `seed`). */\n seed?: number;\n /**\n * Open this flow AS IT WAS: a blob from `saveFlow`, applied to the freshly\n * opened (or replaced) flow before the handle comes back\n * (design/engine-server.md 4.1).\n *\n * An option on `openFlow` rather than a `Flow.restore` verb on purpose:\n * restoring INTO a running flow is the trap hosts keep falling into\n * (openFlow REPLACES), and \"open this flow as it was\" is one act. Drift is\n * tolerated exactly as `loadGame` tolerates it, with one addition, because\n * this restore lands in a LIVE engine: a shared card whose world copies are\n * all held by the OTHER open flows is not put back, and is reported as\n * `claimed-elsewhere`. Ask `previewFlowRestore` first to see that coming.\n */\n restore?: FlowSave;\n /** Handed the `restore`'s LoadReport as it happens - the same report\n * `previewFlowRestore` returns for the same blob. Ignored without\n * `restore`; the report has nowhere else to go, since `openFlow` returns\n * the handle. */\n onRestoreReport?: (report: LoadReport) => void;\n}\n\n/** A card view in a dealt hand or a peeked list. Carries NO outcome\n * availability - ask `outcomes()` for current truth (schema 5). */\nexport interface DealtCard {\n id: string;\n gameId: string;\n title?: string;\n purpose?: string;\n fields?: Record<string, ScalarValue>;\n}\n\nexport interface OutcomeView {\n id: string;\n gameId: string;\n title?: string;\n purpose?: string;\n /** The outcome's fields, exactly as the bundle carries them: game data\n * declared by the box's `outcomeFields`, never read by the engine. */\n fields?: Record<string, ScalarValue>;\n /** Evaluated against CURRENT state at the moment of the ask. */\n available: boolean;\n}\n\n/** What a peek returns: the top of the stock, looked at and put back.\n * The engine has no pick policy (Reboot 2.1). */\nexport interface RankedList {\n box: string;\n cards: DealtCard[];\n}\n\nexport interface PlayOptions {\n /** Turn advance override; default settings.playAdvancesTurns, or 0 when the\n * card's box is timed (design/engine-server.md 4.8). */\n advanceTurns?: number;\n}\n\n// --- the trace (schema 5): the deal/play log for tooling ----------------------\n\n/** Why a card did or did not make an ask, in availability order (schema 3.1). */\nexport type TraceVerdict =\n | \"dealt\" // in the hand / the returned list\n | \"capped\" // eligible, ranked below the size cap\n | \"cooldown\" // schema 3.1 step 1\n | \"deck-gate\" // step 2\n | \"tags\" // step 3 (incl. the home group's inverted default)\n | \"condition\" // steps 4-5 (a failing or erroring condition)\n | \"priority\" // a priority expression errored or was not a number\n | \"claimed\" // step 6: no free copy on YOUR board\n | \"claimed-elsewhere\" // step 6: another flow holds the world's copies\n | \"taken\"; // a shared redraw:never was spent, by anyone, for everyone\n\n/** One event on the deal/play log - \"why did Ambush at the ford get dealt\n * here?\" is answered by the ask event's per-card verdicts and keys. The\n * verb is the event type, so a peek is distinguishable from a deal when\n * reading a run back.\n *\n * IDENTITY IS BY GAMEID throughout (design/engine-server.md 4.4). It was\n * mixed until then: `deal.hand` and `peek.box` were gameIds while\n * `evict.hand`, `play.card` and every `cards[].id` were internal ids, so\n * every consumer outside the engine - the Board, the four examiners, the\n * Live Link, a wire a kiosk reads - mapped one to the other itself. */\nexport type TraceEvent =\n | {\n type: \"deal\";\n /** Hand gameId. */\n hand: string;\n /** `id` is the card's GAMEID (design/engine-server.md 4.4). */\n cards: { id: string; verdict: TraceVerdict; priority?: number; specificity?: number }[];\n }\n | {\n type: \"peek\";\n /** Box gameId. */\n box: string;\n criteria: Record<string, string>;\n /** `id` is the card's GAMEID (design/engine-server.md 4.4). */\n cards: { id: string; verdict: TraceVerdict; priority?: number; specificity?: number }[];\n }\n /** Hand and card gameIds. A card the build no longer has (`vanished`) has\n * no gameId left and is named by the id the board carried. */\n | { type: \"evict\"; hand: string; card: string; reason: TraceVerdict | \"hand-condition\" | \"vanished\" }\n /** Card and outcome gameIds; `outcome` is \"\" for a card with no outcomes,\n * played with none. */\n | { type: \"play\"; card: string; outcome: string; turn: number }\n /** One landed outcome change; `path` is the resolved store location, in the\n * address grammar `getProperty` takes - the owner segment is its gameId (a\n * routed @hand write shows where it actually went, schema 3.6). `prev`\n * is the value it replaced, so a log can read \"0 -> 1\". */\n | { type: \"write\"; target: string; path: string; value: ScalarValue; prev?: ScalarValue }\n /** An explicit clock advance via advanceTurns (schema 3.4); `turn` is the\n * box's new value. Plays stamp their own turn on the play event. */\n | { type: \"turns\"; box: string; turn: number }\n /** An expression eval error: never a silent pass (schema 3.1), always a\n * visible diagnostic. */\n | { type: \"diagnostic\"; where: string; message: string };\n\nexport type TraceHandler = (event: TraceEvent) => void;\n/** The engine-level tap: every flow's events, tagged with the flow id -\n * the tools' one stream. */\nexport type EngineTraceHandler = (flow: string, event: TraceEvent) => void;\n\n/** A retained log entry: the trace event plus its place in flow time.\n * `seq` orders the whole flow (monotonic; survives clearLog). `turn` is\n * the clock of the box the event happened in when it fired (peek: the box;\n * deal/evict: the hand's box; play and its writes: the played card's box,\n * stamped together with the play's own turn). Diagnostics carry no turn. */\nexport type LogEntry = TraceEvent & { seq: number; turn?: number };\n\n/** One entry on the ENGINE's log: the same event, plus the flow it happened\n * in. A run is several flows over shared state, so \"what happened in this\n * run\" is only answerable in one ordered stream, and only if each line says\n * who. The flow's own log stays flow-local and unchanged. */\nexport type EngineLogEntry = LogEntry & { flow: string };\n\n// --- internals ---------------------------------------------------------------\n\ninterface CardEntry {\n card: Card<Expression>;\n deck: Deck<Expression>;\n box: Box<Expression>;\n}\n\n/** Is this card scarce across flows (design/shared-scarcity.md)? The deck says\n * what the pile is for and the card may override it, the same inheritance a\n * property has with its scope default. Hoist the deck's flag out of a card\n * loop and pass the answer down: the ask runs this per card per deal. */\nconst cardIsShared = (card: Card<Expression>, deckShared: boolean): boolean =>\n card.shared ?? deckShared;\n\n/** How many hands ACROSS EVERY FLOW may hold this at once. Defaults to\n * `copies`, so the common case writes one number and only \"five in the world,\n * one to a customer\" needs both. Meaningless on an unshared card, and the\n * compiler warns when one sets it. */\nconst sharedCap = (card: Card<Expression>): number => card.sharedCopies ?? card.copies ?? 1;\n\ntype HandSource = { kind: \"value\"; id: string } | { kind: \"hand\"; id: string } | { kind: \"criteria\" };\n\n/** The composed @hand for one ask: the read bag, plus where each name\n * routes on write (schema 3.6). */\ninterface HandEnv {\n bag: PropertyBag;\n sources: Map<string, HandSource>;\n /** tag group id -> bound tag id (home included, its \"tag\" a hand id). */\n boundTags: Map<string, string>;\n}\n\n/** One ask, resolved: a deal (hand present, condition from its template or\n * rule) or a peek (criteria only, no condition - schema 3.1). */\ninterface AskDescriptor {\n box: Box<Expression>;\n hand?: Hand<Expression>;\n condition?: Expression;\n /** tag group id -> tag id, everything the ask binds (fixed + chosen +\n * criteria; for deals also home -> the hand's own id). */\n boundTags: Map<string, string>;\n /** Chosen tags / criteria surfaced into @hand by group gameId, the tag's\n * gameId as the value (schema 3.6). */\n askNames: Record<string, string>;\n}\n\n/** The owner label on everything this engine registers: named in a clash\n * error and carried on the registry's examiner rows. */\nconst OWNER = \"Storylet Engine\";\n\n/** Identity: storylets property names are case-significant as authored. */\nconst identity = (n: string): string => n;\n\n/** The registry keys this engine's bags live under. An id is escaped (`%` and\n * `/`) so no two keys can meet. Every runtime writes the same keys: they are\n * in the save. Owners are keyed by INTERNAL id, as the save always was, so a\n * save survives a rename. */\nconst esc = (id: string): string => id.replace(/%/g, \"%25\").replace(/\\//g, \"%2F\");\nconst unesc = (id: string): string => id.replace(/%2F/g, \"/\").replace(/%25/g, \"%\");\nconst sharedKey = (kind: OwnedScope, id: string): string => `storylets/${kind}/${esc(id)}`;\nconst flowPrefix = (flowId: string): string => `storylets/flow/${esc(flowId)}/`;\nconst flowKey = (flowId: string, kind: FlaggedScope, id?: string): string =>\n kind === \"story\" ? `${flowPrefix(flowId)}story` : `${flowPrefix(flowId)}${kind}/${esc(id!)}`;\n\n/** A registry section's values: registry key -> name -> value. */\ntype Sections = Record<string, PropertyBag>;\n\nconst emptyPartitionValues = (): PropsPartition => ({ story: {}, box: {}, deck: {}, hand: {}, value: {} });\n\n/** Sort a registry save's sections back into partitions, for the load walk:\n * the shared ones, each flow's (only the flows the save restores; the rest\n * are dropped), and everything that is not this engine's, passed through. */\nfunction partitionsFromSections(sections: Sections, flowIds: Set<string>): {\n shared: PropsPartition; flows: Map<string, PropsPartition>; rest: Sections;\n} {\n const shared = emptyPartitionValues();\n const flows = new Map<string, PropsPartition>();\n const rest: Sections = {};\n const flowOf = (escaped: string): PropsPartition | undefined => {\n const id = unesc(escaped);\n if (!flowIds.has(id)) return undefined;\n let p = flows.get(id);\n if (!p) { p = emptyPartitionValues(); flows.set(id, p); }\n return p;\n };\n for (const [key, values] of Object.entries(sections)) {\n let m: RegExpExecArray | null;\n if (key === \"story\") shared.story = values;\n else if ((m = /^storylets\\/(box|deck|hand|value)\\/([^/]+)$/.exec(key))) shared[m[1] as OwnedScope][unesc(m[2]!)] = values;\n else if ((m = /^storylets\\/flow\\/([^/]+)\\/story$/.exec(key))) { const p = flowOf(m[1]!); if (p) p.story = values; }\n else if ((m = /^storylets\\/flow\\/([^/]+)\\/(box|deck|hand|value)\\/([^/]+)$/.exec(key))) {\n const p = flowOf(m[1]!); if (p) p[m[2] as OwnedScope][unesc(m[3]!)] = values;\n } else if (!key.startsWith(\"storylets/\")) rest[key] = values;\n }\n return { shared, flows, rest };\n}\n\n/** A cleaned partition as registry sections, keyed the way its bags register.\n * Empty sections are left out: they would load nothing, and a section for a\n * bag that never registers would wait in the registry for ever. */\nfunction sectionsOf(p: PropsPartition, keyOf: (kind: FlaggedScope, id?: string) => string, out: Sections): void {\n if (Object.keys(p.story).length > 0) out[keyOf(\"story\")] = p.story;\n for (const kind of [\"box\", \"deck\", \"hand\", \"value\"] as const) {\n for (const [id, values] of Object.entries(p[kind])) if (Object.keys(values).length > 0) out[keyOf(kind, id)] = values;\n }\n}\n\n// Stores are shared-kernel bags (@wildwinter/scoperegistry, the properties\n// implementer Patter shares): identity normalisation because storylets\n// property names are case-significant as authored.\n// `pathPrefix` carries its own separator, so a bag composes its rows' addresses itself\n// (`story.gold`, `deck.tavern.drawn`) instead of every caller pasting a prefix onto a row.\nconst bagFromDecls = (decls: PropertyDecl[], pathPrefix: string): StateBag =>\n new StateBag(decls, { normalise: (n) => n, pathPrefix });\n\n// Truthiness for a bare condition. Booleans and numbers as you would expect;\n// a string passes when non-empty and a flag list when non-empty, matching\n// JavaScript's own coercion for those two.\n//\n// Until 2026-09-01 this admitted ONLY booleans and numbers, and Patterplay's\n// `truthy` admitted strings and lists as well. That was drift from writing the\n// two engines at different times, not a considered difference: the two share a\n// property registry, so the same value read from the same registry answered a\n// condition differently depending on which engine asked. expr-specificity calls\n// truthiness host-bound, and it is, but \"host-bound\" is licence for a host to\n// choose, not licence for two hosts in one family to disagree by accident.\nfunction conditionPasses(v: ScalarValue): boolean {\n if (typeof v === \"boolean\") return v;\n if (typeof v === \"number\") return v !== 0;\n if (typeof v === \"string\") return v !== \"\";\n return v.length > 0; // string[] (flags)\n}\n\n// PropertyView is gone. It was the shared PropertyRow plus a `path`, and `path` moved onto\n// that row on 2026-09-02 - so the name was a synonym, and a synonym for a shared type is how\n// the two families drifted in the first place: the same row called PropertyView here,\n// ScopePropertyRow next to it, PropertyRow in the kernel. listProperties() returns PropertyRow.\n\n/** One kernel bag with its store path prefix (story / box.<gameId> / deck.<gameId>\n * / hand.<gameId> / value.<gameId>): the state logger's mount surface\n * (design/engine-runtimes.md 3.4 - the logger builds on the PropertyBag\n * audit hook, so it needs the bags themselves, not just their rows).\n * The Engine lists the shared bags, a Flow its own; the @world container\n * is the host's bag and the host mounts it itself. loadGame() replaces\n * every bag, so re-enumerate after a load. */\nexport interface BagMount {\n prefix: string;\n bag: StateBag;\n}\n\n/** One box on the enumeration surface (examiners, hosts): identity plus\n * its clock (per flow). */\nexport interface BoxView {\n id: string;\n gameId: string;\n title?: string;\n turn: number;\n}\n\n/** The sharing default per scope (design/flows.md, the old system's rule):\n * @story is the playthrough family's globals, shared; the narrower scopes\n * are geographic, per-flow, so \"this flow's danger in the docks\" stays\n * expressible. A declaration's `shared` flag overrides. */\nconst SCOPE_DEFAULT_SHARED = { story: true, box: false, deck: false, hand: false, value: false } as const;\ntype FlaggedScope = keyof typeof SCOPE_DEFAULT_SHARED;\n\nconst isShared = (scope: FlaggedScope, d: PropertyDecl): boolean => d.shared ?? SCOPE_DEFAULT_SHARED[scope];\nconst sharedHalf = (scope: FlaggedScope, decls: PropertyDecl[]): PropertyDecl[] =>\n decls.filter((d) => isShared(scope, d));\nconst flowHalf = (scope: FlaggedScope, decls: PropertyDecl[]): PropertyDecl[] =>\n decls.filter((d) => !isShared(scope, d));\n\n/** One side's five declaration lists, keyed by owner id where the scope has\n * owners. The bags are built from these; so is the load report's answer to\n * \"what does this build declare that the save does not carry\". */\ninterface DeclSet {\n story: PropertyDecl[];\n box: Map<string, PropertyDecl[]>;\n deck: Map<string, PropertyDecl[]>;\n hand: Map<string, PropertyDecl[]>;\n value: Map<string, PropertyDecl[]>;\n}\n\n/** The four owned property scopes: the ones whose address carries an owner\n * segment. `story` has no owner and `world` is the host's. */\ntype OwnedScope = \"box\" | \"deck\" | \"hand\" | \"value\";\nconst OWNED_SCOPES = [\"box\", \"deck\", \"hand\", \"value\"] as const;\n\n/** The owner segment of a property address, both ways round\n * (design/engine-server.md 4.4).\n *\n * `gameId` is the segment the ADDRESS uses; `id` is the internal id everything\n * inside the engine is keyed by - the bags, the save envelope, the ladders.\n * Both maps are built in bundle order and a repeated gameId does NOT\n * overwrite the first.\n *\n * Box, deck, hand and card gameIds are unique bundle-wide, so for three of the\n * four scopes the segment is simply the gameId. A TAG's is unique only within\n * its group, and a group's only within its box, so two boxes may each name a\n * tag \"docks\": the value scope's segment is box-qualified,\n * `value.<boxGameId>/<tagGameId>.<name>`, wherever a gameId repeats, and the\n * short form is REFUSED there rather than resolved to the first in bundle\n * order. `valueAddresses` in the model is the one definition of that rule -\n * the Board draws these addresses from the bundle while the engine builds them\n * from this index, and the two have to agree - and `repeated` is what it\n * found, so a refusal can name the candidates.\n *\n * Two GROUPS in one box naming the same tag is the case the box qualifier\n * cannot separate, and it is closing at the source rather than here (question\n * 16, ruled 2026-09-06): the compiler warns that a tag gameId must be unique\n * within its box, and refuses it from the next release. Until then the first\n * in bundle order answers, as it always did.\n */\ninterface OwnerIndex {\n gameId: Map<string, string>; // internal id -> owner segment\n id: Map<string, string>; // owner segment -> internal id (first in bundle order wins)\n repeated: Map<string, string[]>; // an ambiguous short form -> the qualified candidates\n zoneQualified: Map<string, string>; // \"<box>/<zone>\" -> \"<zone>\", refused (value scope only)\n}\n\ntype OwnerIndexes = Record<OwnedScope, OwnerIndex>;\n\nconst emptyOwnerIndex = (): OwnerIndex =>\n ({ gameId: new Map(), id: new Map(), repeated: new Map(), zoneQualified: new Map() });\nconst emptyOwnerIndexes = (): OwnerIndexes => ({\n box: emptyOwnerIndex(), deck: emptyOwnerIndex(), hand: emptyOwnerIndex(), value: emptyOwnerIndex(),\n});\n\nconst indexOwner = (index: OwnerIndex, entity: { id: string; gameId?: string; title?: string }): void => {\n const gameId = effectiveGameId(entity);\n index.gameId.set(entity.id, gameId);\n if (!index.id.has(gameId)) index.id.set(gameId, entity.id);\n};\n\n/** The value scope's index, whole: the segments to print, the segments to\n * accept, the gameIds that need qualifying, and the box-qualified forms of\n * the project map's zones, which are refused. Built from the bundle rather\n * than tag by tag, because whether a tag's own gameId is enough is a question\n * about the OTHER boxes. */\nconst indexValueOwners = (index: OwnerIndex, bundle: Bundle): void => {\n const addresses = valueAddresses(bundle);\n for (const [id, segment] of addresses.print) index.gameId.set(id, segment);\n for (const [segment, id] of addresses.accept) index.id.set(segment, id);\n for (const [gameId, candidates] of addresses.repeated) index.repeated.set(gameId, candidates);\n for (const [segment, zone] of addresses.zoneQualified) index.zoneQualified.set(segment, zone);\n};\n\n/** One side's five stores (shared on the engine, per-flow on each flow). */\ninterface Partition {\n story: StateBag;\n box: Map<string, StateBag>;\n deck: Map<string, StateBag>;\n hand: Map<string, StateBag>;\n value: Map<string, StateBag>;\n}\n\ntype PartitionKind = keyof Partition;\n\n/** Everything a Flow shares with its Engine: the bundle-derived lookups\n * (immutable), the shared stores (replaced wholesale by loadGame/reset),\n * and the seams. One object, held by both classes - the two are one\n * machine in two lifetimes. */\ninterface Internals {\n bundle: Bundle;\n logCap?: number;\n cardsById: Map<string, CardEntry>;\n cardsByGameId: Map<string, CardEntry>;\n boxesByGameId: Map<string, Box<Expression>>;\n boxesById: Map<string, Box<Expression>>;\n handsById: Map<string, { hand: Hand<Expression>; box: Box<Expression> }>;\n handsByGameId: Map<string, { hand: Hand<Expression>; box: Box<Expression> }>;\n /** The owner segment of a property address, both ways round (4.4). */\n owners: OwnerIndexes;\n templatesById: Map<string, HandTemplate<Expression>>;\n /** Every group by internal id. `box` is absent for the project map's group,\n * which belongs to no box. */\n groupsById: Map<string, { group: TagGroup; box?: Box<Expression> }>;\n requiredGroups: Set<string>;\n nodeCache: WeakMap<Expression, ExprNode>;\n ladders: {\n world: Map<string, readonly string[]>;\n story: Map<string, readonly string[]>;\n box: Map<string, Map<string, readonly string[]>>;\n deck: Map<string, Map<string, readonly string[]>>;\n value: Map<string, Map<string, readonly string[]>>;\n hand: Map<string, Map<string, readonly string[]>>;\n };\n hasQualities: boolean;\n /** Does ANY deck or card in the bundle opt into shared scarcity? False for\n * the overwhelming majority of projects, and when it is false the two\n * claim-ledger walks in dealing are skipped entirely. Same idea as\n * `hasQualities` above: a bundle that does not use a feature must not pay\n * for it. */\n hasShared: boolean;\n /** The per-flow halves of every declaration list, precomputed once: each\n * new flow builds its bags from these. */\n flowDecls: DeclSet;\n /** The shared halves, the same way. Not used to build anything - the shared\n * bags are built straight from the bundle - but a load report has to say\n * what the shared side WOULD hold without building a bag, which is what\n * makes previewLoad pure. */\n sharedDecls: DeclSet;\n /** The shared stores, registered in the registry for the engine's life.\n * Reseeded in place by reset and by a load that carries values. */\n shared: Partition;\n /** The game's one registry (or the engine's own, when it is standalone). */\n registry: ScopeRegistry;\n /** True when the engine made the registry: `saveGame()` then carries its values. */\n ownsRegistry: boolean;\n /** True when the engine self-backed @world (standalone, no resolver bound). */\n selfWorld: boolean;\n /** Every OTHER scope in the registry, as an eval context sees it (instance\n * keys left out), rebuilt only when the registry's set of scopes moves. */\n registryView: () => { scopes: EvalContext[\"scopes\"]; qualities: EvalContext[\"qualities\"] };\n /** @world, read through the registry by name (the scope's own normalisation),\n * so a @world the game registered folded to lower case still answers the\n * names as authored. */\n worldResolver: ScopeResolver;\n /** The @world WRITE seam. `host` says the caller is the GAME's own surface -\n * setProperty, the coverage harness, the CLI's --set - which the shared\n * kernel lets past a `writable: false` (scoperegistry 0.6.0): that flag is\n * the story's promise, not the game's. The story's refusal is the\n * worldReadOnly table below, consulted before this seam is reached. A BOUND\n * resolver is opaque - it takes a name and a value and keeps whatever rule\n * the game has - so the flag only ever reaches the self-backed bag.\n * Undefined when @world cannot be written at all (a resolver bound with no\n * `set`). */\n worldSet?: (name: string, value: ScalarValue, host?: boolean) => void;\n /** @world names declared `writable: false`: the story's promise, kept at\n * runtime as the compiler keeps it at publish (Reboot.md 10). */\n worldReadOnly: Set<string>;\n /** `turn` is the box clock the event happened on, where the caller knows it\n * - the same stamp the flow's own log carries. Unity and Unreal passed it\n * from the start; JS and Godot dropped it, so their examiners printed \"[-]\"\n * on every deal, peek, evict and write line while the other two printed the\n * real turn. Four runtimes, two different run logs (2026-08-29). */\n emitEngine: (flow: string, event: TraceEvent, turn?: number) => void;\n engineTracing: () => boolean;\n}\n\nconst handDeclsOf = (internals: Internals, hand: Hand<Expression>): PropertyDecl[] => {\n if (hand.template !== undefined) {\n return internals.templatesById.get(hand.template)?.properties\n ?? internals.bundle.boxes.flatMap((b) => b.handTemplates).find((t) => t.id === hand.template)?.properties\n ?? [];\n }\n return hand.properties ?? [];\n};\n\n/**\n * One owned property's ADDRESS, owner segment and all: `box.village.mood`.\n *\n * The stores, the save envelope and the ladders stay keyed by internal id -\n * a save must survive a rename, which is the whole reason ids exist - so this\n * is the one place the two vocabularies meet, and it is a formatter, never a\n * lookup key. An owner the build no longer has (a save that outlived an edit)\n * keeps the id it arrived with: there is no gameId left to give it, which is\n * the rule a load report's evictions have always used.\n */\nconst addressOf = (internals: Internals, kind: OwnedScope, id: string): string =>\n `${kind}.${internals.owners[kind].gameId.get(id) ?? id}`;\n\n/**\n * Resolve a property address's owner segment to the internal id the stores are\n * keyed by. `legacy` says the caller used the pre-4.4 form - an internal id\n * where a gameId belongs - which resolves for THIS release and earns a\n * diagnostic; the next lockstep release refuses it, in every scope including\n * `value`, which had the one reprieve until it gained an address of its own.\n * `ambiguous` is a short-form value address two boxes answer to: the caller\n * REFUSES it, listing those candidates. Undefined when the segment names no\n * owner at all, which is the caller's \"no <kind> store\" error.\n */\ntype OwnerLookup = { id: string; legacy: boolean } | { ambiguous: string[] } | { zone: string };\n\nconst resolveOwner = (internals: Internals, kind: OwnedScope, segment: string): OwnerLookup | undefined => {\n // Checked before the lookup, because the short form is deliberately NOT in\n // the accept map when it is ambiguous: silently picking the first tag in\n // bundle order is the bug this removes.\n const candidates = internals.owners[kind].repeated.get(segment);\n if (candidates !== undefined) return { ambiguous: candidates };\n // A box-qualified form of a project-map zone: never accepted, because the\n // zone belongs to no box (design/project-map-contract.md 3.4).\n const zone = internals.owners[kind].zoneQualified.get(segment);\n if (zone !== undefined) return { zone };\n const byGameId = internals.owners[kind].id.get(segment);\n if (byGameId !== undefined) return { id: byGameId, legacy: false };\n // A gameId that equals its id took the branch above, so anything reaching\n // here and known as an id is genuinely the old spelling.\n if (internals.owners[kind].gameId.has(segment)) return { id: segment, legacy: true };\n return undefined;\n};\n\n/** Resolve or throw: the two refusals every property address shares, in one\n * place, so the engine's surface and a flow's answer alike. */\nconst ownerOrThrow = (internals: Internals, kind: OwnedScope, segment: string, name: string): { id: string; legacy: boolean } => {\n const owner = resolveOwner(internals, kind, segment);\n if (owner === undefined) throw new Error(`no ${kind} store \"${segment}\"`);\n if (\"ambiguous\" in owner) throw new Error(ambiguousValueAddressMessage(segment, name, owner.ambiguous));\n if (\"zone\" in owner) throw new Error(zoneQualifiedValueAddressMessage(segment, owner.zone, name));\n return owner;\n};\n\n/** What a legacy address is told. It NAMES the address to move to, because\n * \"that form is deprecated\" without the replacement leaves a host grepping a\n * bundle for ids it never chose. */\nconst legacyAddressMessage = (internals: Internals, kind: OwnedScope, segment: string, name: string): string =>\n `\"${kind}.${segment}.${name}\" names the ${kind} by its internal id; write \"${addressOf(internals, kind, segment)}.${name}\". `\n + `The internal-id form is refused after the next release.`;\n\n/** Build one side of the partition from the bundle. The bags are KEYED by\n * internal id and ADDRESSED by gameId; see addressOf. */\nconst buildPartition = (internals: Internals, half: (scope: FlaggedScope, decls: PropertyDecl[]) => PropertyDecl[]): Partition => {\n const b = internals.bundle;\n const at = (kind: OwnedScope, id: string): string => `${addressOf(internals, kind, id)}.`;\n return {\n story: bagFromDecls(half(\"story\", b.story.properties), \"story.\"),\n box: new Map(b.boxes.map((box) => [box.id, bagFromDecls(half(\"box\", box.properties), at(\"box\", box.id))])),\n deck: new Map(b.boxes.flatMap((box) => box.decks.map(\n (deck): [string, StateBag] => [deck.id, bagFromDecls(half(\"deck\", deck.properties), at(\"deck\", deck.id))]))),\n // A template instance inherits the template's property declarations;\n // a standalone hand declares its own (schema 2.6).\n hand: new Map(b.boxes.flatMap((box) => box.hands.map(\n (hand): [string, StateBag] => [hand.id, bagFromDecls(half(\"hand\", handDeclsOf(internals, hand)), at(\"hand\", hand.id))]))),\n // Every box's tags, then the project map's zones ONCE (design/project-\n // map-contract.md 3.3): a zone is one bag per partition, whichever boxes'\n // hands are dealt to it.\n value: new Map(allTagGroups(b).flatMap((group) => group.tags.map(\n (tag): [string, StateBag] => [tag.id, bagFromDecls(half(\"value\", tag.properties ?? []), at(\"value\", tag.id))]))),\n };\n};\n\nconst partitionValues = (p: Partition): PropsPartition => ({\n story: p.story.values,\n box: Object.fromEntries([...p.box].map(([id, bag]) => [id, bag.values])),\n deck: Object.fromEntries([...p.deck].map(([id, bag]) => [id, bag.values])),\n hand: Object.fromEntries([...p.hand].map(([id, bag]) => [id, bag.values])),\n value: Object.fromEntries([...p.value].map(([id, bag]) => [id, bag.values])),\n});\n\nconst loadPartition = (p: Partition, values: PropsPartition | undefined): void => {\n // Fresh defaults are already in the bags; the saved values land over\n // them: orphaned keys (deleted entities, re-flagged properties) drop;\n // newly declared properties keep defaults.\n p.story.load(values?.story ?? {});\n for (const kind of [\"box\", \"deck\", \"hand\", \"value\"] as const) {\n for (const [id, bag] of Object.entries(values?.[kind] ?? {})) {\n p[kind].get(id)?.load(bag);\n }\n }\n};\n\n// --- the load report (design/engine-server.md 4.9) ---------------------------\n//\n// One walk, two entry points. `previewLoad` runs it and returns the report;\n// `loadGame` runs it, returns the same report and then applies the CLEANED\n// blob the walk produced. Two implementations of \"what does this save cost\"\n// would drift the first time one of them was fixed, so there is one, and the\n// apply half consumes its output rather than repeating its decisions.\n\n/** The report under construction: unsorted, until finishReport orders it. */\ninterface ReportDraft {\n evicted: LoadEviction[];\n droppedCooldowns: { flow: string; card: string }[];\n droppedSpent: string[];\n droppedProperties: LoadProperty[];\n defaultedProperties: LoadProperty[];\n retypedProperties: LoadProperty[];\n}\n\nconst emptyDraft = (): ReportDraft => ({\n evicted: [], droppedCooldowns: [], droppedSpent: [],\n droppedProperties: [], defaultedProperties: [], retypedProperties: [],\n});\n\n/** The sort key separator: a UNIT SEPARATOR, as the play-history indexes use,\n * because it cannot occur in an id, a gameId or a property name. */\nconst SORT_SEP = \"\\u001f\";\n\nconst byKey = <T>(items: T[], key: (item: T) => string): T[] =>\n [...items].map((item) => ({ item, k: key(item) }))\n .sort((a, b) => (a.k < b.k ? -1 : a.k > b.k ? 1 : 0))\n .map((e) => e.item);\n\nconst propKey = (p: LoadProperty): string => `${p.flow ?? \"\"}${SORT_SEP}${p.path}`;\n\n/**\n * Does a saved value still fit its declaration?\n *\n * The type first, then the declaration's own vocabulary: an enum value or a\n * quality stage the edit struck out is still a string of the right type and\n * still no longer a legal value, and a condition comparing against the ladder\n * would answer nonsense about it. A declaration with no vocabulary (`values` /\n * `stages` absent) constrains nothing, so anything of the right type fits.\n */\nfunction valueFits(decl: PropertyDecl, value: ScalarValue): boolean {\n switch (decl.type) {\n case \"boolean\": return typeof value === \"boolean\";\n case \"number\": return typeof value === \"number\";\n case \"string\": return typeof value === \"string\";\n case \"enum\":\n return typeof value === \"string\" && (decl.values === undefined || decl.values.includes(value));\n case \"quality\":\n return typeof value === \"string\" && (decl.stages === undefined || decl.stages.includes(value));\n case \"flags\":\n return Array.isArray(value) && (decl.values === undefined || value.every((f) => decl.values!.includes(f)));\n default: return true;\n }\n}\n\n/** Walk one bag's worth of saved values against one bag's worth of\n * declarations: report the orphans, the newcomers and the misfits, and\n * return the values that survive. */\nfunction walkScope(\n decls: PropertyDecl[] | undefined,\n saved: PropertyBag | undefined,\n path: (name: string) => string,\n flow: string | undefined,\n draft: ReportDraft,\n): PropertyBag {\n const at = (name: string): LoadProperty =>\n ({ ...(flow !== undefined ? { flow } : {}), path: path(name) });\n const byName = new Map((decls ?? []).map((d) => [d.name, d]));\n const values = saved ?? {};\n const clean: PropertyBag = {};\n for (const [name, value] of Object.entries(values)) {\n const decl = byName.get(name);\n if (decl === undefined) { draft.droppedProperties.push(at(name)); continue; }\n if (!valueFits(decl, value)) { draft.retypedProperties.push(at(name)); continue; }\n clean[name] = value;\n }\n for (const decl of decls ?? []) {\n if (!(decl.name in values)) draft.defaultedProperties.push(at(decl.name));\n }\n return clean;\n}\n\n/** The same walk over all five scopes of one partition. An owner the save\n * carries and the build no longer has drops whole (its bag is gone, so its\n * values have nowhere to land); an owner the build has and the save lacks\n * keeps every default. */\nfunction walkPartition(\n internals: Internals,\n decls: DeclSet,\n values: PropsPartition | undefined,\n flow: string | undefined,\n draft: ReportDraft,\n): PropsPartition {\n const out: PropsPartition = {\n story: walkScope(decls.story, values?.story, (n) => `story.${n}`, flow, draft),\n box: {}, deck: {}, hand: {}, value: {},\n };\n for (const kind of [\"box\", \"deck\", \"hand\", \"value\"] as const) {\n const savedKind = values?.[kind] ?? {};\n const ids = [...new Set([...decls[kind].keys(), ...Object.keys(savedKind)])].sort();\n for (const id of ids) {\n // The report's `path` is exactly what listProperties() prints and what\n // setProperty takes: one grammar, so an operator reading a hot-swap\n // report can paste the address straight back in (4.4).\n const owner = addressOf(internals, kind, id);\n out[kind][id] = walkScope(decls[kind].get(id), savedKind[id],\n (n) => `${owner}.${n}`, flow, draft);\n }\n }\n return out;\n}\n\n/** Order the draft and answer the identity questions. `saved` is the content\n * block the save carries; for a single-flow restore there is none, so the\n * caller passes the bundle's own and no drift is reported. */\nfunction finishReport(bundle: BundleContent, saved: BundleContent, flows: string[], draft: ReportDraft): LoadReport {\n const drift = saved.version !== bundle.version || saved.hash !== bundle.hash;\n const evicted = byKey(draft.evicted, (e) => [e.flow, e.hand, e.card, e.reason].join(SORT_SEP));\n const droppedCooldowns = byKey(draft.droppedCooldowns, (c) => `${c.flow}${SORT_SEP}${c.card}`);\n const droppedSpent = [...draft.droppedSpent].sort();\n const droppedProperties = byKey(draft.droppedProperties, propKey);\n const defaultedProperties = byKey(draft.defaultedProperties, propKey);\n const retypedProperties = byKey(draft.retypedProperties, propKey);\n return {\n // `flows` is what the load restores, not something it had to change, so\n // it never makes a report inexact.\n exact: !drift && evicted.length === 0 && droppedCooldowns.length === 0 && droppedSpent.length === 0\n && droppedProperties.length === 0 && defaultedProperties.length === 0 && retypedProperties.length === 0,\n project: bundle.project,\n version: { saved: saved.version, bundle: bundle.version },\n hash: { saved: saved.hash, bundle: bundle.hash },\n flows,\n evicted, droppedCooldowns, droppedSpent,\n droppedProperties, defaultedProperties, retypedProperties,\n };\n}\n\n// --- the Engine ---------------------------------------------------------------\n\n/**\n * Refuse, at construction, a bundle this engine cannot read faithfully\n * (design/project-map-contract.md 3.8). Throws one error naming every problem\n * found, each naming the box and the group or tag at fault.\n *\n * The compiler refuses all of these first. The engine checks again because it\n * cannot tell a hand-built or stale bundle from a compiled one, and the\n * alternative is the silent half-working the server audit found twice: a hand\n * whose bound group is looked up in the wrong place comes back empty, and an\n * old runtime given a map bundle deals plausibly while every zone value is\n * missing. Only what would make the engine's OWN resolution ambiguous or wrong\n * is refused here; the compiler's bundle-wide group-name rule is stricter.\n */\nconst refuseUnreadableBundle = (bundle: Bundle): void => {\n // The schema tag (D4). Checked alone and first: a bundle of a schema this\n // runtime does not know may not have any of the shape the rest reads.\n const schema = (bundle as { schema?: unknown }).schema;\n if (typeof schema !== \"string\" || !BUNDLE_SCHEMAS.includes(schema)) {\n throw new Error(`unsupported bundle schema: ${String(schema)} (this runtime reads ${BUNDLE_SCHEMAS.join(\" and \")})`);\n }\n const problems: string[] = [];\n const map = bundle.map?.group;\n const mapName = map !== undefined ? effectiveGameId(map) : undefined;\n if (map !== undefined && mapName === PLACE_GROUP) {\n problems.push(`the project map's tag group is called \"${PLACE_GROUP}\", which is reserved for a box's own hands`);\n }\n // Every box tag gameId, for the zone-name rule: a zone's address has no\n // qualified form to fall back on (3.4), so any box tag sharing it anywhere\n // makes `value.<zone>.<name>` ambiguous.\n const boxTags = new Map<string, { box: string; group: string }>();\n for (const box of bundle.boxes) {\n for (const group of box.tagGroups) {\n for (const tag of group.tags) {\n const gameId = effectiveGameId(tag);\n if (!boxTags.has(gameId)) boxTags.set(gameId, { box: effectiveGameId(box), group: effectiveGameId(group) });\n }\n }\n }\n for (const tag of map?.tags ?? []) {\n const zone = effectiveGameId(tag);\n const clash = boxTags.get(zone);\n if (clash !== undefined) {\n problems.push(`the project map's zone \"${zone}\" has the name of tag \"${zone}\" in box \"${clash.box}\", group \"${clash.group}\", `\n + `so \"value.${zone}.<name>\" would name two things`);\n }\n }\n for (const box of bundle.boxes) {\n const boxName = effectiveGameId(box);\n if (box.usesMap === true) {\n if (map === undefined) {\n problems.push(`box \"${boxName}\" uses the project map, but the bundle has no map`);\n continue;\n }\n // One namespace in an opted-in box (3.1): a box group with the map's\n // name would make every name-based lookup there a coin toss.\n const twin = box.tagGroups.find((g) => effectiveGameId(g) === mapName);\n if (twin !== undefined) {\n problems.push(`box \"${boxName}\" uses the project map and declares its own tag group \"${mapName}\", the map's name`);\n }\n continue;\n }\n if (map === undefined) continue;\n // A box NOT on the map may not reference its group at all: every route a\n // reference takes, card tags, template bindings and holes, a hand's\n // chosen tags and a rule's bindings, by the group's id as written.\n const names = (where: string): void => {\n problems.push(`box \"${boxName}\" is not on the project map, but ${where} names the map's tag group \"${mapName}\"`);\n };\n for (const deck of box.decks) {\n for (const card of deck.cards) {\n if (card.tags?.[map.id] !== undefined) names(`card \"${effectiveGameId(card)}\"`);\n }\n }\n for (const template of box.handTemplates) {\n if (template.bindings?.[map.id] !== undefined || template.chooses?.includes(map.id) === true) {\n names(`hand template \"${effectiveGameId(template)}\"`);\n }\n }\n for (const hand of box.hands) {\n if (hand.chosen?.[map.id] !== undefined || hand.rule?.bindings?.[map.id] !== undefined) {\n names(`hand \"${effectiveGameId(hand)}\"`);\n }\n }\n }\n if (problems.length > 0) throw new Error(`bundle refused: ${problems.join(\"; \")}`);\n};\n\nexport class Engine {\n private readonly internals: Internals;\n private readonly seed: number;\n private readonly onReplacedFlow: EngineOptions[\"onReplacedFlow\"];\n private readonly flowsById = new Map<string, Flow>();\n private readonly engineTraceHandlers = new Set<EngineTraceHandler>();\n /** The host's @world binding, if the engine was built with one: it\n * outlives reset/loadGame (the host's container is the host's). The\n * self-backed resolver is rebuilt instead. */\n private readonly hostWorld?: ScopeResolver;\n\n /** The options this engine was built with: hotSwap builds its replacement from them. */\n private readonly creationOptions: EngineOptions;\n /** How to register each shared scope again, in registration order: a failed\n * hotSwap puts this engine back exactly as it was. */\n private readonly sharedMounts: Array<{ key: string; mount: () => void }> = [];\n\n constructor(bundle: Bundle, opts: EngineOptions = {}) {\n // First, before anything is indexed or registered: a bundle this engine\n // cannot read faithfully is refused whole (design/project-map-contract.md\n // 3.8), and a refusal must leave the game's registry untouched.\n refuseUnreadableBundle(bundle);\n this.creationOptions = opts;\n this.seed = opts.seed ?? 0;\n this.onReplacedFlow = opts.onReplacedFlow;\n if (opts.world !== undefined) this.hostWorld = opts.world;\n const internals: Internals = {\n bundle,\n ...(opts.log ? { logCap: typeof opts.log === \"object\" ? (opts.log.cap ?? 1000) : 1000 } : {}),\n cardsById: new Map(), cardsByGameId: new Map(),\n boxesByGameId: new Map(), boxesById: new Map(),\n handsById: new Map(), handsByGameId: new Map(),\n owners: emptyOwnerIndexes(),\n templatesById: new Map(), groupsById: new Map(),\n requiredGroups: new Set(),\n nodeCache: new WeakMap(),\n ladders: { world: new Map(), story: new Map(), box: new Map(), deck: new Map(), value: new Map(), hand: new Map() },\n hasQualities: false,\n hasShared: false,\n flowDecls: { story: [], box: new Map(), deck: new Map(), hand: new Map(), value: new Map() },\n sharedDecls: { story: [], box: new Map(), deck: new Map(), hand: new Map(), value: new Map() },\n shared: undefined as unknown as Partition,\n registry: opts.registry ?? new ScopeRegistry(),\n ownsRegistry: opts.registry === undefined,\n selfWorld: false,\n registryView: () => view(),\n worldResolver: undefined as unknown as ScopeResolver,\n worldReadOnly: new Set<string>(),\n emitEngine: (flow, event, turn) => {\n if (this.internals.logCap !== undefined) {\n this.engineLog.push({ ...event, flow, seq: this.engineSeq++, ...(turn !== undefined ? { turn } : {}) });\n if (this.engineLog.length > this.internals.logCap) {\n this.engineLog.splice(0, this.engineLog.length - this.internals.logCap);\n }\n }\n for (const h of this.engineTraceHandlers) h(flow, event);\n },\n engineTracing: () => this.engineTraceHandlers.size > 0,\n };\n this.internals = internals;\n let viewRevision = -1;\n let viewCache: ReturnType<Internals[\"registryView\"]> = { scopes: {}, qualities: undefined };\n const view = (): ReturnType<Internals[\"registryView\"]> => {\n const reg = internals.registry;\n if (reg.revision !== viewRevision) {\n const ctx = reg.toEvalContext();\n const scopes: EvalContext[\"scopes\"] = {};\n // An instance key (`storylets/deck/x`, another engine's) is no expression token.\n for (const [k, v] of Object.entries(ctx.scopes)) if (!k.includes(\"/\")) scopes[k] = v;\n viewCache = { scopes, qualities: ctx.qualities };\n viewRevision = reg.revision;\n }\n return viewCache;\n };\n\n // The value scope's segments come off the whole bundle at once (a tag\n // gameId is only unique within its group), so they are built before the\n // walk rather than tag by tag inside it.\n indexValueOwners(internals.owners.value, bundle);\n\n for (const box of bundle.boxes) {\n internals.boxesById.set(box.id, box);\n internals.boxesByGameId.set(effectiveGameId(box), box);\n indexOwner(internals.owners.box, box);\n for (const group of box.tagGroups) {\n internals.groupsById.set(group.id, { group, box });\n if (group.required === true) internals.requiredGroups.add(group.id);\n }\n for (const deck of box.decks) {\n indexOwner(internals.owners.deck, deck);\n if (deck.shared === true) internals.hasShared = true;\n for (const card of deck.cards) {\n const entry = { card, deck, box };\n internals.cardsById.set(card.id, entry);\n internals.cardsByGameId.set(effectiveGameId(card), entry);\n if (card.shared === true) internals.hasShared = true;\n }\n }\n for (const template of box.handTemplates) {\n internals.templatesById.set(template.id, template);\n }\n for (const hand of box.hands) {\n internals.handsById.set(hand.id, { hand, box });\n internals.handsByGameId.set(effectiveGameId(hand), { hand, box });\n indexOwner(internals.owners.hand, hand);\n }\n }\n // The project map's group: by id like any group, so a hand's binding, a\n // filled hole and tag matching need no logic of their own for it. Which\n // boxes may NAME it is `groupInBox`'s business (3.1); which may reference\n // it at all was settled by the refusal above.\n if (bundle.map !== undefined) {\n internals.groupsById.set(bundle.map.group.id, { group: bundle.map.group });\n if (bundle.map.group.required === true) internals.requiredGroups.add(bundle.map.group.id);\n }\n this.initLadders();\n\n // Both halves, precomputed once (a bundle's declarations never change):\n // each openFlow builds its bags from the per-flow half, and a load report\n // asks either half what it declares without building anything at all.\n const declSet = (half: (scope: FlaggedScope, decls: PropertyDecl[]) => PropertyDecl[]): DeclSet => ({\n story: half(\"story\", bundle.story.properties),\n box: new Map(bundle.boxes.map((box) => [box.id, half(\"box\", box.properties)])),\n deck: new Map(bundle.boxes.flatMap((box) => box.decks.map(\n (deck): [string, PropertyDecl[]] => [deck.id, half(\"deck\", deck.properties)]))),\n hand: new Map(bundle.boxes.flatMap((box) => box.hands.map(\n (hand): [string, PropertyDecl[]] => [hand.id, half(\"hand\", handDeclsOf(internals, hand))]))),\n value: new Map(allTagGroups(bundle).flatMap((group) => group.tags.map(\n (tag): [string, PropertyDecl[]] => [tag.id, half(\"value\", tag.properties ?? [])]))),\n });\n internals.flowDecls = declSet(flowHalf);\n internals.sharedDecls = declSet(sharedHalf);\n\n this.initShared(this.hostWorld);\n }\n\n /** Build the shared stores, register them and @world, and set up the @world\n * seam. Once, for the engine's life: reset and loads reseed the bags in\n * place, so the registry never sees them come and go. */\n private initShared(hostWorld?: ScopeResolver): void {\n const internals = this.internals;\n const reg = internals.registry;\n const worldDecls = internals.bundle.world.properties as unknown as ScopeDeclaration[];\n internals.shared = buildPartition(internals, sharedHalf);\n internals.worldReadOnly = new Set(internals.bundle.world.properties.filter((d) => d.writable === false).map((d) => d.name));\n const registered: string[] = [];\n // Register now, and remember how, so a failed hotSwap can register again.\n const mount = (key: string, register: () => void): void => {\n register();\n registered.push(key);\n this.sharedMounts.push({ key, mount: register });\n };\n try {\n // `story` is this engine's token whether or not the bundle declares a shared\n // @story property: registering it is what makes a clash show at once.\n const story = internals.shared.story;\n mount(\"story\", () => { reg.mountOwned(\"story\", story, { owner: OWNER }); }); // claims values the game loaded first\n for (const kind of OWNED_SCOPES) {\n for (const [id, bag] of internals.shared[kind]) {\n if (bag.declarations().length === 0) continue; // holds nothing: not registered\n mount(sharedKey(kind, id), () => { reg.mountOwned(sharedKey(kind, id), bag, { owner: OWNER }); });\n }\n }\n if (hostWorld !== undefined) {\n // The game keeps these values: an external scope, never saved.\n mount(\"world\", () => { reg.defineForeign(\"world\", hostWorld, worldDecls, { normalise: identity, owner: OWNER }); });\n } else if (internals.ownsRegistry && !reg.has(\"world\")) {\n // Standalone: self-backed from the declared defaults, DECLARATIONS AND\n // ALL, as a property the registry stores and SAVES (only a resolver the\n // game binds is external). The bag keeps `writable: false` so an\n // examiner still reads it there, and the kernel lets a `{ host: true }`\n // write past it, which is what the game's own surface passes.\n reg.defineOwned(\"world\", worldDecls, { normalise: identity, pathPrefix: \"world.\", owner: OWNER });\n const worldBag = reg.ownedBag(\"world\");\n registered.push(\"world\");\n this.sharedMounts.push({ key: \"world\", mount: () => { reg.mountOwned(\"world\", worldBag, { owner: OWNER }); } });\n internals.selfWorld = true;\n }\n // Given the game's registry and no resolver, @world is the game's to\n // register: this engine registers nothing for it.\n } catch (e) {\n for (const k of registered) reg.remove(k, { keep: true }); // a clash leaves the game's registry as it was\n throw e;\n }\n internals.worldResolver = {\n get: (n) => reg.get(\"world\", n),\n set: (n, v) => { reg.set(\"world\", n, v); },\n };\n if (hostWorld !== undefined) {\n // A bound resolver is opaque: it keeps whatever rule the game has, so the\n // story's `writable: false` is kept by worldReadOnly before this seam.\n internals.worldSet = hostWorld.set !== undefined ? (n, v): void => { reg.set(\"world\", n, v, { host: true }); } : undefined;\n } else {\n internals.worldSet = (n, v, host): void => { reg.set(\"world\", n, v, host === true ? { host: true } : undefined); };\n }\n }\n\n /** Every shared bag back to its declared defaults, in place (the registry\n * keeps them registered), the self-backed @world included. */\n private reseedShared(): void {\n const { shared, sharedDecls, registry } = this.internals;\n shared.story.reseed(sharedDecls.story as unknown as ScopeDeclaration[]);\n for (const kind of OWNED_SCOPES) {\n for (const [id, bag] of shared[kind]) bag.reseed((sharedDecls[kind].get(id) ?? []) as unknown as ScopeDeclaration[]);\n }\n if (this.internals.selfWorld) {\n registry.reseedOwned(\"world\", this.internals.bundle.world.properties as unknown as ScopeDeclaration[]);\n }\n }\n\n /** Quality ladders by scope for the eval channel (design/quality.md):\n * world/story keyed by name; box/deck/value keyed by owner id then name.\n * Built once - a bundle's declarations never change. Ladders are\n * declaration-level, so the sharing flag does not touch them. */\n private initLadders(): void {\n const internals = this.internals;\n const grab = (decls: PropertyDecl[] | undefined): Map<string, readonly string[]> => {\n const m = new Map<string, readonly string[]>();\n for (const d of decls ?? []) if (d.type === \"quality\" && d.stages !== undefined) m.set(d.name, d.stages);\n return m;\n };\n const b = internals.bundle;\n internals.ladders.world = grab(b.world.properties);\n internals.ladders.story = grab(b.story.properties);\n for (const box of b.boxes) {\n internals.ladders.box.set(box.id, grab(box.properties));\n for (const deck of box.decks) internals.ladders.deck.set(deck.id, grab(deck.properties));\n for (const group of box.tagGroups) {\n for (const tag of group.tags) internals.ladders.value.set(tag.id, grab(tag.properties));\n }\n for (const hand of box.hands) internals.ladders.hand.set(hand.id, grab(handDeclsOf(internals, hand)));\n }\n // The zones, once, keyed by tag id like every other tag (3.3).\n for (const tag of b.map?.group.tags ?? []) internals.ladders.value.set(tag.id, grab(tag.properties));\n const any = (m: Map<string, Map<string, readonly string[]>>): boolean =>\n [...m.values()].some((x) => x.size > 0);\n internals.hasQualities = internals.ladders.world.size > 0 || internals.ladders.story.size > 0\n || any(internals.ladders.box) || any(internals.ladders.deck)\n || any(internals.ladders.value) || any(internals.ladders.hand);\n }\n\n // --- flow management (Patter's surface, name for name) ----------------------\n\n /** Open (or REPLACE) the named flow. An existing id's flow is closed\n * first - re-opening a name is a reset of that name's whole per-flow\n * state; shared state is untouched. There is no default flow: \"main\" is\n * a caller convention, not an engine rule. */\n openFlow(id: string, opts: OpenFlowOptions = {}): Flow {\n return this.open(id, opts, false);\n }\n\n /** openFlow, and loadGame's rebuild. `claim` says the new flow's bags take\n * the values the registry holds for them (a load); a fresh open is a reset\n * of that name, so anything waiting for it is discarded first. */\n private open(id: string, opts: OpenFlowOptions, claim: boolean): Flow {\n this.assertExternalScopes();\n // The world's claims as they stand WITHOUT this name, taken before the\n // replace: a resume competes with the other flows, never with the flow it\n // is replacing (which is about to release everything it holds).\n const otherClaims = opts.restore !== undefined ? this.sharedClaimsExcept(id) : undefined;\n // Replacing an existing id KEEPS its place in the order. `close()` would\n // drop the key, and a JS Map re-inserts a deleted key at the END, so\n // openFlow(\"a\"); openFlow(\"b\"); openFlow(\"a\") listed [b, a] here and\n // [a, b] on all three ports - a different `flows()` order and, since\n // `saveGame` keys its flows in that order, a different `.storyletsave`\n // byte stream for the same run (2026-08-29). markClosed without dropFlow\n // is the difference: the old handle goes inert, the slot stays put. The\n // registry cannot keep a key's place the same way (the old flow's keys are\n // removed and the new flow's appended), so `saveGame` writes the registry\n // section in flow order itself: see `registrySection` (2026-10-01).\n const existing = this.flowsById.get(id);\n if (existing) {\n // Say so BEFORE the old flow goes inert, while its board is still readable.\n const dealt = existing.heldCardIds().length;\n if (dealt > 0) this.onReplacedFlow?.(id, dealt);\n existing.markClosed();\n }\n if (!claim) this.internals.registry.discardParked(flowPrefix(id));\n const flow = new Flow(this, this.internals, id, opts.seed ?? this.seed);\n this.flowsById.set(id, flow);\n if (opts.restore !== undefined) {\n const draft = emptyDraft();\n // Cloned: a caller holding one blob may resume two flows from it, and\n // an aliased playLog would then grow in both.\n const clean = this.planFlowRestore(id, structuredClone(opts.restore), otherClaims, draft);\n flow.restore(clean);\n const content = this.internals.bundle.content;\n opts.onRestoreReport?.(finishReport(content, content, [id], draft));\n }\n return flow;\n }\n\n getFlow(id: string): Flow | undefined {\n return this.flowsById.get(id);\n }\n\n /** Every live flow, open order. */\n flows(): Flow[] {\n return [...this.flowsById.values()];\n }\n\n /** Close the named flow: its handle goes INERT (every verb throws). A\n * dropped-but-held flow must not keep writing shared state (Patter's\n * stale-handle lesson). Unknown ids are a quiet no-op, like closing a\n * closed door. */\n closeFlow(id: string): void {\n const flow = this.flowsById.get(id);\n if (!flow) return;\n this.flowsById.delete(id);\n flow.markClosed();\n }\n\n /** @internal - Flow.close() routes here so both doors agree. */\n dropFlow(id: string, flow: Flow): void {\n if (this.flowsById.get(id) === flow) this.flowsById.delete(id);\n }\n\n /** Close every flow and reseed the shared state to its defaults (the\n * self-backed @world included; a host-bound @world is the host's and is\n * not touched). */\n reset(): void {\n this.dropRun(false);\n this.reseedShared();\n // Values loaded for bags nobody has claimed yet are the old run's too: a\n // flow opened after the reset must not pick them up. Other engines' stay.\n this.internals.registry.discardParked(\"storylets/\");\n }\n\n /** End the run: clear the log, close every flow, forget spent cards. Each\n * flow's bags leave the registry; `keepFlows` names the flows whose values\n * are kept there for the flow that replaces them (a load into the game's\n * registry). */\n private dropRun(keepFlows: Set<string> | false): void {\n // The log is a run-lifetime utility and is not saved; a reset is a new run.\n // All three ports cleared it here and the reference did not, so `reset()`\n // (and `loadGame`) left the previous run's entries in place with `seq`\n // continuing across the boundary - while the same call on Godot, Unity or\n // Unreal returned an empty log (2026-08-29).\n this.engineLog = [];\n for (const [id, flow] of this.flowsById) {\n flow.releaseBags(keepFlows !== false && keepFlows.has(id));\n flow.markClosed();\n }\n this.flowsById.clear();\n this.spent.clear();\n }\n\n // --- shared scarcity (design/shared-scarcity.md) -----------------------------\n\n /** Cards a shared `redraw: \"never\"` has taken out of the world, by card id.\n * The claim ledger is DERIVED from live boards and so needs no storage;\n * this one is durable, so it rides the save's shared half. */\n private spent = new Set<string>();\n\n /** @internal */\n isTaken(cardId: string): boolean {\n return this.spent.has(cardId);\n }\n\n /** @internal */\n markTaken(cardId: string): void {\n this.spent.add(cardId);\n }\n\n // --- the run's log (design/shared-scarcity.md 8.2) ---------------------------\n\n /** Every flow's events in one ordered stream, each tagged with its flow.\n * Opt in with the same `log` option the flow logs use; capped the same way.\n *\n * This exists because a flow's own log cannot answer the question a run\n * raises: when a story action in ANOTHER flow moves shared state, your\n * flow's log says nothing and your value simply changes. Reading a run\n * needs one stream that says who did what, and merging the per-flow logs by\n * hand is a thing every host would otherwise have to write. */\n private engineLog: EngineLogEntry[] = [];\n private engineSeq = 0;\n\n log(): readonly EngineLogEntry[] {\n return this.engineLog;\n }\n\n clearLog(): void {\n this.engineLog = [];\n }\n\n /** @internal - shared claims across every LIVE flow, card id -> holders.\n * Derived, which is what makes closeFlow and the openFlow replace release\n * what a flow was holding: its board leaves the map with it. */\n sharedClaims(): Map<string, number> {\n const counts = new Map<string, number>();\n for (const flow of this.flowsById.values()) {\n for (const id of flow.heldCardIds()) counts.set(id, (counts.get(id) ?? 0) + 1);\n }\n return counts;\n }\n\n /** The same ledger with one name left out: what the REST of the world\n * holds, which is the question a resume under that name has to ask. */\n private sharedClaimsExcept(id: string): Map<string, number> {\n const counts = new Map<string, number>();\n for (const [flowId, flow] of this.flowsById) {\n if (flowId === id) continue;\n for (const cardId of flow.heldCardIds()) counts.set(cardId, (counts.get(cardId) ?? 0) + 1);\n }\n return counts;\n }\n\n // --- engine-level state access ----------------------------------------------\n\n /**\n * Read shared state by path: \"world.x\", \"story.gold\" (when shared),\n * \"box.village.heat\" (when shared) - the owner segment is its GAMEID\n * (design/engine-server.md 4.4). A ref that resolves PER-FLOW throws,\n * naming the fix - silently answering with some flow's copy (or a junk\n * default) was the bug Patter's engine.getProperty guard exists to stop.\n */\n getProperty(path: string): ScalarValue {\n const found = this.resolveShared(path);\n const value = found.kind === \"world\" ? this.internals.worldResolver.get(found.name)\n : found.kind === \"scope\" ? this.internals.registry.get(found.token, found.name)\n : found.bag.get(found.name);\n if (value === undefined) throw new Error(`no property at \"${path}\"`);\n return value;\n }\n\n setProperty(path: string, value: ScalarValue): void {\n const found = this.resolveShared(path);\n if (found.kind === \"world\") {\n if (!this.internals.worldSet) {\n throw new Error(`@world is read-only here: the host bound no write`);\n }\n this.internals.worldSet(found.name, value, true);\n return;\n }\n if (found.kind === \"scope\") {\n this.internals.registry.set(found.token, found.name, value, { host: true });\n return;\n }\n // A host write: silent under the firing rule (no subscriber feedback\n // loop), but visible to the bag's audit hook - and a HOST write, so a\n // `writable: false` does not refuse it. That flag is the story's promise\n // about its own outcomes; this is the game speaking, in any scope.\n found.bag.set(found.name, value, { silent: true, reason: \"host setProperty\", host: true });\n }\n\n private resolveShared(path: string):\n | { kind: \"world\"; name: string }\n | { kind: \"scope\"; token: string; name: string }\n | { kind: \"bag\"; bag: StateBag; name: string } {\n const parts = path.split(\".\");\n const perFlow = (): never => {\n throw new Error(`\"${path}\" is per-flow state - read it on a Flow, not the Engine`);\n };\n if (parts.length === 2 && parts[0] === \"world\") return { kind: \"world\", name: parts[1]! };\n // Another engine's game-wide scope (`patter.gold`): every engine reads every scope.\n if (parts.length === 2 && parts[0] !== \"story\" && this.internals.registry.has(parts[0]!)) {\n return { kind: \"scope\", token: parts[0]!, name: parts[1]! };\n }\n if (parts.length === 2 && parts[0] === \"story\") {\n const name = parts[1]!;\n if (this.internals.shared.story.get(name) !== undefined) return { kind: \"bag\", bag: this.internals.shared.story, name };\n if (this.internals.flowDecls.story.some((d) => d.name === name)) perFlow();\n throw new Error(`no property at \"${path}\"`);\n }\n if (parts.length === 3 && (parts[0] === \"box\" || parts[0] === \"deck\" || parts[0] === \"hand\" || parts[0] === \"value\")) {\n const kind = parts[0] as OwnedScope;\n const [, segment, name] = parts as unknown as [string, string, string];\n const owner = ownerOrThrow(this.internals, kind, segment, name);\n if (owner.legacy) this.diagnose(legacyAddressMessage(this.internals, kind, segment, name));\n const id = owner.id;\n const bag = this.internals.shared[kind].get(id);\n if (bag !== undefined && bag.get(name) !== undefined) return { kind: \"bag\", bag, name };\n if (this.internals.flowDecls[kind].get(id)?.some((d) => d.name === name)) perFlow();\n if (bag === undefined && !this.internals.flowDecls[kind].has(id)) throw new Error(`no ${kind} store \"${segment}\"`);\n throw new Error(`no property at \"${path}\"`);\n }\n throw new Error(`bad property path \"${path}\"`);\n }\n\n /** The engine's own surface has no flow, so an engine-level diagnostic\n * carries the empty flow id - the same way a LoadReport's shared half\n * carries no flow. It reaches the run log and the engine tap; there is\n * nowhere else for it to go, and it fires only on a legacy address. */\n private diagnose(message: string): void {\n this.internals.emitEngine(\"\", { type: \"diagnostic\", where: \"property address\", message });\n }\n\n /** Content that names another engine's scope (`@patter.visits`) runs only\n * where that engine is on this registry: without it every read would answer\n * false and every write fail, so the flow is refused as it opens, before\n * anything changes. By then a game has built all of its engines, whatever\n * order it built them in. The same message on every runtime. */\n private assertExternalScopes(): void {\n for (const token of this.internals.bundle.externalScopes ?? []) {\n if (!this.internals.registry.has(token)) {\n throw new Error(`this content names @${token}, which no engine on this registry registered: `\n + `give every engine the game's one registry`);\n }\n }\n }\n\n /** The shared surface as examiner rows: @world (read through the\n * resolver) then the shared partitions. Per-flow rows live on each Flow. */\n listProperties(): PropertyRow[] {\n const out: PropertyRow[] = [];\n for (const d of this.internals.bundle.world.properties) {\n const value = this.internals.worldResolver.get(d.name);\n out.push({\n path: `world.${d.name}`, name: d.name, type: d.type,\n value: value ?? d.default, default: d.default,\n ...(d.values !== undefined ? { values: d.values } : {}),\n ...(d.stages !== undefined ? { stages: d.stages } : {}),\n // @world is FOREIGN - a host resolver backs it - so writability is whether that\n // resolver can be written at all AND what the declaration says, which is the\n // shared registry's own rule for a foreign scope (its foreignWritable). The\n // `as PropertyView` cast this replaced was hiding the field's absence: the row\n // type has always required it, and these rows shipped without one.\n //\n // A row is where `writable: false` is meant to SHOW (Reboot.md 10): it tells a\n // state panel this is the game's value, not the story's. It does not stop the\n // panel editing it - the host's setProperty passes `{ host: true }`.\n writable: this.internals.worldSet !== undefined && !this.internals.worldReadOnly.has(d.name),\n });\n }\n // The bag composes its rows' addresses from its own pathPrefix, so the prefix here is\n // only the caller's label for the mount; the row arrives already addressed.\n const add = (_prefix: string, bag: StateBag): void => {\n for (const row of bag.rows()) out.push(row);\n };\n add(\"story\", this.internals.shared.story);\n for (const kind of OWNED_SCOPES) {\n for (const [id, bag] of this.internals.shared[kind]) add(addressOf(this.internals, kind, id), bag);\n }\n return out;\n }\n\n /** The SHARED kernel bags with their store path prefixes (the state\n * logger's mount surface). The @world container is the host's own bag -\n * the host mounts it itself. */\n listBags(): BagMount[] {\n const mounts: BagMount[] = [{ prefix: \"story\", bag: this.internals.shared.story }];\n for (const kind of [\"box\", \"deck\", \"hand\", \"value\"] as const) {\n for (const [id, bag] of this.internals.shared[kind]) mounts.push({ prefix: addressOf(this.internals, kind, id), bag });\n }\n return mounts;\n }\n\n /** Every flow's trace, one stream, each event tagged with its flow id. */\n subscribeTrace(handler: EngineTraceHandler): () => void {\n this.engineTraceHandlers.add(handler);\n return () => this.engineTraceHandlers.delete(handler);\n }\n\n // --- persistence (schema 4) -------------------------------------------------\n\n /**\n * Live bundle refresh: rebuild on an edited bundle with the whole run carried\n * over, and return the replacement with the report its load produced.\n *\n * Standalone, that is a save and a load into a new engine, and this one is left\n * untouched (discard it). With the game's registry the two cannot both hold the\n * same keys, so this engine is spent afterwards (its flows closed, the\n * replacement holding everything on the same registry): it carries its\n * own values into the snapshot, steps out of the registry, and the replacement\n * loads them the way a standalone save loads: so the report covers the\n * properties the edit dropped, defaulted, or retyped, and a dropped property\n * is dropped rather than kept. Values the game loaded that were still waiting\n * for a flow of this engine carry across as they were, and nothing belonging\n * to any other engine is touched. A save for another project is refused before\n * anything moves; if the rebuild fails for any other reason, this engine takes\n * its registrations back and is left exactly as it was.\n */\n hotSwap(bundle: Bundle, opts: EngineOptions = {}): { engine: Engine; report: LoadReport } {\n if (bundle.content.project !== this.internals.bundle.content.project) {\n throw new Error(`save is for project \"${this.internals.bundle.content.project}\", bundle is \"${bundle.content.project}\"`);\n }\n const options: EngineOptions = { ...this.creationOptions, ...opts };\n const snapshot = this.saveGame();\n const reg = this.internals.registry;\n if (this.internals.ownsRegistry) {\n // Its own registry: a save and a load into a new engine, as it always was,\n // and this engine is left untouched.\n const next = new Engine(bundle, { ...options, registry: undefined });\n return { engine: next, report: next.loadGame(snapshot) };\n }\n // This engine's own values, registered or still waiting for a flow.\n const mine: Record<string, Record<string, ScalarValue>> = {};\n for (const [key, values] of Object.entries(reg.save())) {\n if (key === \"story\" || key.startsWith(\"storylets/\")) mine[key] = values;\n }\n const registeredKeys = new Set([\n ...this.sharedMounts.map((m) => m.key),\n ...[...this.flowsById.values()].flatMap((f) => f.registeredKeys()),\n ]);\n const waiting = Object.fromEntries(Object.entries(mine).filter(([key]) => !registeredKeys.has(key)));\n // Step out of the registry. The bags keep their values, so stepping back in is exact.\n for (const { key } of this.sharedMounts) if (reg.has(key)) reg.remove(key);\n for (const flow of this.flowsById.values()) flow.releaseBags(false);\n let next: Engine | undefined;\n try {\n next = new Engine(bundle, { ...options, registry: reg });\n const report = next.loadGame({ ...snapshot, registry: mine });\n // Values that were waiting for a flow wait on, for the replacement's flow of that name.\n const stillWaiting = Object.fromEntries(Object.entries(waiting).filter(([key]) => !reg.has(key)));\n if (Object.keys(stillWaiting).length > 0) reg.load(stillWaiting, { keepParked: true });\n this.dropRun(false);\n return { engine: next, report };\n } catch (e) {\n // Back as it was. The replacement's registrations go; a constructor that\n // failed part way parked what it had claimed, so this engine's keys are\n // cleared of anything waiting, registered again, and its own values laid\n // back over them (the waiting ones parked again).\n next?.dropRun(false);\n for (const { key } of next?.sharedMounts ?? []) if (reg.has(key)) reg.remove(key);\n reg.discardParked(\"storylets/\");\n for (const { mount } of this.sharedMounts) mount();\n for (const flow of this.flowsById.values()) flow.mountBags();\n // `story` may have claimed what the failed replacement parked there: back to\n // its declarations, then this engine's own values over it.\n this.reseedShared();\n reg.load(mine, { keepParked: true });\n throw e;\n }\n }\n\n /** The whole engine's NON-property state, one envelope: the spent cards\n * once, then every live flow (board, clocks, cooldowns, PRNG, play log)\n * keyed by its id. The property values are the registry's: a standalone\n * engine (one that made its own registry) carries them here under\n * `registry`, self-backed @world included; a game that passed a registry\n * saves it once itself, beside each engine's envelope. */\n saveGame(): SaveEnvelope {\n return structuredClone({\n schema: SAVE_SCHEMA,\n content: this.internals.bundle.content,\n ...(this.internals.ownsRegistry ? { registry: this.registrySection() } : {}),\n shared: { spent: [...this.spent].sort() },\n flows: Object.fromEntries([...this.flowsById].map(([id, flow]) => [id, flow.snapshot(false)])),\n });\n }\n\n /** The registry's values in CANONICAL order, the order a load rebuilds them\n * in: the engine-wide keys as the constructor registered them, then each\n * flow's keys in `flows()` order (each flow's own registration order), then\n * anything else the registry holds (values still waiting for a key), as the\n * registry lists it. The registry itself lists keys in registration order,\n * and a flow replaced in place (`open()` above keeps its slot in\n * `flowsById`) re-registers its keys at the END, so `openFlow(\"a\");\n * openFlow(\"b\"); openFlow(\"a\")` saved b's keys before a's while a load\n * rebuilt a's first: the same run, different `.storyletsave` bytes, and a\n * save loaded and saved again no longer equal to itself. It is the\n * 2026-08-29 rule carried into the section save@2 moved the per-flow values\n * to (2026-10-01). Order does not matter on READ (`partitionsFromSections`\n * sorts by key shape), so a save written in the old order loads as before. */\n private registrySection(): Sections {\n const all = this.internals.registry.save() as Sections;\n const out: Sections = {};\n const take = (key: string): void => {\n if (Object.prototype.hasOwnProperty.call(all, key) && !Object.prototype.hasOwnProperty.call(out, key)) out[key] = all[key]!;\n };\n for (const { key } of this.sharedMounts) take(key);\n for (const flow of this.flowsById.values()) for (const key of flow.registeredKeys()) take(key);\n for (const key of Object.keys(all)) take(key);\n return out;\n }\n\n /** ONE flow's blob, to park a visit that is walking away: the same shape\n * the envelope carries per flow, and the same shape `openFlow`'s `restore`\n * option takes back (design/engine-server.md 4.1). Saving the whole\n * envelope to park one of four hundred players is wrong in cost and in\n * meaning. Throws for a name that is not open - a closed flow has nothing\n * left to save. */\n saveFlow(id: string): FlowSave {\n const flow = this.flowsById.get(id);\n if (!flow) throw new Error(`unknown flow \"${id}\"`);\n // Parked whole, properties included: a parked flow's bags leave the\n // registry when it closes, so its values have to travel with it.\n return structuredClone(flow.snapshot(true));\n }\n\n /** What `loadGame(envelope)` would do that is not a plain restore, without\n * doing any of it (design/engine-server.md 4.9). Pure: nothing on this\n * engine moves. A project mismatch is refused here exactly as `loadGame`\n * refuses it - it is the one thing neither call will tolerate. */\n previewLoad(envelope: SaveEnvelope | SaveEnvelopeV1): LoadReport {\n this.assertSameProject(envelope);\n return this.planLoad(envelope).report;\n }\n\n /** What `openFlow(id, { restore: saved })` would do to a flow of that name,\n * without doing it: the same report shape, since a visit parked under one\n * build and resumed under the next raises the same questions. Pure. */\n previewFlowRestore(id: string, saved: FlowSave): LoadReport {\n const draft = emptyDraft();\n this.planFlowRestore(id, saved, this.sharedClaimsExcept(id), draft);\n const content = this.internals.bundle.content;\n return finishReport(content, content, [id], draft);\n }\n\n /** Restore: shared state once, then every flow REBUILT from its blob.\n * Handles held from before the load are closed and inert (Patter's\n * rule); take fresh ones from getFlow()/flows().\n *\n * Property values come from the registry. An envelope that carries them\n * (a standalone engine's, or a version 1 envelope) has them walked, cleaned,\n * and moved into the registry here, over fresh defaults. Otherwise the game\n * loads its registry itself, before or after this call: each flow's bags\n * are handed back to the registry with their values, and the restored\n * flows claim them. The report then covers only what this envelope holds;\n * the registry's own load rule applies to the values.\n *\n * Returns the report `previewLoad` would have given for this envelope: the\n * drift tolerance that makes a load forgiving is what hides its cost, so\n * the cost comes back with the load whether or not anybody looked first. */\n loadGame(envelope: SaveEnvelope | SaveEnvelopeV1): LoadReport {\n this.assertSameProject(envelope);\n this.assertExternalScopes();\n const plan = this.planLoad(structuredClone(envelope));\n const reg = this.internals.registry;\n if (plan.sections !== undefined) {\n // The envelope carries the values: every bag of this engine back to its\n // defaults, then the cleaned values over them.\n this.reset();\n // The engine's own registry takes the save wholesale. A game's registry may\n // hold values the game loaded for other engines, still waiting: add to\n // those, never replace them.\n if (this.internals.ownsRegistry) reg.load(plan.sections);\n else reg.load(plan.sections, { keepParked: true });\n } else {\n this.dropRun(new Set(plan.flows.map(([id]) => id)));\n }\n for (const id of plan.spent) this.spent.add(id);\n for (const [id, clean] of plan.flows) this.open(id, {}, true).restore(clean);\n return plan.report;\n }\n\n private assertSameProject(envelope: SaveEnvelope | SaveEnvelopeV1): void {\n if (envelope.content.project !== this.internals.bundle.content.project) {\n throw new Error(`save is for project \"${envelope.content.project}\", bundle is \"${this.internals.bundle.content.project}\"`);\n }\n }\n\n /** The whole-envelope walk: the report, and the cleaned state the apply\n * half writes. Nothing here touches the engine, which is what lets\n * previewLoad and loadGame share it. */\n private planLoad(envelope: SaveEnvelope | SaveEnvelopeV1): {\n report: LoadReport;\n /** The cleaned property values to move into the registry, when the\n * envelope carries any. */\n sections?: Sections;\n spent: string[];\n flows: [string, FlowSave][];\n } {\n const schema = (envelope as { schema?: unknown }).schema;\n if (schema !== SAVE_SCHEMA && schema !== SAVE_SCHEMA_V1) throw new Error(`unsupported save schema: ${String(schema)}`);\n const draft = emptyDraft();\n // Where the property values are, if this envelope has them: a version 1\n // envelope's partitions, or a standalone engine's registry sections.\n const flowIds = new Set(Object.keys(envelope.flows ?? {}));\n let moved: { shared: PropsPartition; flows: Map<string, PropsPartition>; rest: Sections } | undefined;\n if (envelope.schema === SAVE_SCHEMA_V1) {\n moved = {\n shared: envelope.shared?.props ?? emptyPartitionValues(),\n flows: new Map(Object.entries(envelope.flows ?? {}).map(([id, f]) => [id, f.props ?? emptyPartitionValues()])),\n rest: {},\n };\n } else if (envelope.registry !== undefined) {\n moved = partitionsFromSections(envelope.registry, flowIds);\n }\n const shared = moved !== undefined\n ? walkPartition(this.internals, this.internals.sharedDecls, moved.shared, undefined, draft)\n : undefined;\n const spent: string[] = [];\n for (const cardId of envelope.shared?.spent ?? []) {\n if (this.internals.cardsById.has(cardId)) spent.push(cardId);\n else draft.droppedSpent.push(cardId);\n }\n const flows: [string, FlowSave][] = [];\n const sections: Sections | undefined = moved !== undefined ? { ...moved.rest } : undefined;\n if (sections !== undefined && shared !== undefined) {\n sectionsOf(shared, (kind, id) => (kind === \"story\" ? \"story\" : sharedKey(kind, id!)), sections);\n }\n for (const [id, saved] of Object.entries(envelope.flows ?? {})) {\n const withProps: FlowSave = moved !== undefined\n ? { ...saved, props: moved.flows.get(id) ?? emptyPartitionValues() }\n : { ...saved };\n const clean = this.planFlowRestore(id, withProps, undefined, draft);\n if (sections !== undefined && clean.props !== undefined) {\n // The flow's values go into the registry, where its bags claim them; the\n // restored flow itself carries none.\n sectionsOf(clean.props, (kind, owner) => flowKey(id, kind, owner), sections);\n delete clean.props;\n }\n flows.push([id, clean]);\n }\n return {\n report: finishReport(this.internals.bundle.content, envelope.content, flows.map(([id]) => id), draft),\n ...(sections !== undefined ? { sections } : {}),\n spent, flows,\n };\n }\n\n /** One flow's walk. `otherClaims` is the rest of the world's shared ledger\n * and is present only for a SINGLE-flow restore into a live engine: a\n * whole-envelope load rebuilds every flow from one consistent moment, so\n * there is nobody else to compete with. */\n private planFlowRestore(\n id: string,\n saved: FlowSave,\n otherClaims: Map<string, number> | undefined,\n draft: ReportDraft,\n ): FlowSave {\n const internals = this.internals;\n // A flow blob without properties (a version 2 envelope's: the registry has\n // them) has nothing to walk.\n const props = saved.props !== undefined ? walkPartition(internals, internals.flowDecls, saved.props, id, draft) : undefined;\n\n const cooldowns: Record<string, number> = {};\n for (const [cardId, turn] of Object.entries(saved.cooldowns ?? {})) {\n if (internals.cardsById.has(cardId)) cooldowns[cardId] = turn;\n else draft.droppedCooldowns.push({ flow: id, card: cardId });\n }\n\n // A deleted entity has no gameId left, so it is named by the id the save\n // carries; everything the build still knows is named by its gameId.\n const cardName = (cardId: string): string => {\n const entry = internals.cardsById.get(cardId);\n return entry ? effectiveGameId(entry.card) : cardId;\n };\n const board: Record<string, string[]> = {};\n const restored = new Map<string, number>();\n for (const [handId, ids] of Object.entries(saved.board ?? {})) {\n const known = internals.handsById.get(handId);\n if (known === undefined) {\n for (const cardId of ids) {\n draft.evicted.push({ flow: id, hand: handId, card: cardName(cardId), reason: \"hand-vanished\" });\n }\n continue;\n }\n const hand = effectiveGameId(known.hand);\n const kept: string[] = [];\n for (const cardId of ids) {\n const entry = internals.cardsById.get(cardId);\n if (entry === undefined) {\n draft.evicted.push({ flow: id, hand, card: cardId, reason: \"vanished\" });\n continue;\n }\n if (otherClaims !== undefined && cardIsShared(entry.card, entry.deck.shared ?? false)) {\n const held = (otherClaims.get(cardId) ?? 0) + (restored.get(cardId) ?? 0);\n if (held >= sharedCap(entry.card)) {\n draft.evicted.push({ flow: id, hand, card: effectiveGameId(entry.card), reason: \"claimed-elsewhere\" });\n continue;\n }\n restored.set(cardId, (restored.get(cardId) ?? 0) + 1);\n }\n kept.push(cardId);\n }\n board[handId] = kept;\n }\n\n return {\n ...(props !== undefined ? { props } : {}),\n turns: saved.turns ?? {},\n prng: saved.prng,\n cooldowns,\n board,\n playLog: saved.playLog ?? [],\n };\n }\n}\n\n// --- the Flow -----------------------------------------------------------------\n\nexport class Flow {\n readonly id: string;\n private readonly engine: Engine;\n private readonly internals: Internals;\n private closed = false;\n\n private prng: Prng;\n /** Per-box turn counters, keyed by box id (schema 3.4) - per flow. */\n private turnCounts = new Map<string, number>();\n private cooldowns: Record<string, number> = {};\n /** The board: hand contents (card ids, dealt order), keyed by hand id. */\n private boardContents = new Map<string, string[]>();\n private playLog: PlayRecord[] = [];\n // --- play-history indexes -------------------------------------------------\n // The four play-history host functions used to SCAN playLog on every call,\n // and they are called once per candidate card per ask, so dealing was\n // O(candidates x playLog): a shipped game got measurably slower the longer\n // somebody played it, which is the failure mode nobody meets in testing.\n // Measured before the change, 2000 cards: a box with no history condition\n // held flat at 0.3ms while `count_played` went 0.8ms -> 27.9ms as the log\n // reached 4000 plays.\n //\n // These are a pure summary of `playLog`, maintained where it is appended and\n // rebuilt where it is replaced, so they cannot drift from it. They are NOT\n // saved: `playLog` is the record, this is a derivation, and rebuilding on\n // load keeps the save format untouched.\n //\n // The tag keys are the played card's OWN (groupId, tagId) pairs, which is\n // what makes the box-local rule survive: a group name resolves inside the\n // ASKING box, so a card in another box carries different ids and cannot\n // match, exactly as the per-record `inTag` check used to decide.\n private playCount = new Map<string, number>();\n private lastPlayOf = new Map<string, PlayRecord>();\n private tagPlayCount = new Map<string, number>();\n private lastPlayInTag = new Map<string, PlayRecord>();\n /** The per-flow property partitions (the not-shared halves), each bag\n * that declares something registered under this flow's keys. */\n private stores: Partition;\n private readonly registered: string[] = [];\n /** This flow's bags that declare something, under their registry keys. */\n private readonly bagKeys: Array<[string, StateBag]> = [];\n\n private traceHandlers = new Set<TraceHandler>();\n private logEntries: LogEntry[] = [];\n private logSeq = 0;\n\n /** Merged read view per scope, built once (bags are stable for the\n * flow's life): the flow's own bag first, the shared bag behind it.\n * Names are disjoint (shared XOR per-flow by declaration), so \"first\"\n * is routing, not shadowing. */\n private readonly storyReader: ScopeResolver;\n private readonly boxReaders = new Map<string, ScopeResolver>();\n private readonly deckReaders = new Map<string, ScopeResolver>();\n\n /** @internal - built by Engine.openFlow / Engine.loadGame only. */\n constructor(engine: Engine, internals: Internals, id: string, seed: number) {\n this.engine = engine;\n this.internals = internals;\n this.id = id;\n this.prng = makePrng(seed);\n this.stores = buildPartition(internals, flowHalf);\n // Register the bags: each claims whatever the registry holds for its key (a\n // load); openFlow discarded that first for a fresh flow.\n const put = (key: string, bag: StateBag): void => {\n if (bag.declarations().length === 0) return; // holds nothing: not registered\n this.bagKeys.push([key, bag]);\n };\n put(flowKey(id, \"story\"), this.stores.story);\n for (const kind of OWNED_SCOPES) for (const [owner, bag] of this.stores[kind]) put(flowKey(id, kind, owner), bag);\n this.mountBags();\n for (const box of internals.bundle.boxes) {\n this.turnCounts.set(box.id, 0);\n for (const hand of box.hands) this.boardContents.set(hand.id, []);\n }\n const pair = (own: StateBag | undefined, shared: StateBag | undefined): ScopeResolver => ({\n get: (n) => own?.get(n) ?? shared?.get(n),\n });\n // `internals.shared` is reassigned wholesale by loadGame/reset, but a\n // load rebuilds every Flow too, so a live flow's readers and the\n // shared partition are always the same generation.\n this.storyReader = pair(this.stores.story, internals.shared.story);\n for (const box of internals.bundle.boxes) {\n this.boxReaders.set(box.id, pair(this.stores.box.get(box.id), internals.shared.box.get(box.id)));\n for (const deck of box.decks) {\n this.deckReaders.set(deck.id, pair(this.stores.deck.get(deck.id), internals.shared.deck.get(deck.id)));\n }\n }\n }\n\n // --- lifetime ----------------------------------------------------------------\n\n get isClosed(): boolean {\n return this.closed;\n }\n\n /** Close this flow: the handle goes inert, every verb throws. */\n close(): void {\n if (this.closed) return;\n this.engine.dropFlow(this.id, this);\n this.markClosed();\n }\n\n /** @internal */\n markClosed(): void {\n this.releaseBags(false);\n this.closed = true;\n }\n\n /** @internal - take this flow's bags out of the registry; with `keep`, their\n * values wait there for the flow that replaces this one (a load into the\n * game's registry). Idempotent. */\n releaseBags(keep: boolean): void {\n for (const key of this.registered) this.internals.registry.remove(key, { keep });\n this.registered.length = 0;\n }\n\n /** @internal - the registry keys this flow holds right now. */\n registeredKeys(): string[] {\n return [...this.registered];\n }\n\n /** @internal - register this flow's bags (again): at construction, and when a\n * failed hotSwap hands them back. Each claims what the registry holds for it. */\n mountBags(): void {\n for (const [key, bag] of this.bagKeys) {\n this.internals.registry.mountOwned(key, bag, { owner: OWNER });\n this.registered.push(key);\n }\n }\n\n private assertOpen(): void {\n if (this.closed) throw new Error(`flow \"${this.id}\" is closed`);\n }\n\n /** A box's current turn (schema 3.4), on THIS flow's clock. */\n turn(boxRef: string): number {\n this.assertOpen();\n const box = this.internals.boxesByGameId.get(boxRef) ?? this.internals.boxesById.get(boxRef);\n if (!box) throw new Error(`unknown box \"${boxRef}\"`);\n return this.turnCounts.get(box.id) ?? 0;\n }\n\n /** Subscribe to this flow's deal/play trace (schema 5). Returns the\n * unsubscribe. With no subscribers anywhere the flow does no trace work. */\n subscribeTrace(handler: TraceHandler): () => void {\n this.traceHandlers.add(handler);\n return () => this.traceHandlers.delete(handler);\n }\n\n private get tracing(): boolean {\n return this.traceHandlers.size > 0 || this.internals.logCap !== undefined || this.internals.engineTracing();\n }\n\n private emit(event: TraceEvent, turn?: number): void {\n if (this.internals.logCap !== undefined) {\n this.logEntries.push({ ...event, seq: this.logSeq++, ...(turn !== undefined ? { turn } : {}) });\n if (this.logEntries.length > this.internals.logCap) this.logEntries.splice(0, this.logEntries.length - this.internals.logCap);\n }\n for (const handler of this.traceHandlers) handler(event);\n this.internals.emitEngine(this.id, event, turn);\n }\n\n /** The retained flow log (opt-in via the Engine's `log`), oldest first,\n * capped. The introspection seam for hosts and tools; the durable play\n * history in a save stays `playLog` (schema 4) - the log is a\n * flow-lifetime utility and is NOT saved. */\n log(): readonly LogEntry[] {\n return this.logEntries;\n }\n\n /** Empty the retained log; `seq` keeps counting, so ordering across a\n * clear stays meaningful. */\n clearLog(): void {\n this.logEntries = [];\n }\n\n // --- expression plumbing ----------------------------------------------------\n\n private node(expr: Expression): ExprNode {\n let node = this.internals.nodeCache.get(expr);\n if (!node) {\n node = deserialiseAst(expr.ast);\n this.internals.nodeCache.set(expr, node);\n }\n return node;\n }\n\n /** Tag group names are box-scoped: two boxes may name a group the same way\n * (schema 1 - boxes namespace their groups), so a name is only ever\n * resolved inside the box being asked, never bundle-wide. Ids are\n * project-unique and accepted here too, still confined to the box.\n *\n * A box on the project map sees ONE namespace: its own groups, then the\n * map's group (design/project-map-contract.md 3.1). A box that has not\n * opted in does not see the map's name at all, so a peek naming it there\n * is the ordinary unknown-group refusal. Own groups first is stated for\n * determinism only: a bundle that loads never has the two share a name. */\n private groupInBox(box: Box<Expression>, ref: string): TagGroup | undefined {\n const groups = groupsOfBox(this.internals.bundle, box);\n return groups.find((g) => effectiveGameId(g) === ref)\n ?? groups.find((g) => g.id === ref);\n }\n\n /** Fold one play into the indexes. O(the card's tags), not O(the log). */\n private indexPlay(record: PlayRecord): void {\n this.playCount.set(record.card, (this.playCount.get(record.card) ?? 0) + 1);\n this.lastPlayOf.set(record.card, record);\n const entry = this.internals.cardsByGameId.get(record.card);\n if (!entry) return;\n for (const [groupId, tagIds] of Object.entries(entry.card.tags ?? {})) {\n for (const tagId of tagIds) {\n // Keyed by the PLAYED card's box: history is box-specific (D7).\n const key = tagKey(entry.box.id, groupId, tagId);\n this.tagPlayCount.set(key, (this.tagPlayCount.get(key) ?? 0) + 1);\n this.lastPlayInTag.set(key, record);\n }\n }\n }\n\n /** Rebuild the indexes from the log. Called wherever `playLog` is REPLACED\n * rather than appended to, which is `restore` alone. */\n private rebuildPlayIndex(): void {\n this.playCount.clear();\n this.lastPlayOf.clear();\n this.tagPlayCount.clear();\n this.lastPlayInTag.clear();\n for (const record of this.playLog) this.indexPlay(record);\n }\n\n /** `box` is the box whose ask is being evaluated: the play-history\n * functions take a bare group name, so it resolves there, and they count\n * only that box's own plays (the box is in the index key). That was\n * automatic while every group was a box's; a project-map zone is shared,\n * and its history is still not (design/project-map-contract.md 3.7, D7).\n * History is THIS flow's: countPlayed answers \"have I done this\". */\n /** One host per box, built once.\n *\n * The closures below read `this.playCount`, `this.turnCounts` and the rest\n * LIVE, so a cached host answers with current state - which is what makes\n * caching safe rather than a snapshot bug. Unreal did this from the start\n * (`hostsByBox_`, built at flow construction) and the other three rebuilt a\n * host, and its closures, on every `evalCtx` call: once per deck per ask,\n * and once per surviving card in the eviction pass. Structural divergence\n * in one port AND the allocation the audit flagged, so the other three\n * copied it (2026-08-29). Lazy rather than eager, so a bundle's unvisited\n * boxes cost nothing. */\n private hostsByBox = new Map<string, StoryletsHost>();\n\n private host(box: Box<Expression>): StoryletsHost {\n const cached = this.hostsByBox.get(box.id);\n if (cached !== undefined) return cached;\n const made = this.makeHost(box);\n this.hostsByBox.set(box.id, made);\n return made;\n }\n\n private makeHost(box: Box<Expression>): StoryletsHost {\n /** A group NAME and tag name resolved in THIS box, as the index's key,\n * with this box in it: a zone's plays in another box are not this box's\n * history. Resolved once per call now, where `inTag` used to resolve it\n * again for every record in the log. Undefined when either name is\n * unknown here, which is the old per-record `false` and answers \"never\". */\n const keyOf = (group: string, tag: string): string | undefined => {\n const found = this.groupInBox(box, group);\n const t = found?.tags.find((v) => v.gameId === tag);\n return found && t ? tagKey(box.id, found.id, t.id) : undefined;\n };\n /** Turns-since is measured on the played card's box's clock (3.4). */\n const since = (record: PlayRecord): number => {\n const entry = this.internals.cardsByGameId.get(record.card);\n if (!entry) return NEVER_PLAYED;\n return (this.turnCounts.get(entry.box.id) ?? 0) - record.turn;\n };\n return {\n nextRandom: () => this.prng.next(),\n countPlayed: (card) => this.playCount.get(card) ?? 0,\n turnsSincePlayed: (card) => {\n const last = this.lastPlayOf.get(card);\n return last ? since(last) : NEVER_PLAYED;\n },\n countPlayedIn: (group, tag) => {\n const key = keyOf(group, tag);\n return key === undefined ? 0 : this.tagPlayCount.get(key) ?? 0;\n },\n turnsSincePlayedIn: (group, tag) => {\n const key = keyOf(group, tag);\n const last = key === undefined ? undefined : this.lastPlayInTag.get(key);\n return last ? since(last) : NEVER_PLAYED;\n },\n };\n }\n\n /** The evaluation environment (schema 3.1/6.2): @box/@deck resolve to the\n * card under evaluation; in hand-condition contexts @deck is an empty bag,\n * so any reference is an eval error (missing-policy throw). Every scope\n * is the flow's MERGED view - its own copies over the shared values,\n * names disjoint - and @world reads through the engine's resolver. */\n private evalCtx(box: Box<Expression>, deck: Deck<Expression> | undefined, handEnv: HandEnv): EvalContext {\n const others = this.internals.registryView();\n return {\n scopes: {\n // Every other engine's game-wide scope first (every engine reads every\n // scope); this engine's own tokens are its merged views, over the top.\n ...others.scopes,\n world: this.internals.worldResolver,\n story: this.storyReader,\n box: this.boxReaders.get(box.id) ?? {},\n deck: deck ? this.deckReaders.get(deck.id) ?? {} : {},\n hand: handEnv.bag,\n },\n host: this.host(box) as unknown as Record<string, unknown>,\n // The quality channel, answering for THIS ask's box and deck. Only wired\n // when a quality exists, so a bundle without one evaluates byte-\n // identically to before the feature.\n ...(this.internals.hasQualities || others.qualities !== undefined ? {\n qualities: (scope: string, name: string): readonly string[] | undefined =>\n scope === \"world\" ? this.internals.ladders.world.get(name) ?? others.qualities?.(scope, name)\n : scope === \"story\" ? this.internals.ladders.story.get(name)\n : scope === \"box\" ? this.internals.ladders.box.get(box.id)?.get(name)\n : scope === \"deck\" && deck ? this.internals.ladders.deck.get(deck.id)?.get(name)\n // @hand is composed, so the ladder belongs to whatever supplied the\n // value THIS ask: the bound tag, or the asking hand. `sources` is\n // already the map that answers that, because write-back needs it.\n : scope === \"hand\" ? this.handLadder(handEnv, name)\n : others.qualities?.(scope, name),\n } : {}),\n };\n }\n\n /** The ladder behind one composed @hand name, or undefined when the name is\n * not a quality (or came from criteria, which are tag NAMES, never state). */\n private handLadder(handEnv: HandEnv, name: string): readonly string[] | undefined {\n const source = handEnv.sources.get(name);\n if (!source) return undefined;\n return source.kind === \"value\" ? this.internals.ladders.value.get(source.id)?.get(name)\n : source.kind === \"hand\" ? this.internals.ladders.hand.get(source.id)?.get(name)\n : undefined;\n }\n\n private eval(expr: Expression, ctx: EvalContext): ScalarValue {\n return evaluate(this.node(expr), ctx, storyletsDialect);\n }\n\n private passes(expr: Expression | undefined, ctx: EvalContext, where?: string): boolean {\n if (!expr) return true;\n try {\n return conditionPasses(this.eval(expr, ctx));\n } catch (e) {\n // An eval error is never a silent pass: the card/deck is unavailable\n // (schema 3.1), and the trace surfaces the diagnostic.\n if (this.tracing) {\n this.emit({ type: \"diagnostic\", where: where ?? \"condition\", message: e instanceof Error ? e.message : String(e) });\n }\n return false;\n }\n }\n\n // --- resolving asks (schema 2.6 + 3.6) -----------------------------------------\n\n private tagByGameId(group: TagGroup, gameId: string): Tag | undefined {\n return group.tags.find((t) => t.gameId === gameId);\n }\n\n /** A deal's ask: the hand's template bindings + chosen tags, or its rule's\n * bindings, plus the implicit home binding (schema 2.4). */\n private askForHand(hand: Hand<Expression>, box: Box<Expression>): AskDescriptor {\n const boundTags = new Map<string, string>();\n const askNames: Record<string, string> = {};\n let condition: Expression | undefined;\n if (hand.template !== undefined) {\n const template = this.internals.templatesById.get(hand.template);\n if (!template) throw new Error(`hand \"${effectiveGameId(hand)}\": unknown template \"${hand.template}\"`);\n for (const [groupId, tagId] of Object.entries(template.bindings ?? {})) {\n boundTags.set(groupId, tagId);\n }\n for (const [groupId, tagId] of Object.entries(hand.chosen ?? {})) {\n // A hole filled from a property rather than with a tag: resolve it\n // now, before tag composition (4.6, the hand that moves).\n if (isHoleRef(tagId)) {\n this.fillHoleFromProperty(hand, groupId, tagId, boundTags, askNames);\n continue;\n }\n boundTags.set(groupId, tagId);\n const found = this.internals.groupsById.get(groupId);\n const tag = found?.group.tags.find((t) => t.id === tagId);\n if (found && tag) askNames[effectiveGameId(found.group)] = effectiveGameId(tag);\n }\n condition = template.condition;\n } else {\n for (const [groupId, tagId] of Object.entries(hand.rule?.bindings ?? {})) {\n if (isHoleRef(tagId)) {\n this.fillHoleFromProperty(hand, groupId, tagId, boundTags, askNames);\n continue;\n }\n boundTags.set(groupId, tagId);\n // ...and name it, exactly as the template branch above does: a card\n // reading @hand.<group> must not care HOW the group got bound\n // (design/hand-typing.md, the residues).\n const found = this.internals.groupsById.get(groupId);\n const tag = found?.group.tags.find((t) => t.id === tagId);\n if (found && tag) askNames[effectiveGameId(found.group)] = effectiveGameId(tag);\n }\n condition = hand.rule?.condition;\n }\n boundTags.set(PLACE_GROUP, hand.id);\n this.bindStateGroups(box, boundTags, askNames);\n return { box, hand, ...(condition !== undefined ? { condition } : {}), boundTags, askNames };\n }\n\n /** A peek's ask: raw criteria ({group gameId: tag gameId}), bindings only,\n * no condition slot (schema 3.1; the boundary, Reboot 4). */\n private askForPeek(box: Box<Expression>, criteria: Record<string, string>): AskDescriptor {\n const boundTags = new Map<string, string>();\n const askNames: Record<string, string> = {};\n for (const [groupRef, tagRef] of Object.entries(criteria)) {\n if (groupRef === PLACE_GROUP) {\n const hand = this.internals.handsByGameId.get(tagRef) ?? this.internals.handsById.get(tagRef);\n if (!hand) throw new Error(`peek: unknown hand \"${tagRef}\" in home criteria`);\n boundTags.set(PLACE_GROUP, hand.hand.id);\n continue;\n }\n const found = this.groupInBox(box, groupRef);\n if (!found) {\n throw new Error(`peek: unknown tag group \"${groupRef}\" in box \"${effectiveGameId(box)}\"`);\n }\n const tag = this.tagByGameId(found, tagRef) ?? found.tags.find((t) => t.id === tagRef);\n if (!tag) throw new Error(`peek: unknown tag \"${tagRef}\" in group \"${effectiveGameId(found)}\"`);\n boundTags.set(found.id, tag.id);\n askNames[effectiveGameId(found)] = effectiveGameId(tag);\n }\n this.bindStateGroups(box, boundTags, askNames);\n return { box, boundTags, askNames };\n }\n\n /**\n * Fill one hole from the property its value names: the hand that moves\n * (design/engine-server.md 4.6).\n *\n * The semantics are `bindStateGroups`' below, word for word, applied per\n * HOLE instead of per group: resolved at ask time, and a value naming no tag\n * leaves the hole UNBOUND (a wildcard) with a diagnostic rather than dealing\n * a silently empty hand. What is added is the `@hand` scope - the asking\n * hand's OWN declared state, read here from the flow's merged view (the\n * shared half under the flow's own, so a `shared: true` declaration moves\n * the hole for every flow and a per-flow one moves it for this flow alone).\n *\n * Read BEFORE tag composition, which is the whole reason it is safe: the\n * @hand bag a card sees is built from the bound tags, so resolving a hole\n * from it would be circular. A hand's own declarations are not, so they are.\n */\n private fillHoleFromProperty(\n hand: Hand<Expression>, groupId: string, ref: string,\n boundTags: Map<string, string>, askNames: Record<string, string>,\n ): void {\n const found = this.internals.groupsById.get(groupId);\n const groupName = found ? effectiveGameId(found.group) : groupId;\n const where = `hand ${effectiveGameId(hand)}, tag group ${groupName}`;\n const parsed = parseHoleRef(ref);\n if (!parsed) {\n this.emit({ type: \"diagnostic\", where, message: `\"${ref}\" is not a @hand, @world or @story property reference` });\n return;\n }\n if (!found) {\n this.emit({ type: \"diagnostic\", where, message: `\"${ref}\" fills a tag group that is not in this box` });\n return;\n }\n let value: ScalarValue | undefined;\n if (parsed.scope === \"hand\") {\n value = this.valuesOf(\"hand\", hand.id)[parsed.name];\n } else {\n try {\n value = this.getProperty(`${parsed.scope}.${parsed.name}`);\n } catch {\n value = undefined;\n }\n }\n if (value === undefined) {\n this.emit({ type: \"diagnostic\", where, message: `\"${ref}\" names a property that is not declared` });\n return;\n }\n const wanted = typeof value === \"string\" ? value : String(value);\n const tag = found.group.tags.find((t) => effectiveGameId(t) === wanted);\n if (!tag) {\n this.emit({ type: \"diagnostic\", where, message: `${ref} is \"${wanted}\", which is not one of the tags of \"${groupName}\"` });\n return;\n }\n boundTags.set(groupId, tag.id);\n askNames[groupName] = effectiveGameId(tag);\n }\n\n /**\n * Bind every `boundBy` group in the box from the property it names.\n *\n * The gap this closes: only a hand could bind a group, and `deal` takes no\n * criteria, so an axis driven by state (an act, a chapter) had nowhere to\n * gate. Runs AFTER the hand's own bindings and never overwrites one: an\n * explicit binding is a deliberate act and beats a default.\n *\n * A value naming no tag in the group leaves the group UNBOUND rather than\n * matching nothing. Unbound is a wildcard, so the ask still deals; a silent\n * empty hand would look like content that does not exist, and the diagnostic\n * is what says otherwise.\n */\n private bindStateGroups(box: Box<Expression>, boundTags: Map<string, string>, askNames: Record<string, string>): void {\n // The box's own groups and, when it is on the project map, the map's\n // group: a `boundBy` there binds in every opted-in box (3.2).\n for (const group of groupsOfBox(this.internals.bundle, box)) {\n if (group.boundBy === undefined || boundTags.has(group.id)) continue;\n const ref = /^@(world|story)\\.([a-z][a-z0-9_-]*)$/.exec(group.boundBy);\n if (!ref) {\n this.emit({ type: \"diagnostic\", where: `tag group ${effectiveGameId(group)}`, message: `boundBy \"${group.boundBy}\" is not a @world or @story property reference` });\n continue;\n }\n let value: ScalarValue | undefined;\n try {\n value = this.getProperty(`${ref[1]}.${ref[2]}`);\n } catch {\n this.emit({ type: \"diagnostic\", where: `tag group ${effectiveGameId(group)}`, message: `boundBy \"${group.boundBy}\" names a property that is not declared` });\n continue;\n }\n const wanted = typeof value === \"string\" ? value : String(value);\n const tag = group.tags.find((t) => effectiveGameId(t) === wanted);\n if (!tag) {\n this.emit({ type: \"diagnostic\", where: `tag group ${effectiveGameId(group)}`, message: `${group.boundBy} is \"${wanted}\", which is not one of its tags` });\n continue;\n }\n boundTags.set(group.id, tag.id);\n askNames[effectiveGameId(group)] = effectiveGameId(tag);\n }\n }\n\n // --- @hand composition (schema 3.6) -------------------------------------------\n\n /** A store's full value view for one owner: the shared half under the\n * flow's half. Names are disjoint, so the spread is routing, not\n * shadowing. */\n private valuesOf(kind: Exclude<PartitionKind, \"story\">, id: string): PropertyBag {\n return {\n ...(this.internals.shared[kind].get(id)?.values ?? {}),\n ...(this.stores[kind].get(id)?.values ?? {}),\n };\n }\n\n private buildHandEnv(ask: AskDescriptor): HandEnv {\n const bag: PropertyBag = {};\n const sources = new Map<string, HandSource>();\n\n // 1. Tag properties of every bound tag (home binds a hand, not a tag).\n for (const [groupId, tagId] of ask.boundTags) {\n if (groupId === PLACE_GROUP) continue;\n for (const [name, value] of Object.entries(this.valuesOf(\"value\", tagId))) {\n bag[name] = value;\n sources.set(name, { kind: \"value\", id: tagId });\n }\n }\n // 2. Hand properties, when the ask is a deal.\n if (ask.hand) {\n for (const [name, value] of Object.entries(this.valuesOf(\"hand\", ask.hand.id))) {\n bag[name] = value;\n sources.set(name, { kind: \"hand\", id: ask.hand.id });\n }\n }\n // 3. Chosen tags / criteria, by group name (the tag's gameId as value).\n for (const [name, value] of Object.entries(ask.askNames)) {\n bag[name] = value;\n sources.set(name, { kind: \"criteria\" });\n }\n return { bag, sources, boundTags: ask.boundTags };\n }\n\n // --- the ask (schema 3.1 + 3.2) ------------------------------------------------\n\n /** The claims ledger, derived from THIS flow's board: card id -> holding\n * hands (schema 3.5). Claims are per flow - another flow holding the\n * card is another playthrough, not a rival hand. */\n private claims(): Map<string, number> {\n const counts = new Map<string, number>();\n for (const contents of this.boardContents.values()) {\n for (const id of contents) counts.set(id, (counts.get(id) ?? 0) + 1);\n }\n return counts;\n }\n\n /** @internal - every card id on THIS flow's board, one entry per holding\n * hand. The engine sums these across live flows for the shared ledger. */\n heldCardIds(): string[] {\n return [...this.boardContents.values()].flat();\n }\n\n private copiesOf(card: Card<Expression>): number {\n return card.copies ?? 1;\n }\n\n /** The claims step (schema 3.1 step 6) for one card, as a verdict or null\n * for \"available\". Two caps apply to a shared card and they are different\n * statements, so they get different verdicts: `copies` is your own board\n * filling up, `sharedCopies` is somebody else already holding it, and a\n * participant told \"claimed\" about a card sitting on another person's\n * table would read it as an engine fault (design/shared-scarcity 9.3.1).\n *\n * `mine` counts this flow's holdings, `world` every live flow's. */\n private claimVerdict(\n card: Card<Expression>,\n shared: boolean,\n mine: Map<string, number>,\n world: Map<string, number>,\n ): \"claimed\" | \"claimed-elsewhere\" | null {\n const id = card.id;\n if ((mine.get(id) ?? 0) >= this.copiesOf(card)) return \"claimed\";\n if (shared && (world.get(id) ?? 0) >= sharedCap(card)) return \"claimed-elsewhere\";\n return null;\n }\n\n /** Tag matching (schema 3.1 step 3): for every bound group the card lists\n * the bound tag or omits the group (wildcard); the home group inverts -\n * a homed card requires a matching home binding (schema 2.4). */\n private tagsMatch(card: Card<Expression>, boundTags: Map<string, string>): boolean {\n const home = card.tags?.[PLACE_GROUP];\n if (home !== undefined && home.length > 0) {\n const bound = boundTags.get(PLACE_GROUP);\n if (bound === undefined || !home.includes(bound)) return false;\n }\n for (const [groupId, tagId] of boundTags) {\n if (groupId === PLACE_GROUP) continue;\n const tags = card.tags?.[groupId];\n if (tags === undefined) {\n // Omission is a wildcard unless the group says otherwise. A required\n // group inverts it, which is what `place` has always done per card.\n if (this.internals.requiredGroups.has(groupId)) return false;\n continue;\n }\n if (!tags.includes(tagId)) return false;\n }\n return true;\n }\n\n /** Run one ask: availability filter then ranking. `claimed` decides the\n * claims step (step 6) per card, returning the verdict that refused it or\n * null for available. `trace` (when a subscriber exists) collects the\n * per-card verdicts. */\n private runAsk(\n ask: AskDescriptor,\n claimed: (card: Card<Expression>, shared: boolean) => \"claimed\" | \"claimed-elsewhere\" | null,\n trace?: { id: string; verdict: TraceVerdict; priority?: number; specificity?: number }[],\n ): { ordered: CardEntry[]; handEnv: HandEnv } {\n const { box } = ask;\n const handEnv = this.buildHandEnv(ask);\n // Identity on the trace is by gameId (4.4), so the helper takes the CARD\n // rather than an id: every call site had one in hand, and taking the id\n // was the whole of how the two vocabularies got mixed.\n const verdict = (card: Card<Expression>, v: TraceVerdict): void => {\n trace?.push({ id: effectiveGameId(card), verdict: v });\n };\n\n // The hand's condition: ask-constant, evaluated once (schema 3.1 step 4).\n if (!this.passes(ask.condition, this.evalCtx(box, undefined, handEnv), `hand ${ask.hand ? effectiveGameId(ask.hand) : \"\"} condition`)) {\n return { ordered: [], handEnv };\n }\n\n // Deck gates: evaluated once per ask, in deck (id) order (schema 2.5).\n const gateOk = new Map<string, boolean>();\n for (const deck of box.decks) {\n gateOk.set(deck.id, this.passes(deck.condition, this.evalCtx(box, deck, handEnv), `deck ${deck.gameId} gate`));\n }\n\n const turn = this.turnCounts.get(box.id) ?? 0;\n const scored: { entry: CardEntry; priority: number; spec: number }[] = [];\n for (const deck of box.decks) {\n // ONE context per deck, not per card. It is built from box, deck and\n // handEnv, none of which vary inside this loop, and a condition is a\n // read-only gate (schema 3.1), so nothing can write through it and make\n // sharing visible. Rebuilding it per card cost an EvalContext, a scopes\n // map and five bag wrappers each time: about half the garbage a peek over\n // a large box produced (port-review-2026-08.md, measured).\n const deckCtx = this.evalCtx(box, deck, handEnv);\n const deckShared = deck.shared ?? false;\n for (const card of deck.cards) {\n const shared = cardIsShared(card, deckShared);\n if (!gateOk.get(deck.id)) {\n verdict(card, \"deck-gate\");\n continue;\n }\n // Taken out of the world by somebody's shared one-shot. Checked\n // before the flow's own clock, because \"cooldown\" would point the\n // reader at a turn counter that has nothing to do with it.\n if (shared && this.engine.isTaken(card.id)) {\n verdict(card, \"taken\");\n continue;\n }\n if ((this.cooldowns[card.id] ?? 0) > turn) {\n verdict(card, \"cooldown\");\n continue;\n }\n if (!this.tagsMatch(card, handEnv.boundTags)) {\n verdict(card, \"tags\");\n continue;\n }\n // The label is only read when an eval THROWS and only when tracing, so\n // building it per card was pure waste on the path that matters. Built\n // when tracing is on, where the cost is already accepted.\n if (card.condition && !this.passes(card.condition, deckCtx,\n this.tracing ? `card ${card.gameId} condition` : undefined)) {\n verdict(card, \"condition\");\n continue;\n }\n const refused = claimed(card, shared); // claims, last (schema 3.1 step 6)\n if (refused) {\n verdict(card, refused);\n continue;\n }\n\n let priority: number;\n if (typeof card.priority === \"number\") {\n priority = card.priority;\n } else {\n try {\n const v = this.eval(card.priority, deckCtx);\n if (typeof v !== \"number\") {\n verdict(card, \"priority\");\n continue;\n }\n priority = v;\n } catch (e) {\n if (this.tracing) {\n this.emit({ type: \"diagnostic\", where: `card ${card.gameId} priority`, message: e instanceof Error ? e.message : String(e) });\n }\n verdict(card, \"priority\");\n continue;\n }\n }\n let spec = 0;\n if (box.ranking.specificity && card.condition) {\n const node = this.node(card.condition);\n spec = matchedSpecificity(node, (n) => {\n try {\n return conditionPasses(evaluate(n, deckCtx, storyletsDialect));\n } catch {\n return false;\n }\n });\n }\n scored.push({ entry: { card, deck, box }, priority, spec });\n }\n }\n\n scored.sort((a, b) => b.priority - a.priority || b.spec - a.spec); // stable\n // Seeded shuffle of each maximal tie run; runs of 1 consume no draws.\n let i = 0;\n while (i < scored.length) {\n let j = i + 1;\n while (j < scored.length\n && scored[j]!.priority === scored[i]!.priority\n && scored[j]!.spec === scored[i]!.spec) j++;\n if (j - i > 1) {\n const run = scored.slice(i, j);\n shuffleInPlace(run, this.prng);\n // Written back element by element, as all three ports do. It used to be\n // `scored.splice(i, j - i, ...run)`, which SPREADS one argument per\n // element: with every card at the default priority 0 the tie run is the\n // whole list, and a box of 150 000 such cards threw `RangeError:\n // Maximum call stack size exceeded` rather than dealing. Far-fetched\n // for one box, but it was a crash where the ports had no limit, and the\n // reference is supposed to be the thing they are transliterated from.\n for (let k = 0; k < run.length; k++) scored[i + k] = run[k]!;\n }\n i = j;\n }\n for (const s of scored) {\n trace?.push({ id: effectiveGameId(s.entry.card), verdict: \"dealt\", priority: s.priority, specificity: s.spec });\n }\n return { ordered: scored.map((s) => s.entry), handEnv };\n }\n\n /** Flip eligible-but-not-taken trace entries to \"capped\". `taken` is keyed\n * by GAMEID, as the trace rows are (4.4): the two must move together or\n * every dealt card silently reads as capped. */\n private capTrace(\n trace: { id: string; verdict: TraceVerdict; priority?: number; specificity?: number }[],\n taken: ReadonlySet<string>,\n ): void {\n for (const entry of trace) {\n if (entry.verdict === \"dealt\" && !taken.has(entry.id)) entry.verdict = \"capped\";\n }\n }\n\n private view(entry: CardEntry): DealtCard {\n const { card } = entry;\n return {\n id: card.id,\n gameId: effectiveGameId(card),\n ...(card.title !== undefined ? { title: card.title } : {}),\n ...(card.purpose !== undefined ? { purpose: card.purpose } : {}),\n ...(card.fields !== undefined ? { fields: card.fields } : {}),\n };\n }\n\n private handCapacity(hand: Hand<Expression>): number {\n if (hand.slots !== undefined) return hand.slots;\n const declared = hand.template !== undefined\n ? this.internals.templatesById.get(hand.template)?.slots\n : hand.rule?.slots;\n return declared === undefined || declared === \"unbounded\" ? Infinity : declared;\n }\n\n private resolveHand(ref: string): { hand: Hand<Expression>; box: Box<Expression> } {\n const found = this.internals.handsByGameId.get(ref) ?? this.internals.handsById.get(ref);\n if (!found) throw new Error(`unknown hand \"${ref}\"`);\n return found;\n }\n\n // --- host surface (schema 5) ---------------------------------------------------\n\n /** Look at the top of the stock through raw tag criteria (schema 3.1):\n * claims respected, nothing registered, nothing left behind but the\n * trace line. You can never play a card you only peeked. */\n peek(boxRef: string, criteria: Record<string, string> = {}, n?: number): RankedList {\n this.assertOpen();\n const box = this.internals.boxesByGameId.get(boxRef) ?? this.internals.boxesById.get(boxRef);\n if (!box) throw new Error(`unknown box \"${boxRef}\"`);\n const ask = this.askForPeek(box, criteria);\n const claimCounts = this.claims();\n // Skipped outright when the bundle shares nothing, which is most bundles:\n // the ledger walks every live flow's whole board, and an empty map answers\n // every question the same way a computed one would.\n const worldClaims = this.internals.hasShared ? this.engine.sharedClaims() : new Map<string, number>();\n const trace = this.tracing ? [] : undefined;\n const { ordered } = this.runAsk(ask, (card, shared) => this.claimVerdict(card, shared, claimCounts, worldClaims), trace);\n // CLAMPED. `slice(0, -1)` drops the last card and returns the rest, so a\n // negative n answered with almost the whole list here while every port\n // returned nothing (2026-08-29).\n const listed = n === undefined ? ordered : ordered.slice(0, Math.max(n, 0));\n if (trace) {\n this.capTrace(trace, new Set(listed.map((e) => effectiveGameId(e.card))));\n this.emit({ type: \"peek\", box: effectiveGameId(box), criteria, cards: trace }, this.turnCounts.get(box.id) ?? 0);\n }\n return { box: effectiveGameId(box), cards: listed.map((e) => this.view(e)) };\n }\n\n /** Refresh one hand (schema 3.5); returns its new shape. */\n deal(handRef: string): DealtCard[] {\n this.assertOpen();\n const { hand } = this.resolveHand(handRef);\n return this.dealMany([handRef])[effectiveGameId(hand)] ?? [];\n }\n\n /** Re-deal several / all hands (schema 3.5): seeded hand-order shuffle\n * (fairness), evict, seed the ledger from survivors, fill in order.\n * Returns the dealt slice - the new contents of exactly the hands this\n * call dealt, keyed by hand gameId (board() stays the whole-board read). */\n dealMany(handRefs?: string[]): Record<string, DealtCard[]> {\n this.assertOpen();\n const dealt = (handRefs ?? [...this.internals.handsById.keys()].sort())\n .map((ref) => this.resolveHand(ref));\n shuffleInPlace(dealt, this.prng);\n\n // Eviction first: drop dealt cards no longer available to their hand\n // (minus the claims check against their own seat).\n for (const { hand, box } of dealt) {\n const ask = this.askForHand(hand, box);\n const handEnv = this.buildHandEnv(ask);\n const conditionOk = this.passes(ask.condition, this.evalCtx(box, undefined, handEnv));\n const gateOk = new Map<string, boolean>();\n for (const deck of box.decks) {\n gateOk.set(deck.id, this.passes(deck.condition, this.evalCtx(box, deck, handEnv)));\n }\n const turn = this.turnCounts.get(box.id) ?? 0;\n // Trace events fire after the state they report has landed (a handler\n // reading the board sees the eviction), so they are collected here and\n // emitted once the survivors are set.\n const evicted: { card: string; reason: Extract<TraceEvent, { type: \"evict\" }>[\"reason\"] }[] = [];\n // The card is named by gameId (4.4). A card the build no longer has -\n // the `vanished` branch below - has no gameId left, so it is named by\n // the id the board carries, which is the rule a load report has always\n // used for the same reason.\n const evict = (cardId: string, reason: Extract<TraceEvent, { type: \"evict\" }>[\"reason\"]): false => {\n const known = this.internals.cardsById.get(cardId);\n evicted.push({ card: known ? effectiveGameId(known.card) : cardId, reason });\n return false;\n };\n const survivors = (this.boardContents.get(hand.id) ?? []).filter((cardId) => {\n if (!conditionOk) return evict(cardId, \"hand-condition\");\n const entry = this.internals.cardsById.get(cardId);\n if (!entry) return evict(cardId, \"vanished\"); // edited content: dropped\n if (!gateOk.get(entry.deck.id)) return evict(cardId, \"deck-gate\");\n if ((this.cooldowns[cardId] ?? 0) > turn) return evict(cardId, \"cooldown\");\n if (!this.tagsMatch(entry.card, handEnv.boundTags)) return evict(cardId, \"tags\");\n if (!this.passes(entry.card.condition, this.evalCtx(box, entry.deck, handEnv), `card ${entry.card.gameId} condition`)) {\n return evict(cardId, \"condition\");\n }\n return true;\n });\n this.boardContents.set(hand.id, survivors);\n if (this.tracing) {\n for (const e of evicted) this.emit({ type: \"evict\", hand: effectiveGameId(hand), card: e.card, reason: e.reason }, turn);\n }\n }\n\n const claimCounts = this.claims();\n // The world ledger is taken once for the whole batch and kept in step with\n // the local one below, so two hands in the SAME deal cannot both take the\n // last shared copy. Skipped outright when the bundle shares nothing (most\n // bundles): an empty map answers every question the same way.\n const worldClaims = this.internals.hasShared ? this.engine.sharedClaims() : new Map<string, number>();\n for (const { hand, box } of dealt) {\n const contents = this.boardContents.get(hand.id) ?? [];\n const free = this.handCapacity(hand) - contents.length;\n if (free <= 0) continue;\n const ask = this.askForHand(hand, box);\n const own = new Set(contents);\n const trace = this.tracing ? [] : undefined;\n // At most once in any one hand; at most `copies` hands here, and at most\n // `sharedCopies` hands anywhere (schema 3.5, shared-scarcity 5).\n const { ordered } = this.runAsk(ask,\n (card, shared) => (own.has(card.id) ? \"claimed\" : this.claimVerdict(card, shared, claimCounts, worldClaims)), trace);\n const taking = ordered.slice(0, free);\n const added = taking.map((e) => e.card.id);\n this.boardContents.set(hand.id, [...contents, ...added]);\n for (const id of added) {\n claimCounts.set(id, (claimCounts.get(id) ?? 0) + 1);\n worldClaims.set(id, (worldClaims.get(id) ?? 0) + 1);\n }\n // Emitted after the hand is set: a handler reading board() sees the deal.\n if (trace) {\n this.capTrace(trace, new Set(taking.map((e) => effectiveGameId(e.card))));\n this.emit({ type: \"deal\", hand: effectiveGameId(hand), cards: trace }, this.turnCounts.get(box.id) ?? 0);\n }\n }\n\n return Object.fromEntries(dealt.map(({ hand }) => [\n effectiveGameId(hand),\n (this.boardContents.get(hand.id) ?? []).map((id) => this.view(this.internals.cardsById.get(id)!)),\n ]));\n }\n\n /** The board: current hand contents, in dealt order, keyed by hand gameId\n * (schema 5). Read it for what is out; peek the stock for what could\n * come.\n *\n * `boxRef` (a box gameId or id) narrows the read to that box's hands, in\n * the same shape and the same order: \"give me the barks hands\" is a\n * common host query, and boxes are how a game separates its storylet\n * systems, so the grouping belongs here rather than in every host. An\n * unknown box throws, as it does on turn() and peek(). */\n board(boxRef?: string): Record<string, DealtCard[]> {\n this.assertOpen();\n let keep: string | undefined;\n if (boxRef !== undefined) {\n const box = this.internals.boxesByGameId.get(boxRef) ?? this.internals.boxesById.get(boxRef);\n if (!box) throw new Error(`unknown box \"${boxRef}\"`);\n keep = box.id;\n }\n return Object.fromEntries([...this.boardContents.entries()]\n .filter(([handId]) => keep === undefined || this.internals.handsById.get(handId)!.box.id === keep)\n .map(([handId, ids]) => [\n effectiveGameId(this.internals.handsById.get(handId)!.hand),\n ids.map((id) => this.view(this.internals.cardsById.get(id)!)),\n ]));\n }\n\n /** Resolve a played/inspected card within a hand on the board. */\n private resolveDealt(cardId: string, handRef: string): { entry: CardEntry; ask: AskDescriptor } {\n const entry = this.internals.cardsById.get(cardId) ?? this.internals.cardsByGameId.get(cardId);\n if (!entry) throw new Error(`unknown card \"${cardId}\"`);\n const { hand, box } = this.resolveHand(handRef);\n if (!(this.boardContents.get(hand.id) ?? []).includes(entry.card.id)) {\n throw new Error(`card \"${effectiveGameId(entry.card)}\" is not dealt to hand \"${effectiveGameId(hand)}\"`);\n }\n return { entry, ask: this.askForHand(hand, box) };\n }\n\n /** Outcome availability, evaluated against CURRENT state on every ask\n * (schema 3.1/5) - never a deal-time snapshot. */\n outcomes(cardId: string, from: string): OutcomeView[] {\n this.assertOpen();\n const { entry, ask } = this.resolveDealt(cardId, from);\n const ctx = this.evalCtx(entry.box, entry.deck, this.buildHandEnv(ask));\n return entry.card.outcomes.map((o) => ({\n id: o.id,\n gameId: effectiveGameId(o),\n ...(o.title !== undefined ? { title: o.title } : {}),\n ...(o.purpose !== undefined ? { purpose: o.purpose } : {}),\n ...(o.fields !== undefined ? { fields: o.fields } : {}),\n available: this.passes(o.condition, ctx),\n }));\n }\n\n /** Apply an outcome (schema 3.7): the card must sit in a hand on the\n * board (you never play a card from inside the deck). Throws before any\n * mutation on a gated-shut outcome or a bad write target.\n *\n * A card with NO outcomes is played with none, named as \"\" (the\n * no-outcome-play brief, 2026-09-14): a masthead, a notice, a codex entry,\n * whose play means \"shown\". It is everything a play is except the writes:\n * the play log and the history functions count it, the box's turn moves by\n * the usual rule, the redraw rests it and it leaves its hand. \"\" is the one\n * spelling in all four runtimes, because a Blueprint pin cannot be absent.\n * Only the empty-for-empty case is new: \"\" on a card that has outcomes is\n * refused, and a named outcome on a card with none is refused as before. */\n play(cardId: string, outcomeGameId: string, from: string, opts: PlayOptions = {}): void {\n this.assertOpen();\n const { entry, ask } = this.resolveDealt(cardId, from);\n const bare = outcomeGameId === \"\";\n if (bare && entry.card.outcomes.length > 0) {\n throw new Error(`card \"${effectiveGameId(entry.card)}\" has outcomes (${entry.card.outcomes.map((o) => effectiveGameId(o)).join(\", \")}); name the one played`);\n }\n const outcome = bare ? undefined : entry.card.outcomes.find((o) => effectiveGameId(o) === outcomeGameId);\n if (!bare && !outcome) throw new Error(`card \"${effectiveGameId(entry.card)}\" has no outcome \"${outcomeGameId}\"`);\n\n const handEnv = this.buildHandEnv(ask);\n const ctx = this.evalCtx(entry.box, entry.deck, handEnv);\n if (outcome && !this.passes(outcome.condition, ctx)) {\n throw new Error(`outcome \"${outcomeGameId}\" on \"${effectiveGameId(entry.card)}\" is gated shut`);\n }\n\n // The played card's box's clock advances (schema 3.4); computed up\n // front so the play and its writes log as one action, one turn stamp.\n //\n // A TIMED box (design/engine-server.md 4.8) defaults to advancing\n // NOTHING: its clock is time, the host ticks it, and a play is not a\n // tick. A call that names `advanceTurns` still gets what it asked for,\n // in either kind of box, because the call says otherwise. This is the\n // whole of `turn`'s effect on the engine: the seconds are never read.\n const perPlay = entry.box.turn !== undefined ? 0 : this.internals.bundle.settings.playAdvancesTurns;\n const newTurn = (this.turnCounts.get(entry.box.id) ?? 0) + (opts.advanceTurns ?? perPlay);\n\n // Every right-hand side evaluates against PRE-play state, then all\n // writes land (schema 3.7).\n const writes: { target: string; value: ScalarValue }[] = [];\n for (const [target, expr] of Object.entries(outcome?.changes ?? {})) {\n writes.push({ target, value: this.eval(expr, ctx) });\n }\n for (const { target, value } of writes) {\n const { path, prev } = this.applyWrite(target, value, entry, handEnv);\n if (this.tracing) this.emit({ type: \"write\", target, path, value, ...(prev !== undefined ? { prev } : {}) }, newTurn);\n }\n\n const outcomeId = outcome ? effectiveGameId(outcome) : \"\";\n const record: PlayRecord = { card: effectiveGameId(entry.card), outcome: outcomeId, turn: newTurn };\n this.playLog.push(record);\n this.indexPlay(record);\n if (entry.card.redraw === \"never\") {\n // A shared one-shot leaves the world rather than this flow: the engine\n // holds it, so every flow is refused. A finite redraw deliberately does\n // NOT share, whatever the deck says - a cooldown is an absolute turn of\n // this flow's box clock, and there is no shared clock to compare it\n // against (design/shared-scarcity.md 9.3.2).\n if (cardIsShared(entry.card, entry.deck.shared ?? false)) this.engine.markTaken(entry.card.id);\n else this.cooldowns[entry.card.id] = Number.MAX_SAFE_INTEGER;\n } else if (typeof entry.card.redraw === \"number\") {\n this.cooldowns[entry.card.id] = newTurn + entry.card.redraw;\n }\n // The card leaves its hand, releasing its claim (schema 3.5/3.7).\n const handId = ask.hand!.id;\n this.boardContents.set(handId,\n (this.boardContents.get(handId) ?? []).filter((id) => id !== entry.card.id));\n this.turnCounts.set(entry.box.id, newTurn);\n // Emitted last: a handler reading the board and the clock sees the play.\n if (this.tracing) this.emit({ type: \"play\", card: effectiveGameId(entry.card), outcome: outcomeId, turn: newTurn }, newTurn);\n }\n\n /** One owned property's address, owner segment and all (4.4). */\n private address(kind: OwnedScope, id: string): string {\n return addressOf(this.internals, kind, id);\n }\n\n /** Land one change in whichever partition declares the name: the flow's\n * bag when the property is per-flow, the shared bag when it is shared -\n * the union/partition invariant made executable. */\n private landIn(kind: Exclude<PartitionKind, \"story\"> | \"story\", id: string | undefined, name: string, value: ScalarValue, path: string): { path: string; prev?: ScalarValue } {\n const own = kind === \"story\" ? this.stores.story : id !== undefined ? this.stores[kind].get(id) : undefined;\n const shared = kind === \"story\" ? this.internals.shared.story : id !== undefined ? this.internals.shared[kind].get(id) : undefined;\n const bag = own !== undefined && own.get(name) !== undefined ? own\n : shared !== undefined && shared.get(name) !== undefined ? shared\n : undefined;\n if (bag === undefined) throw new Error(`no property at \"${path}\"`);\n // An engine write: the bag's subscribers fire (the firing rule).\n const change = bag.set(name, value);\n return { path, ...(change.prev !== undefined ? { prev: change.prev } : {}) };\n }\n\n /** Land one change; returns the resolved store path (for the trace) and\n * the value it replaced (for the log's \"0 -> 1\" reading). */\n private applyWrite(target: string, value: ScalarValue, entry: CardEntry, handEnv: HandEnv): { path: string; prev?: ScalarValue } {\n const match = /^@([a-z]+)\\.([A-Za-z_][A-Za-z0-9_-]*)$/.exec(target);\n if (!match) throw new Error(`bad change target \"${target}\"`);\n const [, scope, name] = match as unknown as [string, string, string];\n switch (scope) {\n case \"world\": {\n const worldSet = this.internals.worldSet;\n if (!worldSet) throw new Error(`@world.${name} cannot be written: the host bound @world read-only`);\n // The story's own promise, kept HERE and only here, because here is where\n // the story does the writing: the table is consulted before the seam, so\n // an outcome never reaches the bag (which would let a host write past it)\n // nor a bound resolver (which cannot tell the two apart). The host's\n // setProperty is its own path and never asks. Patter's runtime refuses the\n // same write through the shared kernel, so both read one way.\n if (this.internals.worldReadOnly.has(name)) throw new Error(`'@world.${name}' is read-only (writable: false)`);\n const prev = this.internals.worldResolver.get(name);\n worldSet(name, value);\n return { path: `world.${name}`, ...(prev !== undefined ? { prev } : {}) };\n }\n case \"story\": return this.landIn(\"story\", undefined, name, value, `story.${name}`);\n case \"box\": return this.landIn(\"box\", entry.box.id, name, value, `${this.address(\"box\", entry.box.id)}.${name}`);\n case \"deck\": return this.landIn(\"deck\", entry.deck.id, name, value, `${this.address(\"deck\", entry.deck.id)}.${name}`);\n case \"hand\": {\n // Write-back routing (schema 3.6): the composed name remembers its\n // source store; writes to criteria/chosen-tag names are errors.\n const source = handEnv.sources.get(name);\n if (!source) throw new Error(`@hand.${name} is not composed in this ask`);\n if (source.kind === \"criteria\") throw new Error(`@hand.${name} is a chosen tag / criteria name and cannot be written`);\n return this.landIn(source.kind, source.id, name, value, `${this.address(source.kind, source.id)}.${name}`);\n }\n default: {\n // Another engine's game-wide scope (`@patter.x`): the family's shared\n // vocabulary lets a card write it, and the registry keeps that engine's\n // rules (a read-only property is refused). A story write, so no host flag.\n if (this.internals.registry.has(scope)) {\n const prev = this.internals.registry.get(scope, name);\n this.internals.registry.set(scope, name, value);\n return { path: `${scope}.${name}`, ...(prev !== undefined ? { prev } : {}) };\n }\n if (this.internals.bundle.externalScopes?.includes(scope)) {\n throw new Error(`@${scope}.${name} cannot be written: no engine on this registry registered @${scope}`);\n }\n throw new Error(`bad change target scope \"@${scope}\"`);\n }\n }\n }\n\n /** Advance one box's clock (schema 3.4): a turn is one draw-from-stock\n * session for that box, on THIS flow's clock. */\n advanceTurns(boxRef: string, n = 1): void {\n this.assertOpen();\n const box = this.internals.boxesByGameId.get(boxRef) ?? this.internals.boxesById.get(boxRef);\n if (!box) throw new Error(`unknown box \"${boxRef}\"`);\n const next = (this.turnCounts.get(box.id) ?? 0) + n;\n this.turnCounts.set(box.id, next);\n if (this.tracing) this.emit({ type: \"turns\", box: effectiveGameId(box), turn: next }, next);\n }\n\n // --- state access (host surface + test tooling) ---------------------------------\n\n /** Every box, bundle order: identity + this flow's clock (the enumeration\n * surface examiners key their turns sections on; parity member). */\n listBoxes(): BoxView[] {\n this.assertOpen();\n return this.internals.bundle.boxes.map((b) => ({\n id: b.id,\n gameId: effectiveGameId(b),\n ...(b.title !== undefined ? { title: b.title } : {}),\n turn: this.turnCounts.get(b.id) ?? 0,\n }));\n }\n\n /** THIS flow's kernel bags with their store path prefixes (the state\n * logger's mount surface; parity member). The shared bags are the\n * Engine's listBags; the flows are rebuilt by loadGame, so consumers\n * re-enumerate after a load. */\n listBags(): BagMount[] {\n this.assertOpen();\n const mounts: BagMount[] = [{ prefix: \"story\", bag: this.stores.story }];\n for (const kind of [\"box\", \"deck\", \"hand\", \"value\"] as const) {\n for (const [id, bag] of this.stores[kind]) mounts.push({ prefix: addressOf(this.internals, kind, id), bag });\n }\n return mounts;\n }\n\n /** The flow's FULL merged view as examiner rows (the property examiner /\n * editor surface, parity across all runtimes): @world read through the\n * resolver, then per scope the shared values and this flow's own.\n * Bundle order: world, story, then per-box / per-deck / per-hand /\n * per-tag stores. */\n listProperties(): PropertyRow[] {\n this.assertOpen();\n const out: PropertyRow[] = [];\n for (const d of this.internals.bundle.world.properties) {\n const value = this.internals.worldResolver.get(d.name);\n out.push({\n path: `world.${d.name}`, name: d.name, type: d.type,\n value: value ?? d.default, default: d.default,\n ...(d.values !== undefined ? { values: d.values } : {}),\n ...(d.stages !== undefined ? { stages: d.stages } : {}),\n // @world is FOREIGN - a host resolver backs it - so writability is whether that\n // resolver can be written at all AND what the declaration says, which is the\n // shared registry's own rule for a foreign scope (its foreignWritable). The\n // `as PropertyView` cast this replaced was hiding the field's absence: the row\n // type has always required it, and these rows shipped without one.\n //\n // A row is where `writable: false` is meant to SHOW (Reboot.md 10): it tells a\n // state panel this is the game's value, not the story's. It does not stop the\n // panel editing it - the host's setProperty passes `{ host: true }`.\n writable: this.internals.worldSet !== undefined && !this.internals.worldReadOnly.has(d.name),\n });\n }\n const add = (_prefix: string, shared: StateBag | undefined, own: StateBag | undefined): void => {\n for (const bag of [shared, own]) {\n if (bag === undefined) continue;\n for (const row of bag.rows()) out.push(row);\n }\n };\n add(\"story\", this.internals.shared.story, this.stores.story);\n for (const kind of OWNED_SCOPES) {\n const ids = new Set([...this.internals.shared[kind].keys(), ...this.stores[kind].keys()]);\n for (const id of ids) {\n add(addressOf(this.internals, kind, id), this.internals.shared[kind].get(id), this.stores[kind].get(id));\n }\n }\n return out;\n }\n\n /** Read by path: \"world.x\", \"story.gold\", \"value.docks.danger\",\n * \"box.village.heat\", \"deck.wares.n\", \"hand.the-elder.zone\" - the flow's\n * merged view, routed by the declaration's sharing.\n *\n * The owner segment is the entity's GAMEID, the name it is called by\n * everywhere else (4.4). Its internal id is accepted for this release and\n * earns a `diagnostic` naming the address to move to; the next lockstep\n * release refuses it. */\n getProperty(path: string): ScalarValue {\n this.assertOpen();\n const found = this.resolvePath(path);\n const value = found.kind === \"world\" ? this.internals.worldResolver.get(found.name)\n : found.kind === \"scope\" ? this.internals.registry.get(found.token, found.name)\n : found.own?.get(found.name) ?? found.shared?.get(found.name);\n if (value === undefined) throw new Error(`no property at \"${path}\"`);\n return value;\n }\n\n setProperty(path: string, value: ScalarValue): void {\n this.assertOpen();\n const found = this.resolvePath(path);\n if (found.kind === \"world\") {\n if (!this.internals.worldSet) throw new Error(`@world is read-only here: the host bound no write`);\n this.internals.worldSet(found.name, value, true);\n return;\n }\n if (found.kind === \"scope\") {\n this.internals.registry.set(found.token, found.name, value, { host: true });\n return;\n }\n const bag = found.own !== undefined && found.own.get(found.name) !== undefined ? found.own\n : found.shared !== undefined && found.shared.get(found.name) !== undefined ? found.shared\n : undefined;\n if (bag === undefined) throw new Error(`no property at \"${path}\"`);\n // A host write: silent under the firing rule (no subscriber feedback\n // loop), visible to the bag's audit hook, and flagged HOST so a\n // `writable: false` does not refuse the game its own value.\n bag.set(found.name, value, { silent: true, reason: \"host setProperty\", host: true });\n }\n\n private resolvePath(path: string):\n | { kind: \"world\"; name: string }\n | { kind: \"scope\"; token: string; name: string }\n | { kind: \"bag\"; own?: StateBag; shared?: StateBag; name: string } {\n const parts = path.split(\".\");\n if (parts.length === 2 && parts[0] === \"world\") return { kind: \"world\", name: parts[1]! };\n if (parts.length === 2 && parts[0] !== \"story\" && this.internals.registry.has(parts[0]!)) {\n return { kind: \"scope\", token: parts[0]!, name: parts[1]! };\n }\n if (parts.length === 2 && parts[0] === \"story\") {\n return { kind: \"bag\", own: this.stores.story, shared: this.internals.shared.story, name: parts[1]! };\n }\n if (parts.length === 3 && (parts[0] === \"box\" || parts[0] === \"deck\" || parts[0] === \"hand\" || parts[0] === \"value\")) {\n const kind = parts[0] as OwnedScope;\n const [, segment, name] = parts as unknown as [string, string, string];\n const owner = ownerOrThrow(this.internals, kind, segment, name);\n if (owner.legacy && this.tracing) {\n this.emit({ type: \"diagnostic\", where: \"property address\", message: legacyAddressMessage(this.internals, kind, segment, name) });\n }\n const own = this.stores[kind].get(owner.id);\n const shared = this.internals.shared[kind].get(owner.id);\n if (own === undefined && shared === undefined) throw new Error(`no ${kind} store \"${segment}\"`);\n return { kind: \"bag\", ...(own !== undefined ? { own } : {}), ...(shared !== undefined ? { shared } : {}), name };\n }\n throw new Error(`bad property path \"${path}\"`);\n }\n\n // --- persistence (schema 4) -------------------------------------------------\n\n /** @internal - this flow's blob: inside the engine's envelope without its\n * properties (the registry has them), or parked whole by saveFlow. */\n snapshot(withProps: boolean): FlowSave {\n return {\n ...(withProps ? { props: partitionValues(this.stores) } : {}),\n turns: Object.fromEntries(this.turnCounts),\n prng: this.prng.state(),\n cooldowns: this.cooldowns,\n board: Object.fromEntries(this.boardContents),\n playLog: this.playLog,\n };\n }\n\n /** @internal - restore a freshly opened flow from its blob (loadGame).\n * Orphaned keys (deleted entities) drop; new declarations keep defaults. */\n restore(saved: FlowSave): void {\n if (saved.props !== undefined) loadPartition(this.stores, saved.props);\n this.turnCounts = new Map(this.internals.bundle.boxes.map((b) => [b.id, 0]));\n for (const [boxId, turn] of Object.entries(saved.turns ?? {})) {\n if (this.turnCounts.has(boxId)) this.turnCounts.set(boxId, turn);\n }\n this.prng = makePrng(saved.prng);\n this.cooldowns = saved.cooldowns ?? {};\n this.playLog = saved.playLog ?? [];\n this.rebuildPlayIndex();\n this.boardContents = new Map(Object.entries(saved.board ?? {})\n .filter(([handId]) => this.internals.handsById.has(handId))\n .map(([handId, ids]) => [handId, ids.filter((id) => this.internals.cardsById.has(id))]));\n for (const handId of this.internals.handsById.keys()) {\n if (!this.boardContents.has(handId)) this.boardContents.set(handId, []);\n }\n }\n}\n","// The contractual PRNG now lives in @wildwinter/expr, the package both product\n// families already depend on: mulberry32 is a fixed published algorithm that\n// neither family owns, and it existed thirteen times across the two of them.\n//\n// This file stays as a re-export so nothing that imports `./prng.js` has to\n// move, and so the runtime's public surface is unchanged.\n// toUint32 is deliberately NOT re-exported: it is the seed-coercion detail a\n// PORT has to reproduce, not something a game author calls, and widening this\n// runtime's public surface by accident is how a sample stops being the answer\n// to \"how do I use this\". Import it from @wildwinter/expr if you need it.\nexport { makePrng, shuffleInPlace } from \"@wildwinter/expr\";\nexport type { Prng } from \"@wildwinter/expr\";\n","// ---------------------------------------------------------------------------\n// describeBundle - the bundle inspector's runtime half (design/engine-runtimes.md\n// section 2, piece 6).\n//\n// A BUNDLE-level API, deliberately NOT a session method: it answers the\n// integrator's question - \"I dropped a .storyletsc into my project, what may\n// my game code call?\" - from the imported asset alone, with no session, no\n// state and no game running. That makes the boundary rule (design 4) visible:\n// hands are what deal() takes, tag groups + tags are what peek() criteria are\n// drawn from, declared properties are what expressions read and a host may\n// set. Card lists are deliberately absent: cards are the engine's business,\n// counts are the orientation an integrator needs.\n//\n// Everything is in bundle order, so the description is deterministic and two\n// runtimes render the same rows in the same sequence. The property scopes are\n// the static twin of session.listProperties(): the same stores, in the same\n// order, before anything is instantiated (a hand instance carries its\n// template's declarations, exactly as the session's hand bags do).\n// ---------------------------------------------------------------------------\n\nimport { effectiveGameId, groupsOfBox, isHoleRef } from \"@storylet-studio/model\";\nimport type {\n Box, Bundle, Expression, Hand, PropertyDecl, PropertyType, ScalarValue,\n} from \"@storylet-studio/model\";\n\n/** What bundle this is: the staleness/identity triple plus the schema tag. */\nexport interface BundleIdentity {\n /** The bundle schema tag (\"storylets/bundle@1\", or \"@0\" from before the\n * project map). */\n schema: string;\n /** content.project - the project name a save must agree with. */\n project: string;\n /** content.version - the authored bundle version. */\n version: string;\n /** content.hash - hash32 over the canonical source shards (schema 2.8). */\n hash: string;\n /** \"full\" | \"stripped\": whether authoring metadata (titles) survived. */\n metadata: string;\n}\n\n/** One hole this hand fills from a property rather than with a tag: the hand\n * MOVES when that property is written (design/engine-server.md 4.6). `group`\n * is the tag group's gameId, `from` the reference exactly as authored. */\nexport interface MovableHole {\n group: string;\n from: string;\n}\n\n/** One hand: the deal() surface. `gameId` is the name deal() is called with. */\nexport interface HandSummary {\n gameId: string;\n title?: string;\n /** The owning box's gameId (peek's first argument for the same stock). */\n box: string;\n /** The effective slot cap: the hand's override, else its template's or\n * rule's, else \"unbounded\". */\n slots: number | \"unbounded\";\n /** The hand template's gameId; absent for a standalone (inline-rule) hand. */\n template?: string;\n /**\n * The holes filled from a property, in bundle order. Absent when the hand\n * has none, which is the ordinary case.\n *\n * Reported because it is the one thing about a hand an integrator cannot see\n * from its name: a movable hole means writing that property MOVES the hand,\n * so it is the difference between a fixed kiosk and a performer who walks\n * about. `setProperty` is the whole verb; there is no other.\n */\n movable?: MovableHole[];\n}\n\n/** One tag group and its tags, by gameId: the peek() criteria surface (a\n * criteria entry is `{ [group gameId]: tag gameId }`). */\nexport interface TagGroupSummary {\n gameId: string;\n tags: string[];\n}\n\n/** One box: identity, its ranking policy, its tag groups, and counts. */\nexport interface BoxSummary {\n gameId: string;\n title?: string;\n /** The box is on the project map (design/project-map-contract.md 3.7): it\n * may name the map's group in peek criteria beside its own `tagGroups`,\n * which list the box's OWN groups only. Absent is \"not on the map\". */\n usesMap?: true;\n /** The only per-box ranking policy (Reboot 2.2). */\n ranking: { specificity: boolean };\n /** Present on a TIMED box (design/engine-server.md 4.8): how long one of\n * its turns lasts. An integrator reading a bundle needs it to know which\n * boxes their host must tick, and how often. Absent is the ordinary box. */\n turn?: { seconds: number };\n /** How many cards in this box are DURABLE (design/engine-server.md 4.2):\n * their `redraw: \"never\"` spend outlives the run, and a server has to lift\n * and restore it. A count rather than a list, like every other number here:\n * an integrator needs to know whether this box has any such cards at all,\n * and which ones is the authoring tool's question. Absent when there are\n * none, which is the ordinary bundle. */\n durableCards?: number;\n tagGroups: TagGroupSummary[];\n counts: {\n decks: number;\n cards: number;\n hands: number;\n templates: number;\n tagGroups: number;\n };\n}\n\n/** One declared property: what expressions read and what a host may set. */\nexport interface PropertySummary {\n name: string;\n type: PropertyType;\n default: ScalarValue;\n /** Enum / flags options, where declared. */\n values?: string[];\n /** Declared DURABLE (design/engine-server.md 4.2): the value survives a run,\n * and a server lifts and restores it across one. The engine never reads it;\n * it is reported because it is the difference between a value an integrator\n * may reset and one somebody is going to expect back. Absent = run-scoped. */\n durable?: true;\n purpose?: string;\n}\n\n/** The scope a declaration block belongs to. `tag` declarations compose into\n * @hand for any ask that binds the tag (schema 3.6). */\nexport type PropertyScopeKind = \"world\" | \"story\" | \"box\" | \"deck\" | \"hand\" | \"tag\";\n\n/** One scope's declared properties. `owner` is the owning entity's gameId\n * (empty for world / story); `box` names its box; `group` names a tag's\n * group. A zone of the project map is a `tag` scope with `group` and NO\n * `box`: it belongs to none. */\nexport interface PropertyScopeSummary {\n scope: PropertyScopeKind;\n owner: string;\n box?: string;\n group?: string;\n properties: PropertySummary[];\n}\n\n/**\n * The project map (design/project-map-contract.md 3.7): its group, which boxes\n * are on it, and how much geometry the bundle carries.\n *\n * Counts rather than the geometry itself, which is the same judgement the rest\n * of this file makes: an inspector answers \"what is in here\", and a host that\n * wants the polygons reads `bundle.map.geometry` directly. The geometry counts\n * are zero when the build did not ask for geometry (`export.map`); the group is\n * there regardless, because hands and cards reference it.\n */\nexport interface MapSummary {\n /** The zone group's gameId: the name an opted-in box's peek criteria use. */\n group: string;\n /** Its tags (the zones), by gameId. */\n tags: string[];\n /** The opted-in boxes, by gameId, in bundle order. */\n boxes: string[];\n /** Drawn zones in the carried geometry. */\n zones: number;\n backgrounds: number;\n /** Box gameId -> placed hands standing on the map (design/engine-server.md\n * 4.3): where the kiosks are. Only boxes with a site have a key. */\n sites: Record<string, number>;\n}\n\n/** What a bundle offers a host, read from the asset alone. */\nexport interface BundleDescription {\n identity: BundleIdentity;\n /** Orientation, not inventory: no card lists (Reboot 2.1). */\n totals: {\n boxes: number;\n decks: number;\n cards: number;\n hands: number;\n templates: number;\n tagGroups: number;\n };\n boxes: BoxSummary[];\n /** Every hand in the bundle, box by box: the deal() surface. */\n hands: HandSummary[];\n /** world, story, then per box: the box, its decks, its hands, its tags;\n * then the project map's zones, once. Scopes that declare nothing are omitted (world and story always show,\n * so their absence reads as \"this bundle declares none\"). */\n properties: PropertyScopeSummary[];\n /** The project map, when the bundle has one. Absent is the bundle with no\n * map at all. */\n map?: MapSummary;\n}\n\nconst summarise = (decls: PropertyDecl[]): PropertySummary[] =>\n decls.map((d) => ({\n name: d.name,\n type: d.type,\n default: d.default,\n ...(d.values !== undefined ? { values: d.values } : {}),\n ...(d.durable === true ? { durable: true as const } : {}),\n ...(d.purpose !== undefined ? { purpose: d.purpose } : {}),\n }));\n\n/** How many cards in a box are durable: the card's own flag, else its deck's\n * (design/engine-server.md 4.2, the same inheritance `shared` has). */\nconst durableCardCount = (box: Box<Expression>): number =>\n box.decks.reduce((n, deck) =>\n n + deck.cards.filter((card) => (card.durable ?? deck.durable) === true).length, 0);\n\n/** A hand's declared @hand state: a template instance inherits its template's\n * declarations, a standalone hand declares its own (schema 2.6) - the same\n * rule the session's hand bags are built on. */\nconst handDecls = (hand: Hand<Expression>, box: Box<Expression>): PropertyDecl[] => {\n if (hand.template !== undefined) {\n return box.handTemplates.find((t) => t.id === hand.template)?.properties ?? [];\n }\n return hand.properties ?? [];\n};\n\n/** The hand's movable holes, in the bundle's own key order: every `chosen` /\n * rule-binding value that is a property reference rather than a tag (4.6).\n * The group is looked up where the engine looks it up: the box's own groups\n * and, for a box on the project map, the map's group, so the roaming\n * character whose hole names a zone is reported rather than lost (3.7). A\n * group id neither place holds is a bundle the engine refuses or cannot\n * bind, and is skipped rather than reported under its raw id: the\n * description speaks gameIds throughout. */\nconst movableHoles = (bundle: Bundle, hand: Hand<Expression>, box: Box<Expression>): MovableHole[] => {\n const filled = hand.template !== undefined ? hand.chosen : hand.rule?.bindings;\n const out: MovableHole[] = [];\n for (const [groupId, value] of Object.entries(filled ?? {})) {\n if (!isHoleRef(value)) continue;\n const group = groupsOfBox(bundle, box).find((g) => g.id === groupId);\n if (group === undefined) continue;\n out.push({ group: effectiveGameId(group), from: value });\n }\n return out;\n};\n\n/** The effective slot cap, resolved the way the session resolves capacity. */\nconst handSlots = (hand: Hand<Expression>, box: Box<Expression>): number | \"unbounded\" => {\n if (hand.slots !== undefined) return hand.slots;\n const declared = hand.template !== undefined\n ? box.handTemplates.find((t) => t.id === hand.template)?.slots\n : hand.rule?.slots;\n return declared === undefined ? \"unbounded\" : declared;\n};\n\n/** Describe a compiled bundle: the callable surface of an imported asset, no\n * session required (design/engine-runtimes.md 2, piece 6). Bundle order\n * throughout; the same shape every runtime returns. */\nexport function describeBundle(bundle: Bundle): BundleDescription {\n const boxes: BoxSummary[] = [];\n const hands: HandSummary[] = [];\n const properties: PropertyScopeSummary[] = [\n { scope: \"world\", owner: \"\", properties: summarise(bundle.world.properties) },\n { scope: \"story\", owner: \"\", properties: summarise(bundle.story.properties) },\n ];\n const totals = { boxes: 0, decks: 0, cards: 0, hands: 0, templates: 0, tagGroups: 0 };\n\n for (const box of bundle.boxes) {\n const boxGameId = effectiveGameId(box);\n const cards = box.decks.reduce((n, deck) => n + deck.cards.length, 0);\n boxes.push({\n gameId: boxGameId,\n ...(box.title !== undefined ? { title: box.title } : {}),\n ...(box.usesMap === true ? { usesMap: true as const } : {}),\n ranking: { specificity: box.ranking.specificity },\n ...(box.turn !== undefined ? { turn: { seconds: box.turn.seconds } } : {}),\n ...(durableCardCount(box) > 0 ? { durableCards: durableCardCount(box) } : {}),\n tagGroups: box.tagGroups.map((group) => ({\n gameId: effectiveGameId(group),\n tags: group.tags.map((tag) => effectiveGameId(tag)),\n })),\n counts: {\n decks: box.decks.length,\n cards,\n hands: box.hands.length,\n templates: box.handTemplates.length,\n tagGroups: box.tagGroups.length,\n },\n });\n totals.boxes += 1;\n totals.decks += box.decks.length;\n totals.cards += cards;\n totals.hands += box.hands.length;\n totals.templates += box.handTemplates.length;\n totals.tagGroups += box.tagGroups.length;\n\n for (const hand of box.hands) {\n const template = hand.template !== undefined\n ? box.handTemplates.find((t) => t.id === hand.template)\n : undefined;\n const movable = movableHoles(bundle, hand, box);\n hands.push({\n gameId: effectiveGameId(hand),\n ...(hand.title !== undefined ? { title: hand.title } : {}),\n box: boxGameId,\n slots: handSlots(hand, box),\n ...(template !== undefined ? { template: effectiveGameId(template) } : {}),\n ...(movable.length > 0 ? { movable } : {}),\n });\n }\n\n // The property scopes, in the session's store order: box, decks, hands,\n // tags. Empty declaration blocks are dropped (nothing to read or set).\n const push = (scope: PropertyScopeKind, owner: string, decls: PropertyDecl[], group?: string): void => {\n if (decls.length === 0) return;\n properties.push({\n scope, owner, box: boxGameId, ...(group !== undefined ? { group } : {}),\n properties: summarise(decls),\n });\n };\n push(\"box\", boxGameId, box.properties);\n for (const deck of box.decks) push(\"deck\", effectiveGameId(deck), deck.properties);\n for (const hand of box.hands) push(\"hand\", effectiveGameId(hand), handDecls(hand, box));\n for (const group of box.tagGroups) {\n for (const tag of group.tags) {\n push(\"tag\", effectiveGameId(tag), tag.properties ?? [], effectiveGameId(group));\n }\n }\n }\n\n // The project map's zones, ONCE and after every box, whichever boxes use\n // them: the same order the engine's value bags are built in. A `tag` scope\n // with no `box`, because a zone belongs to none.\n const map = bundle.map;\n if (map !== undefined) {\n const group = effectiveGameId(map.group);\n for (const tag of map.group.tags) {\n const decls = tag.properties ?? [];\n if (decls.length > 0) properties.push({ scope: \"tag\", owner: effectiveGameId(tag), group, properties: summarise(decls) });\n }\n totals.tagGroups += 1;\n }\n\n return {\n identity: {\n schema: bundle.schema,\n project: bundle.content.project,\n version: bundle.content.version,\n hash: bundle.content.hash,\n metadata: bundle.metadata,\n },\n totals,\n boxes,\n hands,\n properties,\n ...(map !== undefined ? {\n map: {\n group: effectiveGameId(map.group),\n tags: map.group.tags.map((tag) => effectiveGameId(tag)),\n boxes: bundle.boxes.filter((box) => box.usesMap === true).map((box) => effectiveGameId(box)),\n zones: map.geometry?.zones.length ?? 0,\n backgrounds: map.geometry?.backgrounds?.length ?? 0,\n sites: Object.fromEntries(Object.entries(map.geometry?.sites ?? {}).map(([box, sites]) => [box, sites.length])),\n },\n } : {}),\n };\n}\n"],"mappings":"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","names":["next","effectiveGameId","groupsOfBox","isHoleRef"]}
|