@patterkit/ops 0.10.4 → 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 +323 -14
  2. package/dist/index.js +1382 -90
  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';
@@ -375,6 +375,10 @@ interface CoverageBeat {
375
375
  reachedRuns: number;
376
376
  /** reachedRuns / runs-executed * 100; 0 iff never reached. */
377
377
  reachPct: number;
378
+ /** Reached, but in fewer than {@link RARE_REACH_PCT}% of runs: content that CAN play but hangs on an
379
+ * unlikely route or a condition that is nearly always false. Worth a look, not necessarily a fault
380
+ * (one of several random picks is rare by design). Absent on a never-reached beat. */
381
+ rare?: true;
378
382
  /** Set on a never-reached beat that is gated on a host-scope ref (`@world.x`) nothing writes and no
379
383
  * driver provides, i.e. it may just need an input, not be truly dead. Lists the offending refs. */
380
384
  needsInput?: string[];
@@ -414,12 +418,16 @@ interface CoverageReport {
414
418
  block?: string;
415
419
  };
416
420
  beats: CoverageBeat[];
421
+ /** `rare` counts beats reached in fewer than `rareThresholdPct`% of runs (and not never). */
417
422
  totals: {
418
423
  beats: number;
419
424
  covered: number;
420
425
  neverHit: number;
426
+ rare: number;
421
427
  coveragePct: number;
422
428
  };
429
+ /** The reach % below which a reached beat counts as rare ({@link RARE_REACH_PCT}). */
430
+ rareThresholdPct: number;
423
431
  /** How each run ended, for the summary header. */
424
432
  termination: {
425
433
  ended: number;
@@ -437,6 +445,15 @@ interface CoverageReport {
437
445
  dryChoices: DryChoice[];
438
446
  cancelled: boolean;
439
447
  }
448
+ /** Below this share of runs, a beat that WAS reached is flagged rare. Coverage used to flag only the never
449
+ * reached, so a beat that played in 0.5% of runs looked as healthy as one that played in all of them. */
450
+ declare const RARE_REACH_PCT = 5;
451
+ /**
452
+ * The beats least reached first: never-reached at the top, then by reach %, then by times played, with
453
+ * script order kept among equals. The order both Patterpad's Coverage window and `patter coverage` lead
454
+ * with, because the beats a sweep reaches least are the ones worth a look.
455
+ */
456
+ declare function leastReachedFirst(beats: readonly CoverageBeat[]): CoverageBeat[];
440
457
  /**
441
458
  * Auto-propose coverage drivers by scanning the project's conditions for host-scope refs (`@world.x`)
442
459
  * and the literals they are compared against. Each proposed driver is `recurring`/`sometimes` and offers
@@ -466,9 +483,14 @@ interface CoverageAsyncHooks extends CoverageHooks {
466
483
  * it for a full sample.
467
484
  */
468
485
  declare function runCoverageAsync(loaded: LoadedProject, options?: CoverageOptions, hooks?: CoverageAsyncHooks): Promise<CoverageReport>;
469
- /** Render a coverage report as the CLI's readable text: a summary, then a per-scene beat table with
470
- * never-reached (0%) rows marked. */
471
- declare function renderCoverageText(report: CoverageReport, sceneName?: (id: string) => string): string[];
486
+ /** Which order the beat table is in: least reached first (the default: the rows worth a look lead), or
487
+ * the script's own order, scene by scene. */
488
+ type CoverageOrder = "least" | "script";
489
+ /** Render a coverage report as the CLI's readable text: a summary, then the beat table with never-reached
490
+ * and rarely reached rows marked, least reached first unless `order` says script order. */
491
+ declare function renderCoverageText(report: CoverageReport, sceneName?: (id: string) => string, opts?: {
492
+ order?: CoverageOrder;
493
+ }): string[];
472
494
 
473
495
  /** Resolve where a flow starts: an explicit override, else the project's authored `start`, else `{}`
474
496
  * (the runtime's first-scene default). Shared by `runPlay` and `runCoverage`. */
@@ -712,33 +734,42 @@ interface TextRun {
712
734
  * reader's structure cue. `snippet` is an id shared by every element of one snippet WHEN that snippet sits
713
735
  * inside a selector (branch / sequence / choice); the renderers draw a light left edge spanning each such
714
736
  * snippet, so rows that would otherwise blur (a sequence's steps) read as distinct beats. Absent = a
715
- * 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. */
716
741
  type ScriptElement = {
717
742
  kind: "scene";
743
+ id: string;
718
744
  text: string;
719
745
  } | {
720
746
  kind: "block";
747
+ id: string;
721
748
  text: string;
722
749
  }
723
750
  /** A spoken line: SPEAKER cue (coloured, uppercase), an optional (direction), and the body runs. */
724
751
  | {
725
752
  kind: "line";
753
+ id: string;
726
754
  indent: number;
727
755
  snippet?: number;
728
756
  character: string;
729
757
  direction?: string;
730
758
  runs: TextRun[];
731
759
  }
732
- /** 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. */
733
761
  | {
734
762
  kind: "narration";
763
+ id: string;
735
764
  indent: number;
736
765
  snippet?: number;
737
766
  runs: TextRun[];
738
767
  }
739
- /** 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. */
740
770
  | {
741
771
  kind: "condition";
772
+ id: string;
742
773
  indent: number;
743
774
  snippet?: number;
744
775
  text: string;
@@ -746,43 +777,73 @@ type ScriptElement = {
746
777
  /** A selector group's label ("Choose", "One of · first match wins", "In sequence"). */
747
778
  | {
748
779
  kind: "group";
780
+ id: string;
749
781
  indent: number;
750
782
  label: string;
751
783
  }
752
- /** 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. */
753
785
  | {
754
786
  kind: "else";
787
+ id: string;
755
788
  indent: number;
756
789
  }
757
- /** 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. */
758
792
  | {
759
793
  kind: "option";
794
+ id: string;
795
+ node: string;
760
796
  indent: number;
761
797
  snippet?: number;
762
798
  runs: TextRun[];
763
799
  tag?: string;
764
800
  }
765
- /** 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). */
766
803
  | {
767
804
  kind: "jump";
805
+ id: string;
806
+ to: string;
768
807
  indent: number;
769
808
  snippet?: number;
770
809
  text: string;
771
810
  }
772
- /** 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. */
773
812
  | {
774
813
  kind: "gameEvent";
814
+ id: string;
775
815
  indent: number;
776
816
  snippet?: number;
777
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;
824
+ indent: number;
825
+ snippet?: number;
826
+ text: string;
827
+ class?: string;
778
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
+ }
779
840
  interface ScriptDoc {
780
841
  /** Project display name - the document title. */
781
842
  project: string;
782
843
  elements: ScriptElement[];
783
844
  }
784
845
  /** Compute the readable script document. Pure: data out, no I/O. */
785
- declare function runScriptDoc(loaded: LoadedProject): ScriptDoc;
846
+ declare function runScriptDoc(loaded: LoadedProject, opts?: ScriptDocOptions): ScriptDoc;
786
847
 
787
848
  /** Render the readable screenplay as a Word document. */
788
849
  declare function scriptToDocx(doc: ScriptDoc): Promise<Buffer>;
@@ -962,6 +1023,9 @@ interface DocumentManifest {
962
1023
  /** The game scopes files the pack carries as `game-scopes/<name>` entries, by name, sorted. Absent
963
1024
  * when the project has no game scopes folder (or it holds none). */
964
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[];
965
1029
  }
966
1030
  /** Pack a project's source shards into a `.patterpack` document (zip bytes). */
967
1031
  declare function runPack(startPath: string): Promise<Buffer>;
@@ -1034,7 +1098,7 @@ declare class UnsafeEntryError extends Error {
1034
1098
  /** What unpacking a document plans: its shards, and its game scopes snapshot (empty for a pack with none,
1035
1099
  * which is every pack from before packs carried one). */
1036
1100
  interface UnpackResult {
1037
- /** The shards, under `targetDir`. */
1101
+ /** The shards, under `targetDir`, with any open handoff records the pack carries (`handoffs/`). */
1038
1102
  shards: PlannedWrite[];
1039
1103
  /** The game's scopes files, in `<targetDir>/game-scopes/`, where the new project finds them first. */
1040
1104
  scopes: PlannedWrite[];
@@ -1093,6 +1157,9 @@ interface UnpackMergeResult {
1093
1157
  path: string;
1094
1158
  error?: string;
1095
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[];
1096
1163
  }
1097
1164
  /**
1098
1165
  * Merge a RETURNED `.patterpack` document (`theirs`) back into the project at
@@ -1114,4 +1181,246 @@ declare function classesForChannel(classes: DocumentationClass[], channel: strin
1114
1181
  */
1115
1182
  declare function resolveDocumentation(loaded: LoadedProject, channel: string): Map<string, DocLine[]>;
1116
1183
 
1117
- export { AUTHORING_HANDLED, type ApplyStats, type BundlePosture, CONFLICT_SIDECAR, type CharacterReport, type Conflict, type ConflictKind, type CoverageAsyncHooks, type CoverageBeat, type CoverageHooks, type CoverageOptions, 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, 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, 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 };