@patterkit/model 0.4.1 → 0.6.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/dist/index.cjs CHANGED
@@ -30,6 +30,8 @@ __export(index_exports, {
30
30
  RERECORD_STATUS: () => RERECORD_STATUS,
31
31
  RERECORD_STATUS_DECL: () => RERECORD_STATUS_DECL,
32
32
  RESERVED_PROPERTY_NAMES: () => import_expr.RESERVED_PROPERTY_NAMES,
33
+ SAVE_SCHEMA: () => SAVE_SCHEMA,
34
+ SAVE_VERSION: () => SAVE_VERSION,
33
35
  castStringKey: () => castStringKey,
34
36
  deriveRecordingFolders: () => deriveRecordingFolders,
35
37
  effectiveGameId: () => effectiveGameId,
@@ -113,6 +115,8 @@ function castStringKey(name) {
113
115
  }
114
116
  var DEFAULT_CAPTION_DELIMITERS = { open: "[", close: "]" };
115
117
  var DEFAULT_CAPTION_CHARACTER = "SFX";
118
+ var SAVE_SCHEMA = "patter/save@0";
119
+ var SAVE_VERSION = 3;
116
120
  // Annotate the CommonJS export names for ESM import in node:
117
121
  0 && (module.exports = {
118
122
  COMMON_GENDERS,
@@ -125,6 +129,8 @@ var DEFAULT_CAPTION_CHARACTER = "SFX";
125
129
  RERECORD_STATUS,
126
130
  RERECORD_STATUS_DECL,
127
131
  RESERVED_PROPERTY_NAMES,
132
+ SAVE_SCHEMA,
133
+ SAVE_VERSION,
128
134
  castStringKey,
129
135
  deriveRecordingFolders,
130
136
  effectiveGameId,
package/dist/index.d.cts CHANGED
@@ -809,6 +809,10 @@ interface Bundle {
809
809
  /** Host / world scope declarations, baked from the project so the runtime can self-back a declared
810
810
  * scope (`@world`, ...) when no host resolver claims its token. Absent = no host scopes. */
811
811
  scopeRegistry?: HostScopeRegistry;
812
+ /** Other engines' game-wide scopes the content names (`story`), sorted: the family's shared vocabulary,
813
+ * opaque to the compiler and never self-backed. The engine reports when the game has not registered
814
+ * one. Absent when none. */
815
+ externalScopes?: string[];
812
816
  gameDataFields?: GameDataFields;
813
817
  scenes: Record<string, CompiledScene>;
814
818
  /** locale -> (beatId -> text). In "embedded" localisation this carries every included locale; in "ids"
@@ -845,5 +849,112 @@ declare const DEFAULT_CAPTION_DELIMITERS: CaptionDelimiters;
845
849
  /** The default caption character: a cast member named `SFX` whose lines are pure captions (omitted when
846
850
  * captions are off). Applies even to a project that pins no `closedCaptions`. */
847
851
  declare const DEFAULT_CAPTION_CHARACTER = "SFX";
852
+ declare const SAVE_SCHEMA = "patter/save@0";
853
+ /** The `save.version` inside the envelope. Bumped only when a reader would MISREAD an older save. */
854
+ declare const SAVE_VERSION = 3;
855
+ /** The tagged envelope a host stores: `serializeState` writes it, `deserializeState` refuses anything else. */
856
+ interface SaveEnvelope {
857
+ schema: typeof SAVE_SCHEMA;
858
+ save: SaveGame;
859
+ }
860
+ /** A registry's values: registry key -> property name -> value (`{ patter: { gold: 7 } }`). */
861
+ type EngineSave = Record<string, Record<string, ScalarValue>>;
862
+ /** Serialised `sequence` selector visit state for one group (spec §4 / §7). Every key is OPTIONAL and
863
+ * present only once the selector has used it: `seq` after the first sequential pick, `bag` once a
864
+ * shuffle has drawn, `last` once there is a no-immediate-repeat memory. A port that stores "started"
865
+ * flags derives them from key presence rather than writing them. */
866
+ interface SelectorSnapshot {
867
+ seq?: number;
868
+ bag?: string[];
869
+ last?: string;
870
+ }
871
+ /** One entry on a flow's continuation stack: a position within a container's children. */
872
+ interface StackFrame {
873
+ sceneId: string;
874
+ /** A block id or a run-group id (both are sequential containers). */
875
+ containerId: string;
876
+ index: number;
877
+ /** SNAPSHOT-ONLY (never on a live frame): the id of the child at `index` when the save was taken, so a
878
+ * restore against an EDITED bundle re-finds the position by id. Absent when the frame sat at its
879
+ * container's end (no next child), or in an older save. */
880
+ nextId?: string;
881
+ }
882
+ /** The prompt of a saved choice option: the choice text as a structured line/text beat. */
883
+ interface SavedChoicePrompt {
884
+ kind: "line" | "text";
885
+ text: string;
886
+ character?: string;
887
+ characterName?: string;
888
+ direction?: string;
889
+ }
890
+ /** One option of a pending choice, saved VERBATIM: re-deriving on load would re-evaluate conditions. */
891
+ interface SavedChoiceOption {
892
+ id: string;
893
+ prompt?: SavedChoicePrompt;
894
+ eligible: boolean;
895
+ gameData?: GameData;
896
+ }
897
+ /** A pending choice as saved: the option set the player was shown, replayed on load (schema 9.3). */
898
+ interface SavedChoice {
899
+ groupId: string;
900
+ options: SavedChoiceOption[];
901
+ }
902
+ /** The flow's execution position: where it is, and what it is waiting on. */
903
+ interface FlowCursor {
904
+ flowEnded: boolean;
905
+ currentSceneId: string | null;
906
+ /** The continuation stack (call frames + the active block run), root first. */
907
+ stack: StackFrame[];
908
+ activeSnippetId: string | null;
909
+ beatIndex: number;
910
+ /** Present (non-null) iff the flow is stopped at a choice. */
911
+ pendingChoice: SavedChoice | null;
912
+ /** The chosen option owning a prompt still to be replayed (a save taken between choose + advance).
913
+ * Optional / null in older saves -> no pending prompt. */
914
+ pendingPromptOwnerId?: string | null;
915
+ /** This flow's (non-shared) selector cursors, keyed by group id. */
916
+ selectors: Record<string, SelectorSnapshot>;
917
+ }
918
+ /** The serialised cursor + PRNG + visits of a single flow. Its properties are the registry's. */
919
+ interface FlowSnapshot {
920
+ /** This flow's built-in PRNG position (mulberry32 state, uint32; older saves may carry it signed). */
921
+ rngState: number;
922
+ /** This flow's per-node entry counts (node id -> times entered by this flow). */
923
+ visits: Record<string, number>;
924
+ cursor: FlowCursor;
925
+ }
926
+ /** A full resumable save-game (version 3): everything that is not a property, plus the registry's
927
+ * values when the engine made its own registry. */
928
+ interface SaveGame {
929
+ version: 3;
930
+ /** The engine's own registry's values, keyed by registry key: present only when the engine made the
931
+ * registry itself (a standalone game). A game that passed a registry saves it once, beside this. */
932
+ registry?: EngineSave;
933
+ /** World-wide per-node entry counts (node id -> times entered by any flow). */
934
+ sharedVisits: Record<string, number>;
935
+ /** Shared selector cursors (node id -> snapshot) for `shared` memoried selectors. */
936
+ sharedSelectors: Record<string, SelectorSnapshot>;
937
+ /** Each live flow's snapshot, keyed by flow id. */
938
+ flows: Record<string, FlowSnapshot>;
939
+ }
940
+ /** A version 2 flow snapshot, which carried the flow's property values itself. Still read. */
941
+ interface FlowSnapshotV2 extends FlowSnapshot {
942
+ /** The NOT-shared `@patter` globals, under token "patter". */
943
+ scopes: EngineSave;
944
+ /** Per-scene NOT-shared `@scene` bags (scene id -> name -> value). */
945
+ sceneBags: Record<string, Record<string, ScalarValue>>;
946
+ }
947
+ /** A version 2 save, from before the registry held the properties. Every runtime still reads it: its
948
+ * property sections move into the registry (under the keys in the header above) as it loads. */
949
+ interface SaveGameV2 {
950
+ version: 2;
951
+ /** Shared `@patter` globals (owned scope "patter"). */
952
+ shared: EngineSave;
953
+ sharedVisits: Record<string, number>;
954
+ sharedSelectors: Record<string, SelectorSnapshot>;
955
+ /** Shared, scene-namespaced `@scene` bags (scene id -> name -> value). */
956
+ stageBags: Record<string, Record<string, ScalarValue>>;
957
+ flows: Record<string, FlowSnapshotV2>;
958
+ }
848
959
 
849
- export { type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, COMMON_GENDERS, type CaptionDelimiters, type CastMember, type Comment, type CommentMessage, type CommentRange, type CompiledBlock, type CompiledEffect, type CompiledGroup, type CompiledScene, type CompiledSnippet, type CoverageDriver, DEFAULT_CAPTION_CHARACTER, DEFAULT_CAPTION_DELIMITERS, DEFAULT_DOCUMENTATION_CLASSES, DEFAULT_RECORDING_STATUSES, DEFAULT_WRITING_STATUSES, type DocLine, type DocumentationClass, type EditRecord, type Effect, type EstimatingConfig, type Expression, type FlowFile, type FlowNode, type GameData, type GameDataField, type GameDataFieldType, type GameDataFields, type GameDataNodeKind, type GameEventBeat, type GrammaticalGender, type Group, type HostScopeDecl, type HostScopeRegistry, type HostScopeSpec, type Jump, type JumpTarget, type LineBeat, type LocaleFile, PROJECT_LOCALE_SCENE, type ProjectDictionary, type ProjectFile, type PromptBeat, type PropertyDecl, type PropertyType, RERECORD_STATUS, RERECORD_STATUS_DECL, type RecordingFolder, type RecordingStatusDecl, type ScalarValue, type Scene, type Selector, type SelectorExhaust, type SelectorOrder, type SequenceOptions, type Snippet, type Suggestion, type TextBeat, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, gameIdify, isContentlessBeat, isValidGameId, walkNodes };
960
+ export { type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, COMMON_GENDERS, type CaptionDelimiters, type CastMember, type Comment, type CommentMessage, type CommentRange, type CompiledBlock, type CompiledEffect, type CompiledGroup, type CompiledScene, type CompiledSnippet, type CoverageDriver, DEFAULT_CAPTION_CHARACTER, DEFAULT_CAPTION_DELIMITERS, DEFAULT_DOCUMENTATION_CLASSES, DEFAULT_RECORDING_STATUSES, DEFAULT_WRITING_STATUSES, type DocLine, type DocumentationClass, type EditRecord, type Effect, type EngineSave, type EstimatingConfig, type Expression, type FlowCursor, type FlowFile, type FlowNode, type FlowSnapshot, type FlowSnapshotV2, type GameData, type GameDataField, type GameDataFieldType, type GameDataFields, type GameDataNodeKind, type GameEventBeat, type GrammaticalGender, type Group, type HostScopeDecl, type HostScopeRegistry, type HostScopeSpec, type Jump, type JumpTarget, type LineBeat, type LocaleFile, PROJECT_LOCALE_SCENE, type ProjectDictionary, type ProjectFile, type PromptBeat, type PropertyDecl, type PropertyType, RERECORD_STATUS, RERECORD_STATUS_DECL, type RecordingFolder, type RecordingStatusDecl, SAVE_SCHEMA, SAVE_VERSION, type SaveEnvelope, type SaveGame, type SaveGameV2, type SavedChoice, type SavedChoiceOption, type SavedChoicePrompt, type ScalarValue, type Scene, type Selector, type SelectorExhaust, type SelectorOrder, type SelectorSnapshot, type SequenceOptions, type Snippet, type StackFrame, type Suggestion, type TextBeat, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, gameIdify, isContentlessBeat, isValidGameId, walkNodes };
package/dist/index.d.ts CHANGED
@@ -809,6 +809,10 @@ interface Bundle {
809
809
  /** Host / world scope declarations, baked from the project so the runtime can self-back a declared
810
810
  * scope (`@world`, ...) when no host resolver claims its token. Absent = no host scopes. */
811
811
  scopeRegistry?: HostScopeRegistry;
812
+ /** Other engines' game-wide scopes the content names (`story`), sorted: the family's shared vocabulary,
813
+ * opaque to the compiler and never self-backed. The engine reports when the game has not registered
814
+ * one. Absent when none. */
815
+ externalScopes?: string[];
812
816
  gameDataFields?: GameDataFields;
813
817
  scenes: Record<string, CompiledScene>;
814
818
  /** locale -> (beatId -> text). In "embedded" localisation this carries every included locale; in "ids"
@@ -845,5 +849,112 @@ declare const DEFAULT_CAPTION_DELIMITERS: CaptionDelimiters;
845
849
  /** The default caption character: a cast member named `SFX` whose lines are pure captions (omitted when
846
850
  * captions are off). Applies even to a project that pins no `closedCaptions`. */
847
851
  declare const DEFAULT_CAPTION_CHARACTER = "SFX";
852
+ declare const SAVE_SCHEMA = "patter/save@0";
853
+ /** The `save.version` inside the envelope. Bumped only when a reader would MISREAD an older save. */
854
+ declare const SAVE_VERSION = 3;
855
+ /** The tagged envelope a host stores: `serializeState` writes it, `deserializeState` refuses anything else. */
856
+ interface SaveEnvelope {
857
+ schema: typeof SAVE_SCHEMA;
858
+ save: SaveGame;
859
+ }
860
+ /** A registry's values: registry key -> property name -> value (`{ patter: { gold: 7 } }`). */
861
+ type EngineSave = Record<string, Record<string, ScalarValue>>;
862
+ /** Serialised `sequence` selector visit state for one group (spec §4 / §7). Every key is OPTIONAL and
863
+ * present only once the selector has used it: `seq` after the first sequential pick, `bag` once a
864
+ * shuffle has drawn, `last` once there is a no-immediate-repeat memory. A port that stores "started"
865
+ * flags derives them from key presence rather than writing them. */
866
+ interface SelectorSnapshot {
867
+ seq?: number;
868
+ bag?: string[];
869
+ last?: string;
870
+ }
871
+ /** One entry on a flow's continuation stack: a position within a container's children. */
872
+ interface StackFrame {
873
+ sceneId: string;
874
+ /** A block id or a run-group id (both are sequential containers). */
875
+ containerId: string;
876
+ index: number;
877
+ /** SNAPSHOT-ONLY (never on a live frame): the id of the child at `index` when the save was taken, so a
878
+ * restore against an EDITED bundle re-finds the position by id. Absent when the frame sat at its
879
+ * container's end (no next child), or in an older save. */
880
+ nextId?: string;
881
+ }
882
+ /** The prompt of a saved choice option: the choice text as a structured line/text beat. */
883
+ interface SavedChoicePrompt {
884
+ kind: "line" | "text";
885
+ text: string;
886
+ character?: string;
887
+ characterName?: string;
888
+ direction?: string;
889
+ }
890
+ /** One option of a pending choice, saved VERBATIM: re-deriving on load would re-evaluate conditions. */
891
+ interface SavedChoiceOption {
892
+ id: string;
893
+ prompt?: SavedChoicePrompt;
894
+ eligible: boolean;
895
+ gameData?: GameData;
896
+ }
897
+ /** A pending choice as saved: the option set the player was shown, replayed on load (schema 9.3). */
898
+ interface SavedChoice {
899
+ groupId: string;
900
+ options: SavedChoiceOption[];
901
+ }
902
+ /** The flow's execution position: where it is, and what it is waiting on. */
903
+ interface FlowCursor {
904
+ flowEnded: boolean;
905
+ currentSceneId: string | null;
906
+ /** The continuation stack (call frames + the active block run), root first. */
907
+ stack: StackFrame[];
908
+ activeSnippetId: string | null;
909
+ beatIndex: number;
910
+ /** Present (non-null) iff the flow is stopped at a choice. */
911
+ pendingChoice: SavedChoice | null;
912
+ /** The chosen option owning a prompt still to be replayed (a save taken between choose + advance).
913
+ * Optional / null in older saves -> no pending prompt. */
914
+ pendingPromptOwnerId?: string | null;
915
+ /** This flow's (non-shared) selector cursors, keyed by group id. */
916
+ selectors: Record<string, SelectorSnapshot>;
917
+ }
918
+ /** The serialised cursor + PRNG + visits of a single flow. Its properties are the registry's. */
919
+ interface FlowSnapshot {
920
+ /** This flow's built-in PRNG position (mulberry32 state, uint32; older saves may carry it signed). */
921
+ rngState: number;
922
+ /** This flow's per-node entry counts (node id -> times entered by this flow). */
923
+ visits: Record<string, number>;
924
+ cursor: FlowCursor;
925
+ }
926
+ /** A full resumable save-game (version 3): everything that is not a property, plus the registry's
927
+ * values when the engine made its own registry. */
928
+ interface SaveGame {
929
+ version: 3;
930
+ /** The engine's own registry's values, keyed by registry key: present only when the engine made the
931
+ * registry itself (a standalone game). A game that passed a registry saves it once, beside this. */
932
+ registry?: EngineSave;
933
+ /** World-wide per-node entry counts (node id -> times entered by any flow). */
934
+ sharedVisits: Record<string, number>;
935
+ /** Shared selector cursors (node id -> snapshot) for `shared` memoried selectors. */
936
+ sharedSelectors: Record<string, SelectorSnapshot>;
937
+ /** Each live flow's snapshot, keyed by flow id. */
938
+ flows: Record<string, FlowSnapshot>;
939
+ }
940
+ /** A version 2 flow snapshot, which carried the flow's property values itself. Still read. */
941
+ interface FlowSnapshotV2 extends FlowSnapshot {
942
+ /** The NOT-shared `@patter` globals, under token "patter". */
943
+ scopes: EngineSave;
944
+ /** Per-scene NOT-shared `@scene` bags (scene id -> name -> value). */
945
+ sceneBags: Record<string, Record<string, ScalarValue>>;
946
+ }
947
+ /** A version 2 save, from before the registry held the properties. Every runtime still reads it: its
948
+ * property sections move into the registry (under the keys in the header above) as it loads. */
949
+ interface SaveGameV2 {
950
+ version: 2;
951
+ /** Shared `@patter` globals (owned scope "patter"). */
952
+ shared: EngineSave;
953
+ sharedVisits: Record<string, number>;
954
+ sharedSelectors: Record<string, SelectorSnapshot>;
955
+ /** Shared, scene-namespaced `@scene` bags (scene id -> name -> value). */
956
+ stageBags: Record<string, Record<string, ScalarValue>>;
957
+ flows: Record<string, FlowSnapshotV2>;
958
+ }
848
959
 
849
- export { type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, COMMON_GENDERS, type CaptionDelimiters, type CastMember, type Comment, type CommentMessage, type CommentRange, type CompiledBlock, type CompiledEffect, type CompiledGroup, type CompiledScene, type CompiledSnippet, type CoverageDriver, DEFAULT_CAPTION_CHARACTER, DEFAULT_CAPTION_DELIMITERS, DEFAULT_DOCUMENTATION_CLASSES, DEFAULT_RECORDING_STATUSES, DEFAULT_WRITING_STATUSES, type DocLine, type DocumentationClass, type EditRecord, type Effect, type EstimatingConfig, type Expression, type FlowFile, type FlowNode, type GameData, type GameDataField, type GameDataFieldType, type GameDataFields, type GameDataNodeKind, type GameEventBeat, type GrammaticalGender, type Group, type HostScopeDecl, type HostScopeRegistry, type HostScopeSpec, type Jump, type JumpTarget, type LineBeat, type LocaleFile, PROJECT_LOCALE_SCENE, type ProjectDictionary, type ProjectFile, type PromptBeat, type PropertyDecl, type PropertyType, RERECORD_STATUS, RERECORD_STATUS_DECL, type RecordingFolder, type RecordingStatusDecl, type ScalarValue, type Scene, type Selector, type SelectorExhaust, type SelectorOrder, type SequenceOptions, type Snippet, type Suggestion, type TextBeat, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, gameIdify, isContentlessBeat, isValidGameId, walkNodes };
960
+ export { type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, COMMON_GENDERS, type CaptionDelimiters, type CastMember, type Comment, type CommentMessage, type CommentRange, type CompiledBlock, type CompiledEffect, type CompiledGroup, type CompiledScene, type CompiledSnippet, type CoverageDriver, DEFAULT_CAPTION_CHARACTER, DEFAULT_CAPTION_DELIMITERS, DEFAULT_DOCUMENTATION_CLASSES, DEFAULT_RECORDING_STATUSES, DEFAULT_WRITING_STATUSES, type DocLine, type DocumentationClass, type EditRecord, type Effect, type EngineSave, type EstimatingConfig, type Expression, type FlowCursor, type FlowFile, type FlowNode, type FlowSnapshot, type FlowSnapshotV2, type GameData, type GameDataField, type GameDataFieldType, type GameDataFields, type GameDataNodeKind, type GameEventBeat, type GrammaticalGender, type Group, type HostScopeDecl, type HostScopeRegistry, type HostScopeSpec, type Jump, type JumpTarget, type LineBeat, type LocaleFile, PROJECT_LOCALE_SCENE, type ProjectDictionary, type ProjectFile, type PromptBeat, type PropertyDecl, type PropertyType, RERECORD_STATUS, RERECORD_STATUS_DECL, type RecordingFolder, type RecordingStatusDecl, SAVE_SCHEMA, SAVE_VERSION, type SaveEnvelope, type SaveGame, type SaveGameV2, type SavedChoice, type SavedChoiceOption, type SavedChoicePrompt, type ScalarValue, type Scene, type Selector, type SelectorExhaust, type SelectorOrder, type SelectorSnapshot, type SequenceOptions, type Snippet, type StackFrame, type Suggestion, type TextBeat, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, gameIdify, isContentlessBeat, isValidGameId, walkNodes };
package/dist/index.js CHANGED
@@ -75,6 +75,8 @@ function castStringKey(name) {
75
75
  }
76
76
  var DEFAULT_CAPTION_DELIMITERS = { open: "[", close: "]" };
77
77
  var DEFAULT_CAPTION_CHARACTER = "SFX";
78
+ var SAVE_SCHEMA = "patter/save@0";
79
+ var SAVE_VERSION = 3;
78
80
  export {
79
81
  COMMON_GENDERS,
80
82
  DEFAULT_CAPTION_CHARACTER,
@@ -86,6 +88,8 @@ export {
86
88
  RERECORD_STATUS,
87
89
  RERECORD_STATUS_DECL,
88
90
  RESERVED_PROPERTY_NAMES,
91
+ SAVE_SCHEMA,
92
+ SAVE_VERSION,
89
93
  castStringKey,
90
94
  deriveRecordingFolders,
91
95
  effectiveGameId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patterkit/model",
3
- "version": "0.4.1",
3
+ "version": "0.6.0",
4
4
  "description": "Patter data-model types: source (scene/block/group/snippet/beat/jump), project, locale, authoring. The shape source-of-truth.",
5
5
  "type": "module",
6
6
  "license": "MIT",