@patterkit/model 0.1.1 → 0.2.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
@@ -26,6 +26,8 @@ __export(index_exports, {
26
26
  DEFAULT_RECORDING_STATUSES: () => DEFAULT_RECORDING_STATUSES,
27
27
  DEFAULT_WRITING_STATUSES: () => DEFAULT_WRITING_STATUSES,
28
28
  PROJECT_LOCALE_SCENE: () => PROJECT_LOCALE_SCENE,
29
+ RERECORD_STATUS: () => RERECORD_STATUS,
30
+ RERECORD_STATUS_DECL: () => RERECORD_STATUS_DECL,
29
31
  castStringKey: () => castStringKey,
30
32
  deriveRecordingFolders: () => deriveRecordingFolders,
31
33
  effectiveGameId: () => effectiveGameId,
@@ -81,6 +83,8 @@ var DEFAULT_RECORDING_STATUSES = [
81
83
  { name: "final", colour: 9 }
82
84
  // purple
83
85
  ];
86
+ var RERECORD_STATUS = "rerecord";
87
+ var RERECORD_STATUS_DECL = { name: RERECORD_STATUS, colour: 1 };
84
88
  function deriveRecordingFolders(audioRoot, statuses) {
85
89
  const root = audioRoot?.trim();
86
90
  return statuses.map((s, i) => {
@@ -110,6 +114,8 @@ var DEFAULT_CAPTION_CHARACTER = "SFX";
110
114
  DEFAULT_RECORDING_STATUSES,
111
115
  DEFAULT_WRITING_STATUSES,
112
116
  PROJECT_LOCALE_SCENE,
117
+ RERECORD_STATUS,
118
+ RERECORD_STATUS_DECL,
113
119
  castStringKey,
114
120
  deriveRecordingFolders,
115
121
  effectiveGameId,
package/dist/index.d.cts CHANGED
@@ -293,11 +293,18 @@ interface CoverageDriver {
293
293
  /** The pool the harness picks from (uniform). Empty = the driver is inert. */
294
294
  values: ScalarValue[];
295
295
  }
296
+ /** A character's grammatical gender, for localisation. Translators need it to inflect the speaker's own
297
+ * lines in gendered languages (adjectives, participles, pronouns), which the source text alone often
298
+ * cannot tell them. Absent means "not specified". Authoring-only: it never reaches the runtime bundle,
299
+ * but it IS carried into the localisation handoff formats as translator context (spec §14). */
300
+ type GrammaticalGender = "male" | "female" | "neuter";
296
301
  interface CastMember {
297
302
  /** Canonical speaker name (matched by a beat's `character`); language-neutral key. */
298
303
  name: string;
299
304
  /** Localised player-facing name - a localisation id (project-level strings). */
300
305
  displayName?: string;
306
+ /** Grammatical gender for translators (see `GrammaticalGender`); absent = not specified. */
307
+ gender?: GrammaticalGender;
301
308
  /** Free-text production notes about the character (casting, voice, intent) - authoring only. */
302
309
  notes?: string;
303
310
  /** The voice actor cast for this character, if known - surfaced in the VO script export (spec §16).
@@ -305,6 +312,12 @@ interface CastMember {
305
312
  actor?: string;
306
313
  gameData?: GameData;
307
314
  }
315
+ /** The cast as it reaches a compiled bundle: the player-facing fields only. `notes`, `actor` and
316
+ * `gender` are authoring / production / translation context, and the compiler drops them, so a shipped
317
+ * game never carries a real person's name or a writer's private notes. The compiler copies the shipping
318
+ * fields across explicitly (an allow-list), which is what actually keeps a new authoring field out of
319
+ * the bundle; this type states the resulting contract for anyone reading a bundle. */
320
+ type BundleCastMember = Omit<CastMember, "notes" | "actor" | "gender">;
308
321
  /** A node TYPE that can carry author-defined gameData fields (the gameData schema, project-level).
309
322
  * Beat kinds map straight through: dialogue = `line`, narration = `text`, game event = `gameEvent`. */
310
323
  type GameDataNodeKind = "scene" | "block" | "snippet" | "line" | "text" | "gameEvent";
@@ -357,6 +370,13 @@ interface RecordingStatusDecl {
357
370
  /** The default recording-status ladder (used when a project declares none). The FIRST rung is the
358
371
  * level-0 / absence status: a beat with no recorded status counts as `missing`. */
359
372
  declare const DEFAULT_RECORDING_STATUSES: RecordingStatusDecl[];
373
+ /** The reserved recording status a line takes when it is flagged **needs re-record** (#227): a recorded
374
+ * take exists but is unusable (bad quality, wrong take), so it must be redone. It is NOT a ladder rung -
375
+ * it is a regression flag that MASKS the derived / manual rung for the recording script, the production
376
+ * report, and status browse, so a line "recorded" on disk still shows up as work to do. Reserved so it
377
+ * can't collide with an author-declared rung; carries its own alert colour. */
378
+ declare const RERECORD_STATUS = "rerecord";
379
+ declare const RERECORD_STATUS_DECL: RecordingStatusDecl;
360
380
  /** One recording rung mapped to the folder its audio files live in (Audio Folders mode). */
361
381
  interface RecordingFolder {
362
382
  name: string;
@@ -475,6 +495,12 @@ interface ProjectFile {
475
495
  /** Autosave: periodically persist the edited scene without an explicit Save. Default ON (omitted ===
476
496
  * enabled); set `false` to require manual saves. */
477
497
  autosave?: boolean;
498
+ /** Auto Rebuild: recompile the `.patterc` bundle automatically after edits (debounced), so the on-disk
499
+ * build stays current without a manual Publish Bundle. Editor-only; never reaches the bundle. Default OFF
500
+ * (omitted === off) - opt-in, since it writes the bundle on every real change (poor fit if you commit the
501
+ * bundle to a lock-based VCS). The rebuild is deduped (skipped when the compiled bundle is unchanged) and
502
+ * a mid-edit invalid project silently keeps the last good build. */
503
+ autoRebuild?: boolean;
478
504
  /** Closed captions (#214): the delimiter pair that wraps non-spoken caption cues inside DIALOGUE
479
505
  * lines (e.g. `(sigh)` in `Oh dear. (sigh) What now?`). A game can turn captions off at runtime
480
506
  * (`setClosedCaptions(false)`), and the runtime then strips every `open…close` span - delimiters and
@@ -657,6 +683,14 @@ interface AuthoringFile {
657
683
  * it as a separate "cut: N" figure so a removal is visible, not vanished.
658
684
  */
659
685
  cut?: Record<string, boolean>;
686
+ /**
687
+ * **Needs re-record** (#227): dialogue-line ids whose recorded take is unusable and must be redone
688
+ * (bad quality, wrong take, misread). Orthogonal to the recording ladder - a flagged line keeps its
689
+ * audio on disk, but its recording status is MASKED to the reserved `rerecord` status for the recording
690
+ * script / report / status browse (see `RERECORD_STATUS`), so a "recorded" line still reads as work.
691
+ * Authoring-only; never compiled into a bundle.
692
+ */
693
+ rerecord?: Record<string, boolean>;
660
694
  }
661
695
  /** A compiled expression envelope: canonical source + pre-derived tagged-tuple AST. */
662
696
  interface Expression {
@@ -742,7 +776,8 @@ interface Bundle {
742
776
  default: string;
743
777
  included: string[];
744
778
  };
745
- cast?: CastMember[];
779
+ /** Player-facing cast only: the compiler strips notes / actor / gender (see `BundleCastMember`). */
780
+ cast?: BundleCastMember[];
746
781
  properties?: PropertyDecl[];
747
782
  /** Host / world scope declarations, baked from the project so the runtime can self-back a declared
748
783
  * scope (`@world`, ...) when no host resolver claims its token. Absent = no host scopes. */
@@ -784,4 +819,4 @@ declare const DEFAULT_CAPTION_DELIMITERS: CaptionDelimiters;
784
819
  * captions are off). Applies even to a project that pins no `closedCaptions`. */
785
820
  declare const DEFAULT_CAPTION_CHARACTER = "SFX";
786
821
 
787
- export { type AuthoringFile, type Beat, type Block, type Bundle, 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 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, 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 };
822
+ export { type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, 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 };
package/dist/index.d.ts CHANGED
@@ -293,11 +293,18 @@ interface CoverageDriver {
293
293
  /** The pool the harness picks from (uniform). Empty = the driver is inert. */
294
294
  values: ScalarValue[];
295
295
  }
296
+ /** A character's grammatical gender, for localisation. Translators need it to inflect the speaker's own
297
+ * lines in gendered languages (adjectives, participles, pronouns), which the source text alone often
298
+ * cannot tell them. Absent means "not specified". Authoring-only: it never reaches the runtime bundle,
299
+ * but it IS carried into the localisation handoff formats as translator context (spec §14). */
300
+ type GrammaticalGender = "male" | "female" | "neuter";
296
301
  interface CastMember {
297
302
  /** Canonical speaker name (matched by a beat's `character`); language-neutral key. */
298
303
  name: string;
299
304
  /** Localised player-facing name - a localisation id (project-level strings). */
300
305
  displayName?: string;
306
+ /** Grammatical gender for translators (see `GrammaticalGender`); absent = not specified. */
307
+ gender?: GrammaticalGender;
301
308
  /** Free-text production notes about the character (casting, voice, intent) - authoring only. */
302
309
  notes?: string;
303
310
  /** The voice actor cast for this character, if known - surfaced in the VO script export (spec §16).
@@ -305,6 +312,12 @@ interface CastMember {
305
312
  actor?: string;
306
313
  gameData?: GameData;
307
314
  }
315
+ /** The cast as it reaches a compiled bundle: the player-facing fields only. `notes`, `actor` and
316
+ * `gender` are authoring / production / translation context, and the compiler drops them, so a shipped
317
+ * game never carries a real person's name or a writer's private notes. The compiler copies the shipping
318
+ * fields across explicitly (an allow-list), which is what actually keeps a new authoring field out of
319
+ * the bundle; this type states the resulting contract for anyone reading a bundle. */
320
+ type BundleCastMember = Omit<CastMember, "notes" | "actor" | "gender">;
308
321
  /** A node TYPE that can carry author-defined gameData fields (the gameData schema, project-level).
309
322
  * Beat kinds map straight through: dialogue = `line`, narration = `text`, game event = `gameEvent`. */
310
323
  type GameDataNodeKind = "scene" | "block" | "snippet" | "line" | "text" | "gameEvent";
@@ -357,6 +370,13 @@ interface RecordingStatusDecl {
357
370
  /** The default recording-status ladder (used when a project declares none). The FIRST rung is the
358
371
  * level-0 / absence status: a beat with no recorded status counts as `missing`. */
359
372
  declare const DEFAULT_RECORDING_STATUSES: RecordingStatusDecl[];
373
+ /** The reserved recording status a line takes when it is flagged **needs re-record** (#227): a recorded
374
+ * take exists but is unusable (bad quality, wrong take), so it must be redone. It is NOT a ladder rung -
375
+ * it is a regression flag that MASKS the derived / manual rung for the recording script, the production
376
+ * report, and status browse, so a line "recorded" on disk still shows up as work to do. Reserved so it
377
+ * can't collide with an author-declared rung; carries its own alert colour. */
378
+ declare const RERECORD_STATUS = "rerecord";
379
+ declare const RERECORD_STATUS_DECL: RecordingStatusDecl;
360
380
  /** One recording rung mapped to the folder its audio files live in (Audio Folders mode). */
361
381
  interface RecordingFolder {
362
382
  name: string;
@@ -475,6 +495,12 @@ interface ProjectFile {
475
495
  /** Autosave: periodically persist the edited scene without an explicit Save. Default ON (omitted ===
476
496
  * enabled); set `false` to require manual saves. */
477
497
  autosave?: boolean;
498
+ /** Auto Rebuild: recompile the `.patterc` bundle automatically after edits (debounced), so the on-disk
499
+ * build stays current without a manual Publish Bundle. Editor-only; never reaches the bundle. Default OFF
500
+ * (omitted === off) - opt-in, since it writes the bundle on every real change (poor fit if you commit the
501
+ * bundle to a lock-based VCS). The rebuild is deduped (skipped when the compiled bundle is unchanged) and
502
+ * a mid-edit invalid project silently keeps the last good build. */
503
+ autoRebuild?: boolean;
478
504
  /** Closed captions (#214): the delimiter pair that wraps non-spoken caption cues inside DIALOGUE
479
505
  * lines (e.g. `(sigh)` in `Oh dear. (sigh) What now?`). A game can turn captions off at runtime
480
506
  * (`setClosedCaptions(false)`), and the runtime then strips every `open…close` span - delimiters and
@@ -657,6 +683,14 @@ interface AuthoringFile {
657
683
  * it as a separate "cut: N" figure so a removal is visible, not vanished.
658
684
  */
659
685
  cut?: Record<string, boolean>;
686
+ /**
687
+ * **Needs re-record** (#227): dialogue-line ids whose recorded take is unusable and must be redone
688
+ * (bad quality, wrong take, misread). Orthogonal to the recording ladder - a flagged line keeps its
689
+ * audio on disk, but its recording status is MASKED to the reserved `rerecord` status for the recording
690
+ * script / report / status browse (see `RERECORD_STATUS`), so a "recorded" line still reads as work.
691
+ * Authoring-only; never compiled into a bundle.
692
+ */
693
+ rerecord?: Record<string, boolean>;
660
694
  }
661
695
  /** A compiled expression envelope: canonical source + pre-derived tagged-tuple AST. */
662
696
  interface Expression {
@@ -742,7 +776,8 @@ interface Bundle {
742
776
  default: string;
743
777
  included: string[];
744
778
  };
745
- cast?: CastMember[];
779
+ /** Player-facing cast only: the compiler strips notes / actor / gender (see `BundleCastMember`). */
780
+ cast?: BundleCastMember[];
746
781
  properties?: PropertyDecl[];
747
782
  /** Host / world scope declarations, baked from the project so the runtime can self-back a declared
748
783
  * scope (`@world`, ...) when no host resolver claims its token. Absent = no host scopes. */
@@ -784,4 +819,4 @@ declare const DEFAULT_CAPTION_DELIMITERS: CaptionDelimiters;
784
819
  * captions are off). Applies even to a project that pins no `closedCaptions`. */
785
820
  declare const DEFAULT_CAPTION_CHARACTER = "SFX";
786
821
 
787
- export { type AuthoringFile, type Beat, type Block, type Bundle, 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 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, 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 };
822
+ export { type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, 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 };
package/dist/index.js CHANGED
@@ -45,6 +45,8 @@ var DEFAULT_RECORDING_STATUSES = [
45
45
  { name: "final", colour: 9 }
46
46
  // purple
47
47
  ];
48
+ var RERECORD_STATUS = "rerecord";
49
+ var RERECORD_STATUS_DECL = { name: RERECORD_STATUS, colour: 1 };
48
50
  function deriveRecordingFolders(audioRoot, statuses) {
49
51
  const root = audioRoot?.trim();
50
52
  return statuses.map((s, i) => {
@@ -73,6 +75,8 @@ export {
73
75
  DEFAULT_RECORDING_STATUSES,
74
76
  DEFAULT_WRITING_STATUSES,
75
77
  PROJECT_LOCALE_SCENE,
78
+ RERECORD_STATUS,
79
+ RERECORD_STATUS_DECL,
76
80
  castStringKey,
77
81
  deriveRecordingFolders,
78
82
  effectiveGameId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patterkit/model",
3
- "version": "0.1.1",
3
+ "version": "0.2.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",