@patterkit/ops 0.1.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.d.ts +833 -0
- package/dist/index.js +3317 -0
- package/dist/script-fonts-AQNQOADI.js +20 -0
- package/package.json +42 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,833 @@
|
|
|
1
|
+
import { ProjectFile, Scene, LocaleFile, AuthoringFile, Bundle, GameData, CoverageDriver, DocumentationClass, DocLine } from '@patterkit/model';
|
|
2
|
+
import { ValidationIssue } from '@patterkit/core';
|
|
3
|
+
import { ConditionIssue } from '@patterkit/compiler';
|
|
4
|
+
import { ChoiceOption } from '@patterkit/runtime';
|
|
5
|
+
|
|
6
|
+
interface LoadedProject {
|
|
7
|
+
root: string;
|
|
8
|
+
projectFile: string;
|
|
9
|
+
project: ProjectFile;
|
|
10
|
+
scenes: Scene[];
|
|
11
|
+
locales: LocaleFile[];
|
|
12
|
+
/** Source file for each scene (scene id -> absolute path) - "where it lives". */
|
|
13
|
+
sceneFiles: Record<string, string>;
|
|
14
|
+
/** Source file of each entry in `locales`, index-aligned. */
|
|
15
|
+
localeFiles: string[];
|
|
16
|
+
/** Authoring metadata shards (comments / statuses / estimates - spec section 5 schema). */
|
|
17
|
+
authoring: AuthoringFile[];
|
|
18
|
+
/** Source file of each entry in `authoring`, index-aligned. */
|
|
19
|
+
authoringFiles: string[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Find the nearest `*.patterproj` at or above `startPath` - one readdir per
|
|
23
|
+
* level (never a recursive scan of ancestors). Throws if none is found, or if
|
|
24
|
+
* a directory holds more than one (ambiguous - the alphabetically-first would
|
|
25
|
+
* silently win).
|
|
26
|
+
*/
|
|
27
|
+
declare function findProjectFile(startPath: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* The scene id a shard path belongs to, for a file-association launch (Finder / argv onto a scene's flow
|
|
30
|
+
* / loc / authoring file): a flow file declares its scene, a loc file names its scene, an authoring shard
|
|
31
|
+
* mirrors the flow stem. Returns undefined for the project root / manifest / any non-scene path (so the
|
|
32
|
+
* caller lands on the remembered scene instead). Cheap - parses at most the one shard (and, for an
|
|
33
|
+
* authoring shard, its sibling flow file).
|
|
34
|
+
*/
|
|
35
|
+
declare function sceneIdForShard(shardPath: string): string | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Phase-1 "landing" load (Patterpad's lazy open): parse the manifest and ONLY the landing scene's shards
|
|
38
|
+
* (its flow file + its source-language loc), leaving the rest of the project unparsed. The result is a
|
|
39
|
+
* partial `LoadedProject` whose `scenes` / `locales` hold just the landing scene, so the editor can paint
|
|
40
|
+
* it immediately; `loadProject` (the full eager parse) hydrates the rest in phase 2.
|
|
41
|
+
*
|
|
42
|
+
* The landing scene is the one named by `launchPath` (a file-association open onto a scene shard), else
|
|
43
|
+
* `preferId` (the remembered scene), else the first scene file. `authoring` is left empty - it is read
|
|
44
|
+
* lazily per scene from disk (project.ts), never from this array.
|
|
45
|
+
*/
|
|
46
|
+
declare function loadProjectLanding(startPath: string, opts?: {
|
|
47
|
+
launchPath?: string;
|
|
48
|
+
preferId?: string;
|
|
49
|
+
}): LoadedProject;
|
|
50
|
+
/** Sort scenes into the project's authored nav order (`ProjectFile.sceneOrder`), in place.
|
|
51
|
+
* Listed scenes come first in list order; unlisted scenes follow in their existing (file) order;
|
|
52
|
+
* listed ids that no longer exist are simply ignored. Presentation only - play order is untouched. */
|
|
53
|
+
declare function applySceneOrder(scenes: Scene[], order: string[] | undefined): void;
|
|
54
|
+
declare function loadProject(startPath: string): LoadedProject;
|
|
55
|
+
|
|
56
|
+
/** One file write an op wants performed. `content` is full canonical file text. */
|
|
57
|
+
interface PlannedWrite {
|
|
58
|
+
path: string;
|
|
59
|
+
content: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Commit planned writes to disk (UTF-8), creating parent directories. The PLAIN
|
|
63
|
+
* filesystem applier - for tests and no-VCS embedders only; product code (the
|
|
64
|
+
* CLI, Patterpad) routes through @patterkit/vcs so writes land correctly in a
|
|
65
|
+
* Perforce / locked workspace (spec §12).
|
|
66
|
+
*/
|
|
67
|
+
declare function applyWrites(writes: PlannedWrite[]): void;
|
|
68
|
+
|
|
69
|
+
/** A raw-bytes hygiene problem in one source file (repairable by `format`). */
|
|
70
|
+
interface HygieneIssue {
|
|
71
|
+
file: string;
|
|
72
|
+
message: string;
|
|
73
|
+
}
|
|
74
|
+
interface ValidateResult {
|
|
75
|
+
structural: ValidationIssue[];
|
|
76
|
+
conditions: ConditionIssue[];
|
|
77
|
+
/** Inline `{@ref}` interpolation issues (voiced-line slots, unknown/malformed refs). */
|
|
78
|
+
interpolation: ConditionIssue[];
|
|
79
|
+
/** Encoding/EOL hygiene (BOM, CRLF) - spec §10. */
|
|
80
|
+
hygiene: HygieneIssue[];
|
|
81
|
+
/** Committed `.patterc` bundles whose hash no longer matches source (spec §11). */
|
|
82
|
+
staleBundles: HygieneIssue[];
|
|
83
|
+
/** Lingering `.patterconflict` sidecars - an unresolved merge (patter-merge.md §3.6). */
|
|
84
|
+
unresolvedMerges: HygieneIssue[];
|
|
85
|
+
ok: boolean;
|
|
86
|
+
}
|
|
87
|
+
/** Run structural + expression + interpolation + hygiene + bundle-staleness + merge validation. */
|
|
88
|
+
declare function runValidate(loaded: LoadedProject): ValidateResult;
|
|
89
|
+
|
|
90
|
+
/** Compile a loaded project to the runtime bundle, applying its build localisation mode (spec §11):
|
|
91
|
+
* "embedded" (default) keeps every locale's strings inline; "ids" strips them so the runtime emits beat
|
|
92
|
+
* IDs (the game localises). `sourceDebug` keeps only the SOURCE locale, embedded for debug playback and
|
|
93
|
+
* flagged so the runtime warns it is not a shippable build. */
|
|
94
|
+
declare function runExport(loaded: LoadedProject): Bundle;
|
|
95
|
+
/** Compile WITHOUT the localisation-mode transform - the full bundle with every locale inline. Used where
|
|
96
|
+
* the host needs all strings regardless of build mode (e.g. Patterpad's Play window + Export Localisation). */
|
|
97
|
+
declare function runExportFull(loaded: LoadedProject): Bundle;
|
|
98
|
+
/**
|
|
99
|
+
* The conventional output path for the compiled `.patterc` bundle (spec §11):
|
|
100
|
+
* the project's `export.bundle` (relative to the root, or absolute) if set,
|
|
101
|
+
* else `dist/<project-file-stem>.patterc`. This is where `patter export` writes
|
|
102
|
+
* with no `-o`, and a stable place the staleness gate (validate) can find.
|
|
103
|
+
*/
|
|
104
|
+
declare function bundleOutputPath(loaded: LoadedProject): string;
|
|
105
|
+
|
|
106
|
+
/** Build a single self-contained playable HTML document for the loaded project. Pure: returns the file's
|
|
107
|
+
* text; the caller writes it. One file to email anyone; it plays offline in any browser. */
|
|
108
|
+
declare function runExportHtml(loaded: LoadedProject): string;
|
|
109
|
+
/** The Publish-for-Web split (Inky-style): the same page as four files. `index.html` + `style.css`
|
|
110
|
+
* are the writer's HARNESS - published once, then left alone so their customisations survive;
|
|
111
|
+
* `story.js` + `patterplay.js` are refreshed on every publish. The story is a plain script-tag
|
|
112
|
+
* ASSIGNMENT (no fetch), so the folder still plays straight from disk with no server. */
|
|
113
|
+
interface WebExport {
|
|
114
|
+
/** The harness page: markup only, linking the other three files. Published once. */
|
|
115
|
+
indexHtml: string;
|
|
116
|
+
/** The look of the page, separated so it's approachable to edit. Published once. */
|
|
117
|
+
styleCss: string;
|
|
118
|
+
/** The Patterplay runtime + this page's player glue. Refreshed on every publish. */
|
|
119
|
+
patterplayJs: string;
|
|
120
|
+
/** The compiled story as `window.PATTER_BUNDLE = …`. Refreshed on every publish. */
|
|
121
|
+
storyJs: string;
|
|
122
|
+
}
|
|
123
|
+
declare function runExportWeb(loaded: LoadedProject): WebExport;
|
|
124
|
+
|
|
125
|
+
declare function scanAudioStatus(loaded: LoadedProject): Map<string, string> | undefined;
|
|
126
|
+
|
|
127
|
+
interface PlayOptions {
|
|
128
|
+
/** Scene id to start at (defaults to the bundle's first scene). */
|
|
129
|
+
scene?: string;
|
|
130
|
+
/** Block id within the scene to start at. */
|
|
131
|
+
block?: string;
|
|
132
|
+
/** Scripted choice-option ids, consumed in order at each choice point. */
|
|
133
|
+
choices?: string[];
|
|
134
|
+
/** Seed for the runtime PRNG (shuffle / random), for reproducible runs. */
|
|
135
|
+
seed?: number;
|
|
136
|
+
/** Safety bound on steps (default 1000) to stop runaway loops. */
|
|
137
|
+
maxSteps?: number;
|
|
138
|
+
}
|
|
139
|
+
/** One thing that happened during a playthrough, in order. */
|
|
140
|
+
type PlayEvent = {
|
|
141
|
+
type: "line";
|
|
142
|
+
id: string;
|
|
143
|
+
text: string;
|
|
144
|
+
character?: string;
|
|
145
|
+
direction?: string;
|
|
146
|
+
gameData?: GameData;
|
|
147
|
+
} | {
|
|
148
|
+
type: "text";
|
|
149
|
+
id: string;
|
|
150
|
+
text: string;
|
|
151
|
+
gameData?: GameData;
|
|
152
|
+
} | {
|
|
153
|
+
type: "gameEvent";
|
|
154
|
+
id: string;
|
|
155
|
+
gameData?: GameData;
|
|
156
|
+
} | {
|
|
157
|
+
type: "choice";
|
|
158
|
+
options: ChoiceOption[];
|
|
159
|
+
picked?: string;
|
|
160
|
+
};
|
|
161
|
+
/** "end" = the flow finished; "stalled" = a choice with no pickable option; "max-steps" = bound hit. */
|
|
162
|
+
type PlayOutcome = "end" | "stalled" | "max-steps";
|
|
163
|
+
interface PlayResult {
|
|
164
|
+
events: PlayEvent[];
|
|
165
|
+
outcome: PlayOutcome;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Compile a loaded project and play it headlessly through the reference
|
|
169
|
+
* runtime. At each choice point it consumes the next scripted choice id, else
|
|
170
|
+
* picks the first eligible option - so it always runs to an outcome. The whole
|
|
171
|
+
* pipeline in one call: load -> export -> Engine playthrough.
|
|
172
|
+
*/
|
|
173
|
+
declare function runPlay(loaded: LoadedProject, opts?: PlayOptions): PlayResult;
|
|
174
|
+
/** Render a play result as the CLI's readable transcript lines. */
|
|
175
|
+
declare function renderPlay(result: PlayResult): string[];
|
|
176
|
+
|
|
177
|
+
interface CoverageOptions {
|
|
178
|
+
/** Number of random playthroughs (default 5000). */
|
|
179
|
+
runs?: number;
|
|
180
|
+
/** Per-run step cap, a divert-cycle guard (default 200). */
|
|
181
|
+
maxSteps?: number;
|
|
182
|
+
/** Seed for the harness PRNG; the whole run is reproducible from it (default 0). */
|
|
183
|
+
seed?: number;
|
|
184
|
+
/** Start-point override (else the project's authored start, else the first scene). */
|
|
185
|
+
scene?: string;
|
|
186
|
+
block?: string;
|
|
187
|
+
/** Input drivers to feed host scopes (`@world`) across the run; defaults to the project's
|
|
188
|
+
* `coverageDrivers`. Pass `proposeCoverageDrivers(loaded)` to auto-drive from the conditions. */
|
|
189
|
+
drivers?: CoverageDriver[];
|
|
190
|
+
}
|
|
191
|
+
interface CoverageHooks {
|
|
192
|
+
/** Periodic progress (done runs, total). Called occasionally, not every run. */
|
|
193
|
+
onProgress?: (done: number, total: number) => void;
|
|
194
|
+
/** Cooperative cancel; checked between runs. The partial report is returned. */
|
|
195
|
+
signal?: {
|
|
196
|
+
readonly aborted: boolean;
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
/** One beat in the coverage population, with how often it was reached. */
|
|
200
|
+
interface CoverageBeat {
|
|
201
|
+
id: string;
|
|
202
|
+
scene: string;
|
|
203
|
+
kind: "line" | "text" | "gameEvent";
|
|
204
|
+
character?: string;
|
|
205
|
+
/** A short text preview for the results table ("(game event)" for game-event beats). */
|
|
206
|
+
preview: string;
|
|
207
|
+
/** Total hits across all runs (weighting). */
|
|
208
|
+
hits: number;
|
|
209
|
+
/** Distinct runs that reached it - the numerator for reach %. */
|
|
210
|
+
reachedRuns: number;
|
|
211
|
+
/** reachedRuns / runs-executed * 100; 0 iff never reached. */
|
|
212
|
+
reachPct: number;
|
|
213
|
+
/** Set on a never-reached beat that is gated on a host-scope ref (`@world.x`) nothing writes and no
|
|
214
|
+
* driver provides, i.e. it may just need an input, not be truly dead. Lists the offending refs. */
|
|
215
|
+
needsInput?: string[];
|
|
216
|
+
}
|
|
217
|
+
/** A choice that ran DRY during the coverage run: at some point it had no takeable option and no eligible
|
|
218
|
+
* fallback, so it fell through silently and the flow carried on past it. This is easy to author by
|
|
219
|
+
* accident (all options gated and every condition happened to fail, or a re-enterable hub whose once-only
|
|
220
|
+
* options all got consumed) and the runtime hides it, so coverage surfaces it explicitly. */
|
|
221
|
+
interface DryChoice {
|
|
222
|
+
/** The choice group's id. */
|
|
223
|
+
id: string;
|
|
224
|
+
/** The scene the choice lives in. */
|
|
225
|
+
scene: string;
|
|
226
|
+
/** Distinct runs in which this choice ran dry (out of runs executed). */
|
|
227
|
+
runs: number;
|
|
228
|
+
}
|
|
229
|
+
interface CoverageReport {
|
|
230
|
+
/** Runs actually executed (= requested, unless cancelled). */
|
|
231
|
+
runs: number;
|
|
232
|
+
maxSteps: number;
|
|
233
|
+
seed: number;
|
|
234
|
+
start: {
|
|
235
|
+
scene?: string;
|
|
236
|
+
block?: string;
|
|
237
|
+
};
|
|
238
|
+
beats: CoverageBeat[];
|
|
239
|
+
totals: {
|
|
240
|
+
beats: number;
|
|
241
|
+
covered: number;
|
|
242
|
+
neverHit: number;
|
|
243
|
+
coveragePct: number;
|
|
244
|
+
};
|
|
245
|
+
/** How each run ended, for the summary header. */
|
|
246
|
+
termination: {
|
|
247
|
+
ended: number;
|
|
248
|
+
capped: number;
|
|
249
|
+
stalled: number;
|
|
250
|
+
evalError: number;
|
|
251
|
+
};
|
|
252
|
+
/** The input drivers actually applied this run (empty when none). */
|
|
253
|
+
drivers: CoverageDriver[];
|
|
254
|
+
/** Host-scope refs (`@world.x`) that gate a never-reached beat but nothing writes and no driver feeds:
|
|
255
|
+
* the "add an input?" candidates, deduped across the report. */
|
|
256
|
+
unwrittenInputs: string[];
|
|
257
|
+
/** Choices observed running dry (falling through with nothing takeable) during the run, most-frequent
|
|
258
|
+
* first. Empty when none. A dry choice is a likely dead-end-by-accident the runtime hides. */
|
|
259
|
+
dryChoices: DryChoice[];
|
|
260
|
+
cancelled: boolean;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Auto-propose coverage drivers by scanning the project's conditions for host-scope refs (`@world.x`)
|
|
264
|
+
* and the literals they are compared against. Each proposed driver is `recurring`/`sometimes` and offers
|
|
265
|
+
* the straddling values (e.g. `>= 50` → 49, 50, 51; an enum/bool → its members). Refs the story already
|
|
266
|
+
* writes are skipped (they are covered for free). The author edits + saves the result as `coverageDrivers`.
|
|
267
|
+
*/
|
|
268
|
+
declare function proposeCoverageDrivers(loaded: LoadedProject): CoverageDriver[];
|
|
269
|
+
/**
|
|
270
|
+
* Run narrative coverage over a loaded project. Pure (compiles once, then N
|
|
271
|
+
* independent playthroughs); optional progress + cancel via `hooks`.
|
|
272
|
+
*/
|
|
273
|
+
declare function runCoverage(loaded: LoadedProject, options?: CoverageOptions, hooks?: CoverageHooks): CoverageReport;
|
|
274
|
+
/** Render a coverage report as the CLI's readable text: a summary, then a per-scene beat table with
|
|
275
|
+
* never-reached (0%) rows marked. */
|
|
276
|
+
declare function renderCoverageText(report: CoverageReport, sceneName?: (id: string) => string): string[];
|
|
277
|
+
|
|
278
|
+
/** Resolve where a flow starts: an explicit override, else the project's authored `start`, else `{}`
|
|
279
|
+
* (the runtime's first-scene default). Shared by `runPlay` and `runCoverage`. */
|
|
280
|
+
declare function resolveStart(loaded: LoadedProject, override?: {
|
|
281
|
+
scene?: string;
|
|
282
|
+
block?: string;
|
|
283
|
+
}): {
|
|
284
|
+
scene?: string;
|
|
285
|
+
block?: string;
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
interface FormatResult {
|
|
289
|
+
file: string;
|
|
290
|
+
changed: boolean;
|
|
291
|
+
/** The canonical content to commit - present only when `changed`. */
|
|
292
|
+
write?: PlannedWrite;
|
|
293
|
+
}
|
|
294
|
+
/** Compute the canonical form of each file. Returns planned writes; writes nothing. */
|
|
295
|
+
declare function runFormat(files: string[]): FormatResult[];
|
|
296
|
+
|
|
297
|
+
/** Counts for the WRITTEN population (line + text + label beats). */
|
|
298
|
+
interface WrittenCounts {
|
|
299
|
+
count: number;
|
|
300
|
+
words: number;
|
|
301
|
+
byWriting: Record<string, number>;
|
|
302
|
+
}
|
|
303
|
+
/** Counts for the VOICED population (line beats only) - adds recording + readiness. */
|
|
304
|
+
interface VoicedCounts extends WrittenCounts {
|
|
305
|
+
byRecording: Record<string, number>;
|
|
306
|
+
readyToRecord: number;
|
|
307
|
+
readyToShip: number;
|
|
308
|
+
}
|
|
309
|
+
interface SceneReport {
|
|
310
|
+
sceneId: string;
|
|
311
|
+
name: string;
|
|
312
|
+
file?: string;
|
|
313
|
+
/** The scene's writing status: its LOWEST-rung status-tracked beat. Absent when it has no such beats. */
|
|
314
|
+
status?: string;
|
|
315
|
+
/** True when this scene is guesswork-estimated (its actuals are replaced by `estimate`). */
|
|
316
|
+
estimated: boolean;
|
|
317
|
+
choices: number;
|
|
318
|
+
/** Actual VOICED counts. Empty (zeroed) for an estimated scene - its numbers come from the estimate. */
|
|
319
|
+
voiced: VoicedCounts;
|
|
320
|
+
/** Actual WRITTEN counts. Empty for an estimated scene. */
|
|
321
|
+
written: WrittenCounts;
|
|
322
|
+
/** The scene's estimate in written lines, when `estimated`. */
|
|
323
|
+
estimate?: number;
|
|
324
|
+
/** Written / voiced lines DONE and REMAINING. For an estimated scene: 0 done, the estimate remaining. */
|
|
325
|
+
writtenDone: number;
|
|
326
|
+
writtenRemaining: number;
|
|
327
|
+
voicedDone: number;
|
|
328
|
+
voicedRemaining: number;
|
|
329
|
+
}
|
|
330
|
+
interface CharacterReport {
|
|
331
|
+
character: string;
|
|
332
|
+
/** Actual (authored, non-estimated) spoken lines. */
|
|
333
|
+
lines: number;
|
|
334
|
+
words: number;
|
|
335
|
+
/** Lines projected onto this character by estimated scenes (their share of those scenes' estimates). */
|
|
336
|
+
estimatedLines: number;
|
|
337
|
+
recording: Record<string, number>;
|
|
338
|
+
}
|
|
339
|
+
interface LocaleReport {
|
|
340
|
+
locale: string;
|
|
341
|
+
translated: number;
|
|
342
|
+
missing: number;
|
|
343
|
+
/** Translated but the source changed since (source modifiedAt > localisedAt). */
|
|
344
|
+
stale: number;
|
|
345
|
+
words: number;
|
|
346
|
+
}
|
|
347
|
+
interface ReportTotals {
|
|
348
|
+
voiced: VoicedCounts;
|
|
349
|
+
written: WrittenCounts;
|
|
350
|
+
choices: number;
|
|
351
|
+
writtenDone: number;
|
|
352
|
+
writtenRemaining: number;
|
|
353
|
+
voicedDone: number;
|
|
354
|
+
voicedRemaining: number;
|
|
355
|
+
/** writtenDone + writtenRemaining (built scenes + estimated scenes' estimates). */
|
|
356
|
+
projectedWritten: number;
|
|
357
|
+
projectedVoiced: number;
|
|
358
|
+
}
|
|
359
|
+
interface ReportData {
|
|
360
|
+
project: {
|
|
361
|
+
id: string;
|
|
362
|
+
name: string;
|
|
363
|
+
};
|
|
364
|
+
voiced: boolean;
|
|
365
|
+
/** Whether audio/recording status is tracked (#206): a voiced project that hasn't opted out via
|
|
366
|
+
* `trackAudioStatus`. Gates the recording-status breakdown in every renderer (text / xlsx / view). */
|
|
367
|
+
recordingTracked: boolean;
|
|
368
|
+
writingLadder: string[];
|
|
369
|
+
recordingLadder: string[];
|
|
370
|
+
scenes: SceneReport[];
|
|
371
|
+
characters: CharacterReport[];
|
|
372
|
+
locales: LocaleReport[];
|
|
373
|
+
/** Cut content (excluded from everything above), surfaced so removals are visible. */
|
|
374
|
+
cut: {
|
|
375
|
+
scenes: number;
|
|
376
|
+
voicedLines: number;
|
|
377
|
+
writtenLines: number;
|
|
378
|
+
};
|
|
379
|
+
/** Whether Estimating is turned on (renderers hide estimate figures when false). */
|
|
380
|
+
estimating: boolean;
|
|
381
|
+
/** How many scenes sit at each writing-ladder rung (by their lowest-beat status). */
|
|
382
|
+
scenesByStatus: Record<string, number>;
|
|
383
|
+
/** Estimate coverage: only meaningful when `estimating` is on. */
|
|
384
|
+
coverage: {
|
|
385
|
+
totalScenes: number;
|
|
386
|
+
estimated: number;
|
|
387
|
+
};
|
|
388
|
+
totals: ReportTotals;
|
|
389
|
+
}
|
|
390
|
+
/** Compute the production report. Pure: data out, no rendering, no I/O. */
|
|
391
|
+
declare function runReport(loaded: LoadedProject, recordingOverride?: Map<string, string>): ReportData;
|
|
392
|
+
/** Render the report as compact console lines (the CLI view). */
|
|
393
|
+
declare function renderReportText(data: ReportData): string[];
|
|
394
|
+
|
|
395
|
+
/** Render the report as an .xlsx workbook. */
|
|
396
|
+
declare function runReportXlsx(data: ReportData): Promise<Buffer>;
|
|
397
|
+
|
|
398
|
+
/** One localisable string. `id` is the beat id (or `cast:<NAME>` for a display name). */
|
|
399
|
+
interface LocEntry {
|
|
400
|
+
id: string;
|
|
401
|
+
/** Owning scene id, or `@project` for project-level strings (display names). */
|
|
402
|
+
scene: string;
|
|
403
|
+
/** The default-locale source text. */
|
|
404
|
+
source: string;
|
|
405
|
+
/** The target-locale text ("" when missing / a template). */
|
|
406
|
+
translation: string;
|
|
407
|
+
/** Localiser-channel notes for this id (DocLine text, ancestors outermost-first). */
|
|
408
|
+
comments: string[];
|
|
409
|
+
/** Best-effort context for the translator. */
|
|
410
|
+
context?: {
|
|
411
|
+
character?: string;
|
|
412
|
+
kind?: string;
|
|
413
|
+
};
|
|
414
|
+
/** Translated, but the source changed since (source modifiedAt > localisedAt[locale]). */
|
|
415
|
+
stale: boolean;
|
|
416
|
+
}
|
|
417
|
+
interface LocCatalog {
|
|
418
|
+
/** Project id (ProjectFile.project.id). */
|
|
419
|
+
project: string;
|
|
420
|
+
defaultLocale: string;
|
|
421
|
+
/** The target locale this catalog carries, or undefined for a source-only TEMPLATE (POT). */
|
|
422
|
+
locale?: string;
|
|
423
|
+
entries: LocEntry[];
|
|
424
|
+
}
|
|
425
|
+
interface ApplyStats {
|
|
426
|
+
/** Distinct ids whose translation was written. */
|
|
427
|
+
updated: number;
|
|
428
|
+
/** Loc shard files touched. */
|
|
429
|
+
files: number;
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Build the format-neutral localisation catalog. With no `locale` (or the default locale) it is a
|
|
433
|
+
* TEMPLATE: every `translation` is "". Otherwise translations come from that locale's shards.
|
|
434
|
+
*/
|
|
435
|
+
declare function extractLoc(loaded: LoadedProject, opts?: {
|
|
436
|
+
locale?: string;
|
|
437
|
+
}): LocCatalog;
|
|
438
|
+
/**
|
|
439
|
+
* Write a catalog's translations back. Produces the loc-shard writes (one per scene touched) and stamps
|
|
440
|
+
* `localisedAt[locale]` into the per-scene authoring shards (skipped when importing the default locale -
|
|
441
|
+
* staleness is tracked against the source, not for it). Caller commits the returned writes.
|
|
442
|
+
*
|
|
443
|
+
* Import conflict policy (decision 3a): a translation is accepted even when the source has since changed;
|
|
444
|
+
* the stale flag stays derivable from `localisedAt` vs source `modifiedAt` and surfaces on the next export.
|
|
445
|
+
*/
|
|
446
|
+
declare function applyLoc(loaded: LoadedProject, catalog: LocCatalog, opts?: {
|
|
447
|
+
now?: string;
|
|
448
|
+
}): {
|
|
449
|
+
writes: PlannedWrite[];
|
|
450
|
+
stats: ApplyStats;
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
/** The catalog IS the JSON shape: a stable, lossless, human-diffable envelope. */
|
|
454
|
+
declare function catalogToJson(catalog: LocCatalog): string;
|
|
455
|
+
/** Parse a JSON catalog; light validation so a hand-mangled file fails loudly, not deep in apply. */
|
|
456
|
+
declare function jsonToCatalog(text: string): LocCatalog;
|
|
457
|
+
/** Render the catalog as a PO file (or a POT template when `catalog.locale` is undefined). */
|
|
458
|
+
declare function catalogToPo(catalog: LocCatalog): string;
|
|
459
|
+
/** Parse a PO / POT file back into a catalog. `locale` (from the Language header) may be overridden by
|
|
460
|
+
* the caller's --locale. Entries without a msgctxt (the header) are skipped. */
|
|
461
|
+
declare function poToCatalog(text: string): LocCatalog;
|
|
462
|
+
|
|
463
|
+
/** Render the catalog as an .xlsx workbook: a sheet per scene, translator-facing columns. */
|
|
464
|
+
declare function catalogToXlsx(catalog: LocCatalog): Promise<Buffer>;
|
|
465
|
+
/** Parse an .xlsx workbook back into a catalog. Scene = sheet name; stale = Status "stale". `locale` is
|
|
466
|
+
* not carried in the sheet, so the caller supplies it (--locale). */
|
|
467
|
+
declare function xlsxToCatalog(buffer: Buffer): Promise<LocCatalog>;
|
|
468
|
+
|
|
469
|
+
interface VoiceLine {
|
|
470
|
+
/** Readable container trail (`Scene › Block › Option`) - the scope changes signal a new run / branch. */
|
|
471
|
+
scope: string;
|
|
472
|
+
/** The line beat's id (recordings / filenames key to this). */
|
|
473
|
+
id: string;
|
|
474
|
+
/** The canonical speaker token. */
|
|
475
|
+
character: string;
|
|
476
|
+
/** The cast member's voice actor, if known. */
|
|
477
|
+
actor?: string;
|
|
478
|
+
/** The line's source-locale text. */
|
|
479
|
+
text: string;
|
|
480
|
+
/** `vo` notes: the line's own, plus the enclosing group/option's on the first line of a run. */
|
|
481
|
+
comments: string[];
|
|
482
|
+
/** The line's recording-ladder status (the "voice status"). */
|
|
483
|
+
recordingStatus: string;
|
|
484
|
+
}
|
|
485
|
+
interface VoiceScript {
|
|
486
|
+
project: string;
|
|
487
|
+
voiced: boolean;
|
|
488
|
+
recordingLadder: string[];
|
|
489
|
+
/** True when the filter was bypassed (every voiced line, not just ready-to-record). */
|
|
490
|
+
everything: boolean;
|
|
491
|
+
lines: VoiceLine[];
|
|
492
|
+
}
|
|
493
|
+
/** Compute the production VO script. Pure: data out, no I/O. `recordingOverride` replaces the
|
|
494
|
+
* manual recording map with status derived from files on disk (#206 Audio Folders) - the same
|
|
495
|
+
* contract as `runReport`, so the script agrees with the report and the inspector. */
|
|
496
|
+
declare function runVoiceScript(loaded: LoadedProject, opts?: {
|
|
497
|
+
everything?: boolean;
|
|
498
|
+
recordingOverride?: Map<string, string>;
|
|
499
|
+
}): VoiceScript;
|
|
500
|
+
|
|
501
|
+
/** Render the VO script as an .xlsx workbook (a single "Voice Script" sheet). */
|
|
502
|
+
declare function voiceScriptToXlsx(data: VoiceScript): Promise<Buffer>;
|
|
503
|
+
|
|
504
|
+
/** A formatting run of body text. `code` marks an inline `{@property}` interpolation (rendered as accent
|
|
505
|
+
* mono); `bold`/`italic` carry Patter's closed `<b>/<i>/<bi>` markup. Renderers turn these into Word runs
|
|
506
|
+
* or PDF font/colour switches. */
|
|
507
|
+
interface TextRun {
|
|
508
|
+
text: string;
|
|
509
|
+
bold: boolean;
|
|
510
|
+
italic: boolean;
|
|
511
|
+
code: boolean;
|
|
512
|
+
}
|
|
513
|
+
/** One renderable item in reading order. `indent` is the structural nesting depth (0 = block-level) - the
|
|
514
|
+
* reader's structure cue. `snippet` is an id shared by every element of one snippet WHEN that snippet sits
|
|
515
|
+
* inside a selector (branch / sequence / choice); the renderers draw a light left edge spanning each such
|
|
516
|
+
* snippet, so rows that would otherwise blur (a sequence's steps) read as distinct beats. Absent = a
|
|
517
|
+
* top-level snippet (delimited by space alone). Headings carry no indent (they reset it). */
|
|
518
|
+
type ScriptElement = {
|
|
519
|
+
kind: "scene";
|
|
520
|
+
text: string;
|
|
521
|
+
} | {
|
|
522
|
+
kind: "block";
|
|
523
|
+
text: string;
|
|
524
|
+
}
|
|
525
|
+
/** A spoken line: SPEAKER cue (coloured, uppercase), an optional (direction), and the body runs. */
|
|
526
|
+
| {
|
|
527
|
+
kind: "line";
|
|
528
|
+
indent: number;
|
|
529
|
+
snippet?: number;
|
|
530
|
+
character: string;
|
|
531
|
+
direction?: string;
|
|
532
|
+
runs: TextRun[];
|
|
533
|
+
}
|
|
534
|
+
/** Prose narration / on-screen text (speaker-less), upright in a soft ink, flush left. */
|
|
535
|
+
| {
|
|
536
|
+
kind: "narration";
|
|
537
|
+
indent: number;
|
|
538
|
+
snippet?: number;
|
|
539
|
+
runs: TextRun[];
|
|
540
|
+
}
|
|
541
|
+
/** A gating condition, set in accent mono above the beat it controls: `‹ if @brave ›`. */
|
|
542
|
+
| {
|
|
543
|
+
kind: "condition";
|
|
544
|
+
indent: number;
|
|
545
|
+
snippet?: number;
|
|
546
|
+
text: string;
|
|
547
|
+
}
|
|
548
|
+
/** A selector group's label ("Choose", "One of · first match wins", "In sequence"). */
|
|
549
|
+
| {
|
|
550
|
+
kind: "group";
|
|
551
|
+
indent: number;
|
|
552
|
+
label: string;
|
|
553
|
+
}
|
|
554
|
+
/** A branch's catch-all row header ("else · catch-all"). */
|
|
555
|
+
| {
|
|
556
|
+
kind: "else";
|
|
557
|
+
indent: number;
|
|
558
|
+
}
|
|
559
|
+
/** A choice option: a ◇-led prompt, plus a quiet small-caps flag tag (once only / repeatable). */
|
|
560
|
+
| {
|
|
561
|
+
kind: "option";
|
|
562
|
+
indent: number;
|
|
563
|
+
snippet?: number;
|
|
564
|
+
runs: TextRun[];
|
|
565
|
+
tag?: string;
|
|
566
|
+
}
|
|
567
|
+
/** A jump, set apart right-aligned in accent: `↪ The Crossroads` (readable target, never the id). */
|
|
568
|
+
| {
|
|
569
|
+
kind: "jump";
|
|
570
|
+
indent: number;
|
|
571
|
+
snippet?: number;
|
|
572
|
+
text: string;
|
|
573
|
+
}
|
|
574
|
+
/** A game event, set apart right-aligned in accent mono: `⚙ game event · door.open`. */
|
|
575
|
+
| {
|
|
576
|
+
kind: "gameEvent";
|
|
577
|
+
indent: number;
|
|
578
|
+
snippet?: number;
|
|
579
|
+
text: string;
|
|
580
|
+
};
|
|
581
|
+
interface ScriptDoc {
|
|
582
|
+
/** Project display name - the document title. */
|
|
583
|
+
project: string;
|
|
584
|
+
elements: ScriptElement[];
|
|
585
|
+
}
|
|
586
|
+
/** Compute the readable script document. Pure: data out, no I/O. */
|
|
587
|
+
declare function runScriptDoc(loaded: LoadedProject): ScriptDoc;
|
|
588
|
+
|
|
589
|
+
/** Render the readable screenplay as a Word document. */
|
|
590
|
+
declare function scriptToDocx(doc: ScriptDoc): Promise<Buffer>;
|
|
591
|
+
|
|
592
|
+
/** Render the readable screenplay as a PDF. Resolves once PDFKit has flushed the whole document. */
|
|
593
|
+
declare function scriptToPdf(doc: ScriptDoc): Promise<Buffer>;
|
|
594
|
+
|
|
595
|
+
type InitVcs = "git" | "perforce" | "plastic" | "svn";
|
|
596
|
+
/** Whether the compiled `.patterc` bundle is committed or built in CI (spec §11). */
|
|
597
|
+
type BundlePosture = "commit" | "ignore";
|
|
598
|
+
interface InitOptions {
|
|
599
|
+
/** Directory to scaffold into (created by the caller's `applyWrites`). */
|
|
600
|
+
dir: string;
|
|
601
|
+
/** Project name; defaults to the directory's basename. */
|
|
602
|
+
name?: string;
|
|
603
|
+
/** Emit VCS config for this VCS (spec §12). */
|
|
604
|
+
vcs?: InitVcs;
|
|
605
|
+
/** Compiled-bundle posture (spec §11): "commit" (default - team ships it,
|
|
606
|
+
* kept honest by the validate staleness gate) or "ignore" (built in CI). */
|
|
607
|
+
bundle?: BundlePosture;
|
|
608
|
+
}
|
|
609
|
+
interface InitResult {
|
|
610
|
+
writes: PlannedWrite[];
|
|
611
|
+
/** Path of the project file the scaffold creates. */
|
|
612
|
+
projectFile: string;
|
|
613
|
+
name: string;
|
|
614
|
+
}
|
|
615
|
+
/** Scaffold a new project as planned writes. Throws if `dir` already holds a project. */
|
|
616
|
+
declare function runInit(opts: InitOptions): InitResult;
|
|
617
|
+
/** The VCS-specific config writes for a project (spec §12): the `vcs-setup.md` guide, git's
|
|
618
|
+
* `.gitattributes`, and the VCS's ignore file. Shared by `runInit` (scaffold) and the Project Settings
|
|
619
|
+
* "switch VCS" path (which re-emits these for the newly-chosen VCS). No collision check - callers
|
|
620
|
+
* overwrite when switching. */
|
|
621
|
+
declare function vcsConfigWrites(dir: string, vcs: InitVcs | undefined, bundle?: BundlePosture): PlannedWrite[];
|
|
622
|
+
|
|
623
|
+
/** The editor's caret context, so a search can float the current scene's hits (from the caret onwards) to
|
|
624
|
+
* the top. Omit for a context-free search (the CLI). */
|
|
625
|
+
interface SearchFocus {
|
|
626
|
+
/** The scene the editor is currently showing. */
|
|
627
|
+
sceneId: string;
|
|
628
|
+
/** The beat id the caret is in (its hits, and later ones in the scene, rank first). */
|
|
629
|
+
fromBeatId?: string;
|
|
630
|
+
}
|
|
631
|
+
interface ResolveEntry {
|
|
632
|
+
id: string;
|
|
633
|
+
kind: "scene" | "block" | "group" | "snippet" | "beat";
|
|
634
|
+
/** The author name (scenes / blocks only - other nodes are unnamed). */
|
|
635
|
+
name?: string;
|
|
636
|
+
/** The host-facing Game ID address (scenes / blocks only). */
|
|
637
|
+
gameId?: string;
|
|
638
|
+
/** The default-locale text content (line / text beats + choice prompts) - for the content search. */
|
|
639
|
+
text?: string;
|
|
640
|
+
/** The named location trail: scene name, then block name. */
|
|
641
|
+
location: string[];
|
|
642
|
+
/** The id of the scene this node lives in (for jump-to in the editor). */
|
|
643
|
+
sceneId: string;
|
|
644
|
+
/** The scene source file the node lives in. */
|
|
645
|
+
file?: string;
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* Look up a query against every node and beat in the project. Matching, in
|
|
649
|
+
* priority order: exact id -> exact Game ID -> exact name (case-insensitive) ->
|
|
650
|
+
* substring of id / Game ID / name (case-insensitive). The first tier with any
|
|
651
|
+
* hits wins, so an exact match never drowns in fuzzy ones. This is the path that
|
|
652
|
+
* answers "a locale string / audio file / log names id X - what line is that?".
|
|
653
|
+
*/
|
|
654
|
+
declare function runResolve(loaded: LoadedProject, query: string): ResolveEntry[];
|
|
655
|
+
/**
|
|
656
|
+
* The editor's MAIN search (spec §6): content-oriented, the everyday "go to a thing" path. Matches a
|
|
657
|
+
* query against **Game IDs, scene / block titles, and dialogue / narration / choice text**, with the
|
|
658
|
+
* "Go to ID" power-search folded in: paste an opaque id and the node it names is found. Ranking: title /
|
|
659
|
+
* Game-ID, then dialogue / text content, then raw id.
|
|
660
|
+
*/
|
|
661
|
+
declare function runSearch(loaded: LoadedProject, query: string, focus?: SearchFocus): ResolveEntry[];
|
|
662
|
+
/**
|
|
663
|
+
* Status browse (Patterpad #205): every LINE / TEXT beat whose writing status is `status`, in document
|
|
664
|
+
* order (the caret's scene first when `focus` is given). A beat with no explicit status reads as the LOWEST
|
|
665
|
+
* rung, so browsing the lowest status surfaces every un-started line. Actions and choice prompts are never
|
|
666
|
+
* status-tracked, so they're excluded (mirrors the surface + the production report).
|
|
667
|
+
*/
|
|
668
|
+
declare function runStatusBrowse(loaded: LoadedProject, status: string, dimension?: "writing" | "recording", focus?: SearchFocus, recordingOverride?: Map<string, string>): ResolveEntry[];
|
|
669
|
+
/**
|
|
670
|
+
* List every distinct author tag (#215) used anywhere in the project, with how many nodes carry it, sorted
|
|
671
|
+
* alphabetically. Drives the search window's Tag tab chips (the tag counterpart to the status ladder).
|
|
672
|
+
* Counts a node's OWN tags only (not the accumulated runtime union), so the number is "places I applied it".
|
|
673
|
+
*/
|
|
674
|
+
declare function listProjectTags(loaded: LoadedProject): Array<{
|
|
675
|
+
name: string;
|
|
676
|
+
count: number;
|
|
677
|
+
}>;
|
|
678
|
+
/**
|
|
679
|
+
* Tag browse (#215 follow-up): every node whose OWN tags include `tag`, at any level (scene, block, group,
|
|
680
|
+
* snippet, prompt, or beat), in document order (the caret's scene first when `focus` is given). Matches the
|
|
681
|
+
* authored tag, not the accumulated runtime union, so it points at where the tag was actually applied.
|
|
682
|
+
* A row previews what the node is: a beat / prompt shows its text, a snippet its first beat, a scene / block
|
|
683
|
+
* its name.
|
|
684
|
+
*/
|
|
685
|
+
declare function runTagBrowse(loaded: LoadedProject, tag: string, focus?: SearchFocus): ResolveEntry[];
|
|
686
|
+
/**
|
|
687
|
+
* Property-usage search (#205 follow-up): every node that REFERENCES a property in a **condition**, an
|
|
688
|
+
* **effect** (a `set` target or value), or **interpolated text**: the coverage-driven "this dead branch's
|
|
689
|
+
* condition uses `@x`; where else is `@x` used?" path. `query` is a property ref (`@gold`, `gold`,
|
|
690
|
+
* `@world.threat`), optionally followed by a value to narrow to usages that also mention it (`gold 10`,
|
|
691
|
+
* `faction rebels`). Returns a row per usage, with `text` describing it (the condition, the `set`, or the
|
|
692
|
+
* interpolated string). Bare names also match their explicit `@patter.` form.
|
|
693
|
+
*/
|
|
694
|
+
declare function runPropertyUsage(loaded: LoadedProject, query: string, focus?: SearchFocus): ResolveEntry[];
|
|
695
|
+
|
|
696
|
+
interface ReplaceOptions {
|
|
697
|
+
/** The literal text to find (not a regex: special characters match themselves). */
|
|
698
|
+
query: string;
|
|
699
|
+
/** The literal replacement text. */
|
|
700
|
+
replacement: string;
|
|
701
|
+
/** Match case (default off). */
|
|
702
|
+
caseSensitive?: boolean;
|
|
703
|
+
/** Match whole words only (word boundaries around the query; default off). */
|
|
704
|
+
wholeWord?: boolean;
|
|
705
|
+
/** Restrict the replacement to a single beat id (the per-row "Replace this one"). */
|
|
706
|
+
onlyId?: string;
|
|
707
|
+
}
|
|
708
|
+
/** One replaced string, for the preview / confirm list. */
|
|
709
|
+
interface ReplaceHit {
|
|
710
|
+
id: string;
|
|
711
|
+
sceneId: string;
|
|
712
|
+
/** Scene › block breadcrumb. */
|
|
713
|
+
location: string[];
|
|
714
|
+
before: string;
|
|
715
|
+
after: string;
|
|
716
|
+
}
|
|
717
|
+
interface ReplacePlan {
|
|
718
|
+
hits: ReplaceHit[];
|
|
719
|
+
/** Shard writes the caller commits through the VC layer (one per touched scene). */
|
|
720
|
+
writes: PlannedWrite[];
|
|
721
|
+
/** The rewritten shard objects (index-aligned with `writes`), so the caller can swap them into its
|
|
722
|
+
* in-memory `LoadedProject.locales` after committing: keeping reads + the open scene current. */
|
|
723
|
+
shards: LocaleFile[];
|
|
724
|
+
/** Distinct scenes touched. */
|
|
725
|
+
scenes: number;
|
|
726
|
+
}
|
|
727
|
+
/**
|
|
728
|
+
* Plan a project-wide replacement. Walks the default-locale string shards (the source prose), substitutes
|
|
729
|
+
* matches, and returns the hits + the shard writes. With `onlyId`, only that one beat's string is touched.
|
|
730
|
+
*/
|
|
731
|
+
declare function runReplace(loaded: LoadedProject, opts: ReplaceOptions): ReplacePlan;
|
|
732
|
+
|
|
733
|
+
/** The source-shard extensions a document carries (the merge-friendly truth). */
|
|
734
|
+
declare const SHARD_EXTENSIONS: readonly [".patterflow", ".patterloc", ".patterx", ".patterproj"];
|
|
735
|
+
/** Manifest embedded at the document root - what this envelope is and contains. */
|
|
736
|
+
interface DocumentManifest {
|
|
737
|
+
schema: "patter/document@0";
|
|
738
|
+
project: {
|
|
739
|
+
id: string;
|
|
740
|
+
name: string;
|
|
741
|
+
};
|
|
742
|
+
/** Shard paths (relative, forward-slashed), sorted - the document's contents. */
|
|
743
|
+
files: string[];
|
|
744
|
+
}
|
|
745
|
+
/** Pack a project's source shards into a `.patterpack` document (zip bytes). */
|
|
746
|
+
declare function runPack(startPath: string): Promise<Buffer>;
|
|
747
|
+
|
|
748
|
+
type MergeFileType = "flow" | "loc" | "authoring" | "project";
|
|
749
|
+
type ConflictKind = "both-changed" | "delete-vs-edit" | "no-timestamp" | "moved" | "added-both" | "structural";
|
|
750
|
+
/** One unresolved 3-way conflict; provisional output is OURS. */
|
|
751
|
+
interface Conflict {
|
|
752
|
+
/** The unit id (beat/node/comment/scene id or planned name); "" for a file-level field. */
|
|
753
|
+
id: string;
|
|
754
|
+
/** Dotted path within the file, e.g. `strings.L_1` or `writing.L_1`. */
|
|
755
|
+
path: string;
|
|
756
|
+
base: unknown;
|
|
757
|
+
ours: unknown;
|
|
758
|
+
theirs: unknown;
|
|
759
|
+
kind: ConflictKind;
|
|
760
|
+
}
|
|
761
|
+
/** A non-blocking note - the merge proceeded, but a human may want to check. */
|
|
762
|
+
interface Warning {
|
|
763
|
+
id: string;
|
|
764
|
+
path: string;
|
|
765
|
+
message: string;
|
|
766
|
+
}
|
|
767
|
+
interface MergeResult {
|
|
768
|
+
type: MergeFileType;
|
|
769
|
+
/** The merged model - valid canonical source; conflicts resolved to OURS. */
|
|
770
|
+
merged: Record<string, unknown>;
|
|
771
|
+
conflicts: Conflict[];
|
|
772
|
+
/** Advisory notes (e.g. both sides inserted at the same anchor, kept ours-then-theirs). */
|
|
773
|
+
warnings: Warning[];
|
|
774
|
+
}
|
|
775
|
+
/** Thrown when asked to merge a type M1 does not handle yet (flow / project). */
|
|
776
|
+
declare class UnsupportedMergeError extends Error {
|
|
777
|
+
}
|
|
778
|
+
type Obj = Record<string, unknown>;
|
|
779
|
+
/** Detect the merge type from a file's `schema` tag. */
|
|
780
|
+
declare function detectMergeType(file: {
|
|
781
|
+
schema?: unknown;
|
|
782
|
+
}): MergeFileType;
|
|
783
|
+
/** 3-way merge BASE / OURS / THEIRS (parsed models). Dispatches by file type. */
|
|
784
|
+
declare function runMerge(base: Obj, ours: Obj, theirs: Obj, opts?: {
|
|
785
|
+
type?: MergeFileType;
|
|
786
|
+
}): MergeResult;
|
|
787
|
+
|
|
788
|
+
/** A document entry whose path escapes the target dir (rejected). */
|
|
789
|
+
declare class UnsafeEntryError extends Error {
|
|
790
|
+
}
|
|
791
|
+
/** Unpack a `.patterpack` document (zip bytes) into planned writes under `targetDir`. */
|
|
792
|
+
declare function runUnpack(bytes: Buffer | Uint8Array, targetDir: string): Promise<PlannedWrite[]>;
|
|
793
|
+
/** One shard's outcome in a merge-unpack. */
|
|
794
|
+
interface MergedShard {
|
|
795
|
+
/** Relative path within the project. */
|
|
796
|
+
path: string;
|
|
797
|
+
/** Merge result, or undefined when the shard was ADDED (new file from the author). */
|
|
798
|
+
result?: MergeResult;
|
|
799
|
+
added: boolean;
|
|
800
|
+
}
|
|
801
|
+
interface UnpackMergeResult {
|
|
802
|
+
shards: MergedShard[];
|
|
803
|
+
/** Merged (and added) shard contents to write into the project. */
|
|
804
|
+
writes: PlannedWrite[];
|
|
805
|
+
/** `.patterconflict` sidecars for shards with conflicts. */
|
|
806
|
+
sidecars: PlannedWrite[];
|
|
807
|
+
conflicts: number;
|
|
808
|
+
warnings: number;
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* Merge a RETURNED `.patterpack` document (`theirs`) back into the project at
|
|
812
|
+
* `projectDir` (`ours`), using the document originally sent (`base`) as the
|
|
813
|
+
* common ancestor. Per shard: 3-way merge (added files written verbatim). Pure -
|
|
814
|
+
* returns planned writes + sidecars; the caller commits. A shard the author
|
|
815
|
+
* DELETED is left in the working tree (whole-file deletes are not propagated in
|
|
816
|
+
* v1 - safe, no data loss).
|
|
817
|
+
*/
|
|
818
|
+
declare function runUnpackMerge(returnedBytes: Buffer | Uint8Array, baseBytes: Buffer | Uint8Array, projectDir: string): Promise<UnpackMergeResult>;
|
|
819
|
+
/** True if a document entry is an absolute path or would escape the target dir.
|
|
820
|
+
* (JSZip's own API normalises `..` away, but a zip from any other tool may not.) */
|
|
821
|
+
declare function isUnsafeEntry(name: string): boolean;
|
|
822
|
+
|
|
823
|
+
/** The class names whose notes deliver to `channel` (a class with `deliver: "*"` matches every channel). */
|
|
824
|
+
declare function classesForChannel(classes: DocumentationClass[], channel: string): Set<string>;
|
|
825
|
+
/**
|
|
826
|
+
* Resolve documentation for an export `channel`: a map from node/beat id to the
|
|
827
|
+
* ordered notes delivered there - ancestors outermost-first, then the node's own.
|
|
828
|
+
* Only ids with at least one delivered note appear. Untyped notes are skipped
|
|
829
|
+
* (editor-only).
|
|
830
|
+
*/
|
|
831
|
+
declare function resolveDocumentation(loaded: LoadedProject, channel: string): Map<string, DocLine[]>;
|
|
832
|
+
|
|
833
|
+
export { type ApplyStats, type BundlePosture, type CharacterReport, type Conflict, type ConflictKind, type CoverageBeat, type CoverageHooks, type CoverageOptions, type CoverageReport, type DocumentManifest, type FormatResult, type HygieneIssue, type InitOptions, type InitResult, type InitVcs, type LoadedProject, type LocCatalog, type LocEntry, type LocaleReport, type MergeFileType, type MergeResult, type MergedShard, type PlannedWrite, type PlayEvent, type PlayOptions, type PlayOutcome, type PlayResult, type ReplaceHit, type ReplaceOptions, type ReplacePlan, type ReportData, type ReportTotals, type ResolveEntry, SHARD_EXTENSIONS, type SceneReport, type ScriptDoc, type ScriptElement, type SearchFocus, type UnpackMergeResult, UnsafeEntryError, UnsupportedMergeError, type ValidateResult, type VoiceLine, type VoiceScript, type VoicedCounts, type WebExport, type WrittenCounts, applyLoc, applySceneOrder, applyWrites, bundleOutputPath, catalogToJson, catalogToPo, catalogToXlsx, classesForChannel, detectMergeType, extractLoc, findProjectFile, isUnsafeEntry, jsonToCatalog, listProjectTags, loadProject, loadProjectLanding, poToCatalog, proposeCoverageDrivers, renderCoverageText, renderPlay, renderReportText, resolveDocumentation, resolveStart, runCoverage, 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, vcsConfigWrites, voiceScriptToXlsx, xlsxToCatalog };
|