@patterkit/ops 0.11.0 → 0.12.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.
Files changed (3) hide show
  1. package/dist/index.d.ts +298 -11
  2. package/dist/index.js +1333 -74
  3. package/package.json +5 -4
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ProjectFile, Bundle, HostScopeRegistry, Scene, LocaleFile, AuthoringFile, GameData, CoverageDriver, GrammaticalGender, DocumentationClass, DocLine } from '@patterkit/model';
1
+ import { ProjectFile, Bundle, HostScopeRegistry, Scene, LocaleFile, AuthoringFile, GameData, CoverageDriver, GrammaticalGender, DocumentationClass, DocLine, HandoffFile, Suggestion, LineBeat, Comment } from '@patterkit/model';
2
2
  import { NamedScopesFile, MergedScopes, ScopesIssue, ScopesCatalogueEntry, ScopesFile } from '@wildwinter/scoperegistry/scopes';
3
3
  export { GAME_SCOPES_DIR, GAME_SCOPES_FILE, serialiseScopesFile } from '@wildwinter/scoperegistry/scopes';
4
4
  import { ScopeDeclaration, ScopeRegistry } from '@wildwinter/scoperegistry';
@@ -734,33 +734,42 @@ interface TextRun {
734
734
  * reader's structure cue. `snippet` is an id shared by every element of one snippet WHEN that snippet sits
735
735
  * inside a selector (branch / sequence / choice); the renderers draw a light left edge spanning each such
736
736
  * snippet, so rows that would otherwise blur (a sequence's steps) read as distinct beats. Absent = a
737
- * top-level snippet (delimited by space alone). Headings carry no indent (they reset it). */
737
+ * top-level snippet (delimited by space alone). Headings carry no indent (they reset it).
738
+ *
739
+ * `id` is the scene, block, node, or beat the element shows, so an export that hands the script to someone
740
+ * outside (the editable script) can tie each row back to the project. The readable script ignores it. */
738
741
  type ScriptElement = {
739
742
  kind: "scene";
743
+ id: string;
740
744
  text: string;
741
745
  } | {
742
746
  kind: "block";
747
+ id: string;
743
748
  text: string;
744
749
  }
745
750
  /** A spoken line: SPEAKER cue (coloured, uppercase), an optional (direction), and the body runs. */
746
751
  | {
747
752
  kind: "line";
753
+ id: string;
748
754
  indent: number;
749
755
  snippet?: number;
750
756
  character: string;
751
757
  direction?: string;
752
758
  runs: TextRun[];
753
759
  }
754
- /** Prose narration / on-screen text (speaker-less), upright in a soft ink, flush left. */
760
+ /** Prose narration / on-screen text (speaker-less), upright in a soft ink, flush left. `id` is the beat. */
755
761
  | {
756
762
  kind: "narration";
763
+ id: string;
757
764
  indent: number;
758
765
  snippet?: number;
759
766
  runs: TextRun[];
760
767
  }
761
- /** A gating condition, set in accent mono above the beat it controls: `‹ if @brave ›`. */
768
+ /** A gating condition, set in accent mono above the beat it controls: `‹ if @brave ›`. `id` is the node
769
+ * it gates. */
762
770
  | {
763
771
  kind: "condition";
772
+ id: string;
764
773
  indent: number;
765
774
  snippet?: number;
766
775
  text: string;
@@ -768,43 +777,73 @@ type ScriptElement = {
768
777
  /** A selector group's label ("Choose", "One of · first match wins", "In sequence"). */
769
778
  | {
770
779
  kind: "group";
780
+ id: string;
771
781
  indent: number;
772
782
  label: string;
773
783
  }
774
- /** A branch's catch-all row header ("else · catch-all"). */
784
+ /** A branch's catch-all row header ("else · catch-all"). `id` is the catch-all row's node. */
775
785
  | {
776
786
  kind: "else";
787
+ id: string;
777
788
  indent: number;
778
789
  }
779
- /** A choice option: a ◇-led prompt, plus a quiet small-caps flag tag (once only / repeatable). */
790
+ /** A choice option: a ◇-led prompt, plus a quiet small-caps flag tag (once only / repeatable). `id` is the
791
+ * prompt beat, `node` the option itself. */
780
792
  | {
781
793
  kind: "option";
794
+ id: string;
795
+ node: string;
782
796
  indent: number;
783
797
  snippet?: number;
784
798
  runs: TextRun[];
785
799
  tag?: string;
786
800
  }
787
- /** A jump, set apart right-aligned in accent: `↪ The Crossroads` (readable target, never the id). */
801
+ /** A jump, set apart right-aligned in accent: `↪ The Crossroads` (readable target, never the id). `id` is
802
+ * the snippet carrying it, `to` the target's id (or END). */
788
803
  | {
789
804
  kind: "jump";
805
+ id: string;
806
+ to: string;
790
807
  indent: number;
791
808
  snippet?: number;
792
809
  text: string;
793
810
  }
794
- /** A game event, set apart right-aligned in accent mono: `⚙ game event · door.open`. */
811
+ /** A game event, set apart right-aligned in accent mono: `⚙ game event · door.open`. `id` is the beat. */
795
812
  | {
796
813
  kind: "gameEvent";
814
+ id: string;
815
+ indent: number;
816
+ snippet?: number;
817
+ text: string;
818
+ }
819
+ /** A documentation note on the element above, when the caller asked for notes (`ScriptDocOptions.notes`).
820
+ * `id` is the node or beat the note is on. The readable script asks for none. */
821
+ | {
822
+ kind: "note";
823
+ id: string;
797
824
  indent: number;
798
825
  snippet?: number;
799
826
  text: string;
827
+ class?: string;
800
828
  };
829
+ /** What `runScriptDoc` includes beyond the readable script's defaults. */
830
+ interface ScriptDocOptions {
831
+ /** Only these scenes (by id), in project order. All scenes when absent. */
832
+ scenes?: string[];
833
+ /** Documentation notes to show under the node they're on: those delivered to a channel (`{ channel:
834
+ * "editor" }`), or every classed note (`"all"`). Untyped notes are editor-only and never shown. Absent:
835
+ * no notes, as the readable script has none. */
836
+ notes?: {
837
+ channel: string;
838
+ } | "all";
839
+ }
801
840
  interface ScriptDoc {
802
841
  /** Project display name - the document title. */
803
842
  project: string;
804
843
  elements: ScriptElement[];
805
844
  }
806
845
  /** Compute the readable script document. Pure: data out, no I/O. */
807
- declare function runScriptDoc(loaded: LoadedProject): ScriptDoc;
846
+ declare function runScriptDoc(loaded: LoadedProject, opts?: ScriptDocOptions): ScriptDoc;
808
847
 
809
848
  /** Render the readable screenplay as a Word document. */
810
849
  declare function scriptToDocx(doc: ScriptDoc): Promise<Buffer>;
@@ -984,6 +1023,9 @@ interface DocumentManifest {
984
1023
  /** The game scopes files the pack carries as `game-scopes/<name>` entries, by name, sorted. Absent
985
1024
  * when the project has no game scopes folder (or it holds none). */
986
1025
  gameScopes?: string[];
1026
+ /** The open handoff records the pack carries as `handoffs/<id>.json` entries, by entry name, sorted.
1027
+ * Absent when there are none. */
1028
+ handoffs?: string[];
987
1029
  }
988
1030
  /** Pack a project's source shards into a `.patterpack` document (zip bytes). */
989
1031
  declare function runPack(startPath: string): Promise<Buffer>;
@@ -1056,7 +1098,7 @@ declare class UnsafeEntryError extends Error {
1056
1098
  /** What unpacking a document plans: its shards, and its game scopes snapshot (empty for a pack with none,
1057
1099
  * which is every pack from before packs carried one). */
1058
1100
  interface UnpackResult {
1059
- /** The shards, under `targetDir`. */
1101
+ /** The shards, under `targetDir`, with any open handoff records the pack carries (`handoffs/`). */
1060
1102
  shards: PlannedWrite[];
1061
1103
  /** The game's scopes files, in `<targetDir>/game-scopes/`, where the new project finds them first. */
1062
1104
  scopes: PlannedWrite[];
@@ -1115,6 +1157,9 @@ interface UnpackMergeResult {
1115
1157
  path: string;
1116
1158
  error?: string;
1117
1159
  };
1160
+ /** Handoff records the pack brought (relative paths): added, or with reimports from their side added to
1161
+ * ours. Their writes are in `writes`. Absent when the pack carried none that changed anything. */
1162
+ handoffs?: string[];
1118
1163
  }
1119
1164
  /**
1120
1165
  * Merge a RETURNED `.patterpack` document (`theirs`) back into the project at
@@ -1136,4 +1181,246 @@ declare function classesForChannel(classes: DocumentationClass[], channel: strin
1136
1181
  */
1137
1182
  declare function resolveDocumentation(loaded: LoadedProject, channel: string): Map<string, DocLine[]>;
1138
1183
 
1139
- export { AUTHORING_HANDLED, type ApplyStats, type BundlePosture, CONFLICT_SIDECAR, type CharacterReport, type Conflict, type ConflictKind, type CoverageAsyncHooks, type CoverageBeat, type CoverageHooks, type CoverageOptions, type CoverageOrder, type CoverageReport, type DocumentManifest, type FormatResult, GAME_SCOPES_OWNER, type GameScopes, type GameScopesIssue, type HygieneIssue, type InitOptions, type InitResult, type InitVcs, type LoadedProject, type LocCatalog, type LocEntry, type LocaleReport, type MergeFileType, type MergeResult, type MergedShard, PATTER_SCOPES_FILE, PATTER_SCOPES_OWNER, type PinPlan, type PinnedName, type PlannedWrite, type PlayEvent, type PlayOptions, type PlayOutcome, type PlayResult, type ProvenanceCheck, RARE_REACH_PCT, type ReplaceHit, type ReplaceOptions, type ReplacePlan, type ReportData, type ReportTotals, type ResolveEntry, SHARD_EXTENSIONS, type SceneReport, type ScriptDoc, type ScriptElement, type SearchFocus, type UnpackMergeResult, type UnpackResult, UnsafeEntryError, UnsupportedMergeError, type ValidateResult, type VoiceLine, type VoiceScript, type VoicedCounts, type WebExport, type WrittenCounts, applyLoc, applySceneOrder, applyWrites, bundleOutputPath, catalogToJson, catalogToPo, catalogToXlsx, classesForChannel, defaultGameScopesDir, detectMergeType, discoverGameScopes, drivableScopes, extractLoc, findProjectFile, gameScopeTokens, gameScopesCatalogue, gameScopesSnapshot, hostScopeTokens, jsonToCatalog, leastReachedFirst, listProjectTags, loadProject, loadProjectLanding, patterScopesFile, patterScopesStale, patterScopesWrite, planPins, planReturnedWorld, planShareScopes, planWorldSave, poToCatalog, previewRegistry, proposeCoverageDrivers, reachabilityIssues, readGameScopes, renderCoverageText, renderPlay, renderReportText, resolveDocumentation, resolveStart, runCoverage, runCoverageAsync, runExport, runExportFull, runExportHtml, runExportWeb, runFormat, runInit, runMerge, runPack, runPlay, runPropertyUsage, runReplace, runReport, runReportXlsx, runResolve, runScriptDoc, runSearch, runStatusBrowse, runTagBrowse, runUnpack, runUnpackMerge, runValidate, runVoiceScript, scanAudioStatus, sceneIdForShard, scriptToDocx, scriptToPdf, sidecarIssues, vcsConfigWrites, voiceScriptToXlsx, worldSettingsScopes, xlsxToCatalog };
1184
+ /** The project folder handoff records live in. */
1185
+ declare const HANDOFF_DIR = "handoffs";
1186
+ /** Where a handoff's record lives in the project at `root`. */
1187
+ declare function handoffPath(root: string, id: string): string;
1188
+ /** A record as it is written: stable key order is the caller's (the record is built in one place), two-space
1189
+ * JSON with a trailing newline, like the other JSON a project keeps. */
1190
+ declare function serialiseHandoff(handoff: HandoffFile): string;
1191
+ /** The planned write for a record. */
1192
+ declare function handoffWrite(root: string, handoff: HandoffFile): PlannedWrite;
1193
+ /** Parse a record, or say why it isn't one. */
1194
+ declare function parseHandoff(text: string): HandoffFile;
1195
+ /** A record that couldn't be read, naming its file. */
1196
+ interface HandoffIssue {
1197
+ file: string;
1198
+ message: string;
1199
+ }
1200
+ /** Every handoff record in the project at `root`, sorted by creation time, plus any that wouldn't parse.
1201
+ * No folder means no handoffs: every project before this feature. */
1202
+ declare function readHandoffs(root: string): {
1203
+ handoffs: HandoffFile[];
1204
+ issues: HandoffIssue[];
1205
+ };
1206
+ /** One handoff record by id, or undefined when the project has none by that id. Throws if it exists but
1207
+ * won't parse: a damaged record is a problem to report, not a missing one. */
1208
+ declare function readHandoff(root: string, id: string): HandoffFile | undefined;
1209
+ /** A source of randomness in [0, 1): `Math.random` by default, seeded in tests. */
1210
+ type Random = () => number;
1211
+ /** How many body characters codes for `count` lines need: enough that the codes in use fill at most one
1212
+ * in a thousand of the space, so a mistyped code almost never lands on another line's. At least 3. */
1213
+ declare function markerLength(count: number): number;
1214
+ /** Issue `count` distinct marker codes (body plus check character), in a random order. */
1215
+ declare function issueMarkerCodes(count: number, random?: Random): string[];
1216
+ /** A marker as it is printed beside a box. */
1217
+ declare function formatMarker(code: string): string;
1218
+ /** A handoff id ("H-7Q2K") that `taken` doesn't already use. */
1219
+ declare function newHandoffId(taken?: Iterable<string>, random?: Random): string;
1220
+ /** A marker read back from a returned document. */
1221
+ interface ReadMarker {
1222
+ /** The normalised code (upper case, Crockford substitutions applied). */
1223
+ code: string;
1224
+ /** Whether its check character is right. A wrong one means the marker was damaged. */
1225
+ valid: boolean;
1226
+ }
1227
+ /** Read a marker from a margin cell's text, leniently: `[#K7Q2M]`, `[ # k7q2m ]`, `[K7Q2M]` all read the
1228
+ * same, and the Crockford look-alikes (O for 0, I or L for 1) are taken as the digits they resemble.
1229
+ * Undefined when the text holds no marker at all. */
1230
+ declare function readMarker(text: string): ReadMarker | undefined;
1231
+
1232
+ /** Which parts of a suggestion no longer match the project (empty: it still applies cleanly). */
1233
+ declare function staleParts(s: Suggestion, liveText: string, line: LineBeat | undefined): string[];
1234
+ /** An open suggestion, where it is, and whether it still applies. */
1235
+ interface OpenSuggestion {
1236
+ suggestion: Suggestion;
1237
+ sceneId?: string;
1238
+ /** Parts that changed since it was made (empty: clean). */
1239
+ stale: string[];
1240
+ }
1241
+ /** Every open (unresolved) suggestion in the project, optionally only those from one handoff, in scene
1242
+ * order then by time. One whose line is gone is listed as stale. */
1243
+ declare function listOpenSuggestions(loaded: LoadedProject, filter?: {
1244
+ handoff?: string;
1245
+ }): OpenSuggestion[];
1246
+ /** Accept or reject one suggestion. */
1247
+ interface SuggestionDecision {
1248
+ id: string;
1249
+ accept: boolean;
1250
+ }
1251
+ /** What became of one decision. */
1252
+ interface DecisionResult {
1253
+ id: string;
1254
+ outcome: "accepted" | "rejected" | "stale" | "missing" | "resolved-already";
1255
+ /** Why a stale or missing one wasn't applied, in words for the person who asked. */
1256
+ reason?: string;
1257
+ }
1258
+ interface DecisionPlan {
1259
+ /** Loc, flow, and authoring shard writes, one per touched file, for the caller to commit. */
1260
+ writes: PlannedWrite[];
1261
+ results: DecisionResult[];
1262
+ }
1263
+ /**
1264
+ * Accept or reject suggestions, planning the writes. Decisions apply in order, so two suggestions on one
1265
+ * line both accepted leaves the second stale (the first changed the text it was made against).
1266
+ */
1267
+ declare function applySuggestionDecisions(loaded: LoadedProject, decisions: SuggestionDecision[], opts?: {
1268
+ now?: string;
1269
+ by?: string;
1270
+ }): DecisionPlan;
1271
+ /** Mark nodes or beats cut (or bring them back), planning the authoring writes, one per scene touched.
1272
+ * Ids that aren't in the project are skipped and returned. */
1273
+ declare function setCut(loaded: LoadedProject, ids: string[], cut: boolean): {
1274
+ writes: PlannedWrite[];
1275
+ unknown: string[];
1276
+ };
1277
+
1278
+ interface EditableScriptOptions {
1279
+ /** Scene ids to export, in project order. The whole project when absent. */
1280
+ scenes?: string[];
1281
+ /** Who it's going to, shown on the front page and kept in the record. */
1282
+ recipient?: string;
1283
+ /** Notes shown under the node they're on: the `editor` channel's (default) or every classed note. */
1284
+ notes?: "editor" | "all";
1285
+ /** Show each line's writing status in the margin. */
1286
+ status?: boolean;
1287
+ /** A cast page before the script. */
1288
+ cast?: boolean;
1289
+ /** Who is exporting (the record's `createdBy`). */
1290
+ by: string;
1291
+ /** The export time (ISO); now by default. */
1292
+ now?: string;
1293
+ /** Randomness for markers and the handoff id; seeded in tests. */
1294
+ random?: Random;
1295
+ }
1296
+ interface EditableScript {
1297
+ docx: Buffer;
1298
+ handoff: HandoffFile;
1299
+ /** The handoff record, for the caller to commit through VC with nothing else. */
1300
+ writes: PlannedWrite[];
1301
+ }
1302
+ /** Export the editable script and plan its handoff record. */
1303
+ declare function exportEditableScript(loaded: LoadedProject, opts: EditableScriptOptions): Promise<EditableScript>;
1304
+
1305
+ /** One tracked change, as found. */
1306
+ interface TrackedChange {
1307
+ kind: "insert" | "delete" | "moveFrom" | "moveTo";
1308
+ author: string;
1309
+ date?: string;
1310
+ text: string;
1311
+ }
1312
+ /** Text in both views, with what changed and which comments start inside it. */
1313
+ interface ReadText {
1314
+ /** Every tracked change accepted, with Patter markup for bold / italic. */
1315
+ proposed: string;
1316
+ /** Every tracked change rejected, with the same markup. */
1317
+ original: string;
1318
+ changes: TrackedChange[];
1319
+ /** Ids of comments whose range starts here (or that point here). */
1320
+ comments: string[];
1321
+ /** Formatting other than bold and italic that was dropped (colour, highlight, size, ...), counted. */
1322
+ droppedFormatting: number;
1323
+ }
1324
+ /** One editable box, read back. */
1325
+ interface ReadBox {
1326
+ kind: "box";
1327
+ /** The marker read from the margin cell; `recovered` when it was only found inside a tracked deletion. */
1328
+ marker?: ReadMarker & {
1329
+ recovered?: boolean;
1330
+ };
1331
+ /** The words: the text cell, its paragraphs joined by a single space. */
1332
+ text: ReadText;
1333
+ /** How many paragraphs the text cell held (more than one: an Enter inside the box). */
1334
+ paragraphs: number;
1335
+ /** The lead cell (cue, direction, or ◇) and the margin cell (tag, status, marker), as plain text. */
1336
+ lead: ReadText;
1337
+ margin: ReadText;
1338
+ /** The whole row was deleted with tracking on. */
1339
+ rowDeleted: boolean;
1340
+ /** The table's left indent in twips (Google writes it as "360.0"), when given. */
1341
+ indent?: number;
1342
+ }
1343
+ /** An ordinary paragraph, or a table that isn't a box (its text flattened). */
1344
+ interface ReadParagraph {
1345
+ kind: "paragraph" | "table";
1346
+ text: ReadText;
1347
+ /** The paragraph style (Heading1, ...), when one is set. */
1348
+ style?: string;
1349
+ }
1350
+ type ReadItem = ReadBox | ReadParagraph;
1351
+ interface ReadComment {
1352
+ id: string;
1353
+ author: string;
1354
+ date?: string;
1355
+ text: string;
1356
+ replies: Array<{
1357
+ author: string;
1358
+ date?: string;
1359
+ text: string;
1360
+ }>;
1361
+ }
1362
+ interface ReturnedDoc {
1363
+ /** The handoff id from the page header (or, failing that, the front page). */
1364
+ handoffId?: string;
1365
+ /** Body content in document order. */
1366
+ items: ReadItem[];
1367
+ /** Top-level comments; replies hang off their parent. */
1368
+ comments: ReadComment[];
1369
+ }
1370
+ /** Read a returned editable script. Throws only when the bytes aren't a .docx at all. */
1371
+ declare function readEditableDocx(bytes: Buffer | Uint8Array): Promise<ReturnedDoc>;
1372
+
1373
+ interface ImportOptions {
1374
+ /** Who is importing (the import log). */
1375
+ by: string;
1376
+ /** The name changes without a recorded author are credited to (the dialog's "Edits by"): the
1377
+ * handoff's recipient when absent. */
1378
+ as?: string;
1379
+ /** Count curly versus straight quotes and `...` versus `…` as edits (off: they're a tool's habit). */
1380
+ strictQuotes?: boolean;
1381
+ /** Accept the clean suggestions (not stale, no problems) on the way in, instead of leaving them open. */
1382
+ direct?: boolean;
1383
+ /** SHA-256 of the returned file, for the import log. */
1384
+ fileHash: string;
1385
+ now?: string;
1386
+ random?: Random;
1387
+ }
1388
+ /** Something about the returned file the person importing should know. */
1389
+ interface ImportProblem {
1390
+ severity: "warning" | "info";
1391
+ kind: "damaged-marker" | "repaired-marker" | "duplicate-marker" | "missing-box" | "moved" | "placeholders" | "line-gone" | "unknown-speaker" | "added-text" | "context-edited" | "untracked-edits" | "joined-paragraphs" | "dropped-formatting" | "stale";
1392
+ message: string;
1393
+ /** The project line or node it concerns, for "Go to". */
1394
+ anchor?: string;
1395
+ marker?: string;
1396
+ }
1397
+ interface ImportReport {
1398
+ handoffId?: string;
1399
+ /** Set when nothing was imported, saying why. */
1400
+ refused?: string;
1401
+ counts: {
1402
+ changed: number;
1403
+ unchanged: number;
1404
+ stale: number;
1405
+ comments: number;
1406
+ problems: number;
1407
+ };
1408
+ problems: ImportProblem[];
1409
+ }
1410
+ interface ImportPlan {
1411
+ report: ImportReport;
1412
+ /** The suggestions and comments this import adds (also inside `writes`). */
1413
+ suggestions: Suggestion[];
1414
+ comments: Comment[];
1415
+ /** Authoring shards (and, with `direct`, the loc and flow shards the accepts touch) plus the handoff
1416
+ * record with this import logged. Empty when refused. */
1417
+ writes: PlannedWrite[];
1418
+ /** The handoff this file belongs to, when found. */
1419
+ handoff?: HandoffFile;
1420
+ }
1421
+ /** The share of a handoff's lines that may come back missing or damaged before the file is refused. */
1422
+ declare const REFUSE_MISSING_SHARE = 0.25;
1423
+ /** Plan an import. Reads the handoff record named in the document from the project. */
1424
+ declare function planEditableImport(loaded: LoadedProject, returned: ReturnedDoc, opts: ImportOptions): ImportPlan;
1425
+
1426
+ export { AUTHORING_HANDLED, type ApplyStats, type BundlePosture, CONFLICT_SIDECAR, type CharacterReport, type Conflict, type ConflictKind, type CoverageAsyncHooks, type CoverageBeat, type CoverageHooks, type CoverageOptions, type CoverageOrder, type CoverageReport, type DecisionPlan, type DecisionResult, type DocumentManifest, type EditableScript, type EditableScriptOptions, type FormatResult, GAME_SCOPES_OWNER, type GameScopes, type GameScopesIssue, HANDOFF_DIR, type HandoffIssue, type HygieneIssue, type ImportOptions, type ImportPlan, type ImportProblem, type ImportReport, type InitOptions, type InitResult, type InitVcs, type LoadedProject, type LocCatalog, type LocEntry, type LocaleReport, type MergeFileType, type MergeResult, type MergedShard, type OpenSuggestion, PATTER_SCOPES_FILE, PATTER_SCOPES_OWNER, type PinPlan, type PinnedName, type PlannedWrite, type PlayEvent, type PlayOptions, type PlayOutcome, type PlayResult, type ProvenanceCheck, RARE_REACH_PCT, REFUSE_MISSING_SHARE, type Random, type ReadBox, type ReadComment, type ReadItem, type ReadMarker, type ReadParagraph, type ReadText, type ReplaceHit, type ReplaceOptions, type ReplacePlan, type ReportData, type ReportTotals, type ResolveEntry, type ReturnedDoc, SHARD_EXTENSIONS, type SceneReport, type ScriptDoc, type ScriptElement, type SearchFocus, type SuggestionDecision, type TrackedChange, type UnpackMergeResult, type UnpackResult, UnsafeEntryError, UnsupportedMergeError, type ValidateResult, type VoiceLine, type VoiceScript, type VoicedCounts, type WebExport, type WrittenCounts, applyLoc, applySceneOrder, applySuggestionDecisions, applyWrites, bundleOutputPath, catalogToJson, catalogToPo, catalogToXlsx, classesForChannel, defaultGameScopesDir, detectMergeType, discoverGameScopes, drivableScopes, exportEditableScript, extractLoc, findProjectFile, formatMarker, gameScopeTokens, gameScopesCatalogue, gameScopesSnapshot, handoffPath, handoffWrite, hostScopeTokens, issueMarkerCodes, jsonToCatalog, leastReachedFirst, listOpenSuggestions, listProjectTags, loadProject, loadProjectLanding, markerLength, newHandoffId, parseHandoff, patterScopesFile, patterScopesStale, patterScopesWrite, planEditableImport, planPins, planReturnedWorld, planShareScopes, planWorldSave, poToCatalog, previewRegistry, proposeCoverageDrivers, reachabilityIssues, readEditableDocx, readGameScopes, readHandoff, readHandoffs, readMarker, renderCoverageText, renderPlay, renderReportText, resolveDocumentation, resolveStart, runCoverage, runCoverageAsync, runExport, runExportFull, runExportHtml, runExportWeb, runFormat, runInit, runMerge, runPack, runPlay, runPropertyUsage, runReplace, runReport, runReportXlsx, runResolve, runScriptDoc, runSearch, runStatusBrowse, runTagBrowse, runUnpack, runUnpackMerge, runValidate, runVoiceScript, scanAudioStatus, sceneIdForShard, scriptToDocx, scriptToPdf, serialiseHandoff, setCut, sidecarIssues, staleParts, vcsConfigWrites, voiceScriptToXlsx, worldSettingsScopes, xlsxToCatalog };