@rslsp1/fa-app-tools 2.0.78 → 2.0.82

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.
@@ -0,0 +1,1379 @@
1
+ import { Q as QueryResult, T as TextGenerationPort, C as CommandResult } from './contracts-DdYOMBl9.mjs';
2
+
3
+ /** Ein einzelner Validierungsbefund, im Aufbau an ajv angelehnt. */
4
+ interface SchemaError {
5
+ /** JSON-Pointer auf die fehlerhafte Stelle in der Instanz, z.B. `/payload/nodes/0`. */
6
+ instancePath: string;
7
+ /** Menschenlesbare Ursache. */
8
+ message: string;
9
+ /** Schlüsselwort, das gegriffen hat, z.B. `required` oder `additionalProperties`. */
10
+ keyword: string;
11
+ /**
12
+ * Bei `keyword === 'required'`: der Name des fehlenden Pflichtfelds.
13
+ *
14
+ * Er steht auch in `message`, aber dort als Prosa. Wer die Fehlstelle
15
+ * maschinell adressieren will — die Rekonstruktion tut das —, müsste sie
16
+ * sonst aus dem Text parsen. Ein Feldname, der über eine Zeichenkettensuche
17
+ * rekonstruiert wird, ist genau die Sorte Kopplung, die später still bricht.
18
+ */
19
+ property?: string;
20
+ }
21
+ type Json = unknown;
22
+ type SchemaObject = Record<string, Json>;
23
+ /** Aufgelöste Schemasammlung, bereit zum Validieren. */
24
+ interface CompiledSchemas {
25
+ /** Schema-Dokumente, geschlüsselt nach `$id`. */
26
+ byId: Map<string, SchemaObject>;
27
+ /** `$id` je Quelldateiname, z.B. `scene.schema.json`. */
28
+ idByFile: Map<string, string>;
29
+ }
30
+ /** Wirft bei einem Schema, das dieser Validator nicht vollständig abdeckt. */
31
+ declare class UnsupportedSchemaError extends Error {
32
+ }
33
+ /**
34
+ * Baut die Schemaregistry auf und prüft dabei jedes Dokument auf Abdeckung.
35
+ *
36
+ * @param schemasByFile Rohschemas, geschlüsselt nach Quelldateiname.
37
+ * @throws UnsupportedSchemaError bei fehlendem `$id` oder unbekanntem Schlüsselwort.
38
+ */
39
+ declare function compileSchemas(schemasByFile: Record<string, SchemaObject>): CompiledSchemas;
40
+ /** Ergebnis einer Schemaprüfung. */
41
+ interface SchemaValidationResult {
42
+ valid: boolean;
43
+ errors: SchemaError[];
44
+ }
45
+ /**
46
+ * Validiert eine Instanz gegen ein Schema aus der Registry.
47
+ *
48
+ * @param schemas Registry aus `compileSchemas`.
49
+ * @param file Quelldateiname des Einstiegsschemas, z.B. `element-version.schema.json`.
50
+ * @param instance Zu prüfender Wert.
51
+ */
52
+ declare function validateAgainst(schemas: CompiledSchemas, file: string, instance: Json): SchemaValidationResult;
53
+
54
+ /** Die dreizehn Elementtypen des Modells. Reihenfolge wie im Umschlagschema. */
55
+ declare const SZENEN_ELEMENT_TYPES: readonly ["scene_component", "scene", "shot_concept", "camera_preset", "camera_pattern", "style", "scene_setup", "shot", "prompt_policy", "prompt_fragment", "target_model", "sequence", "scene_derivation_policy"];
56
+ type SzenenElementType = (typeof SZENEN_ELEMENT_TYPES)[number];
57
+
58
+ /** Ergebnis der strukturellen Prüfung einer Elementversion. */
59
+ interface ElementVersionValidation {
60
+ valid: boolean;
61
+ errors: SchemaError[];
62
+ }
63
+ /**
64
+ * Kompiliert die Schemaregistry beim ersten Aufruf und merkt sie sich.
65
+ *
66
+ * @throws UnsupportedSchemaError wenn ein Schema ein Schlüsselwort verwendet,
67
+ * das der Validator nicht prüft. Das ist Absicht: lieber ein Fehler beim Start
68
+ * als eine Prüfung, die stillschweigend nichts tut.
69
+ */
70
+ declare function getSzenenSchemas(): CompiledSchemas;
71
+ /**
72
+ * Prüft eine vollständige Elementversion (Umschlag + typisierte Payload).
73
+ *
74
+ * Der Umschlag wählt über `type` das passende Payload-Schema — ein untypisiertes
75
+ * `inhalt JSON` ist ausdrücklich unzulässig (Blocker 4 des PR-336-Reviews).
76
+ *
77
+ * @param candidate Der zu prüfende Wert, üblicherweise frisch geparstes JSON.
78
+ */
79
+ declare function validateElementVersion(candidate: unknown): ElementVersionValidation;
80
+ /**
81
+ * Prüft nur die Payload eines bekannten Typs, ohne Umschlag.
82
+ *
83
+ * Gedacht für Editoren, die eine Payload prüfen wollen, bevor Umschlagfelder wie
84
+ * `server_received_at` überhaupt existieren — beim Entwurf gibt es die noch nicht.
85
+ */
86
+ declare function validatePayload(type: SzenenElementType, payload: unknown): ElementVersionValidation;
87
+ /** Fehlerliste als einzeiliger Text, für Logs und Fehlermeldungen. */
88
+ declare function formatSchemaErrors(errors: readonly SchemaError[]): string;
89
+
90
+ /** Art der Abstammung zwischen zwei Versionen (`element_version_parents.relation`). */
91
+ type ParentRelation = 'derived_from' | 'merged_from';
92
+ /** Kante zum Vorgänger. */
93
+ interface VersionParentLink {
94
+ parent_version_id: string;
95
+ relation: ParentRelation;
96
+ }
97
+ /**
98
+ * Knoten des Versions-DAG.
99
+ *
100
+ * Bewusst **ohne** `client_created_at`, `server_received_at` oder eine
101
+ * Sequenznummer: Abstammung kommt ausschließlich aus `parents` (§2.4).
102
+ */
103
+ interface VersionNode {
104
+ version_id: string;
105
+ element_id: string;
106
+ parents: readonly VersionParentLink[];
107
+ }
108
+ /** Ein Aufbaufehler des Graphen. Er verhindert den Aufbau, er meldet nicht nur. */
109
+ declare class VersionDagError extends Error {
110
+ }
111
+ /** Aufgebauter, zyklenfreier Versionsgraph eines Elements. */
112
+ interface VersionDag {
113
+ readonly elementId: string;
114
+ /** Alle Versionskennungen, in Eingabereihenfolge. */
115
+ readonly versionIds: readonly string[];
116
+ /** Version zu einer Kennung, oder `undefined`. */
117
+ get(versionId: string): VersionNode | undefined;
118
+ /** Direkte Vorgänger. */
119
+ parentsOf(versionId: string): readonly VersionParentLink[];
120
+ /** Direkte Nachfolger. */
121
+ childrenOf(versionId: string): readonly string[];
122
+ /** Versionen ohne Nachfolger — die Heads (`all_heads`, §2.5). */
123
+ heads(): readonly string[];
124
+ /** Versionen ohne Vorgänger. Normalerweise genau eine. */
125
+ roots(): readonly string[];
126
+ /** Mehr als ein Head (`has_fork`, §2.5). */
127
+ hasFork(): boolean;
128
+ /** Alle Vorfahren, transitiv, ohne die Version selbst. */
129
+ ancestorsOf(versionId: string): ReadonlySet<string>;
130
+ /** Alle Nachfahren, transitiv, ohne die Version selbst. */
131
+ descendantsOf(versionId: string): ReadonlySet<string>;
132
+ /** Ob `candidate` ein echter Vorfahre von `versionId` ist. */
133
+ isAncestorOf(candidate: string, versionId: string): boolean;
134
+ }
135
+ /**
136
+ * Baut den Versions-DAG eines Elements auf.
137
+ *
138
+ * Der Aufbau ist streng: doppelte Versionen, fremde Elemente, unbekannte
139
+ * Parents und Zyklen brechen ab. Ein halb gültiger Abstammungsgraph ist
140
+ * schlimmer als keiner — auf ihm ruht die Auflösung des Preferred Head.
141
+ *
142
+ * @param versions Alle bekannten Versionen **eines** Elements.
143
+ * @throws VersionDagError bei Duplikat, Fremdelement, unbekanntem Parent, Selbstbezug oder Zyklus.
144
+ */
145
+ declare function buildVersionDag(versions: readonly VersionNode[]): VersionDag;
146
+ /**
147
+ * Auswahl eines Heads für einen Kontext (`element_preferred_heads`).
148
+ *
149
+ * Ohne Zeitstempel — die Auswahl gilt, weil jemand sie getroffen hat, nicht
150
+ * weil sie die jüngste ist.
151
+ */
152
+ interface PreferredHeadSelection {
153
+ context_id: string | null;
154
+ version_id: string;
155
+ }
156
+ /** Woher die geltende Auswahl stammt. Entspricht den Stufen 1–3 aus D-36. */
157
+ type PreferredHeadSource =
158
+ /** Der Arbeitskontext hat eine eigene Auswahl (Stufe 1). */
159
+ 'context'
160
+ /** Ein erbender Kontext der Kette, nach `priority` (Stufe 2). */
161
+ | 'inherited'
162
+ /** Der Kontext, in dem das Element liegt (Stufe 3). */
163
+ | 'owning';
164
+ /** Ergebnis der Auflösung. */
165
+ type PreferredHeadResolution =
166
+ /** Genau ein Head, keine Auswahl nötig. */
167
+ {
168
+ kind: 'single';
169
+ versionId: string;
170
+ heads: readonly string[];
171
+ }
172
+ /** Eine Auswahl greift. */
173
+ | {
174
+ kind: 'selected';
175
+ versionId: string;
176
+ source: PreferredHeadSource;
177
+ /** `null` = die Auswahl gilt für kontextlose Arbeit. */
178
+ contextId: string | null;
179
+ heads: readonly string[];
180
+ /** Die gewählte Version ist inzwischen kein Head mehr — jemand hat weitergebaut. */
181
+ stale: boolean;
182
+ }
183
+ /**
184
+ * Mehrere Heads und nirgends eine Auswahl (D-36 Punkt 4). **Kein** Head wird
185
+ * bevorzugt; die UI zeigt den Fork und verlangt eine Entscheidung.
186
+ */
187
+ | {
188
+ kind: 'fork';
189
+ heads: readonly string[];
190
+ };
191
+ /** Eingaben der Auflösung. */
192
+ interface ResolvePreferredHeadOptions {
193
+ dag: VersionDag;
194
+ /**
195
+ * Kontext, in dem gearbeitet wird.
196
+ *
197
+ * `null` ist zulaessig und bedeutet **kontextlos** — nicht „egal". Der
198
+ * Serveraufrufer hat von Anfang an `null` durchgereicht; der Typ sagte
199
+ * `string` und verdeckte das, solange nur JavaScript ihn aufrief.
200
+ */
201
+ workingContextId: string | null;
202
+ /**
203
+ * Erbende Kontexte zwischen Arbeitskontext und besitzendem Kontext,
204
+ * **bereits nach `priority` sortiert** (höchste zuerst). Die Kette selbst
205
+ * liegt in der Zuständigkeit der Workspace-Domain, nicht hier.
206
+ */
207
+ inheritanceChain?: readonly string[];
208
+ /** Kontext, in dem das Element liegt. `null` = kontextloses Element. */
209
+ owningContextId?: string | null;
210
+ /** Alle bekannten Auswahlen dieses Elements, über alle Kontexte. */
211
+ selections?: readonly PreferredHeadSelection[];
212
+ }
213
+ /** Auflösung samt Befunden, die nicht das Ergebnis ändern, aber sichtbar gehören. */
214
+ interface PreferredHeadOutcome {
215
+ resolution: PreferredHeadResolution;
216
+ /**
217
+ * Auswahlen, die auf eine dem Graphen unbekannte Version zeigen. Sie werden
218
+ * übersprungen, damit die Kette weiterläuft — aber nicht verschwiegen: das ist
219
+ * ein Datenfehler, kein Normalfall.
220
+ */
221
+ ignoredSelections: readonly PreferredHeadSelection[];
222
+ }
223
+ /**
224
+ * Löst den Preferred Head entlang der Vererbungskette auf (D-36).
225
+ *
226
+ * Reihenfolge: eigener Kontext → erbende Kontexte nach `priority` → besitzender
227
+ * Kontext. Greift nirgends eine Auswahl und gibt es mehr als einen Head, ist das
228
+ * Ergebnis `fork` — **niemals** ein automatisch gewählter Head. Der zeitlich
229
+ * jüngste Head zu nehmen wäre `MAX(ts)` durch die Hintertür und genau der
230
+ * Fehler, den §2.5 abstellt.
231
+ */
232
+ declare function resolvePreferredHead(options: ResolvePreferredHeadOptions): PreferredHeadOutcome;
233
+ /**
234
+ * Die aufzulösende Version, oder `null`, wenn eine Entscheidung aussteht.
235
+ *
236
+ * Bequemlichkeit für Aufrufer, die nur den Erfolgsfall brauchen. `null` ist ein
237
+ * regulärer Zustand und **kein** Anlass, einen Head zu raten.
238
+ */
239
+ declare function preferredVersionId(resolution: PreferredHeadResolution): string | null;
240
+
241
+ /** Ein Kandidat der Suche, so wie ihn eine Meldung nennen können muss. */
242
+ interface TargetModelCandidate {
243
+ elementId: string;
244
+ contextId: string | null;
245
+ }
246
+ /**
247
+ * Ergebnis der Zielmodell-Auflösung.
248
+ *
249
+ * **Jeder Ausgang ist eigenständig.** Keiner fällt auf `null` zusammen, und
250
+ * keiner wird zu einem anderen vereinfacht: „nirgends vorhanden", „vorhanden,
251
+ * aber stillgelegt", „mehrdeutig" und „Fork" sind vier verschiedene Aussagen
252
+ * über den Bestand und verlangen vier verschiedene Meldungen.
253
+ */
254
+ type TargetModelResolution = {
255
+ kind: 'resolved';
256
+ elementId: string;
257
+ versionId: string;
258
+ payload: unknown;
259
+ contextId: string | null;
260
+ /** Glied der Kette, auf dem der Treffer lag. `0` = Arbeitskontext. */
261
+ chainIndex: number;
262
+ /** Wie die Version bestimmt wurde — unverändert aus `resolvePreferredHead`. */
263
+ head: PreferredHeadResolution;
264
+ /**
265
+ * Stillgelegte Kandidaten, die auf dem Weg übergangen wurden (E-7).
266
+ *
267
+ * Stilllegen ist Ausblenden (D-04): Der Kandidat verlässt den Suchraum,
268
+ * die Kette läuft weiter. **Aber nie still** — wer eine lokale
269
+ * Feinabstimmung stilllegt, bekommt fortan ein anderes Modell, und genau
270
+ * das steht hier.
271
+ */
272
+ shadowedRetired: readonly TargetModelCandidate[];
273
+ }
274
+ /** Nirgends in der Kette ein Kandidat — auch kein stillgelegter. */
275
+ | {
276
+ kind: 'not_found';
277
+ key: string;
278
+ chain: readonly (string | null)[];
279
+ }
280
+ /** Zwei sichtbare Kandidaten auf **demselben** Glied. Es wird keiner gewählt. */
281
+ | {
282
+ kind: 'ambiguous';
283
+ key: string;
284
+ chainIndex: number;
285
+ candidates: readonly TargetModelCandidate[];
286
+ }
287
+ /** Es gab Kandidaten, aber **alle** sind stillgelegt. Liste, kein Einzelwert. */
288
+ | {
289
+ kind: 'retired';
290
+ key: string;
291
+ candidates: readonly TargetModelCandidate[];
292
+ }
293
+ /** Der Kandidat hat mehrere Heads und nirgends eine greifende Auswahl (D-36). */
294
+ | {
295
+ kind: 'fork';
296
+ key: string;
297
+ elementId: string;
298
+ heads: readonly string[];
299
+ };
300
+ /** Eingabe der Auflösung. */
301
+ interface TargetModelQuery {
302
+ /** Der gesuchte `payload.key`, wörtlich aus `prompt_render_settings`. */
303
+ key: string;
304
+ /**
305
+ * Das **Shot-Element**. Sein Kontext ist der Arbeitskontext der
306
+ * Preferred-Head-Auflösung; zugleich wird geprüft, dass die übergebene Kette
307
+ * tatsächlich zu diesem Element gehört.
308
+ */
309
+ forElementId: string;
310
+ /**
311
+ * Wirksame Kontextkette aus `ContextChainPort.chainFor`: Arbeitskontext
312
+ * zuerst, dann die geerbten Kontexte nach `priority`, zuletzt `null` für
313
+ * global.
314
+ */
315
+ contextChain: readonly (string | null)[];
316
+ }
317
+ /** Der Lesezugriff, den die Auflösung braucht — mehr nicht. */
318
+ type TargetModelQueries = Pick<SzenenQueries, 'listElements' | 'getElement'>;
319
+ /**
320
+ * Löst `target_model_id` entlang der Kontextkette auf.
321
+ *
322
+ * Reihenfolge (§4.8.2 des Start-Events): Glied für Glied, das erste Glied mit
323
+ * einem sichtbaren Kandidaten gewinnt. Ein geerbter Zwischenkontext schlägt
324
+ * damit den globalen Fallback — „direkter Kontext plus global" wäre keine
325
+ * Kontextvererbung (D-04, D-36).
326
+ *
327
+ * Ein **technischer** Lesefehler wird unverändert weitergereicht und nie zu
328
+ * `not_found`: Das wäre eine fachliche Aussage über ein Zielmodell, das es
329
+ * vielleicht gibt (Grundsatzregel 5).
330
+ */
331
+ declare function resolveTargetModelOver(queries: TargetModelQueries, input: TargetModelQuery): Promise<QueryResult<TargetModelResolution>>;
332
+ /** Kette als lesbarer Text für Fehlermeldungen (Grundsatzregel 8). */
333
+ declare function showChain(chain: readonly (string | null)[]): string;
334
+ /**
335
+ * Meldung zu einem nicht auflösbaren Zielmodell.
336
+ *
337
+ * Eine Stelle, damit P-17 (S1b) und der Lauf denselben Text ausgeben — und
338
+ * damit jede Meldung die relevanten Werte nennt statt „nicht gefunden".
339
+ */
340
+ declare function describeTargetModelFailure(resolution: Exclude<TargetModelResolution, {
341
+ kind: 'resolved';
342
+ }>): string;
343
+
344
+ /** Schweregrad eines Befundes. */
345
+ type FindingSeverity =
346
+ /** Verhindert die Veröffentlichung. */
347
+ 'blocking'
348
+ /** Hinweis; die erklärte Absicht gewinnt (P-11, P-14). */
349
+ | 'advisory';
350
+ /** Ein Befund einer Publish-Prüfung. */
351
+ interface PublishFinding {
352
+ /** Regel-ID, z.B. `P-01`. */
353
+ rule: string;
354
+ severity: FindingSeverity;
355
+ /** JSON-Pointer auf die Stelle in der Payload, soweit bestimmbar. */
356
+ path: string;
357
+ message: string;
358
+ }
359
+ /** Eine veröffentlichte Version, wie die Prüfungen sie brauchen. */
360
+ interface ResolvedVersion {
361
+ version_id: string;
362
+ element_id: string;
363
+ type: SzenenElementType;
364
+ payload: unknown;
365
+ /** `false`, wenn die Version zwar existiert, aber nicht sichtbar ist (D-04). */
366
+ visible?: boolean;
367
+ /**
368
+ * Abstammung dieser Version. P-03 braucht sie, weil sich der Zustand einer
369
+ * `camera_id` (aktiv, entfernt, unbekannt) erst aus der **gesamten**
370
+ * erreichbaren Ahnenhistorie ergibt — nicht aus dem direkten Vorgänger.
371
+ *
372
+ * Fehlt das Feld, kann die Kette nicht weiterverfolgt werden; P-03 meldet
373
+ * das, statt einen unvollständigen Lauf als bestanden auszuweisen.
374
+ */
375
+ parents?: readonly {
376
+ parent_version_id: string;
377
+ relation: string;
378
+ }[];
379
+ }
380
+ /**
381
+ * Zugriff auf andere Versionen. Der Port, über den die referenzabhängigen
382
+ * Regeln arbeiten — kein Datenbankzugriff im Prüfcode (R-2).
383
+ */
384
+ interface ReferenceResolver {
385
+ /** Eine veröffentlichte Version, oder `null`, wenn unbekannt oder Draft. */
386
+ getVersion(versionId: string): Promise<ResolvedVersion | null>;
387
+ /**
388
+ * Löst `target_model_id` entlang der Kontextkette auf — Stufe 3, S1a.
389
+ *
390
+ * **Optional, und das ist die Aussage:** Die Auflösung braucht die
391
+ * Kontextkette, und die ist eine Workspace-Tatsache. Wer sie nicht
392
+ * beschaffen kann, bekommt die Operation nicht — statt einer Suche, die
393
+ * mangels Kette nur den eigenen Kontext sieht und ein `not_found` liefert,
394
+ * das keines ist. `resolverFromQueries` setzt sie deshalb nur, wenn ein
395
+ * `ContextChainPort` übergeben wurde.
396
+ *
397
+ * Konsument ist P-17 (S1b): Fehlt die Operation, führt die Regel sich als
398
+ * **ungeprüft** — dieselbe Mechanik wie bei einem fehlenden Resolver, und
399
+ * nie ein stilles Bestehen.
400
+ *
401
+ * Wirft bei technischen Lesefehlern, wie `getVersion` sie meldet.
402
+ */
403
+ resolveTargetModel?(key: string, forElementId: string): Promise<TargetModelResolution>;
404
+ }
405
+ /** Eingabe der Publish-Prüfung. */
406
+ interface PublishCheckInput {
407
+ type: SzenenElementType;
408
+ payload: unknown;
409
+ elementId: string;
410
+ /** Vorgänger im Versions-DAG; für P-03 und P-10. */
411
+ parents?: readonly {
412
+ parent_version_id: string;
413
+ relation: string;
414
+ }[];
415
+ /** Fehlt er, werden die referenzabhängigen Regeln als ungeprüft gemeldet. */
416
+ resolver?: ReferenceResolver;
417
+ }
418
+ interface PublishCheckResult {
419
+ /** `true`, wenn kein `blocking`-Befund vorliegt. */
420
+ ok: boolean;
421
+ findings: readonly PublishFinding[];
422
+ /** Regeln, die in diesem Lauf tatsächlich geprüft wurden. */
423
+ checked: readonly string[];
424
+ /** Regeln, die **nicht** geprüft werden konnten, mit Grund. */
425
+ unchecked: readonly {
426
+ rule: string;
427
+ reason: string;
428
+ }[];
429
+ }
430
+ /** Alle Regel-IDs, in der Reihenfolge aus `schemas/README.md`. */
431
+ declare const ALL_PUBLISH_RULES: readonly ["P-01", "P-02", "P-03", "P-04", "P-05", "P-06", "P-07", "P-08", "P-09", "P-10", "P-11", "P-12", "P-13", "P-14", "P-15", "P-16", "P-17"];
432
+ /**
433
+ * Führt die Publish-Prüfungen aus.
434
+ *
435
+ * @returns `ok: false`, sobald eine blockierende Regel greift. Hinweise
436
+ * (P-11, P-14) verhindern die Veröffentlichung **nicht**.
437
+ */
438
+ declare function runPublishChecks(input: PublishCheckInput): Promise<PublishCheckResult>;
439
+
440
+ /** Die Elementtypen, die eine Rekonstruktion vorschlagen kann (D-72). */
441
+ declare const DERIVABLE_TYPES: readonly ["scene", "scene_setup", "shot"];
442
+ type DerivableType = (typeof DERIVABLE_TYPES)[number];
443
+ /** Wie die Rekonstruktion angestoßen wurde. */
444
+ type DerivationInputMode = 'prompt' | 'image' | 'image_prompt';
445
+ /**
446
+ * Woher ein Eingabebild stammt — **das** wird eingefroren, nicht das Bild (D-73).
447
+ *
448
+ * Base64-Daten gehören nicht in das Ereignislog: es ist der autoritative
449
+ * Speicher (D-62) und wird in Flow-FA Pure vollständig geladen. Ein Log, das
450
+ * mit Bildern vollläuft, ist dort nicht mehr ladbar.
451
+ */
452
+ type ImageProvenance = {
453
+ kind: 'library';
454
+ media_ref: string;
455
+ mime_type: string;
456
+ } | {
457
+ kind: 'upload';
458
+ sha256: string;
459
+ bytes: number;
460
+ mime_type: string;
461
+ };
462
+ /** Ein Eingabebild: die Daten für den Lauf, die Herkunft für den Bestand. */
463
+ interface DerivationImage {
464
+ /** Base64, ohne `data:`-Praefix. Wird **nicht** gespeichert. */
465
+ data: string;
466
+ provenance: ImageProvenance;
467
+ }
468
+ /** Die Policy-Payload, so wie sie im Element steht (D-70). */
469
+ interface DerivationPolicyPayload {
470
+ key: string;
471
+ name: string;
472
+ text: string;
473
+ locale: string;
474
+ input_modes: readonly DerivationInputMode[];
475
+ produces: readonly DerivableType[];
476
+ node_granularity?: 'coarse' | 'normal' | 'fine';
477
+ allow_placement?: boolean;
478
+ forbidden_inventions?: readonly string[];
479
+ }
480
+ /**
481
+ * Eine wählbare, bereits veröffentlichte Version.
482
+ *
483
+ * Ein `scene_setup` braucht `preset_ref` auf ein Camera Preset, ein `shot`
484
+ * kann auf ein Shot Concept zeigen — beides Versionskennungen, die das Modell
485
+ * unmöglich wissen kann. Ohne Katalog bliebe ihm nur, sie zu erfinden, und
486
+ * eine erfundene UUID sieht aus wie eine echte.
487
+ *
488
+ * Deshalb bekommt es die Auswahl vorgelegt und darf **nur** daraus wählen.
489
+ * Was nicht im Katalog steht, ist kein gültiger Verweis (geprüft in
490
+ * `checkDerivationResponse`).
491
+ */
492
+ interface CatalogueEntry {
493
+ type: SzenenElementType;
494
+ element_id: string;
495
+ version_id: string;
496
+ /** Menschenlesbar, damit das Modell fachlich wählen kann statt nach UUID. */
497
+ title: string;
498
+ }
499
+ interface SceneDerivationInput {
500
+ policy: DerivationPolicyPayload;
501
+ /** Die veröffentlichte Policy-Version — sie friert die Regel ein (Konzept §8). */
502
+ policy_version_id: string;
503
+ mode: DerivationInputMode;
504
+ /** Der Referenzprompt, sofern es einen gibt. */
505
+ prompt_text: string | null;
506
+ images: readonly DerivationImage[];
507
+ /** Veröffentlichte Versionen, auf die ein Vorschlag zeigen darf. */
508
+ catalogue: readonly CatalogueEntry[];
509
+ }
510
+ /** Eine Angabe, die aus der Eingabe nicht ableitbar war (D-75). */
511
+ interface NotDerivable {
512
+ /** Wohin die Angabe gehört hätte, als JSON-Pointer oder Feldname. */
513
+ field: string;
514
+ reason: string;
515
+ }
516
+ /** Ein Widerspruch zwischen Bild und begleitendem Prompt (D-74). */
517
+ interface DerivationConflict {
518
+ field: string;
519
+ /** Was das Bild zeigt. */
520
+ from_image: string;
521
+ /** Was der Prompt behauptet. */
522
+ from_prompt: string;
523
+ }
524
+ /** Ein Vorschlag für genau einen Elementtyp. */
525
+ /**
526
+ * Eine benannte Fehlstelle in einem Vorschlag.
527
+ *
528
+ * `pointer` ist ein JSON-Pointer auf **genau** das fehlende Pflichtfeld, etwa
529
+ * `/camera_rig` oder `/camera_rig/cameras/0/preset_ref`. Er wird nicht frei
530
+ * formuliert, sondern gegen die Schemaprüfung abgeglichen: Die Menge der
531
+ * benannten Lücken muss der Menge der tatsächlich fehlenden Pflichtfelder
532
+ * entsprechen — Stelle für Stelle.
533
+ */
534
+ interface ProposalGap {
535
+ pointer: string;
536
+ reason: string;
537
+ }
538
+ /**
539
+ * Ein Rekonstruktionsvorschlag — **vollständig oder ausdrücklich teilweise**.
540
+ *
541
+ * Der Vertrag ist bewusst ein eigener und nicht „reguläre Payload, aber
542
+ * Pflichtfelder egal". Zwei Ebenen, die nicht vermischt werden dürfen:
543
+ *
544
+ * - Dass ein **Draft** unvollständig sein darf, ist eine Eigenschaft des
545
+ * Speichermodells (`checkWriteDraftInput` prüft nur Vorhandensein).
546
+ * - Was ein **gültiger Vorschlag** ist, ist Semantik der Stufe 6.5.
547
+ *
548
+ * Würde man das erste als Begründung fürs zweite nehmen, entstünde ein
549
+ * Sondervalidator — „das normale Schema gilt, ausser `required`, sofern
550
+ * irgendwo ein passender `not_derivable`-Eintrag steht". Bei verschachtelten
551
+ * Pflichtstrukturen wie `camera_rig.cameras[0].preset_ref.version_id` müsste
552
+ * dann definiert werden, welche Ebene als benannt genügt. Das wäre ein
553
+ * zweites, implizites Schemasystem.
554
+ *
555
+ * Stattdessen: `complete` erfüllt das **normale** Element-Schema unverändert.
556
+ * `partial` erfüllt es bis auf fehlende Pflichtfelder, und **jede** dieser
557
+ * Fehlstellen ist in `gaps` benannt. Kein schwächer validierter KI-Pfad —
558
+ * ein anderer, engerer Vertrag.
559
+ */
560
+ interface DerivationProposal {
561
+ type: DerivableType;
562
+ /** Reguläre Payload des Typs — dieselben Schemas wie bei Handarbeit. */
563
+ payload: Record<string, unknown>;
564
+ /**
565
+ * `complete`: erfüllt das reguläre Schema vollständig.
566
+ * `partial`: erfüllt es bis auf die in `gaps` benannten Pflichtfelder.
567
+ */
568
+ status: 'complete' | 'partial';
569
+ /** Leer bei `complete`; bei `partial` **exakt** die fehlenden Pflichtfelder. */
570
+ gaps: readonly ProposalGap[];
571
+ /**
572
+ * Namensvorschlag des Modells (D-83), schon getrimmt.
573
+ *
574
+ * Fehlt, wenn das Modell keinen brauchbaren geliefert hat — und zwar als
575
+ * **weggelassener Schlüssel**, nicht als `undefined`: Der Vorschlag reist
576
+ * einmal durch das Ereignislog und einmal durch REST, und ein Schlüssel mit
577
+ * `undefined` überlebt die JSON-Serialisierung nicht. Beide Hosts müssen
578
+ * denselben Datensatz erzeugen (`hostParity.test.ts`).
579
+ */
580
+ title?: string;
581
+ }
582
+ interface SceneDerivationOutput {
583
+ proposals: readonly DerivationProposal[];
584
+ /** Pflicht, wie `feedback` beim Prompt-Lauf (D-55): ohne Begründung nicht beurteilbar. */
585
+ feedback: string;
586
+ assumptions: readonly string[];
587
+ not_derivable: readonly NotDerivable[];
588
+ conflicts: readonly DerivationConflict[];
589
+ /**
590
+ * Die Antwort des Modells auf die Beanstandung eines Folgelaufs (D-90).
591
+ *
592
+ * **Optional, nie Pflicht** — dieselbe Begründung wie beim Titel: Ein neues
593
+ * Pflichtfeld ist eine neue Möglichkeit, einen bezahlten Lauf zu verlieren
594
+ * (D-84). Sie darf ausdrücklich ein *Widerspruch* sein: Unsere Beanstandung
595
+ * kann unbegründet sein, und dann ist die Antwort des Modells das
596
+ * Wertvollste am ganzen Lauf.
597
+ */
598
+ reply?: string;
599
+ }
600
+ /**
601
+ * Woraus ein Lauf folgt (D-88).
602
+ *
603
+ * Ein Folgelauf ist ein **eigener** Lauf, kein zweiter Versuch im selben: Ein
604
+ * Laufsatz ist unveränderlich (D-71) und längst geschrieben, wenn der Mensch
605
+ * gefragt wird, ob ein Korrektur- oder Ergänzungslauf folgen soll.
606
+ *
607
+ * Die vorige **Antwort** steht hier nicht — sie liegt im Vorgängerlauf und ist
608
+ * über `run_id` auffindbar. Sie zu verdoppeln hieße, dieselbe (und größte)
609
+ * Zeichenkette zweimal zu pflegen (R-2).
610
+ */
611
+ interface DerivationFollowUp {
612
+ run_id: string;
613
+ /** Die Beanstandung, die dem Modell vorgelegt wurde — wörtlich. */
614
+ note: string;
615
+ /** Die zusätzliche Anweisung des Nutzers, sofern er eine gab. */
616
+ user_instruction: string | null;
617
+ }
618
+ /** Warum ein Lauf gescheitert ist — dieselben Klassen wie beim Prompt-Lauf. */
619
+ type DerivationFailureClass = 'response_parse' | 'response_schema' | 'safety_blocked' | 'finish_reason' | 'empty_content' | 'provider_error';
620
+ /**
621
+ * Ein maschinenlesbarer Befund an einer Antwort (A1 der Stufe 6.6).
622
+ *
623
+ * Bis 6.5 trug ein Fehlschlag nur `failure.message` — einen Satz für Menschen.
624
+ * Für die Fehlerrettung reicht das nicht: Die Ansicht muss sagen können,
625
+ * *welcher* Vorschlag *welches* Feld verletzt, ohne dafür Meldungstexte zu
626
+ * zerlegen. Ein geparster Fehlertext ist eine Schnittstelle, die niemand
627
+ * gepflegt hat und die beim nächsten Umformulieren bricht.
628
+ *
629
+ * `message` bleibt menschenlesbar und wortgleich zu dem, was `failure.message`
630
+ * schon immer sagte — die Diagnose ist die **Ergänzung**, nicht der Ersatz.
631
+ */
632
+ interface DerivationDiagnostic {
633
+ /** Stabile Kennung, z. B. `proposal.schema_violation`. Nie übersetzt. */
634
+ code: string;
635
+ severity: 'error' | 'warning';
636
+ /** Für Menschen. Sprache folgt dem Code, nicht `locale` (es ist unsere Meldung). */
637
+ message: string;
638
+ /** Der betroffene Vorschlag, sofern der Befund einem zuzuordnen ist. */
639
+ proposal_type?: DerivableType;
640
+ /** JSON-Pointer auf die betroffene Stelle, sofern bekannt. */
641
+ pointer?: string;
642
+ /** Bei Parsefehlern: Position im Rohtext, 1-basiert. */
643
+ line?: number;
644
+ column?: number;
645
+ }
646
+ interface DerivationFailure {
647
+ class: DerivationFailureClass;
648
+ message: string;
649
+ provider_detail?: unknown;
650
+ /**
651
+ * Die strukturierte Fassung von `message` und allem, was daneben noch
652
+ * auffiel (6.6/A1). Fehlt bei Läufen von vor 6.6 — der Leser darf sie
653
+ * deshalb nie voraussetzen.
654
+ */
655
+ diagnostics?: readonly DerivationDiagnostic[];
656
+ }
657
+ /** Ein Vorschlag, der seinen Vertrag **nicht** erfüllt, mit dem Grund dafür. */
658
+ interface UnusableProposal {
659
+ type: DerivableType;
660
+ diagnostics: readonly DerivationDiagnostic[];
661
+ }
662
+ /** Alles an einer Antwort außer den Vorschlägen — soweit es gültig war. */
663
+ interface DerivationEnvelope {
664
+ feedback: string;
665
+ assumptions: readonly string[];
666
+ not_derivable: readonly NotDerivable[];
667
+ conflicts: readonly DerivationConflict[];
668
+ reply?: string;
669
+ }
670
+ /**
671
+ * Die **Bewertung** einer geparsten Antwort — ohne Urteil über den Lauf
672
+ * (A2 der Stufe 6.6).
673
+ *
674
+ * Bis 6.5 fielen beide Fragen zusammen: `checkDerivationResponse()` prüfte und
675
+ * entschied in einem Zug, und die erste Vertragsverletzung beendete alles.
676
+ * Für einen bezahlten Lauf, dessen Antwort teilweise brauchbar ist, war das
677
+ * fatal — ein einziger Formfehler im `shot` warf auch die gültige `scene` weg.
678
+ *
679
+ * Diese Funktion trennt die Fragen. Sie sagt, **was an der Antwort dran ist**:
680
+ * welche Vorschläge ihren Vertrag erfüllen, welche nicht und warum, und was
681
+ * an der Hülle verletzt ist. Ob daraus ein `succeeded`- oder ein
682
+ * `failed`-Lauf wird, entscheidet danach `checkDerivationResponse()` — und
683
+ * zwar unverändert streng (D-100 lockert die Laufsemantik nicht, sie macht das
684
+ * Material danach verwertbar).
685
+ */
686
+ interface DerivationAssessment {
687
+ /**
688
+ * **Jeder** Befund, in genau der Reihenfolge, in der geprüft wurde.
689
+ *
690
+ * Die Reihenfolge ist Vertrag, nicht Zufall: `checkDerivationResponse()`
691
+ * meldet den ersten Fehler, und der muss derselbe bleiben wie vor 6.6 —
692
+ * sonst änderte sich die Meldung bereits abgenommener Läufe.
693
+ */
694
+ diagnostics: readonly DerivationDiagnostic[];
695
+ /** Vorschläge, die den Proposal-Vertrag aus D-82/D-86 erfüllen. */
696
+ usable: readonly DerivationProposal[];
697
+ /**
698
+ * Vorschläge, die ihn verletzen. Die Befunde sind dieselben Objekte wie in
699
+ * `diagnostics` — nach Vorschlag gruppiert, nicht kopiert.
700
+ */
701
+ unusable: readonly UnusableProposal[];
702
+ /**
703
+ * Hülleninhalt, soweit lesbar. `null` heißt: Die Antwort war so kaputt, dass
704
+ * nicht einmal `feedback` und `proposals` zu finden waren — dann gibt es
705
+ * auch nichts zu retten.
706
+ */
707
+ envelope: DerivationEnvelope | null;
708
+ /**
709
+ * Erfüllt die Antwort den vollständigen 6.5-Vertrag? Genau dann, wenn kein
710
+ * Befund die Schwere `error` trägt.
711
+ */
712
+ contract_ok: boolean;
713
+ }
714
+ type SceneDerivationOutcome = {
715
+ status: 'succeeded';
716
+ output: SceneDerivationOutput;
717
+ raw_output: string;
718
+ model_id: string;
719
+ provider: string;
720
+ } | {
721
+ status: 'failed';
722
+ failure: DerivationFailure;
723
+ raw_output: string | null;
724
+ model_id: string;
725
+ provider: string;
726
+ };
727
+ /**
728
+ * Platzhalter für eine noch nicht existierende Referenz.
729
+ *
730
+ * `scene_setup` referenziert eine Szenen**version**, `shot` ein Setup — und
731
+ * `versionRef` verlangt eine `version_id`, Draft-Referenzen sind unzulässig
732
+ * (D-03). Zum Zeitpunkt des Vorschlags gibt es diese Versionen noch nicht:
733
+ * die Szene ist bestenfalls ein Entwurf.
734
+ *
735
+ * Damit ein Vorschlag trotzdem **sofort** gegen sein Schema geprüft werden
736
+ * kann — und nicht erst Minuten später bei der Übernahme —, wird für die
737
+ * Prüfung diese Kennung eingesetzt. Sie wird **nie gespeichert**: der
738
+ * Vorschlag im Laufsatz trägt das Referenzfeld gar nicht, und bei der
739
+ * Übernahme setzt der Server die echte, veröffentlichte Version ein und prüft
740
+ * erneut. Das ist die maßgebliche Prüfung; diese hier ist die frühe.
741
+ */
742
+ declare const PROBE_VERSION_ID = "00000000-0000-0000-0000-000000000000";
743
+ /** Welches Referenzfeld ein Typ braucht, und auf welchen Typ es zeigt. */
744
+ declare const REFERENCE_FIELD: Partial<Record<DerivableType, {
745
+ field: string;
746
+ refersTo: DerivableType;
747
+ }>>;
748
+ /**
749
+ * Setzt eine Referenz in eine Vorschlagspayload ein.
750
+ *
751
+ * Wird zweimal gebraucht: mit der Probe für die frühe Prüfung und mit der
752
+ * echten Version bei der Übernahme. **Eine** Funktion für beides, damit die
753
+ * geprüfte und die gespeicherte Form nicht auseinanderlaufen können.
754
+ */
755
+ declare function withReference(type: DerivableType, payload: Record<string, unknown>, reference: {
756
+ element_id: string;
757
+ version_id: string;
758
+ } | null): Record<string, unknown>;
759
+ /**
760
+ * Der Systemprompt der Rekonstruktion.
761
+ *
762
+ * Mitgespeichert wie beim Prompt-Lauf (D-22): Ändert er sich, ist an einem
763
+ * alten Lauf noch erkennbar, unter welchen Annahmen er entstand.
764
+ */
765
+ declare function buildSystemInstruction(input: SceneDerivationInput): string;
766
+ /** Die Nutzernachricht: der Referenzprompt, sonst der Arbeitsauftrag. */
767
+ declare function buildUserPrompt(input: SceneDerivationInput): string;
768
+ /**
769
+ * Prüft die Eingabe, **bevor** ein Modell gerufen wird.
770
+ *
771
+ * Ein Lauf ohne Eingabe oder mit einer Policy, die diesen Eingang gar nicht
772
+ * abdeckt, ist kein Modellfehler — er darf nicht als Lauf mit Fehlerdiagnose
773
+ * im Bestand landen und schon gar nichts kosten.
774
+ */
775
+ declare function validateDerivationInput(input: SceneDerivationInput): string | null;
776
+ /**
777
+ * Sammelt jeden Verweis auf eine Elementversion aus einer Payload, beliebig tief.
778
+ *
779
+ * Erkannt wird die Form, die `common.schema.json#/$defs/versionRef` und seine
780
+ * Verwandten (`componentRef`, `styleRef`) alle teilen: ein Objekt mit
781
+ * `element_id` **und** `version_id` als Zeichenketten. Die Suche ist bewusst
782
+ * strukturell und nicht an Feldnamen gebunden — eine Liste bekannter Namen
783
+ * würde beim nächsten Schema still unvollständig.
784
+ */
785
+ declare function collectVersionRefs(value: unknown): readonly {
786
+ element_id: string;
787
+ version_id: string;
788
+ }[];
789
+ /**
790
+ * Löst das JSON aus dem Text — wortgleich zum Prompt-Lauf und aus demselben
791
+ * Grund: die für Prosa gedachte Bereinigung darf ein JSON-Dokument nicht
792
+ * anfassen (D-56). Erlaubt ist einzig das Auspacken eines Codeblocks.
793
+ */
794
+ declare function parseDerivationResponse(raw: string): {
795
+ ok: true;
796
+ value: unknown;
797
+ } | {
798
+ ok: false;
799
+ message: string;
800
+ diagnostic: DerivationDiagnostic;
801
+ };
802
+ /**
803
+ * **Bewertet** die geparste Antwort, ohne über den Lauf zu urteilen (6.6/A2).
804
+ *
805
+ * Bis 6.5 waren Bewertung und Urteil dieselbe Funktion, und die erste
806
+ * Vertragsverletzung beendete beides. Ein einziger Formfehler im `shot` warf
807
+ * damit auch eine tadellose `scene` weg — bei einem bereits bezahlten Lauf ist
808
+ * das der teuerste denkbare Ausgang.
809
+ *
810
+ * Hier wird deshalb nur noch festgestellt, **was an der Antwort dran ist**:
811
+ * jeder Vorschlag unabhängig gegen seinen Vertrag (D-82, D-86), die Hülle
812
+ * getrennt davon, und jeder Befund maschinenlesbar (D-100 Regel 1 und 4).
813
+ * Ob daraus ein `failed`-Lauf wird, entscheidet `checkDerivationResponse()`
814
+ * unverändert streng.
815
+ *
816
+ * Die **Reihenfolge** der Befunde ist die alte Prüfreihenfolge. Nur so bleibt
817
+ * der erste Fehler derselbe wie vor 6.6.
818
+ */
819
+ declare function assessDerivationResponse(value: unknown, input: SceneDerivationInput): DerivationAssessment;
820
+ /**
821
+ * Prüft die geparste Antwort — Struktur, Pflichtdiagnosen und **jede
822
+ * Vorschlagspayload gegen ihr echtes Schema**.
823
+ *
824
+ * Der letzte Punkt ist der Kern von 6.5-C: Es gibt keinen schwächer
825
+ * validierten AI-Pfad. Was hier nicht durchkommt, wird nicht still repariert,
826
+ * sondern ist ein Lauf mit Fehlerklasse `response_schema`.
827
+ *
828
+ * Seit 6.6 ist das nur noch das **Urteil**; die Prüfarbeit steht in
829
+ * `assessDerivationResponse()`. Die Strenge ist unverändert: Genau die
830
+ * Antworten, die vor 6.6 `failed` waren, sind es weiterhin (A2). Neu ist
831
+ * allein, dass die Bewertung daneben erhalten bleibt und in der Fehlerrettung
832
+ * weiterverwendet werden kann.
833
+ */
834
+ declare function checkDerivationResponse(value: unknown, input: SceneDerivationInput): {
835
+ ok: true;
836
+ output: SceneDerivationOutput;
837
+ } | {
838
+ ok: false;
839
+ message: string;
840
+ diagnostics: readonly DerivationDiagnostic[];
841
+ };
842
+ /**
843
+ * Ein deterministischer Port ohne Provider — für Tests **und** für eine
844
+ * ausdrücklich angeforderte Simulation in der Entwicklung.
845
+ *
846
+ * Er ist nie ein Rückfall: Wer ihn benutzt, hat ihn gewählt, und der
847
+ * gespeicherte Lauf trägt `provider: 'simulation'`. Die Antwort läuft durch
848
+ * denselben Parser und dieselbe Schemaprüfung wie eine echte — eine
849
+ * Simulation, die die Prüfungen umginge, wiese nichts nach.
850
+ *
851
+ * Er bekommt die Eingabe **ausdrücklich übergeben**, weil er anders als beim
852
+ * Prompt-Lauf nicht aus der Nutzernachricht ablesen kann, was verlangt ist:
853
+ * dort ist sie die Renderer-Eingabe als JSON, hier freier Text.
854
+ *
855
+ * Was er nicht ehrlich bauen kann, baut er nicht: Ein `scene_setup` braucht
856
+ * mindestens ein Camera Preset aus dem Katalog. Fehlt es, scheitert die
857
+ * Simulation laut, statt eine Payload zu erfinden, die am Schema vorbeiginge.
858
+ */
859
+ declare function createSimulationSceneDerivationPort(input: SceneDerivationInput): TextGenerationPort;
860
+ /**
861
+ * Führt den Rekonstruktionslauf aus.
862
+ *
863
+ * Gibt **immer** ein Ergebnis zurück — `succeeded` oder `failed`. Ein
864
+ * technischer Ausfall des Ports (Netz, fehlende Konfiguration) wirft dagegen:
865
+ * er ist kein Lauf, sondern ein Betriebsfehler und darf nicht als „das Modell
866
+ * hat abgelehnt" im Bestand stehen.
867
+ */
868
+ declare function runSceneDerivation(input: SceneDerivationInput, port: TextGenerationPort,
869
+ /**
870
+ * Ersetzt die Nutzernachricht. Der Folgelauf schickt seine eigene (D-89) —
871
+ * dieselbe Regel, dieselben Schemas, nur ein anderer Auftrag im Gespräch.
872
+ */
873
+ userPrompt?: string): Promise<SceneDerivationOutcome & {
874
+ system_prompt: string;
875
+ }>;
876
+
877
+ /** Die Felder, über die ein Kettenknoten auf einen anderen zeigt. */
878
+ declare const CHAIN_LINK_FIELDS: readonly ["scene_ref", "scene_setup_ref"];
879
+ type ChainLinkField = (typeof CHAIN_LINK_FIELDS)[number];
880
+ /**
881
+ * Welche Kante 6.6 zulässt — und **nur** diese beiden.
882
+ *
883
+ * Bewusst eine Tabelle und keine freie Kantenmenge: Ein Graph, der alles
884
+ * erlaubt, verlangt einen Zykluscheck und eine Erreichbarkeitsanalyse. Die
885
+ * fachliche Kette hat genau zwei Kanten (`domain-model.md` §2), und mehr zu
886
+ * ermöglichen hieße, eine Allgemeinheit zu bauen, die niemand bestellt hat.
887
+ */
888
+ declare const CHAIN_EDGES: Readonly<Record<ChainLinkField, {
889
+ /** Der Typ, der das Feld trägt. */
890
+ from: DerivableType;
891
+ /** Der Typ, auf den es zeigt. */
892
+ to: DerivableType;
893
+ }>>;
894
+ /** Ein kettenintern geführter Verweis auf einen anderen Draft derselben Kette. */
895
+ interface DraftChainLink {
896
+ field: ChainLinkField;
897
+ target_element_id: string;
898
+ /**
899
+ * Die Draft-Kennung des Zielknotens.
900
+ *
901
+ * Dass sie über Revisionen stabil bleibt, ist in `draftIdentity.test.ts` und
902
+ * im Port-Vertrag belegt (Gate B0) — für HF **und** MySQL. Ohne diesen
903
+ * Nachweis wäre der Link wertlos.
904
+ */
905
+ target_draft_id: string;
906
+ }
907
+ /** Die Kettenmetadaten eines einzelnen Drafts. */
908
+ interface DraftChainMeta {
909
+ /** Gemeinsame Kennung aller Knoten **einer** Übernahme. */
910
+ chain_id: string;
911
+ /** Der Rekonstruktionslauf, aus dem die Vorschläge stammen. */
912
+ source_run_id: string;
913
+ /** Gesetzt, wenn der Inhalt aus einer geprüften Arbeitsfassung kam (D-99). */
914
+ source_recovery_id?: string;
915
+ links: readonly DraftChainLink[];
916
+ }
917
+ type ChainVerdict = {
918
+ ok: true;
919
+ } | {
920
+ ok: false;
921
+ message: string;
922
+ };
923
+ /**
924
+ * Prüft Kettenmetadaten für sich genommen — Form, erlaubte Kanten, keine
925
+ * Dubletten.
926
+ *
927
+ * Was hier **nicht** geprüft werden kann: ob das Ziel existiert und ob es
928
+ * dieselbe `chain_id` trägt. Das weiß nur der Speicher, und dort steht die
929
+ * Prüfung auch (`checkChainTargets`). Diese Funktion hier behauptet nicht mehr,
930
+ * als sie wissen kann.
931
+ *
932
+ * @param type Der Elementtyp des Drafts, an dem die Metadaten hängen. Ohne ihn
933
+ * ließe sich nicht sagen, ob eine Kante an dieser Stelle überhaupt zulässig
934
+ * ist — ein `scene`-Draft mit einem `scene_ref` wäre Unsinn.
935
+ */
936
+ declare function checkDraftChainMeta(meta: unknown, type: string | null): ChainVerdict;
937
+ /** Was der Speicher über ein Linkziel wissen muss, um es zu beurteilen. */
938
+ interface ChainTarget {
939
+ element_id: string;
940
+ /** Der Elementtyp des Ziels, oder `null`, wenn es das Element nicht gibt. */
941
+ type: string | null;
942
+ /** Der aktuelle Draft des Ziels, oder `null` — kein Draft, kein Ziel. */
943
+ draft: {
944
+ draft_id: string;
945
+ chain_id: string | null;
946
+ } | null;
947
+ }
948
+ /**
949
+ * Prüft die Links gegen die tatsächlichen Ziele.
950
+ *
951
+ * Drei Ablehnungen, und jede hat einen eigenen Grund:
952
+ *
953
+ * * **Ziel fehlt** — ein Link ins Leere ist schlimmer als kein Link, weil er
954
+ * aussieht, als gäbe es etwas.
955
+ * * **Falscher Typ** — ein `scene_ref` auf einen `shot` ergäbe beim Einfrieren
956
+ * eine Renderer-Eingabe, die niemand gemeint hat.
957
+ * * **Fremde Kette** — der Kern von D-96. Ein Link über Kettengrenzen hinweg
958
+ * hebelt die Zusage aus, dass eine Kette **eine** Übernahme ist; das
959
+ * Einfrieren wüsste dann nicht mehr, welchen Umfang es einfriert.
960
+ */
961
+ declare function checkChainTargets(meta: DraftChainMeta, targets: readonly ChainTarget[]): ChainVerdict;
962
+ /** Der Link eines Feldes, oder `null`. */
963
+ declare function linkFor(meta: DraftChainMeta | null | undefined, field: ChainLinkField): DraftChainLink | null;
964
+
965
+ /** Element-Stammsatz (`elements`, §2.1). Nach Anlage unveränderlich: `id`, `type`. */
966
+ interface ElementRecord {
967
+ element_id: string;
968
+ /** Lesbarer Stammtitel fuer Listen und Auswahlen; kein Versionsinhalt (D-35). */
969
+ title?: string;
970
+ type: SzenenElementType;
971
+ subtype: string | null;
972
+ /** Kontext, in dem das Element liegt. `null` = global. */
973
+ context_id: string | null;
974
+ retired: boolean;
975
+ }
976
+ /**
977
+ * Elementmetadaten (`element_metadata`, §2.2).
978
+ *
979
+ * Der Titel ist **kein Versionsinhalt** (D-35): eine Umbenennung erzeugt weder
980
+ * eine neue Version noch ein Update-Angebot.
981
+ */
982
+ interface ElementMetadata {
983
+ element_id: string;
984
+ title: string;
985
+ description: string | null;
986
+ /** Autorensprache des Titels. */
987
+ locale: string;
988
+ revision: number;
989
+ }
990
+ /** Veröffentlichte Elementversion (`element_versions`, §2.3). Unveränderlich (D-02). */
991
+ interface PublishedVersion extends VersionNode {
992
+ schema_version: string;
993
+ payload: unknown;
994
+ published_by: string;
995
+ }
996
+ /** Entwurf (`element_drafts`, §3). Veränderlich und **nicht** referenzierbar. */
997
+ interface DraftRecord {
998
+ draft_id: string;
999
+ element_id: string;
1000
+ base_version_id: string | null;
1001
+ payload: unknown;
1002
+ revision: number;
1003
+ updated_by_client: string;
1004
+ /**
1005
+ * Kettenmetadaten, falls dieser Draft Teil einer Draft-Kette ist (D-96).
1006
+ *
1007
+ * **Additiv und optional.** Ein Draft ohne dieses Feld ist ein gewöhnlicher
1008
+ * Einzelentwurf und verhält sich wie vor 6.6 — jeder Bestandsdraft ist
1009
+ * genau das. Wer das Feld voraussetzt, bricht die Altdaten.
1010
+ *
1011
+ * Es liegt bewusst **neben** der Payload: Die Payload ist das, was
1012
+ * veröffentlicht wird, und sie trägt an den Referenzstellen weiterhin keine
1013
+ * erfundene `version_id` (D-95).
1014
+ */
1015
+ chain?: DraftChainMeta;
1016
+ }
1017
+ /**
1018
+ * Ein Entwurf, den mehrere Clients gleichzeitig auf derselben Revision
1019
+ * fortgeschrieben haben (D-29: „parallele Draft-Heads werden auf HF-Seite
1020
+ * sichtbar gemacht").
1021
+ */
1022
+ interface DraftFork {
1023
+ element_id: string;
1024
+ revision: number;
1025
+ /** Die konkurrierenden Stände, einer je schreibendem Client. */
1026
+ candidates: readonly DraftRecord[];
1027
+ }
1028
+ /** Vollständiger Stand eines Elements, wie ihn ein Editor braucht. */
1029
+ interface ElementSnapshot {
1030
+ element: ElementRecord;
1031
+ metadata: ElementMetadata | null;
1032
+ /** Alle veröffentlichten Versionen. Eingang in `buildVersionDag`. */
1033
+ versions: readonly PublishedVersion[];
1034
+ /** Aktueller Entwurf, falls einer existiert. */
1035
+ draft: DraftRecord | null;
1036
+ /** Gesetzt, wenn mehrere Clients denselben Entwurf gleichzeitig fortgeschrieben haben. */
1037
+ draftFork: DraftFork | null;
1038
+ /** Preferred-Head-Auswahlen über alle Kontexte (§2.6). */
1039
+ preferredHeads: readonly PreferredHeadSelection[];
1040
+ }
1041
+ /**
1042
+ * Konflikt beim Schreiben mit erwarteter Revision (§3.1).
1043
+ *
1044
+ * **Kein Fehler, sondern ein regulärer Ausgang.** Die Regel lautet: kein stilles
1045
+ * Last-Write-Wins. Der Aufrufer bekommt die aktuelle Revision und den aktuellen
1046
+ * Stand und entscheidet zwischen Verwerfen, Übernehmen und Zusammenführen.
1047
+ */
1048
+ interface WriteConflict<T> {
1049
+ kind: 'conflict';
1050
+ expectedRevision: number;
1051
+ actualRevision: number;
1052
+ current: T;
1053
+ }
1054
+ /**
1055
+ * Eine Veröffentlichung, die an der Validierung gescheitert ist.
1056
+ *
1057
+ * Getrennt von `error`, weil es kein technisches Problem ist, sondern eine
1058
+ * fachliche Ablehnung mit einer Befundliste, die die UI anzeigen soll.
1059
+ */
1060
+ interface PublishRejected {
1061
+ kind: 'rejected';
1062
+ errors: readonly SchemaError[];
1063
+ /**
1064
+ * Prüfungen, die dieser Port nicht durchführen konnte. Solange
1065
+ * P-01…P-16 nicht implementiert sind, steht hier deren Kennung —
1066
+ * damit niemand `ok` für eine vollständige Freigabe hält.
1067
+ */
1068
+ unchecked: readonly string[];
1069
+ }
1070
+ /** Ergebnis eines Szenen-Kommandos: die Standardfälle plus Konflikt und Ablehnung. */
1071
+ type SzenenCommandResult<T, C = T> = CommandResult<T> | WriteConflict<C> | PublishRejected;
1072
+ /** Lesezugriffe auf den Elementspeicher. */
1073
+ interface SzenenQueries {
1074
+ /** Alle Elemente eines Kontexts, optional nach einem Typ oder einer Typmenge gefiltert. */
1075
+ listElements(filter?: {
1076
+ contextId?: string | null;
1077
+ type?: SzenenElementType;
1078
+ types?: readonly SzenenElementType[];
1079
+ includeRetired?: boolean;
1080
+ }): Promise<QueryResult<readonly ElementRecord[]>>;
1081
+ /** Vollständiger Stand eines Elements, oder `null`, wenn unbekannt. */
1082
+ getElement(elementId: string): Promise<QueryResult<ElementSnapshot | null>>;
1083
+ /**
1084
+ * Eine **veröffentlichte** Version, so wie die Publish-Prüfungen sie
1085
+ * brauchen — oder `null`, wenn die Kennung unbekannt ist oder nur zu einem
1086
+ * Entwurf gehört. Entwürfe sind nie referenzierbar (D-03).
1087
+ *
1088
+ * Der Grund für diese Operation im Lesevertrag (D-67): Ohne sie kommt kein
1089
+ * Aufrufer an einen `ReferenceResolver` und kann die referenzabhängigen
1090
+ * Regeln **vor** dem Schreiben nicht laufen lassen. `resolverOver()` im
1091
+ * HF-Speicher ist privat und läuft nur intern beim Veröffentlichen.
1092
+ *
1093
+ * Rückgabetyp ist `ResolvedVersion` und nicht `PublishedVersion`: Die
1094
+ * Prüfungen brauchen `type` und `visible`, und beide hängen am **Element**,
1095
+ * nicht an der Version.
1096
+ *
1097
+ * Ein stillgelegtes Element liefert die Version mit `visible: false` —
1098
+ * nicht `null`. Stilllegen ist Ausblenden, kein Löschen (D-04), und P-04
1099
+ * muss den Unterschied zwischen „unbekannt" und „unsichtbar" melden können.
1100
+ */
1101
+ getVersion(versionId: string): Promise<QueryResult<ResolvedVersion | null>>;
1102
+ /**
1103
+ * Löst `shot.prompt_render_settings.target_model_id` entlang der
1104
+ * Kontextkette auf — Stufe 3, S1a.
1105
+ *
1106
+ * Der Grund für diese Operation im Lesevertrag: `target_model_id` ist ein
1107
+ * freier String und keine `versionRef`. P-17 (beim Veröffentlichen) und der
1108
+ * Prompt-Ableitungslauf müssen **dieselbe** Auflösung sehen; stünde sie in
1109
+ * einem der Speicher, gäbe es zwei.
1110
+ *
1111
+ * Die **Kette** kommt von außen (`ContextChainPort`) und wird nicht hier
1112
+ * abgeleitet: Sie steht in `contexts`/`context_inheritance` und damit in
1113
+ * MySQL. Ein Elementspeicher, der sie selbst ermittelte, wäre in Flow-FA
1114
+ * Pure nicht erfüllbar.
1115
+ */
1116
+ resolveTargetModel(input: TargetModelQuery): Promise<QueryResult<TargetModelResolution>>;
1117
+ }
1118
+ /**
1119
+ * Die wirksame Kontextkette — **eigener Port**, weil die Vererbung nicht der
1120
+ * Szenen-Domain gehört.
1121
+ *
1122
+ * Sie liegt in `contexts` und `context_inheritance` (Workspace-Domain), wird
1123
+ * dort nach `priority` aufgelöst und ist für die Szenen-Domain eine Eingabe wie
1124
+ * jede andere. Ein Host ohne Kontextgraph liefert `[eigenerKontext, null]` —
1125
+ * das ist dort keine verkürzte Vererbung, sondern die vollständige. Damit der
1126
+ * Unterschied nicht unsichtbar bleibt, friert der Prompt-Lauf die verwendete
1127
+ * Kette ein.
1128
+ */
1129
+ interface ContextChainPort {
1130
+ /**
1131
+ * Arbeitskontext zuerst, dann die geerbten Kontexte nach `priority`,
1132
+ * zuletzt `null` für global. `null` ist immer das letzte Glied.
1133
+ */
1134
+ chainFor(contextId: string | null): Promise<QueryResult<readonly (string | null)[]>>;
1135
+ }
1136
+ /**
1137
+ * Macht aus einem Lese-Port den `ReferenceResolver` der Publish-Prüfungen.
1138
+ *
1139
+ * Bewusst klein und ohne Kenntnis der Command-Varianten: `SzenenQueries` ist
1140
+ * der Lesevertrag, dort gibt es weder `conflict` noch `rejected`.
1141
+ *
1142
+ * **Ein technischer Lesefehler wirft.** Er wird nicht zu `null`, denn `null`
1143
+ * hieße für P-04 „diese Version ist nicht veröffentlicht" — eine fachliche
1144
+ * Aussage über eine Referenz, die einwandfrei sein kann. Eine kaputte
1145
+ * Datenbankverbindung darf keinen Publish-Blocker erfinden (Grundsatzregel 5).
1146
+ */
1147
+ declare function resolverFromQueries(queries: SzenenQueries, contexts?: ContextChainPort): ReferenceResolver;
1148
+ /** Eingabe zum Anlegen eines Elements. */
1149
+ interface CreateElementInput {
1150
+ type: SzenenElementType;
1151
+ subtype?: string | null;
1152
+ contextId?: string | null;
1153
+ title: string;
1154
+ description?: string | null;
1155
+ locale?: string;
1156
+ }
1157
+ /** Eingabe zum Schreiben eines Entwurfs. */
1158
+ interface WriteDraftInput {
1159
+ elementId: string;
1160
+ payload: unknown;
1161
+ /** Version, auf der der Entwurf aufsetzt. `null` bei der ersten Version. */
1162
+ baseVersionId?: string | null;
1163
+ /**
1164
+ * Kettenmetadaten setzen oder fortschreiben (D-96).
1165
+ *
1166
+ * Weggelassen heißt **unverändert lassen**, nicht löschen: Wer eine Payload
1167
+ * fortschreibt, soll die Kette seines Drafts nicht versehentlich kappen.
1168
+ * `null` löscht sie ausdrücklich — der Draft wird dann wieder ein
1169
+ * gewöhnlicher Einzelentwurf.
1170
+ */
1171
+ chain?: DraftChainMeta | null;
1172
+ /**
1173
+ * Erwartete Revision des Entwurfs. `0` heißt: es soll noch keinen geben.
1174
+ * Weicht sie ab, ist das Ergebnis ein `conflict` — nie ein stiller Überschreiber.
1175
+ */
1176
+ expectedRevision: number;
1177
+ }
1178
+ /** Eingabe zum Veröffentlichen einer Version. */
1179
+ interface PublishVersionInput {
1180
+ elementId: string;
1181
+ payload: unknown;
1182
+ schemaVersion: string;
1183
+ /** Vorgänger im Versions-DAG. Leer bei der ersten Version. */
1184
+ parents?: readonly {
1185
+ parent_version_id: string;
1186
+ relation: 'derived_from' | 'merged_from';
1187
+ }[];
1188
+ publishedBy: string;
1189
+ }
1190
+ /** Eingabe zum Setzen des Preferred Head. */
1191
+ interface SetPreferredHeadInput {
1192
+ elementId: string;
1193
+ contextId: string;
1194
+ versionId: string;
1195
+ expectedRevision: number;
1196
+ selectedBy: string;
1197
+ }
1198
+ /**
1199
+ * Eingabe zum Ändern der Elementmetadaten.
1200
+ *
1201
+ * **Partielles Update** (Review §8): Ein Feld, das **fehlt**, behält seinen
1202
+ * bisherigen Wert; ein Feld, das ausdrücklich auf `null` gesetzt wird, wird
1203
+ * gelöscht. Vorher war es eine Mischform — `description` verschwand, wenn sie
1204
+ * nicht mitgesendet wurde, `locale` blieb erhalten. Ein reiner Titelwechsel
1205
+ * löschte damit eine bestehende Beschreibung.
1206
+ *
1207
+ * `title` ist Pflicht: ein Element ohne Titel wäre in keiner Liste auffindbar.
1208
+ */
1209
+ interface ReviseMetadataInput {
1210
+ elementId: string;
1211
+ title: string;
1212
+ /** Fehlt = unverändert. `null` = löschen. */
1213
+ description?: string | null;
1214
+ /** Fehlt = unverändert. */
1215
+ locale?: string;
1216
+ expectedRevision: number;
1217
+ }
1218
+ /**
1219
+ * Schreibzugriffe.
1220
+ *
1221
+ * Ein Host, der eine Operation nicht anbietet, lässt das Feld weg — das ist der
1222
+ * `unsupported`-Fall aus R-1 und kein Fehler.
1223
+ */
1224
+ interface SzenenCommands {
1225
+ createElement(input: CreateElementInput): Promise<SzenenCommandResult<ElementRecord>>;
1226
+ writeDraft(input: WriteDraftInput): Promise<SzenenCommandResult<DraftRecord, DraftRecord | null>>;
1227
+ publishVersion(input: PublishVersionInput): Promise<SzenenCommandResult<PublishedVersion>>;
1228
+ setPreferredHead?(input: SetPreferredHeadInput): Promise<SzenenCommandResult<PreferredHeadSelection, PreferredHeadSelection | null>>;
1229
+ reviseMetadata?(input: ReviseMetadataInput): Promise<SzenenCommandResult<ElementMetadata, ElementMetadata | null>>;
1230
+ /**
1231
+ * Legt ein Element still — **idempotent** (Review §9).
1232
+ *
1233
+ * Ein zweiter Aufruf auf ein bereits stillgelegtes Element liefert wieder
1234
+ * `ok` mit demselben Stand und ändert nichts. Es gibt keine erwartete
1235
+ * Revision: Stilllegen kennt nur einen sinnvollen Zielzustand, und zwei
1236
+ * gleichzeitige Aufrufe können sich nicht widersprechen. Das unterscheidet
1237
+ * es bewusst von den übrigen mutierenden Operationen.
1238
+ */
1239
+ retireElement?(elementId: string): Promise<SzenenCommandResult<ElementRecord>>;
1240
+ }
1241
+ /** Der vollständige Elementspeicher eines Hosts. */
1242
+ interface SzenenElementStore extends SzenenQueries, SzenenCommands {
1243
+ }
1244
+ /** Rolle eines Speichers im Gefälle aus D-62. */
1245
+ type StoreAuthority =
1246
+ /** Führt die fachliche Wahrheit. Nur HF erfüllt das in allen Hosts. */
1247
+ 'authoritative'
1248
+ /** Materialisierte Ableitung eines autoritativen Bestands. */
1249
+ | 'projection';
1250
+ /**
1251
+ * Der autoritative fachliche Speicher.
1252
+ *
1253
+ * Fachliche Änderungen werden **hier** abgeschlossen; erst danach gilt eine
1254
+ * Änderung als erfolgt. Konflikte und `expectedRevision` entscheiden
1255
+ * ausschließlich gegen diesen Stand.
1256
+ */
1257
+ interface AuthoritativeSzenenStore extends SzenenElementStore {
1258
+ readonly authority: 'authoritative';
1259
+ }
1260
+ /**
1261
+ * Zustand einer Projektion (D-62 §2.4).
1262
+ *
1263
+ * `current` – nachweislich auf dem Stand der Quellrevision
1264
+ * `stale` – die Quelle ist weiter, die Projektion hinterher
1265
+ * `rebuilding` – wird gerade vollständig neu aufgebaut
1266
+ * `failed` – der letzte Projektionsversuch ist gescheitert
1267
+ */
1268
+ type ProjectionStatus = 'current' | 'stale' | 'rebuilding' | 'failed';
1269
+ /**
1270
+ * Buchführung einer Projektion.
1271
+ *
1272
+ * Ohne sie lässt sich nicht entscheiden, ob ein MySQL-Lesezugriff die aktuelle
1273
+ * Wahrheit trifft — und genau das darf nach D-62 nie stillschweigend
1274
+ * angenommen werden.
1275
+ */
1276
+ interface ProjectionState {
1277
+ status: ProjectionStatus;
1278
+ /** Quellrevision oder Cursor im autoritativen Speicher; `null` = nie projiziert. */
1279
+ sourceRevision: string | null;
1280
+ /** Zeitpunkt der letzten **erfolgreichen** Projektion, ISO-8601. */
1281
+ projectedAt: string | null;
1282
+ /** Letzter Projektionsfehler, solange er nicht durch Erfolg abgelöst ist. */
1283
+ lastError: string | null;
1284
+ }
1285
+ /**
1286
+ * Eine materialisierte Projektion des autoritativen Bestands.
1287
+ *
1288
+ * Lesen darf bevorzugt hier geschehen, **solange die Projektion nachweisbar
1289
+ * aktuell ist**. Ist sie es nicht, muss der Aufrufer auf den autoritativen
1290
+ * Speicher zurückfallen oder den Stand ausdrücklich als veraltet ausweisen.
1291
+ * Deshalb ist `getProjectionState` Teil des Vertrags und nicht Beiwerk.
1292
+ */
1293
+ interface SzenenProjection extends SzenenQueries {
1294
+ readonly authority: 'projection';
1295
+ getProjectionState(): Promise<QueryResult<ProjectionState>>;
1296
+ }
1297
+ /**
1298
+ * Ist diese Projektion als Wahrheit lesbar?
1299
+ *
1300
+ * Bewusst eine Funktion und kein Feld: der einzige Zustand, der zum Lesen
1301
+ * berechtigt, ist `current` — jede spätere Erweiterung der Statuswerte fällt
1302
+ * damit automatisch auf die sichere Seite.
1303
+ */
1304
+ declare const isProjectionCurrent: (state: ProjectionState) => boolean;
1305
+ /** Schmales Prädikat für `SzenenCommandResult`. */
1306
+ declare const isOk: <T, C>(result: SzenenCommandResult<T, C>) => result is {
1307
+ kind: "ok";
1308
+ value: T;
1309
+ };
1310
+
1311
+ /** Optionale Kommandos, ohne die einzelne Prüfungen entfallen. */
1312
+ type OptionalCommand = 'setPreferredHead' | 'reviseMetadata' | 'retireElement';
1313
+ /** Eine einzelne Vertragsprüfung. */
1314
+ interface ContractCheck {
1315
+ /** Thematische Gruppe, für die Ausgabe. */
1316
+ group: string;
1317
+ name: string;
1318
+ /**
1319
+ * Kommando, das dieser Check braucht. Bietet der Port es nicht an, wird
1320
+ * übersprungen statt rot — `unsupported` ist der Normalfall aus R-1.
1321
+ */
1322
+ requires?: OptionalCommand;
1323
+ run(store: SzenenElementStore): Promise<void>;
1324
+ }
1325
+ /** Was ein Kandidat für den Contract-Test mitbringen muss. */
1326
+ interface ElementStoreContractHarness {
1327
+ /** Ein frischer, leerer Speicher je Prüfung. */
1328
+ createStore(): Promise<SzenenElementStore> | SzenenElementStore;
1329
+ /** Kommandos, die dieser Port nicht anbietet. */
1330
+ optionalCommandsMissing?: readonly OptionalCommand[];
1331
+ }
1332
+ /** Schemagültige Payload eines `style` — der einfachste Typ ohne Referenzen. */
1333
+ declare const STYLE_PAYLOAD: {
1334
+ readonly role: "medium";
1335
+ readonly name: "Kohlezeichnung";
1336
+ readonly text: "grobe Kohle auf Papier";
1337
+ readonly locale: "de";
1338
+ };
1339
+ /** Zweite, ebenfalls gültige `style`-Payload. */
1340
+ declare const STYLE_PAYLOAD_V2: {
1341
+ readonly role: "medium";
1342
+ readonly name: "Kohlezeichnung, weicher";
1343
+ readonly text: "weiche Kohle, gewischt";
1344
+ readonly locale: "de";
1345
+ };
1346
+ declare class ContractViolation extends Error {
1347
+ }
1348
+ /**
1349
+ * Alle Prüfungen, die jeder `SzenenElementStore` erfüllen muss.
1350
+ *
1351
+ * Rein und zustandslos: jede Prüfung bekommt einen frischen Speicher.
1352
+ */
1353
+ declare function elementStoreContractChecks(): readonly ContractCheck[];
1354
+ /** Ausgang einer einzelnen Prüfung. */
1355
+ interface ContractCheckResult {
1356
+ group: string;
1357
+ name: string;
1358
+ status: 'passed' | 'failed' | 'skipped';
1359
+ /** Bei `failed`: die Meldung. Bei `skipped`: warum. */
1360
+ message?: string;
1361
+ }
1362
+ interface ContractRunResult {
1363
+ results: readonly ContractCheckResult[];
1364
+ passed: number;
1365
+ failed: number;
1366
+ skipped: number;
1367
+ /** Kurzform: keine Prüfung fehlgeschlagen. */
1368
+ ok: boolean;
1369
+ }
1370
+ /**
1371
+ * Führt den Vertrag gegen einen Port aus, ohne Testframework.
1372
+ *
1373
+ * Für Umgebungen, die kein vitest haben — insbesondere den Szenario-Runner des
1374
+ * Backends, der den MySQL-Port aus Stufe 1d prüft. Der vitest-Adapter für
1375
+ * fa-app-tools liegt in `storeContractVitest.ts` und nutzt dieselben Prüfungen.
1376
+ */
1377
+ declare function runElementStoreContract(harness: ElementStoreContractHarness): Promise<ContractRunResult>;
1378
+
1379
+ export { type PublishVersionInput as $, ALL_PUBLISH_RULES as A, type DraftChainMeta as B, CHAIN_EDGES as C, DERIVABLE_TYPES as D, type DraftFork as E, type DraftRecord as F, type ElementMetadata as G, type ElementRecord as H, type ElementSnapshot as I, type ElementStoreContractHarness as J, type ElementVersionValidation as K, type FindingSeverity as L, type ImageProvenance as M, type NotDerivable as N, type OptionalCommand as O, PROBE_VERSION_ID as P, type ParentRelation as Q, type PreferredHeadOutcome as R, type PreferredHeadResolution as S, type PreferredHeadSelection as T, type PreferredHeadSource as U, type ProjectionState as V, type ProjectionStatus as W, type PublishCheckInput as X, type PublishCheckResult as Y, type PublishFinding as Z, type PublishRejected as _, type AuthoritativeSzenenStore as a, validatePayload as a$, type PublishedVersion as a0, REFERENCE_FIELD as a1, type ReferenceResolver as a2, type ResolvePreferredHeadOptions as a3, type ResolvedVersion as a4, type ReviseMetadataInput as a5, STYLE_PAYLOAD as a6, STYLE_PAYLOAD_V2 as a7, SZENEN_ELEMENT_TYPES as a8, type SceneDerivationInput as a9, buildUserPrompt as aA, buildVersionDag as aB, checkChainTargets as aC, checkDerivationResponse as aD, checkDraftChainMeta as aE, collectVersionRefs as aF, compileSchemas as aG, createSimulationSceneDerivationPort as aH, describeTargetModelFailure as aI, elementStoreContractChecks as aJ, formatSchemaErrors as aK, getSzenenSchemas as aL, isOk as aM, isProjectionCurrent as aN, linkFor as aO, parseDerivationResponse as aP, preferredVersionId as aQ, resolvePreferredHead as aR, resolveTargetModelOver as aS, resolverFromQueries as aT, runElementStoreContract as aU, runPublishChecks as aV, runSceneDerivation as aW, showChain as aX, validateAgainst as aY, validateDerivationInput as aZ, validateElementVersion as a_, type SceneDerivationOutcome as aa, type SceneDerivationOutput as ab, type SchemaError as ac, type SchemaValidationResult as ad, type SetPreferredHeadInput as ae, type StoreAuthority as af, type SzenenCommandResult as ag, type SzenenCommands as ah, type SzenenElementStore as ai, type SzenenElementType as aj, type SzenenProjection as ak, type SzenenQueries as al, type TargetModelCandidate as am, type TargetModelQueries as an, type TargetModelQuery as ao, type TargetModelResolution as ap, UnsupportedSchemaError as aq, type UnusableProposal as ar, type VersionDag as as, VersionDagError as at, type VersionNode as au, type VersionParentLink as av, type WriteConflict as aw, type WriteDraftInput as ax, assessDerivationResponse as ay, buildSystemInstruction as az, CHAIN_LINK_FIELDS as b, withReference as b0, type CatalogueEntry as c, type ChainLinkField as d, type ChainTarget as e, type ChainVerdict as f, type CompiledSchemas as g, type ContextChainPort as h, type ContractCheck as i, type ContractCheckResult as j, type ContractRunResult as k, ContractViolation as l, type CreateElementInput as m, type DerivableType as n, type DerivationAssessment as o, type DerivationConflict as p, type DerivationDiagnostic as q, type DerivationEnvelope as r, type DerivationFailure as s, type DerivationFailureClass as t, type DerivationFollowUp as u, type DerivationImage as v, type DerivationInputMode as w, type DerivationPolicyPayload as x, type DerivationProposal as y, type DraftChainLink as z };