@storylet-studio/runtime 0.4.0 → 0.5.0
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 -1
- package/dist/index.cjs +531 -80
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +215 -23
- package/dist/index.d.ts +215 -23
- package/dist/index.js +531 -80
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ScalarValue, ScopeResolver, ExprNode } from '@wildwinter/expr';
|
|
2
2
|
export { Prng, makePrng, shuffleInPlace } from '@wildwinter/expr';
|
|
3
|
-
import { Bundle, Card, Expression, Deck, Box, Hand, HandTemplate, TagGroup, PropertyDecl,
|
|
3
|
+
import { Bundle, FlowSave, LoadReport, Card, Expression, Deck, Box, Hand, HandTemplate, TagGroup, PropertyDecl, SaveEnvelope, PropertyType, ScalarValue as ScalarValue$1 } from '@storylet-studio/model';
|
|
4
4
|
import { PropertyBag, PropertyRow } from '@wildwinter/scoperegistry';
|
|
5
5
|
export { PropertyRow } from '@wildwinter/scoperegistry';
|
|
6
6
|
|
|
@@ -38,6 +38,25 @@ interface EngineOptions {
|
|
|
38
38
|
interface OpenFlowOptions {
|
|
39
39
|
/** Seed for this flow's PRNG (defaults to the engine's `seed`). */
|
|
40
40
|
seed?: number;
|
|
41
|
+
/**
|
|
42
|
+
* Open this flow AS IT WAS: a blob from `saveFlow`, applied to the freshly
|
|
43
|
+
* opened (or replaced) flow before the handle comes back
|
|
44
|
+
* (design/engine-server.md 4.1).
|
|
45
|
+
*
|
|
46
|
+
* An option on `openFlow` rather than a `Flow.restore` verb on purpose:
|
|
47
|
+
* restoring INTO a running flow is the trap hosts keep falling into
|
|
48
|
+
* (openFlow REPLACES), and "open this flow as it was" is one act. Drift is
|
|
49
|
+
* tolerated exactly as `loadGame` tolerates it, with one addition, because
|
|
50
|
+
* this restore lands in a LIVE engine: a shared card whose world copies are
|
|
51
|
+
* all held by the OTHER open flows is not put back, and is reported as
|
|
52
|
+
* `claimed-elsewhere`. Ask `previewFlowRestore` first to see that coming.
|
|
53
|
+
*/
|
|
54
|
+
restore?: FlowSave;
|
|
55
|
+
/** Handed the `restore`'s LoadReport as it happens - the same report
|
|
56
|
+
* `previewFlowRestore` returns for the same blob. Ignored without
|
|
57
|
+
* `restore`; the report has nowhere else to go, since `openFlow` returns
|
|
58
|
+
* the handle. */
|
|
59
|
+
onRestoreReport?: (report: LoadReport) => void;
|
|
41
60
|
}
|
|
42
61
|
/** A card view in a dealt hand or a peeked list. Carries NO outcome
|
|
43
62
|
* availability - ask `outcomes()` for current truth (schema 5). */
|
|
@@ -63,7 +82,8 @@ interface RankedList {
|
|
|
63
82
|
cards: DealtCard[];
|
|
64
83
|
}
|
|
65
84
|
interface PlayOptions {
|
|
66
|
-
/** Turn advance override; default settings.playAdvancesTurns
|
|
85
|
+
/** Turn advance override; default settings.playAdvancesTurns, or 0 when the
|
|
86
|
+
* card's box is timed (design/engine-server.md 4.8). */
|
|
67
87
|
advanceTurns?: number;
|
|
68
88
|
}
|
|
69
89
|
/** Why a card did or did not make an ask, in availability order (schema 3.1). */
|
|
@@ -71,11 +91,18 @@ type TraceVerdict = "dealt" | "capped" | "cooldown" | "deck-gate" | "tags" | "co
|
|
|
71
91
|
/** One event on the deal/play log - "why did Ambush at the ford get dealt
|
|
72
92
|
* here?" is answered by the ask event's per-card verdicts and keys. The
|
|
73
93
|
* verb is the event type, so a peek is distinguishable from a deal when
|
|
74
|
-
* reading a run back.
|
|
94
|
+
* reading a run back.
|
|
95
|
+
*
|
|
96
|
+
* IDENTITY IS BY GAMEID throughout (design/engine-server.md 4.4). It was
|
|
97
|
+
* mixed until then: `deal.hand` and `peek.box` were gameIds while
|
|
98
|
+
* `evict.hand`, `play.card` and every `cards[].id` were internal ids, so
|
|
99
|
+
* every consumer outside the engine - the Board, the four examiners, the
|
|
100
|
+
* Live Link, a wire a kiosk reads - mapped one to the other itself. */
|
|
75
101
|
type TraceEvent = {
|
|
76
102
|
type: "deal";
|
|
77
103
|
/** Hand gameId. */
|
|
78
104
|
hand: string;
|
|
105
|
+
/** `id` is the card's GAMEID (design/engine-server.md 4.4). */
|
|
79
106
|
cards: {
|
|
80
107
|
id: string;
|
|
81
108
|
verdict: TraceVerdict;
|
|
@@ -87,24 +114,31 @@ type TraceEvent = {
|
|
|
87
114
|
/** Box gameId. */
|
|
88
115
|
box: string;
|
|
89
116
|
criteria: Record<string, string>;
|
|
117
|
+
/** `id` is the card's GAMEID (design/engine-server.md 4.4). */
|
|
90
118
|
cards: {
|
|
91
119
|
id: string;
|
|
92
120
|
verdict: TraceVerdict;
|
|
93
121
|
priority?: number;
|
|
94
122
|
specificity?: number;
|
|
95
123
|
}[];
|
|
96
|
-
}
|
|
124
|
+
}
|
|
125
|
+
/** Hand and card gameIds. A card the build no longer has (`vanished`) has
|
|
126
|
+
* no gameId left and is named by the id the board carried. */
|
|
127
|
+
| {
|
|
97
128
|
type: "evict";
|
|
98
129
|
hand: string;
|
|
99
130
|
card: string;
|
|
100
131
|
reason: TraceVerdict | "hand-condition" | "vanished";
|
|
101
|
-
}
|
|
132
|
+
}
|
|
133
|
+
/** Card and outcome gameIds. */
|
|
134
|
+
| {
|
|
102
135
|
type: "play";
|
|
103
136
|
card: string;
|
|
104
137
|
outcome: string;
|
|
105
138
|
turn: number;
|
|
106
139
|
}
|
|
107
|
-
/** One landed outcome change; `path` is the resolved store location
|
|
140
|
+
/** One landed outcome change; `path` is the resolved store location, in the
|
|
141
|
+
* address grammar `getProperty` takes - the owner segment is its gameId (a
|
|
108
142
|
* routed @hand write shows where it actually went, schema 3.6). `prev`
|
|
109
143
|
* is the value it replaced, so a log can read "0 -> 1". */
|
|
110
144
|
| {
|
|
@@ -153,8 +187,8 @@ interface CardEntry {
|
|
|
153
187
|
deck: Deck<Expression>;
|
|
154
188
|
box: Box<Expression>;
|
|
155
189
|
}
|
|
156
|
-
/** One kernel bag with its store path prefix (story / box.<
|
|
157
|
-
* / hand.<
|
|
190
|
+
/** One kernel bag with its store path prefix (story / box.<gameId> / deck.<gameId>
|
|
191
|
+
* / hand.<gameId> / value.<gameId>): the state logger's mount surface
|
|
158
192
|
* (design/engine-runtimes.md 3.4 - the logger builds on the PropertyBag
|
|
159
193
|
* audit hook, so it needs the bags themselves, not just their rows).
|
|
160
194
|
* The Engine lists the shared bags, a Flow its own; the @world container
|
|
@@ -172,6 +206,50 @@ interface BoxView {
|
|
|
172
206
|
title?: string;
|
|
173
207
|
turn: number;
|
|
174
208
|
}
|
|
209
|
+
/** One side's five declaration lists, keyed by owner id where the scope has
|
|
210
|
+
* owners. The bags are built from these; so is the load report's answer to
|
|
211
|
+
* "what does this build declare that the save does not carry". */
|
|
212
|
+
interface DeclSet {
|
|
213
|
+
story: PropertyDecl[];
|
|
214
|
+
box: Map<string, PropertyDecl[]>;
|
|
215
|
+
deck: Map<string, PropertyDecl[]>;
|
|
216
|
+
hand: Map<string, PropertyDecl[]>;
|
|
217
|
+
value: Map<string, PropertyDecl[]>;
|
|
218
|
+
}
|
|
219
|
+
/** The four owned property scopes: the ones whose address carries an owner
|
|
220
|
+
* segment. `story` has no owner and `world` is the host's. */
|
|
221
|
+
type OwnedScope = "box" | "deck" | "hand" | "value";
|
|
222
|
+
/** The owner segment of a property address, both ways round
|
|
223
|
+
* (design/engine-server.md 4.4).
|
|
224
|
+
*
|
|
225
|
+
* `gameId` is the segment the ADDRESS uses; `id` is the internal id everything
|
|
226
|
+
* inside the engine is keyed by - the bags, the save envelope, the ladders.
|
|
227
|
+
* Both maps are built in bundle order and a repeated gameId does NOT
|
|
228
|
+
* overwrite the first.
|
|
229
|
+
*
|
|
230
|
+
* Box, deck, hand and card gameIds are unique bundle-wide, so for three of the
|
|
231
|
+
* four scopes the segment is simply the gameId. A TAG's is unique only within
|
|
232
|
+
* its group, and a group's only within its box, so two boxes may each name a
|
|
233
|
+
* tag "docks": the value scope's segment is box-qualified,
|
|
234
|
+
* `value.<boxGameId>/<tagGameId>.<name>`, wherever a gameId repeats, and the
|
|
235
|
+
* short form is REFUSED there rather than resolved to the first in bundle
|
|
236
|
+
* order. `valueAddresses` in the model is the one definition of that rule -
|
|
237
|
+
* the Board draws these addresses from the bundle while the engine builds them
|
|
238
|
+
* from this index, and the two have to agree - and `repeated` is what it
|
|
239
|
+
* found, so a refusal can name the candidates.
|
|
240
|
+
*
|
|
241
|
+
* Two GROUPS in one box naming the same tag is the case the box qualifier
|
|
242
|
+
* cannot separate, and it is closing at the source rather than here (question
|
|
243
|
+
* 16, ruled 2026-09-06): the compiler warns that a tag gameId must be unique
|
|
244
|
+
* within its box, and refuses it from the next release. Until then the first
|
|
245
|
+
* in bundle order answers, as it always did.
|
|
246
|
+
*/
|
|
247
|
+
interface OwnerIndex {
|
|
248
|
+
gameId: Map<string, string>;
|
|
249
|
+
id: Map<string, string>;
|
|
250
|
+
repeated: Map<string, string[]>;
|
|
251
|
+
}
|
|
252
|
+
type OwnerIndexes = Record<OwnedScope, OwnerIndex>;
|
|
175
253
|
/** One side's five stores (shared on the engine, per-flow on each flow). */
|
|
176
254
|
interface Partition {
|
|
177
255
|
story: PropertyBag;
|
|
@@ -199,6 +277,8 @@ interface Internals {
|
|
|
199
277
|
hand: Hand<Expression>;
|
|
200
278
|
box: Box<Expression>;
|
|
201
279
|
}>;
|
|
280
|
+
/** The owner segment of a property address, both ways round (4.4). */
|
|
281
|
+
owners: OwnerIndexes;
|
|
202
282
|
templatesById: Map<string, HandTemplate<Expression>>;
|
|
203
283
|
groupsById: Map<string, {
|
|
204
284
|
group: TagGroup;
|
|
@@ -223,17 +303,26 @@ interface Internals {
|
|
|
223
303
|
hasShared: boolean;
|
|
224
304
|
/** The per-flow halves of every declaration list, precomputed once: each
|
|
225
305
|
* new flow builds its bags from these. */
|
|
226
|
-
flowDecls:
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
};
|
|
306
|
+
flowDecls: DeclSet;
|
|
307
|
+
/** The shared halves, the same way. Not used to build anything - the shared
|
|
308
|
+
* bags are built straight from the bundle - but a load report has to say
|
|
309
|
+
* what the shared side WOULD hold without building a bag, which is what
|
|
310
|
+
* makes previewLoad pure. */
|
|
311
|
+
sharedDecls: DeclSet;
|
|
233
312
|
/** The shared stores. Reassigned wholesale by loadGame/reset. */
|
|
234
313
|
shared: Partition;
|
|
235
314
|
/** @world: the host's resolver, or the self-backed bag's. */
|
|
236
315
|
worldResolver: ScopeResolver;
|
|
316
|
+
/** The @world WRITE seam. `host` says the caller is the GAME's own surface -
|
|
317
|
+
* setProperty, the coverage harness, the CLI's --set - which the shared
|
|
318
|
+
* kernel lets past a `writable: false` (scoperegistry 0.6.0): that flag is
|
|
319
|
+
* the story's promise, not the game's. The story's refusal is the
|
|
320
|
+
* worldReadOnly table below, consulted before this seam is reached. A BOUND
|
|
321
|
+
* resolver is opaque - it takes a name and a value and keeps whatever rule
|
|
322
|
+
* the game has - so the flag only ever reaches the self-backed bag.
|
|
323
|
+
* Undefined when @world cannot be written at all (a resolver bound with no
|
|
324
|
+
* `set`). */
|
|
325
|
+
worldSet?: (name: string, value: ScalarValue, host?: boolean) => void;
|
|
237
326
|
/** @world names declared `writable: false`: the story's promise, kept at
|
|
238
327
|
* runtime as the compiler keeps it at publish (Reboot.md 10). */
|
|
239
328
|
worldReadOnly: Set<string>;
|
|
@@ -307,15 +396,24 @@ declare class Engine {
|
|
|
307
396
|
* Derived, which is what makes closeFlow and the openFlow replace release
|
|
308
397
|
* what a flow was holding: its board leaves the map with it. */
|
|
309
398
|
sharedClaims(): Map<string, number>;
|
|
399
|
+
/** The same ledger with one name left out: what the REST of the world
|
|
400
|
+
* holds, which is the question a resume under that name has to ask. */
|
|
401
|
+
private sharedClaimsExcept;
|
|
310
402
|
/**
|
|
311
403
|
* Read shared state by path: "world.x", "story.gold" (when shared),
|
|
312
|
-
* "box.
|
|
404
|
+
* "box.village.heat" (when shared) - the owner segment is its GAMEID
|
|
405
|
+
* (design/engine-server.md 4.4). A ref that resolves PER-FLOW throws,
|
|
313
406
|
* naming the fix - silently answering with some flow's copy (or a junk
|
|
314
407
|
* default) was the bug Patter's engine.getProperty guard exists to stop.
|
|
315
408
|
*/
|
|
316
409
|
getProperty(path: string): ScalarValue;
|
|
317
410
|
setProperty(path: string, value: ScalarValue): void;
|
|
318
411
|
private resolveShared;
|
|
412
|
+
/** The engine's own surface has no flow, so an engine-level diagnostic
|
|
413
|
+
* carries the empty flow id - the same way a LoadReport's shared half
|
|
414
|
+
* carries no flow. It reaches the run log and the engine tap; there is
|
|
415
|
+
* nowhere else for it to go, and it fires only on a legacy address. */
|
|
416
|
+
private diagnose;
|
|
319
417
|
/** The shared surface as examiner rows: @world (read through the
|
|
320
418
|
* resolver) then the shared partitions. Per-flow rows live on each Flow. */
|
|
321
419
|
listProperties(): PropertyRow[];
|
|
@@ -329,10 +427,40 @@ declare class Engine {
|
|
|
329
427
|
* every live flow keyed by its id. @world is NEVER here - the host
|
|
330
428
|
* saves its container, each engine saves its own envelope. */
|
|
331
429
|
saveGame(): SaveEnvelope;
|
|
430
|
+
/** ONE flow's blob, to park a visit that is walking away: the same shape
|
|
431
|
+
* the envelope carries per flow, and the same shape `openFlow`'s `restore`
|
|
432
|
+
* option takes back (design/engine-server.md 4.1). Saving the whole
|
|
433
|
+
* envelope to park one of four hundred players is wrong in cost and in
|
|
434
|
+
* meaning. Throws for a name that is not open - a closed flow has nothing
|
|
435
|
+
* left to save. */
|
|
436
|
+
saveFlow(id: string): FlowSave;
|
|
437
|
+
/** What `loadGame(envelope)` would do that is not a plain restore, without
|
|
438
|
+
* doing any of it (design/engine-server.md 4.9). Pure: nothing on this
|
|
439
|
+
* engine moves. A project mismatch is refused here exactly as `loadGame`
|
|
440
|
+
* refuses it - it is the one thing neither call will tolerate. */
|
|
441
|
+
previewLoad(envelope: SaveEnvelope): LoadReport;
|
|
442
|
+
/** What `openFlow(id, { restore: saved })` would do to a flow of that name,
|
|
443
|
+
* without doing it: the same report shape, since a visit parked under one
|
|
444
|
+
* build and resumed under the next raises the same questions. Pure. */
|
|
445
|
+
previewFlowRestore(id: string, saved: FlowSave): LoadReport;
|
|
332
446
|
/** Restore: shared state once, then every flow REBUILT from its blob.
|
|
333
447
|
* Handles held from before the load are closed and inert (Patter's
|
|
334
|
-
* rule); take fresh ones from getFlow()/flows().
|
|
335
|
-
|
|
448
|
+
* rule); take fresh ones from getFlow()/flows().
|
|
449
|
+
*
|
|
450
|
+
* Returns the report `previewLoad` would have given for this envelope: the
|
|
451
|
+
* drift tolerance that makes a load forgiving is what hides its cost, so
|
|
452
|
+
* the cost comes back with the load whether or not anybody looked first. */
|
|
453
|
+
loadGame(envelope: SaveEnvelope): LoadReport;
|
|
454
|
+
private assertSameProject;
|
|
455
|
+
/** The whole-envelope walk: the report, and the cleaned state the apply
|
|
456
|
+
* half writes. Nothing here touches the engine, which is what lets
|
|
457
|
+
* previewLoad and loadGame share it. */
|
|
458
|
+
private planLoad;
|
|
459
|
+
/** One flow's walk. `otherClaims` is the rest of the world's shared ledger
|
|
460
|
+
* and is present only for a SINGLE-flow restore into a live engine: a
|
|
461
|
+
* whole-envelope load rebuilds every flow from one consistent moment, so
|
|
462
|
+
* there is nobody else to compete with. */
|
|
463
|
+
private planFlowRestore;
|
|
336
464
|
}
|
|
337
465
|
declare class Flow {
|
|
338
466
|
readonly id: string;
|
|
@@ -432,6 +560,23 @@ declare class Flow {
|
|
|
432
560
|
/** A peek's ask: raw criteria ({group gameId: tag gameId}), bindings only,
|
|
433
561
|
* no condition slot (schema 3.1; the boundary, Reboot 4). */
|
|
434
562
|
private askForPeek;
|
|
563
|
+
/**
|
|
564
|
+
* Fill one hole from the property its value names: the hand that moves
|
|
565
|
+
* (design/engine-server.md 4.6).
|
|
566
|
+
*
|
|
567
|
+
* The semantics are `bindStateGroups`' below, word for word, applied per
|
|
568
|
+
* HOLE instead of per group: resolved at ask time, and a value naming no tag
|
|
569
|
+
* leaves the hole UNBOUND (a wildcard) with a diagnostic rather than dealing
|
|
570
|
+
* a silently empty hand. What is added is the `@hand` scope - the asking
|
|
571
|
+
* hand's OWN declared state, read here from the flow's merged view (the
|
|
572
|
+
* shared half under the flow's own, so a `shared: true` declaration moves
|
|
573
|
+
* the hole for every flow and a per-flow one moves it for this flow alone).
|
|
574
|
+
*
|
|
575
|
+
* Read BEFORE tag composition, which is the whole reason it is safe: the
|
|
576
|
+
* @hand bag a card sees is built from the bound tags, so resolving a hole
|
|
577
|
+
* from it would be circular. A hand's own declarations are not, so they are.
|
|
578
|
+
*/
|
|
579
|
+
private fillHoleFromProperty;
|
|
435
580
|
/**
|
|
436
581
|
* Bind every `boundBy` group in the box from the property it names.
|
|
437
582
|
*
|
|
@@ -477,7 +622,9 @@ declare class Flow {
|
|
|
477
622
|
* null for available. `trace` (when a subscriber exists) collects the
|
|
478
623
|
* per-card verdicts. */
|
|
479
624
|
private runAsk;
|
|
480
|
-
/** Flip eligible-but-not-taken trace entries to "capped".
|
|
625
|
+
/** Flip eligible-but-not-taken trace entries to "capped". `taken` is keyed
|
|
626
|
+
* by GAMEID, as the trace rows are (4.4): the two must move together or
|
|
627
|
+
* every dealt card silently reads as capped. */
|
|
481
628
|
private capTrace;
|
|
482
629
|
private view;
|
|
483
630
|
private handCapacity;
|
|
@@ -512,6 +659,8 @@ declare class Flow {
|
|
|
512
659
|
* board (you never play a card from inside the deck). Throws before any
|
|
513
660
|
* mutation on a gated-shut outcome or a bad write target. */
|
|
514
661
|
play(cardId: string, outcomeGameId: string, from: string, opts?: PlayOptions): void;
|
|
662
|
+
/** One owned property's address, owner segment and all (4.4). */
|
|
663
|
+
private address;
|
|
515
664
|
/** Land one change in whichever partition declares the name: the flow's
|
|
516
665
|
* bag when the property is per-flow, the shared bag when it is shared -
|
|
517
666
|
* the union/partition invariant made executable. */
|
|
@@ -536,9 +685,14 @@ declare class Flow {
|
|
|
536
685
|
* Bundle order: world, story, then per-box / per-deck / per-hand /
|
|
537
686
|
* per-tag stores. */
|
|
538
687
|
listProperties(): PropertyRow[];
|
|
539
|
-
/** Read by path: "world.x", "story.gold", "value.
|
|
540
|
-
* "box.
|
|
541
|
-
* merged view, routed by the declaration's sharing.
|
|
688
|
+
/** Read by path: "world.x", "story.gold", "value.docks.danger",
|
|
689
|
+
* "box.village.heat", "deck.wares.n", "hand.the-elder.zone" - the flow's
|
|
690
|
+
* merged view, routed by the declaration's sharing.
|
|
691
|
+
*
|
|
692
|
+
* The owner segment is the entity's GAMEID, the name it is called by
|
|
693
|
+
* everywhere else (4.4). Its internal id is accepted for this release and
|
|
694
|
+
* earns a `diagnostic` naming the address to move to; the next lockstep
|
|
695
|
+
* release refuses it. */
|
|
542
696
|
getProperty(path: string): ScalarValue;
|
|
543
697
|
setProperty(path: string, value: ScalarValue): void;
|
|
544
698
|
private resolvePath;
|
|
@@ -562,6 +716,13 @@ interface BundleIdentity {
|
|
|
562
716
|
/** "full" | "stripped": whether authoring metadata (titles) survived. */
|
|
563
717
|
metadata: string;
|
|
564
718
|
}
|
|
719
|
+
/** One hole this hand fills from a property rather than with a tag: the hand
|
|
720
|
+
* MOVES when that property is written (design/engine-server.md 4.6). `group`
|
|
721
|
+
* is the tag group's gameId, `from` the reference exactly as authored. */
|
|
722
|
+
interface MovableHole {
|
|
723
|
+
group: string;
|
|
724
|
+
from: string;
|
|
725
|
+
}
|
|
565
726
|
/** One hand: the deal() surface. `gameId` is the name deal() is called with. */
|
|
566
727
|
interface HandSummary {
|
|
567
728
|
gameId: string;
|
|
@@ -573,6 +734,16 @@ interface HandSummary {
|
|
|
573
734
|
slots: number | "unbounded";
|
|
574
735
|
/** The hand template's gameId; absent for a standalone (inline-rule) hand. */
|
|
575
736
|
template?: string;
|
|
737
|
+
/**
|
|
738
|
+
* The holes filled from a property, in bundle order. Absent when the hand
|
|
739
|
+
* has none, which is the ordinary case.
|
|
740
|
+
*
|
|
741
|
+
* Reported because it is the one thing about a hand an integrator cannot see
|
|
742
|
+
* from its name: a movable hole means writing that property MOVES the hand,
|
|
743
|
+
* so it is the difference between a fixed kiosk and a performer who walks
|
|
744
|
+
* about. `setProperty` is the whole verb; there is no other.
|
|
745
|
+
*/
|
|
746
|
+
movable?: MovableHole[];
|
|
576
747
|
}
|
|
577
748
|
/** One tag group and its tags, by gameId: the peek() criteria surface (a
|
|
578
749
|
* criteria entry is `{ [group gameId]: tag gameId }`). */
|
|
@@ -588,6 +759,19 @@ interface BoxSummary {
|
|
|
588
759
|
ranking: {
|
|
589
760
|
specificity: boolean;
|
|
590
761
|
};
|
|
762
|
+
/** Present on a TIMED box (design/engine-server.md 4.8): how long one of
|
|
763
|
+
* its turns lasts. An integrator reading a bundle needs it to know which
|
|
764
|
+
* boxes their host must tick, and how often. Absent is the ordinary box. */
|
|
765
|
+
turn?: {
|
|
766
|
+
seconds: number;
|
|
767
|
+
};
|
|
768
|
+
/** How many cards in this box are DURABLE (design/engine-server.md 4.2):
|
|
769
|
+
* their `redraw: "never"` spend outlives the run, and a server has to lift
|
|
770
|
+
* and restore it. A count rather than a list, like every other number here:
|
|
771
|
+
* an integrator needs to know whether this box has any such cards at all,
|
|
772
|
+
* and which ones is the authoring tool's question. Absent when there are
|
|
773
|
+
* none, which is the ordinary bundle. */
|
|
774
|
+
durableCards?: number;
|
|
591
775
|
tagGroups: TagGroupSummary[];
|
|
592
776
|
counts: {
|
|
593
777
|
decks: number;
|
|
@@ -604,6 +788,11 @@ interface PropertySummary {
|
|
|
604
788
|
default: ScalarValue$1;
|
|
605
789
|
/** Enum / flags options, where declared. */
|
|
606
790
|
values?: string[];
|
|
791
|
+
/** Declared DURABLE (design/engine-server.md 4.2): the value survives a run,
|
|
792
|
+
* and a server lifts and restores it across one. The engine never reads it;
|
|
793
|
+
* it is reported because it is the difference between a value an integrator
|
|
794
|
+
* may reset and one somebody is going to expect back. Absent = run-scoped. */
|
|
795
|
+
durable?: true;
|
|
607
796
|
purpose?: string;
|
|
608
797
|
}
|
|
609
798
|
/** The scope a declaration block belongs to. `tag` declarations compose into
|
|
@@ -634,6 +823,9 @@ interface MapSummary {
|
|
|
634
823
|
group: string;
|
|
635
824
|
zones: number;
|
|
636
825
|
backgrounds: number;
|
|
826
|
+
/** Placed hands standing on this map (design/engine-server.md 4.3): where the
|
|
827
|
+
* kiosks are, in a bundle that carries geometry at all. */
|
|
828
|
+
sites: number;
|
|
637
829
|
}
|
|
638
830
|
/** What a bundle offers a host, read from the asset alone. */
|
|
639
831
|
interface BundleDescription {
|
|
@@ -663,4 +855,4 @@ interface BundleDescription {
|
|
|
663
855
|
* throughout; the same shape every runtime returns. */
|
|
664
856
|
declare function describeBundle(bundle: Bundle): BundleDescription;
|
|
665
857
|
|
|
666
|
-
export { type BagMount, type BoxSummary, type BoxView, type BundleDescription, type BundleIdentity, type DealtCard, Engine, type EngineLogEntry, type EngineOptions, type EngineTraceHandler, Flow, type HandSummary, type LogEntry, type MapSummary, type OpenFlowOptions, type OutcomeView, type PlayOptions, type PropertyScopeKind, type PropertyScopeSummary, type PropertySummary, type RankedList, type TagGroupSummary, type TraceEvent, type TraceHandler, type TraceVerdict, describeBundle };
|
|
858
|
+
export { type BagMount, type BoxSummary, type BoxView, type BundleDescription, type BundleIdentity, type DealtCard, Engine, type EngineLogEntry, type EngineOptions, type EngineTraceHandler, Flow, type HandSummary, type LogEntry, type MapSummary, type MovableHole, type OpenFlowOptions, type OutcomeView, type PlayOptions, type PropertyScopeKind, type PropertyScopeSummary, type PropertySummary, type RankedList, type TagGroupSummary, type TraceEvent, type TraceHandler, type TraceVerdict, describeBundle };
|