@storylet-studio/runtime 0.8.1 → 0.9.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 -2
- package/dist/index.cjs +248 -1045
- 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 +183 -969
- package/dist/index.js.map +1 -1
- package/package.json +7 -2
package/dist/index.d.cts
CHANGED
|
@@ -265,6 +265,7 @@ interface OwnerIndex {
|
|
|
265
265
|
gameId: Map<string, string>;
|
|
266
266
|
id: Map<string, string>;
|
|
267
267
|
repeated: Map<string, string[]>;
|
|
268
|
+
zoneQualified: Map<string, string>;
|
|
268
269
|
}
|
|
269
270
|
type OwnerIndexes = Record<OwnedScope, OwnerIndex>;
|
|
270
271
|
/** One side's five stores (shared on the engine, per-flow on each flow). */
|
|
@@ -297,9 +298,11 @@ interface Internals {
|
|
|
297
298
|
/** The owner segment of a property address, both ways round (4.4). */
|
|
298
299
|
owners: OwnerIndexes;
|
|
299
300
|
templatesById: Map<string, HandTemplate<Expression>>;
|
|
301
|
+
/** Every group by internal id. `box` is absent for the project map's group,
|
|
302
|
+
* which belongs to no box. */
|
|
300
303
|
groupsById: Map<string, {
|
|
301
304
|
group: TagGroup;
|
|
302
|
-
box
|
|
305
|
+
box?: Box<Expression>;
|
|
303
306
|
}>;
|
|
304
307
|
requiredGroups: Set<string>;
|
|
305
308
|
nodeCache: WeakMap<Expression, ExprNode>;
|
|
@@ -507,6 +510,20 @@ declare class Engine {
|
|
|
507
510
|
* `registry`, self-backed @world included; a game that passed a registry
|
|
508
511
|
* saves it once itself, beside each engine's envelope. */
|
|
509
512
|
saveGame(): SaveEnvelope;
|
|
513
|
+
/** The registry's values in CANONICAL order, the order a load rebuilds them
|
|
514
|
+
* in: the engine-wide keys as the constructor registered them, then each
|
|
515
|
+
* flow's keys in `flows()` order (each flow's own registration order), then
|
|
516
|
+
* anything else the registry holds (values still waiting for a key), as the
|
|
517
|
+
* registry lists it. The registry itself lists keys in registration order,
|
|
518
|
+
* and a flow replaced in place (`open()` above keeps its slot in
|
|
519
|
+
* `flowsById`) re-registers its keys at the END, so `openFlow("a");
|
|
520
|
+
* openFlow("b"); openFlow("a")` saved b's keys before a's while a load
|
|
521
|
+
* rebuilt a's first: the same run, different `.storyletsave` bytes, and a
|
|
522
|
+
* save loaded and saved again no longer equal to itself. It is the
|
|
523
|
+
* 2026-08-29 rule carried into the section save@2 moved the per-flow values
|
|
524
|
+
* to (2026-10-01). Order does not matter on READ (`partitionsFromSections`
|
|
525
|
+
* sorts by key shape), so a save written in the old order loads as before. */
|
|
526
|
+
private registrySection;
|
|
510
527
|
/** ONE flow's blob, to park a visit that is walking away: the same shape
|
|
511
528
|
* the envelope carries per flow, and the same shape `openFlow`'s `restore`
|
|
512
529
|
* option takes back (design/engine-server.md 4.1). Saving the whole
|
|
@@ -618,7 +635,13 @@ declare class Flow {
|
|
|
618
635
|
/** Tag group names are box-scoped: two boxes may name a group the same way
|
|
619
636
|
* (schema 1 - boxes namespace their groups), so a name is only ever
|
|
620
637
|
* resolved inside the box being asked, never bundle-wide. Ids are
|
|
621
|
-
* project-unique and accepted here too, still confined to the box.
|
|
638
|
+
* project-unique and accepted here too, still confined to the box.
|
|
639
|
+
*
|
|
640
|
+
* A box on the project map sees ONE namespace: its own groups, then the
|
|
641
|
+
* map's group (design/project-map-contract.md 3.1). A box that has not
|
|
642
|
+
* opted in does not see the map's name at all, so a peek naming it there
|
|
643
|
+
* is the ordinary unknown-group refusal. Own groups first is stated for
|
|
644
|
+
* determinism only: a bundle that loads never has the two share a name. */
|
|
622
645
|
private groupInBox;
|
|
623
646
|
/** Fold one play into the indexes. O(the card's tags), not O(the log). */
|
|
624
647
|
private indexPlay;
|
|
@@ -626,8 +649,10 @@ declare class Flow {
|
|
|
626
649
|
* rather than appended to, which is `restore` alone. */
|
|
627
650
|
private rebuildPlayIndex;
|
|
628
651
|
/** `box` is the box whose ask is being evaluated: the play-history
|
|
629
|
-
* functions take a bare group name, so it resolves there
|
|
630
|
-
*
|
|
652
|
+
* functions take a bare group name, so it resolves there, and they count
|
|
653
|
+
* only that box's own plays (the box is in the index key). That was
|
|
654
|
+
* automatic while every group was a box's; a project-map zone is shared,
|
|
655
|
+
* and its history is still not (design/project-map-contract.md 3.7, D7).
|
|
631
656
|
* History is THIS flow's: countPlayed answers "have I done this". */
|
|
632
657
|
/** One host per box, built once.
|
|
633
658
|
*
|
|
@@ -816,7 +841,8 @@ declare class Flow {
|
|
|
816
841
|
|
|
817
842
|
/** What bundle this is: the staleness/identity triple plus the schema tag. */
|
|
818
843
|
interface BundleIdentity {
|
|
819
|
-
/** The bundle schema tag ("storylets/bundle@0"
|
|
844
|
+
/** The bundle schema tag ("storylets/bundle@1", or "@0" from before the
|
|
845
|
+
* project map). */
|
|
820
846
|
schema: string;
|
|
821
847
|
/** content.project - the project name a save must agree with. */
|
|
822
848
|
project: string;
|
|
@@ -866,6 +892,10 @@ interface TagGroupSummary {
|
|
|
866
892
|
interface BoxSummary {
|
|
867
893
|
gameId: string;
|
|
868
894
|
title?: string;
|
|
895
|
+
/** The box is on the project map (design/project-map-contract.md 3.7): it
|
|
896
|
+
* may name the map's group in peek criteria beside its own `tagGroups`,
|
|
897
|
+
* which list the box's OWN groups only. Absent is "not on the map". */
|
|
898
|
+
usesMap?: true;
|
|
869
899
|
/** The only per-box ranking policy (Reboot 2.2). */
|
|
870
900
|
ranking: {
|
|
871
901
|
specificity: boolean;
|
|
@@ -911,7 +941,8 @@ interface PropertySummary {
|
|
|
911
941
|
type PropertyScopeKind = "world" | "story" | "box" | "deck" | "hand" | "tag";
|
|
912
942
|
/** One scope's declared properties. `owner` is the owning entity's gameId
|
|
913
943
|
* (empty for world / story); `box` names its box; `group` names a tag's
|
|
914
|
-
* group.
|
|
944
|
+
* group. A zone of the project map is a `tag` scope with `group` and NO
|
|
945
|
+
* `box`: it belongs to none. */
|
|
915
946
|
interface PropertyScopeSummary {
|
|
916
947
|
scope: PropertyScopeKind;
|
|
917
948
|
owner: string;
|
|
@@ -920,23 +951,28 @@ interface PropertyScopeSummary {
|
|
|
920
951
|
properties: PropertySummary[];
|
|
921
952
|
}
|
|
922
953
|
/**
|
|
923
|
-
*
|
|
954
|
+
* The project map (design/project-map-contract.md 3.7): its group, which boxes
|
|
955
|
+
* are on it, and how much geometry the bundle carries.
|
|
924
956
|
*
|
|
925
957
|
* Counts rather than the geometry itself, which is the same judgement the rest
|
|
926
958
|
* of this file makes: an inspector answers "what is in here", and a host that
|
|
927
|
-
* wants the polygons reads `bundle.
|
|
928
|
-
*
|
|
959
|
+
* wants the polygons reads `bundle.map.geometry` directly. The geometry counts
|
|
960
|
+
* are zero when the build did not ask for geometry (`export.map`); the group is
|
|
961
|
+
* there regardless, because hands and cards reference it.
|
|
929
962
|
*/
|
|
930
963
|
interface MapSummary {
|
|
931
|
-
/** The
|
|
932
|
-
box: string;
|
|
933
|
-
/** The tag group this is a map of, by gameId. */
|
|
964
|
+
/** The zone group's gameId: the name an opted-in box's peek criteria use. */
|
|
934
965
|
group: string;
|
|
966
|
+
/** Its tags (the zones), by gameId. */
|
|
967
|
+
tags: string[];
|
|
968
|
+
/** The opted-in boxes, by gameId, in bundle order. */
|
|
969
|
+
boxes: string[];
|
|
970
|
+
/** Drawn zones in the carried geometry. */
|
|
935
971
|
zones: number;
|
|
936
972
|
backgrounds: number;
|
|
937
|
-
/**
|
|
938
|
-
* kiosks are
|
|
939
|
-
sites: number
|
|
973
|
+
/** Box gameId -> placed hands standing on the map (design/engine-server.md
|
|
974
|
+
* 4.3): where the kiosks are. Only boxes with a site have a key. */
|
|
975
|
+
sites: Record<string, number>;
|
|
940
976
|
}
|
|
941
977
|
/** What a bundle offers a host, read from the asset alone. */
|
|
942
978
|
interface BundleDescription {
|
|
@@ -953,13 +989,13 @@ interface BundleDescription {
|
|
|
953
989
|
boxes: BoxSummary[];
|
|
954
990
|
/** Every hand in the bundle, box by box: the deal() surface. */
|
|
955
991
|
hands: HandSummary[];
|
|
956
|
-
/** world, story, then per box: the box, its decks, its hands, its tags
|
|
957
|
-
* Scopes that declare nothing are omitted (world and story always show,
|
|
992
|
+
/** world, story, then per box: the box, its decks, its hands, its tags;
|
|
993
|
+
* then the project map's zones, once. Scopes that declare nothing are omitted (world and story always show,
|
|
958
994
|
* so their absence reads as "this bundle declares none"). */
|
|
959
995
|
properties: PropertyScopeSummary[];
|
|
960
|
-
/**
|
|
961
|
-
*
|
|
962
|
-
|
|
996
|
+
/** The project map, when the bundle has one. Absent is the bundle with no
|
|
997
|
+
* map at all. */
|
|
998
|
+
map?: MapSummary;
|
|
963
999
|
}
|
|
964
1000
|
/** Describe a compiled bundle: the callable surface of an imported asset, no
|
|
965
1001
|
* session required (design/engine-runtimes.md 2, piece 6). Bundle order
|
package/dist/index.d.ts
CHANGED
|
@@ -265,6 +265,7 @@ interface OwnerIndex {
|
|
|
265
265
|
gameId: Map<string, string>;
|
|
266
266
|
id: Map<string, string>;
|
|
267
267
|
repeated: Map<string, string[]>;
|
|
268
|
+
zoneQualified: Map<string, string>;
|
|
268
269
|
}
|
|
269
270
|
type OwnerIndexes = Record<OwnedScope, OwnerIndex>;
|
|
270
271
|
/** One side's five stores (shared on the engine, per-flow on each flow). */
|
|
@@ -297,9 +298,11 @@ interface Internals {
|
|
|
297
298
|
/** The owner segment of a property address, both ways round (4.4). */
|
|
298
299
|
owners: OwnerIndexes;
|
|
299
300
|
templatesById: Map<string, HandTemplate<Expression>>;
|
|
301
|
+
/** Every group by internal id. `box` is absent for the project map's group,
|
|
302
|
+
* which belongs to no box. */
|
|
300
303
|
groupsById: Map<string, {
|
|
301
304
|
group: TagGroup;
|
|
302
|
-
box
|
|
305
|
+
box?: Box<Expression>;
|
|
303
306
|
}>;
|
|
304
307
|
requiredGroups: Set<string>;
|
|
305
308
|
nodeCache: WeakMap<Expression, ExprNode>;
|
|
@@ -507,6 +510,20 @@ declare class Engine {
|
|
|
507
510
|
* `registry`, self-backed @world included; a game that passed a registry
|
|
508
511
|
* saves it once itself, beside each engine's envelope. */
|
|
509
512
|
saveGame(): SaveEnvelope;
|
|
513
|
+
/** The registry's values in CANONICAL order, the order a load rebuilds them
|
|
514
|
+
* in: the engine-wide keys as the constructor registered them, then each
|
|
515
|
+
* flow's keys in `flows()` order (each flow's own registration order), then
|
|
516
|
+
* anything else the registry holds (values still waiting for a key), as the
|
|
517
|
+
* registry lists it. The registry itself lists keys in registration order,
|
|
518
|
+
* and a flow replaced in place (`open()` above keeps its slot in
|
|
519
|
+
* `flowsById`) re-registers its keys at the END, so `openFlow("a");
|
|
520
|
+
* openFlow("b"); openFlow("a")` saved b's keys before a's while a load
|
|
521
|
+
* rebuilt a's first: the same run, different `.storyletsave` bytes, and a
|
|
522
|
+
* save loaded and saved again no longer equal to itself. It is the
|
|
523
|
+
* 2026-08-29 rule carried into the section save@2 moved the per-flow values
|
|
524
|
+
* to (2026-10-01). Order does not matter on READ (`partitionsFromSections`
|
|
525
|
+
* sorts by key shape), so a save written in the old order loads as before. */
|
|
526
|
+
private registrySection;
|
|
510
527
|
/** ONE flow's blob, to park a visit that is walking away: the same shape
|
|
511
528
|
* the envelope carries per flow, and the same shape `openFlow`'s `restore`
|
|
512
529
|
* option takes back (design/engine-server.md 4.1). Saving the whole
|
|
@@ -618,7 +635,13 @@ declare class Flow {
|
|
|
618
635
|
/** Tag group names are box-scoped: two boxes may name a group the same way
|
|
619
636
|
* (schema 1 - boxes namespace their groups), so a name is only ever
|
|
620
637
|
* resolved inside the box being asked, never bundle-wide. Ids are
|
|
621
|
-
* project-unique and accepted here too, still confined to the box.
|
|
638
|
+
* project-unique and accepted here too, still confined to the box.
|
|
639
|
+
*
|
|
640
|
+
* A box on the project map sees ONE namespace: its own groups, then the
|
|
641
|
+
* map's group (design/project-map-contract.md 3.1). A box that has not
|
|
642
|
+
* opted in does not see the map's name at all, so a peek naming it there
|
|
643
|
+
* is the ordinary unknown-group refusal. Own groups first is stated for
|
|
644
|
+
* determinism only: a bundle that loads never has the two share a name. */
|
|
622
645
|
private groupInBox;
|
|
623
646
|
/** Fold one play into the indexes. O(the card's tags), not O(the log). */
|
|
624
647
|
private indexPlay;
|
|
@@ -626,8 +649,10 @@ declare class Flow {
|
|
|
626
649
|
* rather than appended to, which is `restore` alone. */
|
|
627
650
|
private rebuildPlayIndex;
|
|
628
651
|
/** `box` is the box whose ask is being evaluated: the play-history
|
|
629
|
-
* functions take a bare group name, so it resolves there
|
|
630
|
-
*
|
|
652
|
+
* functions take a bare group name, so it resolves there, and they count
|
|
653
|
+
* only that box's own plays (the box is in the index key). That was
|
|
654
|
+
* automatic while every group was a box's; a project-map zone is shared,
|
|
655
|
+
* and its history is still not (design/project-map-contract.md 3.7, D7).
|
|
631
656
|
* History is THIS flow's: countPlayed answers "have I done this". */
|
|
632
657
|
/** One host per box, built once.
|
|
633
658
|
*
|
|
@@ -816,7 +841,8 @@ declare class Flow {
|
|
|
816
841
|
|
|
817
842
|
/** What bundle this is: the staleness/identity triple plus the schema tag. */
|
|
818
843
|
interface BundleIdentity {
|
|
819
|
-
/** The bundle schema tag ("storylets/bundle@0"
|
|
844
|
+
/** The bundle schema tag ("storylets/bundle@1", or "@0" from before the
|
|
845
|
+
* project map). */
|
|
820
846
|
schema: string;
|
|
821
847
|
/** content.project - the project name a save must agree with. */
|
|
822
848
|
project: string;
|
|
@@ -866,6 +892,10 @@ interface TagGroupSummary {
|
|
|
866
892
|
interface BoxSummary {
|
|
867
893
|
gameId: string;
|
|
868
894
|
title?: string;
|
|
895
|
+
/** The box is on the project map (design/project-map-contract.md 3.7): it
|
|
896
|
+
* may name the map's group in peek criteria beside its own `tagGroups`,
|
|
897
|
+
* which list the box's OWN groups only. Absent is "not on the map". */
|
|
898
|
+
usesMap?: true;
|
|
869
899
|
/** The only per-box ranking policy (Reboot 2.2). */
|
|
870
900
|
ranking: {
|
|
871
901
|
specificity: boolean;
|
|
@@ -911,7 +941,8 @@ interface PropertySummary {
|
|
|
911
941
|
type PropertyScopeKind = "world" | "story" | "box" | "deck" | "hand" | "tag";
|
|
912
942
|
/** One scope's declared properties. `owner` is the owning entity's gameId
|
|
913
943
|
* (empty for world / story); `box` names its box; `group` names a tag's
|
|
914
|
-
* group.
|
|
944
|
+
* group. A zone of the project map is a `tag` scope with `group` and NO
|
|
945
|
+
* `box`: it belongs to none. */
|
|
915
946
|
interface PropertyScopeSummary {
|
|
916
947
|
scope: PropertyScopeKind;
|
|
917
948
|
owner: string;
|
|
@@ -920,23 +951,28 @@ interface PropertyScopeSummary {
|
|
|
920
951
|
properties: PropertySummary[];
|
|
921
952
|
}
|
|
922
953
|
/**
|
|
923
|
-
*
|
|
954
|
+
* The project map (design/project-map-contract.md 3.7): its group, which boxes
|
|
955
|
+
* are on it, and how much geometry the bundle carries.
|
|
924
956
|
*
|
|
925
957
|
* Counts rather than the geometry itself, which is the same judgement the rest
|
|
926
958
|
* of this file makes: an inspector answers "what is in here", and a host that
|
|
927
|
-
* wants the polygons reads `bundle.
|
|
928
|
-
*
|
|
959
|
+
* wants the polygons reads `bundle.map.geometry` directly. The geometry counts
|
|
960
|
+
* are zero when the build did not ask for geometry (`export.map`); the group is
|
|
961
|
+
* there regardless, because hands and cards reference it.
|
|
929
962
|
*/
|
|
930
963
|
interface MapSummary {
|
|
931
|
-
/** The
|
|
932
|
-
box: string;
|
|
933
|
-
/** The tag group this is a map of, by gameId. */
|
|
964
|
+
/** The zone group's gameId: the name an opted-in box's peek criteria use. */
|
|
934
965
|
group: string;
|
|
966
|
+
/** Its tags (the zones), by gameId. */
|
|
967
|
+
tags: string[];
|
|
968
|
+
/** The opted-in boxes, by gameId, in bundle order. */
|
|
969
|
+
boxes: string[];
|
|
970
|
+
/** Drawn zones in the carried geometry. */
|
|
935
971
|
zones: number;
|
|
936
972
|
backgrounds: number;
|
|
937
|
-
/**
|
|
938
|
-
* kiosks are
|
|
939
|
-
sites: number
|
|
973
|
+
/** Box gameId -> placed hands standing on the map (design/engine-server.md
|
|
974
|
+
* 4.3): where the kiosks are. Only boxes with a site have a key. */
|
|
975
|
+
sites: Record<string, number>;
|
|
940
976
|
}
|
|
941
977
|
/** What a bundle offers a host, read from the asset alone. */
|
|
942
978
|
interface BundleDescription {
|
|
@@ -953,13 +989,13 @@ interface BundleDescription {
|
|
|
953
989
|
boxes: BoxSummary[];
|
|
954
990
|
/** Every hand in the bundle, box by box: the deal() surface. */
|
|
955
991
|
hands: HandSummary[];
|
|
956
|
-
/** world, story, then per box: the box, its decks, its hands, its tags
|
|
957
|
-
* Scopes that declare nothing are omitted (world and story always show,
|
|
992
|
+
/** world, story, then per box: the box, its decks, its hands, its tags;
|
|
993
|
+
* then the project map's zones, once. Scopes that declare nothing are omitted (world and story always show,
|
|
958
994
|
* so their absence reads as "this bundle declares none"). */
|
|
959
995
|
properties: PropertyScopeSummary[];
|
|
960
|
-
/**
|
|
961
|
-
*
|
|
962
|
-
|
|
996
|
+
/** The project map, when the bundle has one. Absent is the bundle with no
|
|
997
|
+
* map at all. */
|
|
998
|
+
map?: MapSummary;
|
|
963
999
|
}
|
|
964
1000
|
/** Describe a compiled bundle: the callable surface of an imported asset, no
|
|
965
1001
|
* session required (design/engine-runtimes.md 2, piece 6). Bundle order
|