@rslsp1/fa-app-tools 2.0.73 → 2.0.81

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,2747 @@
1
+ import { ac as SchemaError, Z as PublishFinding, Y as PublishCheckResult, aj as SzenenElementType, a2 as ReferenceResolver, ap as TargetModelResolution, I as ElementSnapshot, w as DerivationInputMode, M as ImageProvenance, s as DerivationFailure, n as DerivableType, N as NotDerivable, p as DerivationConflict, u as DerivationFollowUp, B as DraftChainMeta, q as DerivationDiagnostic, o as DerivationAssessment, h as ContextChainPort, a as AuthoritativeSzenenStore, ai as SzenenElementStore, v as DerivationImage, al as SzenenQueries, ah as SzenenCommands, ar as UnusableProposal } from './storeContract-B2BDgvhN.mjs';
2
+ export { A as ALL_PUBLISH_RULES, C as CHAIN_EDGES, b as CHAIN_LINK_FIELDS, c as CatalogueEntry, d as ChainLinkField, e as ChainTarget, f as ChainVerdict, g as CompiledSchemas, i as ContractCheck, j as ContractCheckResult, k as ContractRunResult, l as ContractViolation, m as CreateElementInput, D as DERIVABLE_TYPES, r as DerivationEnvelope, t as DerivationFailureClass, x as DerivationPolicyPayload, y as DerivationProposal, z as DraftChainLink, E as DraftFork, F as DraftRecord, G as ElementMetadata, H as ElementRecord, J as ElementStoreContractHarness, K as ElementVersionValidation, L as FindingSeverity, O as OptionalCommand, P as PROBE_VERSION_ID, Q as ParentRelation, R as PreferredHeadOutcome, S as PreferredHeadResolution, T as PreferredHeadSelection, U as PreferredHeadSource, V as ProjectionState, W as ProjectionStatus, X as PublishCheckInput, _ as PublishRejected, $ as PublishVersionInput, a0 as PublishedVersion, a1 as REFERENCE_FIELD, a3 as ResolvePreferredHeadOptions, a4 as ResolvedVersion, a5 as ReviseMetadataInput, a6 as STYLE_PAYLOAD, a7 as STYLE_PAYLOAD_V2, a8 as SZENEN_ELEMENT_TYPES, a9 as SceneDerivationInput, aa as SceneDerivationOutcome, ab as SceneDerivationOutput, ad as SchemaValidationResult, ae as SetPreferredHeadInput, af as StoreAuthority, ag as SzenenCommandResult, ak as SzenenProjection, am as TargetModelCandidate, an as TargetModelQueries, ao as TargetModelQuery, aq as UnsupportedSchemaError, as as VersionDag, at as VersionDagError, au as VersionNode, av as VersionParentLink, aw as WriteConflict, ax as WriteDraftInput, ay as assessDerivationResponse, az as buildDerivationSystemInstruction, aA as buildDerivationUserPrompt, aB as buildVersionDag, aC as checkChainTargets, aD as checkDerivationResponse, aE as checkDraftChainMeta, aF as collectVersionRefs, aG as compileSchemas, aH as createSimulationSceneDerivationPort, aI as describeTargetModelFailure, aJ as elementStoreContractChecks, aK as formatSchemaErrors, aL as getSzenenSchemas, aM as isOk, aN as isProjectionCurrent, aO as linkFor, aP as parseDerivationResponse, aQ as preferredVersionId, aR as resolvePreferredHead, aS as resolveTargetModelOver, aT as resolverFromQueries, aU as runElementStoreContract, aV as runPublishChecks, aW as runSceneDerivation, aX as showChain, aY as validateAgainst, aZ as validateDerivationInput, a_ as validateElementVersion, a$ as validatePayload, b0 as withReference } from './storeContract-B2BDgvhN.mjs';
3
+ import { T as TextGenerationPort, Q as QueryResult, C as CommandResult } from './contracts-DdYOMBl9.mjs';
4
+ export { S as SIMULATION_PROVIDER, c as TextGenerationRequest, d as TextGenerationResult, g as createFakeTextGenerationPort, h as createSimulationTextGenerationPort, s as simulatedAnswerFor } from './contracts-DdYOMBl9.mjs';
5
+ import { F as FlowGenerateText } from './flowTextGenerationPort-CeDUFutP.mjs';
6
+ export { C as CreateFlowTextGenerationPortOptions, i as createFlowTextGenerationPort } from './flowTextGenerationPort-CeDUFutP.mjs';
7
+ import React__default from 'react';
8
+
9
+ /** Rohes JSON-Schema, wie es in der Spezifikation steht. */
10
+ type RawSchema = Record<string, unknown>;
11
+ /** Alle Typschemas der Domain, geschluesselt nach Dateiname wie in der Quelle. */
12
+ declare const SZENEN_SCHEMAS: Readonly<Record<string, RawSchema>>;
13
+ /** Dateiname des Umschlagschemas — Einstieg jeder Validierung. */
14
+ declare const ELEMENT_VERSION_SCHEMA_FILE = "element-version.schema.json";
15
+
16
+ /**
17
+ * Ist dieses Scene Setup platzierbar?
18
+ *
19
+ * Genau dann, wenn es ein `coordinate_system` trägt (D-65). Die frühere
20
+ * Fassung in `domain-model.md` §9 verlangte „strukturierte Positionen in
21
+ * `placements[]` **oder belastbare relative Constraints**" — nicht
22
+ * entscheidbar, weil „belastbar" kein Prädikat ist.
23
+ *
24
+ * **Rein lokal:** liest ein Feld der übergebenen Payload und braucht keinen
25
+ * Speicherzugriff. Deshalb lässt sich `can_place` auch ohne `ReferenceResolver`
26
+ * widerlegen — der Fähigkeitsbericht nutzt genau das.
27
+ *
28
+ * **Vertrag: die Payload muss bereits schemavalidiert sein.** Die Funktion
29
+ * prüft nur auf Anwesenheit, nicht auf den erlaubten Wert — `coordinate_system:
30
+ * 123` gälte hier als platzierbar, ist nach dem Schema aber ungültig. Beide
31
+ * Aufrufer halten das ein: Im Publish-Pfad läuft die Schemaprüfung vor P-07,
32
+ * und `capabilityReport` validiert selbst, bevor es hierher kommt. Wer die
33
+ * Funktion neu aufruft, muss dasselbe tun.
34
+ */
35
+ declare function hasPlacementCapability(setupPayload: unknown): boolean;
36
+
37
+ /**
38
+ * Zustand einer Fähigkeit.
39
+ *
40
+ * `unknown` ist ein eigener Zustand und **kein** `false` (D-64). Ein
41
+ * `boolean | null` würde im Aufrufer zu `if (!flag)` und damit still zu „kann
42
+ * nicht" — die stille Falschaussage, die Grundsatzregel 5 verbietet.
43
+ */
44
+ type CapabilityState = 'yes' | 'no' | 'unknown';
45
+ /** Warum ein Flag nicht `yes` ist. Nie leer, solange `state !== 'yes'`. */
46
+ type CapabilityReason =
47
+ /** Die Payload verletzt das Schema des Elementtyps. */
48
+ {
49
+ kind: 'schema';
50
+ error: SchemaError;
51
+ }
52
+ /** Eine Publish-Regel blockiert. */
53
+ | {
54
+ kind: 'blocked';
55
+ finding: PublishFinding;
56
+ }
57
+ /** Eine zuständige Regel konnte nicht geprüft werden. */
58
+ | {
59
+ kind: 'unchecked';
60
+ rule: string;
61
+ reason: string;
62
+ }
63
+ /** Eine Strukturbedingung ist verletzt oder unbestimmt. */
64
+ | {
65
+ kind: 'structure';
66
+ message: string;
67
+ }
68
+ /** Das Flag erbt das Ergebnis von `can_describe_scene`. */
69
+ | {
70
+ kind: 'inherited';
71
+ from: 'can_describe_scene';
72
+ message: string;
73
+ };
74
+ interface CapabilityFlag {
75
+ state: CapabilityState;
76
+ reasons: readonly CapabilityReason[];
77
+ }
78
+ interface CapabilityReportInput {
79
+ /**
80
+ * Elementtyp der Payload. **Pflicht** — er ist aus einer nackten Payload
81
+ * nicht ableitbar: `type` steht im Umschlag (`element-version.schema.json`),
82
+ * nicht im Payload-Schema. `runPublishChecks` bekommt ihn aus demselben
83
+ * Grund explizit.
84
+ */
85
+ type: SzenenElementType;
86
+ /** Payload eines `scene_setup` — veröffentlicht oder Entwurf. */
87
+ setupPayload: unknown;
88
+ /** Element, zu dem die Payload gehört; die referenzabhängigen Regeln brauchen es. */
89
+ elementId: string;
90
+ /** Vorgänger im Versions-DAG; P-03 und P-10 werten sie aus. */
91
+ parents?: readonly {
92
+ parent_version_id: string;
93
+ relation: string;
94
+ }[];
95
+ /** Fehlt er, ist kein Flag besser als `unknown`. Kein stiller Fallback. */
96
+ resolver?: ReferenceResolver;
97
+ /**
98
+ * Die Szene, vorab aufgelöst — Stufe 6.6, C1 (D-96).
99
+ *
100
+ * Ohne dieses Feld holt der Bericht die Szene über `setupPayload.scene_ref`
101
+ * aus einer veröffentlichten Version; das ist der bisherige und unveränderte
102
+ * Weg.
103
+ *
104
+ * Mit diesem Feld kommt sie von außen: Ein Setup einer Draft-Kette trägt
105
+ * `scene_ref` bewusst nicht in seiner Payload, sondern führt den Verweis
106
+ * daneben. Der Bericht bekommt dieselbe Szene, nur über einen anderen Weg —
107
+ * und dieselbe fehlende Referenz wird dann auch in seiner Schemaprüfung
108
+ * nicht als Mangel gewertet.
109
+ *
110
+ * **Es bleibt bei einem Regelwerk** (D-64): Die Publish-Prüfungen laufen
111
+ * unverändert. Geändert hat sich nur, woher die Szene kommt.
112
+ */
113
+ chainScene?: unknown;
114
+ }
115
+ interface CapabilityReport {
116
+ can_describe_scene: CapabilityFlag;
117
+ can_render_prompt: CapabilityFlag;
118
+ can_place: CapabilityFlag;
119
+ /** Der zugrundeliegende Prüflauf, unverändert weitergereicht. */
120
+ checks: PublishCheckResult;
121
+ /**
122
+ * Schemafehler der Payload. Leer, wenn sie dem Typschema entspricht.
123
+ *
124
+ * Steht getrennt von `checks`, weil die Schemaprüfung **vor** den
125
+ * Publish-Regeln läuft und eine andere Frage beantwortet: nicht „hält dieser
126
+ * Stand die Modellregeln ein", sondern „ist das überhaupt ein Scene Setup".
127
+ */
128
+ schemaErrors: readonly SchemaError[];
129
+ }
130
+ /** Ein falscher Anker ist ein Aufruffehler, kein Befund. */
131
+ declare class CapabilityAnchorError extends Error {
132
+ }
133
+ type CapabilityScope = 'scene' | 'camera_rig' | 'placement' | 'global';
134
+ /**
135
+ * Welche Bereiche eine Regel beim Anker `scene_setup` abdeckt.
136
+ *
137
+ * **Positive Liste, und das ist der Kern.** `unchecked` vermischt drei
138
+ * Sachverhalte — nachweisbar an den Meldungstexten in `publishChecks.ts`:
139
+ *
140
+ * „kein ReferenceResolver uebergeben" → echt unbestimmt
141
+ * „Regel gilt nur fuer shot" → nicht anwendbar
142
+ * „Laufzeitregel der Aufloesung" → keine Veröffentlichungsbedingung
143
+ *
144
+ * Eine Abbildung `unchecked → unknown` machte den Bericht deshalb **dauerhaft**
145
+ * unbestimmt: P-01 und P-12 stehen bei jedem Setup-Lauf unter `unchecked`, auch
146
+ * mit vollständig funktionierendem Resolver. Nur was hier steht, wirkt.
147
+ *
148
+ * Eine Regel kann **mehrere** Bereiche abdecken: P-04 prüft die Szenenreferenz
149
+ * und die Preset-Referenzen, P-05 die Node-Referenzen in Overrides, Placements
150
+ * und Kamerafeldern. Ein einzelner Scope-Wert je Regel wäre zu grob.
151
+ */
152
+ declare const RULE_SCOPES: Readonly<Record<string, readonly CapabilityScope[]>>;
153
+ /**
154
+ * Regeln, die beim Anker `scene_setup` bewusst kein Flag beeinflussen —
155
+ * jede mit dem Grund, aus dem sie ausgenommen ist.
156
+ *
157
+ * Zusammen mit `RULE_SCOPES` deckt diese Liste `ALL_PUBLISH_RULES` vollständig
158
+ * ab; ein Test wacht darüber. P-17 aus Stufe 3 hat ihn genau so zum Scheitern
159
+ * gebracht, bis sie unten eingeordnet war — eine neue Regel kann nicht
160
+ * stillschweigend wirkungslos bleiben.
161
+ */
162
+ declare const RULES_WITHOUT_CAPABILITY_EFFECT: Readonly<Record<string, string>>;
163
+ /** Welcher Scope ein Befund betrifft — abgeleitet aus seinem JSON-Pointer. */
164
+ declare function scopeOfPath(path: string): CapabilityScope;
165
+ /**
166
+ * Fähigkeitsbericht zu einem Scene Setup.
167
+ *
168
+ * Reihenfolge der Auswertung je Flag (§7.5 der Spezifikation), erste
169
+ * zutreffende Regel gewinnt:
170
+ *
171
+ * 0. Schemafehler im Scope → `no`
172
+ * 1. lokaler blockierender Befund im Scope → `no`
173
+ * 2. verletzte lokale Strukturbedingung → `no`
174
+ * 3. geerbtes `no` aus can_describe_scene → `no`
175
+ * 4. eigene Regel ungeprüft / unbestimmte
176
+ * Struktur / geerbtes `unknown` → `unknown`
177
+ * 5. sonst → `yes`
178
+ *
179
+ * `no` schlägt `unknown`: Ein nachgewiesener Blocker bleibt einer, auch wenn
180
+ * daneben eine Regel ungeprüft blieb.
181
+ */
182
+ declare function capabilityReport(input: CapabilityReportInput): Promise<CapabilityReport>;
183
+ /**
184
+ * Regeln, die weder eingeordnet noch begründet ausgenommen sind.
185
+ *
186
+ * Der Vollständigkeitstest ruft das auf. Als Funktion und nicht als Konstante,
187
+ * damit er gegen `ALL_PUBLISH_RULES` läuft und nicht gegen eine Kopie davon.
188
+ */
189
+ declare function unclassifiedPublishRules(): readonly string[];
190
+
191
+ /** Ein Beitrag zur Beschreibung eines Knotens, mit Herkunft (D-50). */
192
+ interface NodeContribution {
193
+ source: 'component' | 'node_semantic' | 'setup_override';
194
+ element_id: string | null;
195
+ version_id: string | null;
196
+ role: string | null;
197
+ rank: number;
198
+ locale: string | null;
199
+ text: string;
200
+ }
201
+ /** Ein Knoten der aufgelösten Szene. */
202
+ interface ResolvedNode {
203
+ node_id: string;
204
+ type: string;
205
+ /** Additiv nach `rank`, nie vorgemischt (D-50). */
206
+ contributions: readonly NodeContribution[];
207
+ properties: Record<string, unknown>;
208
+ /** `null`, solange `can_place` nicht gilt — der Renderer erfindet keine Koordinaten. */
209
+ placement: ResolvedPlacement | null;
210
+ /** Vom Shot ausgeblendet (D-40). Der Knoten bleibt im Graphen (D-21). */
211
+ hidden: boolean;
212
+ }
213
+ interface ResolvedPlacement {
214
+ position: readonly number[];
215
+ rotation_euler_deg?: readonly number[];
216
+ scale?: readonly number[];
217
+ }
218
+ interface ResolvedCamera {
219
+ camera_id: string;
220
+ name: string | null;
221
+ preset: unknown;
222
+ placement: unknown;
223
+ orientation: unknown;
224
+ framing: unknown;
225
+ focus: unknown;
226
+ /** Aufgelöste Pattern-Version, falls die Platzierung eines benutzt. */
227
+ pattern: unknown | null;
228
+ }
229
+ /** Die Renderer-Eingabe nach `prompt-derivation.md` §3a. */
230
+ interface RendererInput {
231
+ shot: {
232
+ version_id: string;
233
+ element_id: string;
234
+ camera_id: string;
235
+ shot_concept: unknown | null;
236
+ user_instruction: string | null;
237
+ text_override: string | null;
238
+ };
239
+ scene: {
240
+ version_id: string;
241
+ nodes: readonly ResolvedNode[];
242
+ relations: readonly unknown[];
243
+ environment: unknown | null;
244
+ unit_system: unknown | null;
245
+ };
246
+ camera: ResolvedCamera;
247
+ styles: readonly {
248
+ role: string;
249
+ rank: number;
250
+ weight: number | null;
251
+ text: string;
252
+ locale: string | null;
253
+ }[];
254
+ policies: readonly {
255
+ subtype: string;
256
+ rank: number;
257
+ text: string;
258
+ locale: string | null;
259
+ }[];
260
+ fragments: readonly {
261
+ channel: string;
262
+ rank: number;
263
+ text: string;
264
+ locale: string | null;
265
+ }[];
266
+ target_model: unknown;
267
+ /**
268
+ * Fälle, in denen die Zielsprache nicht verfügbar war (D-48).
269
+ *
270
+ * **In Stufe 3 immer leer.** `version_localizations` ist spezifiziert
271
+ * (`versioning-and-sync.md` §5), aber weder als Tabelle noch als
272
+ * Portoperation umgesetzt. Statt so zu tun, als hätte jemand nachgesehen,
273
+ * steht der Umstand als Annahme in `assumptions`.
274
+ */
275
+ localization_notes: readonly unknown[];
276
+ /** Annahmen, unter denen diese Eingabe entstanden ist. */
277
+ assumptions: readonly string[];
278
+ /** Die Fähigkeiten, die die Auflösung gesehen hat — eingefroren (D-22). */
279
+ capabilities: {
280
+ can_describe_scene: string;
281
+ can_render_prompt: string;
282
+ can_place: string;
283
+ };
284
+ /** Die tatsächlich verwendete Kontextkette (§4.9.1). */
285
+ context_chain: readonly (string | null)[];
286
+ /** Wie das Zielmodell gefunden wurde (§4.9.1). */
287
+ target_model_resolution: {
288
+ element_id: string;
289
+ version_id: string;
290
+ chain_index: number;
291
+ head: unknown;
292
+ shadowed_retired: readonly {
293
+ element_id: string;
294
+ context_id: string | null;
295
+ }[];
296
+ };
297
+ }
298
+ /**
299
+ * Warum eine Auflösung nicht zustande kam.
300
+ *
301
+ * Alles hier ist **fachlich**. Technische Lesefehler werfen und werden nie zu
302
+ * einer dieser Klassen — sonst entstünde aus einer kränkelnden Datenbank eine
303
+ * Aussage über den Bestand (Grundsatzregel 5).
304
+ */
305
+ type ResolveFailure = {
306
+ class: 'not_a_shot';
307
+ message: string;
308
+ type: string;
309
+ } | {
310
+ class: 'shot_not_published';
311
+ message: string;
312
+ versionId: string;
313
+ } | {
314
+ class: 'schema';
315
+ message: string;
316
+ where: 'shot' | 'scene_setup';
317
+ errors: readonly SchemaError[];
318
+ } | {
319
+ class: 'capability_blocked';
320
+ message: string;
321
+ flag: string;
322
+ findings: readonly PublishFinding[];
323
+ } | {
324
+ class: 'capability_undetermined';
325
+ message: string;
326
+ flag: string;
327
+ reasons: readonly CapabilityReason[];
328
+ } | {
329
+ class: 'reference_unresolvable';
330
+ message: string;
331
+ versionId: string;
332
+ path: string;
333
+ reason: 'unknown' | 'invisible' | 'wrong_type';
334
+ } | {
335
+ class: 'target_model_unresolvable';
336
+ message: string;
337
+ resolution: TargetModelResolution;
338
+ };
339
+ type ResolveResult = {
340
+ kind: 'resolved';
341
+ input: RendererInput;
342
+ report: CapabilityReport;
343
+ } | {
344
+ kind: 'rejected';
345
+ failure: ResolveFailure;
346
+ };
347
+ /** Ein technischer Fehler der Auflösung. Kein fachlicher Befund. */
348
+ declare class ResolveTechnicalError extends Error {
349
+ }
350
+ interface ResolveShotInput {
351
+ /** Eine **veröffentlichte** `shot`-Version. Entwürfe erzeugen keinen Lauf. */
352
+ shotVersionId: string;
353
+ resolver: ReferenceResolver;
354
+ /** Die wirksame Kontextkette des Shot-Elements; wird eingefroren (§4.9.1). */
355
+ contextChain: readonly (string | null)[];
356
+ /**
357
+ * Freie Anweisung des Aufrufers für **diesen** Lauf (§4.1).
358
+ *
359
+ * Sie überschreibt `prompt_render_settings.user_instruction` des Shots —
360
+ * zwei verschiedene Sachverhalte: die eine steht dauerhaft an der
361
+ * veröffentlichten Version, die andere gilt nur hier. Wird eine gesetzte
362
+ * Anweisung des Shots überschrieben, steht das in `assumptions`.
363
+ */
364
+ userInstruction?: string | null;
365
+ }
366
+ /**
367
+ * Löst einen Shot zur Renderer-Eingabe auf.
368
+ *
369
+ * Der Ablauf steht in §4.3 des Start-Events und wird hier Schritt für Schritt
370
+ * gegangen. Was scheitert, scheitert mit einer eigenen Klasse — es gibt keinen
371
+ * Sammelfehler „ging nicht".
372
+ */
373
+ declare function resolveShot(input: ResolveShotInput): Promise<ResolveResult>;
374
+ /** Eingabe der Trockenauflösung (§4.6). */
375
+ interface ResolveShotPayloadInput {
376
+ /** Payload eines `shot` — **Entwurf oder veröffentlicht**. */
377
+ shotPayload: unknown;
378
+ /** Element, zu dem die Payload gehört; die Zielmodellsuche braucht es. */
379
+ shotElementId: string;
380
+ /** Kennung der Version, falls es eine gibt. Bei einem Entwurf leer. */
381
+ shotVersionId?: string;
382
+ resolver: ReferenceResolver;
383
+ contextChain: readonly (string | null)[];
384
+ /** Freie Anweisung des Aufrufers für diesen Lauf (§4.1). */
385
+ userInstruction?: string | null;
386
+ /**
387
+ * Vorab aufgelöste Kettenglieder — Stufe 6.6, C0 (D-95/D-96).
388
+ *
389
+ * Ohne dieses Feld holt die Auflösung Setup und Szene über
390
+ * `shot.scene_setup_ref` bzw. `setup.scene_ref` aus **veröffentlichten**
391
+ * Versionen; das ist der bisherige und unveränderte Weg.
392
+ *
393
+ * Mit diesem Feld kommen beide von außen. Genau so bekommt eine Draft-Kette
394
+ * ihren Prompt, ohne dass ein Knoten veröffentlicht sein muss: Der
395
+ * Draft-Loader lädt die Payloads über die Kettenlinks und reicht **dieselben
396
+ * fachlichen Inhalte** in **dieselbe** Zusammensetzung. Es gibt bewusst
397
+ * keinen zweiten Prompt-Zusammenbau und keine zweite Kamera- oder
398
+ * Zielmodell-Logik (Gate C0).
399
+ *
400
+ * Die `version_id` ist bei einem Draft leer — sie wird **nicht** erfunden
401
+ * (D-98/D-75). Alle übrigen Referenzen (Preset, Pattern, Styles, Policies,
402
+ * Zielmodell) bleiben veröffentlichungspflichtig: D-96 erlaubt genau zwei
403
+ * Draft-Kanten, nicht beliebige.
404
+ */
405
+ chain?: {
406
+ setup: {
407
+ element_id: string;
408
+ version_id: string;
409
+ payload: unknown;
410
+ };
411
+ scene: {
412
+ element_id: string;
413
+ version_id: string;
414
+ payload: unknown;
415
+ };
416
+ };
417
+ }
418
+ /**
419
+ * Löst eine Shot-**Payload** auf, ohne eine veröffentlichte Version zu verlangen.
420
+ *
421
+ * Das ist die Trockenauflösung aus §4.6: Ein Autor soll sehen können, was aus
422
+ * seinem Entwurf entstünde, ohne ihn zu veröffentlichen — genau wofür Stufe 2
423
+ * gebaut wurde („prüfen, bevor geschrieben wird"). Es wird nichts gespeichert
424
+ * und kein Modell gerufen.
425
+ *
426
+ * Die **Referenzen** müssen trotzdem veröffentlicht und sichtbar sein (D-03):
427
+ * Ein Entwurf darf auf nichts zeigen, was es noch nicht gibt.
428
+ */
429
+ declare function resolveShotPayload(input: ResolveShotPayloadInput): Promise<ResolveResult>;
430
+ /**
431
+ * Prüft ein Fähigkeits-Flag als Torwächter.
432
+ *
433
+ * `no` und `unknown` bekommen **verschiedene** Klassen. Die Ablehnung bei
434
+ * `unknown` sagt „das liess sich hier nicht feststellen", nicht „die Szene kann
435
+ * das nicht" — der Unterschied ist der ganze Grund, warum `unknown` in D-64 ein
436
+ * eigener Zustand ist.
437
+ */
438
+ declare function capabilityGate(report: CapabilityReport, flag: 'can_render_prompt' | 'can_place'): ResolveFailure | null;
439
+
440
+ interface VisibilityNode {
441
+ node_id: string;
442
+ state: string;
443
+ reason?: string;
444
+ confidence?: string;
445
+ assumption?: boolean;
446
+ }
447
+ interface PromptRunOutput {
448
+ positive: string;
449
+ negative: string | null;
450
+ /** Pflicht (D-55) — die Erläuterung für den Menschen. */
451
+ feedback: string;
452
+ visibility: {
453
+ basis: string;
454
+ nodes: readonly VisibilityNode[];
455
+ assumptions: readonly string[];
456
+ };
457
+ notes: readonly string[];
458
+ }
459
+ /** Warum ein Lauf gescheitert ist — die Klassen aus §4.9.1. */
460
+ type RunFailureClass = 'response_parse' | 'response_schema' | 'safety_blocked' | 'finish_reason' | 'empty_content' | 'provider_error';
461
+ interface RunFailure {
462
+ class: RunFailureClass;
463
+ message: string;
464
+ provider_detail?: unknown;
465
+ }
466
+ /**
467
+ * Ergebnis eines Laufs — **beide Ausgänge werden gespeichert**.
468
+ *
469
+ * Ein Fehlerlauf ist der Nachweis, dass eine bestimmte Kombination beim
470
+ * Provider anstößt (D-23 §6). Ihn zu verwerfen hieße, genau diese Information
471
+ * zu vernichten.
472
+ */
473
+ type PromptRunOutcome = {
474
+ status: 'succeeded';
475
+ output: PromptRunOutput;
476
+ raw_output: string;
477
+ model_id: string;
478
+ provider: string;
479
+ } | {
480
+ status: 'failed';
481
+ failure: RunFailure;
482
+ raw_output: string | null;
483
+ model_id: string;
484
+ provider: string;
485
+ };
486
+ /**
487
+ * Der Systemprompt des Renderers.
488
+ *
489
+ * Bewusst als eigene Funktion und mitgespeichert: D-22 verlangt, dass ein Lauf
490
+ * einfriert, unter welchen Annahmen er entstand — der Systemprompt gehört dazu.
491
+ * Ändert er sich, ist an einem alten Lauf noch erkennbar, was damals galt.
492
+ */
493
+ declare function buildSystemInstruction(input: RendererInput): string;
494
+ /** Die Nutzernachricht: die Renderer-Eingabe als JSON (D-47). */
495
+ declare function buildUserPrompt(input: RendererInput): string;
496
+ /**
497
+ * Löst das JSON aus dem Text.
498
+ *
499
+ * Bewusst **ohne** die für Prosa gedachte Bereinigung aus `cleanAiResponse`
500
+ * (D-56): Sie ist für Fließtext gebaut und darf ein JSON-Dokument nicht
501
+ * anfassen. Erlaubt ist einzig, einen umschließenden Markdown-Codeblock zu
502
+ * entfernen — das ist keine Interpretation des Inhalts, sondern das Auspacken
503
+ * eines Umschlags.
504
+ */
505
+ declare function parseRunResponse(raw: string): {
506
+ ok: true;
507
+ value: unknown;
508
+ } | {
509
+ ok: false;
510
+ message: string;
511
+ };
512
+ /**
513
+ * Prüft die geparste Antwort gegen ihr Schema **und** gegen die Pflichtdiagnosen.
514
+ *
515
+ * Handgeschrieben und nicht über die JSON-Schema-Registry: Die Registry führt
516
+ * die **Elementtypen** der Domain (`schemas/`), und die Antwort des Renderers
517
+ * ist kein Elementtyp. Sie dort einzuhängen hieße, den Schemasatz um etwas zu
518
+ * erweitern, das nie versioniert oder referenziert wird.
519
+ */
520
+ declare function checkRunResponse(value: unknown, input: RendererInput): {
521
+ ok: true;
522
+ output: PromptRunOutput;
523
+ } | {
524
+ ok: false;
525
+ message: string;
526
+ };
527
+ /**
528
+ * Führt den Prompt-Ableitungslauf aus.
529
+ *
530
+ * Gibt **immer** ein Ergebnis zurück — `succeeded` oder `failed`. Ein
531
+ * technischer Ausfall des Ports (Netz, Konfiguration) wirft dagegen; er ist
532
+ * kein Lauf, sondern ein Betriebsfehler und darf nicht als „das Modell hat
533
+ * abgelehnt" gespeichert werden.
534
+ */
535
+ declare function runPromptDerivation(input: RendererInput, port: TextGenerationPort): Promise<PromptRunOutcome & {
536
+ system_prompt: string;
537
+ }>;
538
+
539
+ /** Präfix aller Events dieser Domain im gemeinsamen HF-Event-Kanal. */
540
+ declare const SZENEN_EVENT_PREFIX = "szenen.";
541
+ declare const SZENEN_EVENT_TYPES: {
542
+ readonly elementCreated: "szenen.element_created";
543
+ readonly elementRetired: "szenen.element_retired";
544
+ readonly metadataRevised: "szenen.element_metadata_revised";
545
+ readonly draftWritten: "szenen.element_draft_written";
546
+ readonly versionPublished: "szenen.element_version_published";
547
+ readonly preferredHeadSelected: "szenen.element_preferred_head_selected";
548
+ /**
549
+ * Ein Prompt-Ableitungslauf — Stufe 3, S6 (E-3b).
550
+ *
551
+ * Ein Lauf ist **kein Element**: keine Version, kein DAG, nicht
552
+ * referenzierbar. Er liegt trotzdem im selben autoritativen Log, weil er
553
+ * append-only und unveränderlich ist — genau die Form, die ein Ereignislog
554
+ * nativ trägt — und weil MySQL sonst zu einem zweiten fachlichen Speicher
555
+ * würde, den D-62 abgeschafft hat.
556
+ *
557
+ * Der Elementreducer ignoriert diesen Typ (`default:`-Zweig); die Läufe
558
+ * werden mit `collectPromptRuns` gelesen.
559
+ */
560
+ readonly promptRunRecorded: "szenen.prompt_run_recorded";
561
+ /**
562
+ * Ein Szenen-Rekonstruktionslauf — Stufe 6.5 (D-71).
563
+ *
564
+ * Derselbe Bauplan und dieselbe Begründung wie beim Prompt-Lauf: append-only,
565
+ * unveränderlich, **kein Element** — keine Version, kein DAG, nicht
566
+ * referenzierbar. Er liegt im autoritativen Log, weil er genau die Form hat,
567
+ * die ein Ereignislog nativ trägt.
568
+ *
569
+ * Bewusst ein zweiter Lauftyp und **kein** gemeinsamer: Ein Prompt-Lauf geht
570
+ * von einer veröffentlichten Shot-Version aus, ein Rekonstruktionslauf von
571
+ * einer Referenz, die noch zu gar keinem Element gehört. Sie in einen Typ zu
572
+ * zwingen hieße, beiden ihre Herkunftsfelder zu nehmen.
573
+ *
574
+ * Der Elementreducer ignoriert auch diesen Typ (`default:`-Zweig).
575
+ */
576
+ readonly sceneDerivationRecorded: "szenen.scene_derivation_recorded";
577
+ /**
578
+ * Ein ausdrücklich ausgelöster Lauf gegen den **echten** Provider.
579
+ *
580
+ * Er kostet Geld und wird deshalb nie beiläufig gefahren. Das Ereignis hält
581
+ * fest, was tatsächlich bezahlt wurde: wie viele Modellaufrufe, mit welchem
582
+ * Ausgang, in welcher Umgebung und von wem ausgelöst.
583
+ *
584
+ * Es ersetzt **nicht** die einzelnen Läufe — die werden regulär als
585
+ * `prompt_run_recorded` bzw. `scene_derivation_recorded` protokolliert. Es
586
+ * ist die Klammer darüber und der Grund, warum jemand später nachlesen kann,
587
+ * ob der Durchstich stattgefunden hat, ohne ihn erneut zu bezahlen.
588
+ */
589
+ readonly providerCheckRecorded: "szenen.provider_check_recorded";
590
+ /**
591
+ * Eine geprüfte Arbeitsfassung eines fehlgeschlagenen Rekonstruktionslaufs —
592
+ * Stufe 6.6 (D-99).
593
+ *
594
+ * Sie ist **kein Lauf**: kein Provideraufruf, keine Kosten, kein Zielmodell.
595
+ * Sie ist die lokal geprüfte Korrektur eines bereits bezahlten Ergebnisses
596
+ * und zeigt über `run_id` auf ihren Ursprung. Der `raw_output` jenes Laufs
597
+ * bleibt unangetastet — deshalb ein eigenes Ereignis statt einer Änderung am
598
+ * bestehenden, das es ohnehin nicht geben dürfte (D-71).
599
+ *
600
+ * Mehrere Rettungen zum selben Lauf sind zulässig und erwartet: Jede
601
+ * Korrekturrunde ist nachvollziehbare Arbeit, kein Update der vorigen.
602
+ *
603
+ * Der Elementreducer ignoriert auch diesen Typ (`default:`-Zweig).
604
+ */
605
+ readonly sceneDerivationRecoveryRecorded: "szenen.scene_derivation_recovery_recorded";
606
+ /**
607
+ * Ein bezahlter Bildgenerierungsauftrag beginnt — Stufe 6.7 (D-119).
608
+ *
609
+ * Append-only wie jedes andere Ereignis dieser Domain, geschrieben **vor**
610
+ * dem Provideraufruf. Es traegt **keine Bilddaten** — nur die Kennung, mit
611
+ * der die spaetere kanonische Batch-Persistenz (`saveGeneratedAssetBatch`,
612
+ * Teil C) wiedergefunden wird. Ein Crash zwischen diesem Ereignis und
613
+ * `imageGenerationFinished` loescht den Auftrag nicht: Er bleibt lesbar,
614
+ * ohne dass irgendein automatischer Retry darauf reagiert.
615
+ *
616
+ * Gilt nur fuer `generated_in_app` — ein externer Import (D-108/D-117)
617
+ * ruft keinen Provider und braucht deshalb kein `started`; sein Nachweis
618
+ * ist das gespeicherte Library-Item selbst.
619
+ *
620
+ * Der Elementreducer ignoriert auch diesen Typ (`default:`-Zweig); gelesen
621
+ * wird mit `collectImageGenerationOrders`.
622
+ */
623
+ readonly imageGenerationStarted: "szenen.image_generation_started";
624
+ /**
625
+ * Derselbe Bildgenerierungsauftrag endet — Stufe 6.7 (D-119).
626
+ *
627
+ * Erscheint erst **nach** der kanonischen Batch-Persistenz: Ein technischer
628
+ * Fehler zwischen Provideraufruf und Speichern darf nie als `succeeded`
629
+ * protokolliert werden, nur weil der Provider geantwortet hat. Traegt
630
+ * ebenfalls keine Bilddaten — nur Status, Zaehlung und die Item-Kennung,
631
+ * falls eine entstand.
632
+ */
633
+ readonly imageGenerationFinished: "szenen.image_generation_finished";
634
+ };
635
+ /**
636
+ * Ein Event, wie der Reducer es sieht.
637
+ *
638
+ * Nur `type`, `payload` und `clientId` sind fachlich. `ts` dient allein der
639
+ * **Lesereihenfolge** des Logs und darf nie eine fachliche Vorrangfrage
640
+ * entscheiden — sonst wäre es `MAX(ts)` durch die Hintertür (§2.5, R-3).
641
+ */
642
+ interface ElementEvent<P = unknown> {
643
+ type: string;
644
+ payload: P;
645
+ clientId: string;
646
+ ts: number;
647
+ }
648
+ /** Ein Befund beim Falten: etwas ist widersprüchlich, aber der Zustand bleibt lesbar. */
649
+ interface ReducerFinding {
650
+ code: 'unbekanntes_element' | 'version_doppelt' | 'version_veraendert' | 'draft_fork' | 'metadata_fork' | 'preferred_head_fork' | 'element_doppelt';
651
+ element_id: string;
652
+ message: string;
653
+ }
654
+ /** Abgeleiteter Zustand über alle Elemente. */
655
+ interface ElementStoreState {
656
+ elements: ReadonlyMap<string, ElementSnapshot>;
657
+ findings: readonly ReducerFinding[];
658
+ }
659
+ /**
660
+ * Faltet den Event-Log zum Elementzustand.
661
+ *
662
+ * Der Reducer ist rein: gleiche Events, gleicher Zustand — unabhängig von der
663
+ * Eingabereihenfolge.
664
+ *
665
+ * @param events Alle bekannten Szenen-Events; fremde Typen werden übergangen.
666
+ */
667
+ declare function reduceElementEvents(events: readonly ElementEvent[]): ElementStoreState;
668
+ /** Aktuelle Revision des Entwurfs. `0`, wenn keiner existiert. */
669
+ declare function draftRevisionOf(snapshot: ElementSnapshot | null | undefined): number;
670
+ /**
671
+ * Quellrevision eines gelesenen Event-Logs (D-62 §2.4, D-63 §1.1.2).
672
+ *
673
+ * Die Projektion darf sich nur dann `current` nennen, wenn sie belegen kann,
674
+ * **bis wohin** sie reicht. Dieser Beleg ist die Quellrevision, und sie muss
675
+ * zwei Eigenschaften haben: aus dem Log allein berechenbar (sonst wäre sie eine
676
+ * zweite Buchführung) und für zwei verschiedene Logstände verschieden.
677
+ *
678
+ * Beides leistet `Anzahl@größter-Zeitstempel`. Der Log ist append-only — es
679
+ * verschwindet nie ein Event —, also wächst die Anzahl bei jedem Schreibvorgang.
680
+ * Der Zeitstempel kommt dazu, weil er den Stand für einen Menschen lesbar macht;
681
+ * entscheidend ist die Anzahl.
682
+ *
683
+ * Bewusst **kein** Hash über die Payloads: der wäre teurer und würde
684
+ * Gleichheit über die Zeit versprechen, die der Log ohnehin schon garantiert.
685
+ * Und bewusst hier, nicht im Server: der Projektor rechnet damit, und wer den
686
+ * Stand prüfen will, soll dieselbe Rechnung fahren (R-2).
687
+ */
688
+ declare function logRevisionOf(events: readonly ElementEvent[]): string;
689
+ /** Aktuelle Revision der Preferred-Head-Auswahl eines Kontexts. `0`, wenn keine existiert. */
690
+ declare function preferredHeadRevisionOf(events: readonly ElementEvent[], elementId: string, contextId: string): number;
691
+
692
+ /** Ein protokollierter Lauf, so wie er im Ereignis steht. */
693
+ /**
694
+ * Woher die eingefrorene Eingabe eines Laufs stammt — Stufe 6.6 (D-98).
695
+ *
696
+ * Bis 6.5 gab es nur einen Fall, und er stand flach im Datensatz: eine
697
+ * veröffentlichte Shot-Version. Mit der Draft-Kette gibt es einen zweiten, und
698
+ * er hat keine Versionen — nur Entwürfe mit Kennung und Revision.
699
+ *
700
+ * Bewusst diskriminiert und **ohne** fingierte Versionskennungen: Ein Feld,
701
+ * das ehrlich fehlt, ist besser als eine UUID, die wie eine echte aussieht
702
+ * (D-75). `input_payload` bleibt die eigentliche eingefrorene Wahrheit des
703
+ * Laufs (D-22); `source` erklärt nur, woher sie kam.
704
+ */
705
+ type PromptRunSource = {
706
+ kind: 'published';
707
+ shot_version_id: string;
708
+ scene_setup_version_id: string;
709
+ } | {
710
+ kind: 'draft_chain';
711
+ chain_id: string;
712
+ nodes: readonly {
713
+ type: 'scene' | 'scene_setup' | 'shot';
714
+ element_id: string;
715
+ draft_id: string;
716
+ revision: number;
717
+ }[];
718
+ /**
719
+ * Der Rekonstruktionslauf, aus dem diese Kette entstand (D-123, A2).
720
+ *
721
+ * `DraftChainMeta.source_run_id` trägt das seit 6.6 bereits am Draft;
722
+ * beim Einfrieren wird es additiv in die unveränderliche `source` des
723
+ * entstehenden Prompt-Laufs übernommen, damit Stufe 6.7 die
724
+ * Rekonstruktions-Inputbilder auch dann noch findet, wenn die
725
+ * veränderliche Draft-Kette später nicht mehr existiert. Fehlt bei
726
+ * jedem Lauf von vor 6.7 — nichts wird nachträglich geraten.
727
+ */
728
+ derivation_run_id?: string;
729
+ /** Gesetzt, wenn die Kette aus einer Recovery-Arbeitsfassung kam (D-99). */
730
+ derivation_recovery_id?: string;
731
+ };
732
+ interface PromptRunRecord {
733
+ run_id: string;
734
+ /**
735
+ * Herkunft: die veröffentlichte Shot-Version, aus der der Lauf entstand.
736
+ *
737
+ * Bei einem Lauf aus einer Draft-Kette ist dieses Feld **leer** — dort gibt
738
+ * es keine Version, und eine erfundene wäre von einer echten nicht zu
739
+ * unterscheiden. Wer die Herkunft wissen will, liest `source`.
740
+ */
741
+ shot_version_id: string;
742
+ shot_element_id: string;
743
+ scene_setup_version_id: string;
744
+ camera_id: string;
745
+ target_model_version_id: string;
746
+ provider: string;
747
+ model_id: string;
748
+ system_prompt: string;
749
+ /** Die eingefrorene Zusammensetzung (D-22) — wörtlich, nicht referenziert. */
750
+ input_payload: RendererInput;
751
+ /**
752
+ * Der Ausgang. Ein `failed` ist ein **Erfolg des Systems**: der Nachweis,
753
+ * dass diese Kombination beim Provider anstößt (D-23 §6).
754
+ */
755
+ status: 'succeeded' | 'failed';
756
+ failure: RunFailure | null;
757
+ /** Bei `succeeded` gesetzt, bei `failed` immer `null`. */
758
+ output: PromptRunOutput | null;
759
+ /** Die rohe Modellantwort, soweit es eine gab. */
760
+ raw_output: string | null;
761
+ /**
762
+ * Woher die Eingabe kam (D-98).
763
+ *
764
+ * **Fehlt bei jedem Lauf von vor 6.6.** Alte Laufsätze werden nicht
765
+ * umgeschrieben — sie sind unveränderlich (E-3b) —, und `sourceOf()`
766
+ * normalisiert sie als `published`. Wer das Feld voraussetzt, bricht den
767
+ * Bestand.
768
+ */
769
+ source?: PromptRunSource;
770
+ created_at: string;
771
+ }
772
+ /** Nutzlast des Ereignisses. Identisch mit dem Datensatz — ein Lauf ändert sich nie. */
773
+ type PromptRunRecordedPayload = PromptRunRecord;
774
+ /**
775
+ * Liest alle Läufe aus dem Ereignislog.
776
+ *
777
+ * Bewusst ohne Reducer-Zustandsmaschine: Läufe sind unveränderlich, es gibt
778
+ * kein späteres Ereignis, das einen früheren Lauf ändert. Ein zweiter Eintrag
779
+ * mit derselben `run_id` wäre ein Datenfehler und wird **nicht** stillschweigend
780
+ * überschrieben — der erste gilt, und das ist ehrlich: er war zuerst da.
781
+ */
782
+ declare function collectPromptRuns(events: readonly ElementEvent[]): readonly PromptRunRecord[];
783
+ /** Ein einzelner Lauf aus dem Log, oder `null`. */
784
+ declare function findPromptRun(events: readonly ElementEvent[], runId: string): PromptRunRecord | null;
785
+
786
+ /**
787
+ * Ein Vorschlag, so wie er im Ereignis steht.
788
+ *
789
+ * `adopted_as` hält fest, ob aus diesem Vorschlag ein Draft geworden ist — es
790
+ * ist die einzige Verbindung vom Lauf zum Elementbestand. Sie zeigt auf das
791
+ * Element, nicht auf eine Version: Welche Version daraus später wird,
792
+ * entscheidet die Veröffentlichung, nicht der Lauf.
793
+ */
794
+ interface RecordedProposal {
795
+ type: DerivableType;
796
+ payload: Record<string, unknown>;
797
+ /**
798
+ * `complete`: erfüllt das reguläre Element-Schema.
799
+ * `partial`: erfüllt es bis auf die in `gaps` benannten Pflichtfelder.
800
+ *
801
+ * Steht im Lauf, nicht nur im Arbeitsspeicher: Wer den Vorschlag später
802
+ * übernimmt, muss wissen, dass er einen unvollständigen Draft bekommt — und
803
+ * welche Stellen er zu ergänzen hat, bevor er veröffentlichen kann.
804
+ * Ältere Läufe tragen das Feld nicht; sie sind sämtlich `complete`, weil es
805
+ * vor dem Proposal-Vertrag nichts anderes geben konnte.
806
+ */
807
+ status?: 'complete' | 'partial';
808
+ gaps?: readonly {
809
+ pointer: string;
810
+ reason: string;
811
+ }[];
812
+ /**
813
+ * Der Namensvorschlag des Modells (D-83), sofern es einen brauchbaren gab.
814
+ *
815
+ * Fehlt bei Läufen vor D-83 und bei jedem Lauf, dessen Titel verworfen wurde
816
+ * — ein Titel ist Beiwerk und lässt den Lauf nie scheitern (D-84).
817
+ */
818
+ title?: string;
819
+ }
820
+ /**
821
+ * Die eingefrorene Eingabe — **ohne Bilddaten** (D-73).
822
+ *
823
+ * Base64 gehört nicht in dieses Log: Es ist der autoritative Speicher (D-62)
824
+ * und wird in Flow-FA Pure vollständig geladen. Ein Lauf bleibt über Digest
825
+ * und Herkunft identifizierbar; wiederherstellbar ist ein reiner Upload
826
+ * dadurch nicht, und das ist bewusst in Kauf genommen.
827
+ */
828
+ interface RecordedDerivationInput {
829
+ mode: DerivationInputMode;
830
+ prompt_text: string | null;
831
+ images: readonly ImageProvenance[];
832
+ }
833
+ /** Ein protokollierter Rekonstruktionslauf. */
834
+ interface SceneDerivationRecord {
835
+ run_id: string;
836
+ /** Herkunft der Regel: die veröffentlichte Policy-Version (Konzept §8). */
837
+ policy_version_id: string;
838
+ policy_element_id: string;
839
+ /** In welchem Kontext der Lauf entstand — er bestimmt, wo Drafts landen. */
840
+ context_id: string | null;
841
+ provider: string;
842
+ model_id: string;
843
+ system_prompt: string;
844
+ /** Die eingefrorene Eingabe (D-22/D-73) — wörtlich, nicht referenziert. */
845
+ input: RecordedDerivationInput;
846
+ /**
847
+ * Der Ausgang. Ein `failed` ist ein **Erfolg des Systems**: der Nachweis,
848
+ * dass diese Kombination beim Provider anstößt (D-23 §6).
849
+ */
850
+ status: 'succeeded' | 'failed';
851
+ failure: DerivationFailure | null;
852
+ /** Bei `succeeded` gesetzt, bei `failed` leer. */
853
+ proposals: readonly RecordedProposal[];
854
+ feedback: string | null;
855
+ assumptions: readonly string[];
856
+ not_derivable: readonly NotDerivable[];
857
+ conflicts: readonly DerivationConflict[];
858
+ /** Die rohe Modellantwort, soweit es eine gab. */
859
+ raw_output: string | null;
860
+ /**
861
+ * Woraus dieser Lauf folgt (D-88). Fehlt bei einem ersten Lauf.
862
+ *
863
+ * Ein Folgelauf ist ein eigener Lauf, kein zweiter Versuch im selben: Ein
864
+ * Lauf ist unveränderlich (D-71) und längst geschrieben, wenn der Mensch
865
+ * gefragt wird, ob eine Korrektur folgen soll.
866
+ */
867
+ follows?: DerivationFollowUp;
868
+ /** Antwort des Modells auf die Beanstandung (D-90). */
869
+ reply?: string;
870
+ created_at: string;
871
+ }
872
+ /** Nutzlast des Ereignisses. Identisch mit dem Datensatz — ein Lauf ändert sich nie. */
873
+ type SceneDerivationRecordedPayload = SceneDerivationRecord;
874
+ /**
875
+ * Liest alle Rekonstruktionsläufe aus dem Ereignislog.
876
+ *
877
+ * Bewusst ohne Reducer-Zustandsmaschine: Läufe sind unveränderlich, es gibt
878
+ * kein späteres Ereignis, das einen früheren Lauf ändert. Ein zweiter Eintrag
879
+ * mit derselben `run_id` wäre ein Datenfehler und wird **nicht** stillschweigend
880
+ * überschrieben — der erste gilt, und das ist ehrlich: er war zuerst da.
881
+ */
882
+ declare function collectSceneDerivations(events: readonly ElementEvent[]): readonly SceneDerivationRecord[];
883
+ /** Ein einzelner Lauf aus dem Log, oder `null`. */
884
+ declare function findSceneDerivation(events: readonly ElementEvent[], runId: string): SceneDerivationRecord | null;
885
+
886
+ /** Was bei einer einzelnen Prüfung herauskam. */
887
+ interface ProviderCheckResult {
888
+ kind: string;
889
+ /**
890
+ * `skipped` heißt: **vor** dem Modellaufruf abgebrochen, also kostenlos.
891
+ * `error` heißt: technischer Ausfall — möglicherweise trotzdem bezahlt.
892
+ */
893
+ status: 'succeeded' | 'failed' | 'skipped' | 'error';
894
+ message?: string;
895
+ provider?: string;
896
+ model_id?: string;
897
+ /** Der reguläre Lauf, der dabei entstanden ist. */
898
+ run_id?: string | null;
899
+ persisted?: boolean;
900
+ failure?: unknown;
901
+ excerpt?: string | null;
902
+ proposal_types?: readonly string[];
903
+ not_derivable_count?: number;
904
+ conflict_count?: number;
905
+ duration_ms?: number;
906
+ }
907
+ interface ProviderCheckRecord {
908
+ check_id: string;
909
+ triggered_by: string;
910
+ environment: string;
911
+ /**
912
+ * Die Zahl der tatsächlich abgesetzten Modellaufrufe.
913
+ *
914
+ * Bewusst getrennt von `results.length`: Eine übersprungene Prüfung hat
915
+ * nichts gekostet, und wer später Kosten nachvollziehen will, darf beides
916
+ * nicht verwechseln.
917
+ */
918
+ model_calls: number;
919
+ results: readonly ProviderCheckResult[];
920
+ created_at: string;
921
+ }
922
+ type ProviderCheckRecordedPayload = ProviderCheckRecord;
923
+ /**
924
+ * Liest alle Provider-Checks aus dem Ereignislog.
925
+ *
926
+ * Wie bei den Läufen ohne Reducer: ein Check ist unveränderlich, und ein
927
+ * zweiter Eintrag mit derselben `check_id` wäre ein Datenfehler — der erste
928
+ * gilt.
929
+ */
930
+ declare function collectProviderChecks(events: readonly ElementEvent[]): readonly ProviderCheckRecord[];
931
+ /** Ein einzelner Check aus dem Log, oder `null`. */
932
+ declare function findProviderCheck(events: readonly ElementEvent[], checkId: string): ProviderCheckRecord | null;
933
+ /**
934
+ * Die Zahl der Modellaufrufe über eine Menge von Checks.
935
+ *
936
+ * Eine Stelle, an der summiert wird — sonst zählt die UI anders als der
937
+ * Bericht, und niemand weiß, welche Zahl stimmt.
938
+ */
939
+ declare function totalModelCalls(checks: readonly ProviderCheckRecord[]): number;
940
+
941
+ /** Ein eingefrorener Kettenknoten — die Provenienz des Laufs (D-98). */
942
+ interface FrozenChainNode {
943
+ type: DerivableType;
944
+ element_id: string;
945
+ draft_id: string;
946
+ revision: number;
947
+ }
948
+ interface FreezeSuccess {
949
+ kind: 'ok';
950
+ chainId: string;
951
+ nodes: readonly FrozenChainNode[];
952
+ input: RendererInput;
953
+ /**
954
+ * Der Rekonstruktionslauf, aus dem die Kette entstand (D-123, A2).
955
+ *
956
+ * Alle Knoten einer Kette teilen dieselben Kettenmetadaten (D-96) — die
957
+ * Übernahme entsteht aus **einer** Operation aus **einem** Ursprung —, daher
958
+ * genügt der Wert eines beliebigen erfassten Knotens, hier der des Shots.
959
+ */
960
+ sourceRunId: string;
961
+ /** Gesetzt, wenn der Inhalt der Kette aus einer Recovery-Arbeitsfassung kam. */
962
+ sourceRecoveryId?: string;
963
+ }
964
+ /**
965
+ * Warum eine Kette nicht eingefroren werden konnte.
966
+ *
967
+ * `conflict` ist bewusst von `rejected` getrennt: Das eine ist ein Wettlauf und
968
+ * beim nächsten Versuch weg, das andere ein Mangel der Kette, den jemand
969
+ * beheben muss. Sie gleich zu behandeln hieße, dem Nutzer „nochmal versuchen"
970
+ * für einen unvollständigen Shot anzubieten.
971
+ *
972
+ * `error` kam mit Stufe 6.7.1 (D-125) dazu: **technisch**, nicht fachlich —
973
+ * Netz, Drosselung, Speicher nicht erreichbar. Vor 6.7.1 landete ein solcher
974
+ * Lesefehler beim Einfrieren als `rejected`, und ein HF-429 sah dadurch wie
975
+ * ein Mangel der Kette aus (der reale 429-Durchstich vom 2026-08-13). HF671-10
976
+ * verlangt, dass er stattdessen hier ankommt.
977
+ */
978
+ type FreezeFailure = {
979
+ kind: 'conflict';
980
+ message: string;
981
+ /** Der Knoten, der sich zwischen den beiden Lesedurchgängen änderte. */
982
+ node: {
983
+ type: DerivableType;
984
+ element_id: string;
985
+ draft_id: string;
986
+ };
987
+ expectedRevision: number;
988
+ actualRevision: number;
989
+ } | {
990
+ kind: 'rejected';
991
+ message: string;
992
+ failure?: ResolveFailure;
993
+ } | {
994
+ kind: 'error';
995
+ message: string;
996
+ retryable: boolean;
997
+ };
998
+ type FreezeResult = FreezeSuccess | FreezeFailure;
999
+ /** Ein einzelnes Element aus einer Momentaufnahme — kein Netzzugriff mehr. */
1000
+ interface ChainSnapshot {
1001
+ getElement(elementId: string): {
1002
+ kind: string;
1003
+ message?: string;
1004
+ value?: {
1005
+ element: {
1006
+ element_id: string;
1007
+ type: string;
1008
+ };
1009
+ draft: {
1010
+ draft_id: string;
1011
+ revision: number;
1012
+ payload: unknown;
1013
+ chain?: DraftChainMeta;
1014
+ } | null;
1015
+ draftFork?: unknown | null;
1016
+ } | null;
1017
+ };
1018
+ }
1019
+ /**
1020
+ * Was das Einfrieren vom Elementspeicher braucht — bewusst schmal.
1021
+ *
1022
+ * Seit Stufe 6.7.1 (D-125) keine sechs unabhängigen `getElement()`-Aufrufe
1023
+ * mehr, sondern genau zwei Momentaufnahmen: `readSnapshot({ fresh: false })`
1024
+ * für Durchgang A, `readSnapshot({ fresh: true })` für Durchgang B. „Frisch"
1025
+ * heißt dabei D-125 — inkrementell gegen den Kanal synchronisiert, nicht ein
1026
+ * zweites Mal aus demselben TTL-Cache bedient (sonst könnte B den Konflikt aus
1027
+ * HF671-8/9 nicht mehr sehen).
1028
+ */
1029
+ interface ChainQueries {
1030
+ readSnapshot(options: {
1031
+ fresh: boolean;
1032
+ }): Promise<ChainSnapshot>;
1033
+ }
1034
+ interface FreezeDraftChainInput {
1035
+ /** Das Shot-**Element** der Kette. Eine Version gibt es hier gerade nicht. */
1036
+ shotElementId: string;
1037
+ store: ChainQueries;
1038
+ resolver: ReferenceResolver;
1039
+ contextChain: readonly (string | null)[];
1040
+ userInstruction?: string | null;
1041
+ }
1042
+ /**
1043
+ * Friert die vom Shot erreichbare Draft-Kette ein und baut die Renderer-Eingabe.
1044
+ *
1045
+ * Bei **jedem** Fehlausgang gilt: null Provideraufrufe. Diese Funktion ruft
1046
+ * ohnehin kein Modell — sie liefert nur die Eingabe, und der Aufrufer entscheidet
1047
+ * danach, ob er sie benutzt.
1048
+ */
1049
+ declare function freezeDraftChain(input: FreezeDraftChainInput): Promise<FreezeResult>;
1050
+
1051
+ /**
1052
+ * Wie brauchbar das Material einer Arbeitsfassung ist.
1053
+ *
1054
+ * - `usable` — die Antwort erfuellt den vollen Vertrag; jeder zugesagte
1055
+ * Vorschlag ist verwertbar.
1056
+ * - `partial` — mindestens ein Vorschlag ist verwertbar, aber nicht alles.
1057
+ * - `invalid` — nichts ist verwertbar. Der Text bleibt trotzdem erhalten: Er
1058
+ * ist die Grundlage der naechsten Korrektur.
1059
+ */
1060
+ type RecoveryStatus = 'usable' | 'partial' | 'invalid';
1061
+ /** Eine geprüfte Arbeitsfassung eines fehlgeschlagenen Laufs. */
1062
+ interface SceneDerivationRecoveryRecord {
1063
+ recovery_id: string;
1064
+ /** Der Lauf, aus dem der Text stammt. Über ihn ist das Original erreichbar. */
1065
+ run_id: string;
1066
+ /**
1067
+ * Der geprüfte Text.
1068
+ *
1069
+ * Ob er dem `raw_output` entspricht oder bearbeitet wurde, sagt `edited` —
1070
+ * beides ist zulässig, aber es darf nicht verwechselbar sein. Das Original
1071
+ * ist über `run_id` immer rekonstruierbar; es wird hier **nicht** kopiert
1072
+ * (dieselbe Begründung wie bei D-88: dieselbe große Zeichenkette nicht
1073
+ * zweimal pflegen).
1074
+ */
1075
+ source_text: string;
1076
+ /** `true`, wenn `source_text` vom `raw_output` des Laufs abweicht. */
1077
+ edited: boolean;
1078
+ /** Jeder Befund der Bewertung, in Prüfreihenfolge (6.6/A1). */
1079
+ diagnostics: readonly DerivationDiagnostic[];
1080
+ /**
1081
+ * Die **verwertbaren** Vorschläge, in derselben Form wie im Lauf.
1082
+ *
1083
+ * Bewusst dieselbe Form: Die Graph-Übernahme aus Teil B liest Lauf und
1084
+ * Rettung über denselben Weg, und zwei Vorschlagsformen wären zwei
1085
+ * Wahrheiten (R-2).
1086
+ */
1087
+ proposals: readonly RecordedProposal[];
1088
+ status: RecoveryStatus;
1089
+ created_at: string;
1090
+ }
1091
+ /** Nutzlast des Ereignisses. Identisch mit dem Datensatz — eine Rettung ändert sich nie. */
1092
+ type SceneDerivationRecoveryRecordedPayload = SceneDerivationRecoveryRecord;
1093
+ /**
1094
+ * Leitet den Status aus der Bewertung ab.
1095
+ *
1096
+ * Bewusst genau drei Werte und kein `ok: boolean`: „alles gut", „etwas ist zu
1097
+ * holen" und „hier ist nichts" sind drei verschiedene Auskünfte, und die
1098
+ * mittlere ist die, für die es diese Stufe überhaupt gibt.
1099
+ */
1100
+ declare function recoveryStatusOf(assessment: DerivationAssessment): RecoveryStatus;
1101
+ /**
1102
+ * Liest alle Arbeitsfassungen aus dem Ereignislog.
1103
+ *
1104
+ * Wie bei den Läufen ohne Reducer: Eine Rettung ist unveränderlich, und es gibt
1105
+ * kein späteres Ereignis, das eine frühere ändert. Ein zweiter Eintrag zur
1106
+ * gleichen `recovery_id` ist ein Datenfehler; der erste gilt, weil er zuerst
1107
+ * da war.
1108
+ *
1109
+ * **Mehrere Rettungen zum selben Lauf sind der Normalfall**, kein Fehler: Wer
1110
+ * einen kaputten Rohtext zweimal korrigiert, hat zweimal gearbeitet, und beide
1111
+ * Fassungen bleiben nachvollziehbar (D-99).
1112
+ */
1113
+ declare function collectSceneDerivationRecoveries(events: readonly ElementEvent[]): readonly SceneDerivationRecoveryRecord[];
1114
+ /** Eine einzelne Arbeitsfassung aus dem Log, oder `null`. */
1115
+ declare function findSceneDerivationRecovery(events: readonly ElementEvent[], recoveryId: string): SceneDerivationRecoveryRecord | null;
1116
+ /** Alle Arbeitsfassungen zu einem Lauf, in Anhängereihenfolge. */
1117
+ declare function recoveriesForRun(events: readonly ElementEvent[], runId: string): readonly SceneDerivationRecoveryRecord[];
1118
+
1119
+ /** Präfix jeder Item-Kennung dieser Domain (E4-4). */
1120
+ declare const SZENEN_ITEM_PREFIX = "szn-";
1121
+ /** Die Item-Kennung zu einem Lauf. Deterministisch — das ist der Zweck (E4-4). */
1122
+ declare function itemIdForRun(runId: string): string;
1123
+ /** Ob eine Item-Kennung aus dieser Domain stammt — ohne JSON-Zugriff erkennbar. */
1124
+ declare function isSzenenItemId(itemId: string): boolean;
1125
+ /**
1126
+ * Die Herkunft eines Bild-Batches im vorhandenen `metadata.szenen`-Block
1127
+ * (D-114) — erweitert, nicht dupliziert. Modell, Seed und Dimensionen bleiben
1128
+ * bewusst aussen vor: Sie stehen in `item_images` und werden hier nicht
1129
+ * gespiegelt.
1130
+ *
1131
+ * **Seit dem Nutzerentscheid vom 2026-08-15 kein eigener Namensraum mehr**:
1132
+ * Ein Prompt-Lauf ist fachlich ein Prompt, unabhaengig davon, ob er als
1133
+ * Stufe-4-„Runde" gespeichert oder in Stufe 6.7 bebildert wurde — beides
1134
+ * landet im selben Item unter `itemIdForRun(runId)`. `generation_batch_ids`
1135
+ * ist deshalb **plural und append-only**: jeder weitere Klick auf „Bilder
1136
+ * erzeugen" fuer denselben Lauf haengt seine Bilder an dasselbe Item an,
1137
+ * statt ein neues zu erzeugen. (Vormals `itemIdForBatch(runId, batchId)` und
1138
+ * ein singulaeres `generation_batch_id` — D-113/D-121 wurden entsprechend
1139
+ * korrigiert, siehe `decisions/register.md`.)
1140
+ */
1141
+ interface SzenenBatchOrigin {
1142
+ prompt_run_id: string;
1143
+ generation_batch_ids: readonly string[];
1144
+ source_kind: 'generated_in_app' | 'external_import';
1145
+ /** Nur Anzeige, wenn fachlich sicher bestimmbar — nie Pflicht (D-121). */
1146
+ round?: number;
1147
+ }
1148
+ type SzenenBatchOriginFailure = {
1149
+ field: 'prompt_run_id' | 'generation_batch_id';
1150
+ message: string;
1151
+ } | {
1152
+ field: 'source_kind';
1153
+ message: string;
1154
+ };
1155
+ type SzenenBatchOriginVerdict = {
1156
+ kind: 'ok';
1157
+ value: SzenenBatchOrigin;
1158
+ } | {
1159
+ kind: 'rejected';
1160
+ failure: SzenenBatchOriginFailure;
1161
+ };
1162
+ /**
1163
+ * Prueft **einen einzelnen** neuen Batch-Beitrag, bevor er in
1164
+ * `metadata.szenen` geschrieben wird.
1165
+ *
1166
+ * Bewusst schmal: Diese Funktion kennt weder den Lauf noch eine eventuell
1167
+ * bereits bestehende Herkunft — sie prueft nur, ob DIESER eine Beitrag fuer
1168
+ * sich genommen gueltig ist, und liefert ihn als Einzelelement-Array zurueck.
1169
+ * Das Vereinigen mit einer bestehenden Herkunft (falls das Item schon
1170
+ * existiert) uebernimmt `mergeSzenenBatchOrigin()` — der Aufrufer kennt den
1171
+ * Bestand, diese Funktion nicht (D-109 — keine Textsuche hier).
1172
+ */
1173
+ declare function checkSzenenBatchOrigin(candidate: {
1174
+ prompt_run_id?: unknown;
1175
+ generation_batch_id?: unknown;
1176
+ source_kind?: unknown;
1177
+ round?: unknown;
1178
+ }): SzenenBatchOriginVerdict;
1179
+ /**
1180
+ * Vereinigt eine neu geprüfte Batch-Herkunft mit einer bereits am Item
1181
+ * vorhandenen — der Kern des „ein Prompt bleibt ein Item"-Entscheids.
1182
+ *
1183
+ * `generation_batch_ids` wird vereinigt (keine Duplikate, bestehende
1184
+ * Reihenfolge bleibt vorn). `source_kind` und `round` bleiben vom **ersten**
1185
+ * Schreiber: Ein zweiter Batch soll nicht rückwirkend behaupten, die Herkunft
1186
+ * sei eine andere gewesen. Fehlt `bestehend` (erster Schreiber überhaupt),
1187
+ * gilt `neu` unverändert.
1188
+ */
1189
+ declare function mergeSzenenBatchOrigin(bestehend: SzenenBatchOrigin | undefined, neu: SzenenBatchOrigin): SzenenBatchOrigin;
1190
+ /**
1191
+ * Ein bereits gespeichertes Szenen-Item, so viel wie die Ableitung braucht.
1192
+ *
1193
+ * `sequence` ist die **Speicherreihenfolge** (im Server die `user_library.id`),
1194
+ * nicht die Runde. Beide fallen im Normalfall zusammen und genau dann
1195
+ * auseinander, wenn rückwärts gespeichert wurde — und dieser Fall ist der
1196
+ * Grund, warum das Feld existiert.
1197
+ */
1198
+ interface ExistingSzenenItem {
1199
+ item_id: string;
1200
+ prompt_run_id: string;
1201
+ round: number;
1202
+ generation: number;
1203
+ lineage_root_id: string;
1204
+ sequence: number;
1205
+ valid: boolean;
1206
+ }
1207
+ interface DerivedLineage {
1208
+ parent_item_id: string | null;
1209
+ lineage_root_id: string;
1210
+ generation: number;
1211
+ /** Der Elternteil stammt aus einer **späteren** Runde als dieses Item (A3). */
1212
+ out_of_order: boolean;
1213
+ }
1214
+ /** Die Prompt-Run-Referenz am Item (§4.4). Herkunft, kein Inhalt. */
1215
+ interface DerivedSzenenReference {
1216
+ prompt_run_id: string;
1217
+ shot_version_id: string;
1218
+ shot_element_id: string;
1219
+ scene_setup_version_id: string;
1220
+ camera_id: string;
1221
+ target_model_version_id: string;
1222
+ provider: string;
1223
+ model_id: string;
1224
+ run_created_at: string;
1225
+ /** Stand zum Speicherzeitpunkt — ausdrücklich nicht neu berechnen (§4.6). */
1226
+ round: number;
1227
+ /** Es gibt in Stufe 4 keinen Draft (E4-2). Das Feld hält den Vertrag offen. */
1228
+ created_from_draft_id: string | null;
1229
+ saved_at: string;
1230
+ }
1231
+ /** Eine Lineage-Kante im **Bestandsformat**, damit `LibraryTab` das Item sieht. */
1232
+ interface DerivedRelationship {
1233
+ type: 'parent';
1234
+ id: string;
1235
+ role: string;
1236
+ }
1237
+ /**
1238
+ * Der fertige Item-Entwurf.
1239
+ *
1240
+ * Bewusst in der Sprache des Bestands (`content`, `negative_prompt`, `title`),
1241
+ * nicht in einer neuen: Der Aufrufer reicht das unverändert an
1242
+ * `saveGeneratedAsset` weiter, und jede Umbenennung hier wäre eine
1243
+ * Übersetzungsschicht, die auseinanderlaufen kann.
1244
+ */
1245
+ interface DerivedItem {
1246
+ item_id: string;
1247
+ title: string;
1248
+ /** Der positive Prompt — das bestehende Prompt-Feld (Kompatibilitätszusage §8). */
1249
+ content: string;
1250
+ negative_prompt: string | null;
1251
+ notes: string;
1252
+ rating: number;
1253
+ fsk_level: string;
1254
+ /** Immer leer: das Tag-System wird in den Stufen 1–4 nicht angefasst (R-6/E4-7). */
1255
+ tags: readonly never[];
1256
+ szenen: DerivedSzenenReference;
1257
+ lineage: DerivedLineage;
1258
+ relationships: readonly DerivedRelationship[];
1259
+ }
1260
+ type ItemDerivationFailureClass = 'run_failed' | 'run_without_output' | 'run_not_among_siblings';
1261
+ interface ItemDerivationFailure {
1262
+ class: ItemDerivationFailureClass;
1263
+ message: string;
1264
+ /** Bei `run_failed`: warum der Lauf scheiterte — der Aufrufer soll es nennen. */
1265
+ run_failure?: PromptRunRecord['failure'];
1266
+ }
1267
+ type ItemDerivationResult = {
1268
+ kind: 'ok';
1269
+ value: DerivedItem;
1270
+ } | {
1271
+ kind: 'rejected';
1272
+ failure: ItemDerivationFailure;
1273
+ };
1274
+ interface DeriveItemInput {
1275
+ /** Der ausgewählte Lauf, aus dem autoritativen Log gelesen. */
1276
+ run: PromptRunRecord;
1277
+ /**
1278
+ * **Alle** Läufe derselben `shot_version_id`, in der Reihenfolge, die
1279
+ * `collectPromptRuns` liefert. Sie bestimmen die Rundennummer.
1280
+ */
1281
+ runsOfShot: readonly PromptRunRecord[];
1282
+ /** Bereits gespeicherte Items desselben Shots — auch soft-gelöschte. */
1283
+ existingItems: readonly ExistingSzenenItem[];
1284
+ /** Titel des Shot-Elements, sofern bekannt. Wird nie geraten. */
1285
+ shotTitle?: string | null;
1286
+ /** Wahl des Aufrufers; leer bedeutet „ableiten". */
1287
+ title?: string | null;
1288
+ notes?: string | null;
1289
+ rating?: number | null;
1290
+ fskLevel?: string | null;
1291
+ /** Zeitpunkt des Speicherns, ISO-8601. */
1292
+ savedAt: string;
1293
+ }
1294
+ /**
1295
+ * Die Rundennummer eines Laufs: sein 1-basierter Platz unter den Läufen des
1296
+ * Shots.
1297
+ *
1298
+ * `0`, wenn der Lauf nicht dabei ist — das ist ein Aufrufer-Fehler und wird von
1299
+ * `deriveItemFromRun` als solcher gemeldet, nicht mit einer erfundenen Nummer
1300
+ * überdeckt.
1301
+ */
1302
+ declare function roundOfRun(run: PromptRunRecord, runsOfShot: readonly PromptRunRecord[]): number;
1303
+ /**
1304
+ * Bestimmt die Kette (§5.4).
1305
+ *
1306
+ * Maßgeblich ist die **Speicherreihenfolge**, nicht die Rundenreihenfolge —
1307
+ * Annahme A3 des library-Events sagt das wörtlich für den Rückwärtsfall, und
1308
+ * eine Regel, die nur im Normalfall gilt, ist keine.
1309
+ *
1310
+ * Soft-gelöschte Items scheiden aus: Der Nutzer hat sie entfernt, und jeder
1311
+ * Lesepfad des Bestands filtert `valid = 1`. Ein unsichtbarer Elternteil
1312
+ * erzeugte einen Baum mit Loch.
1313
+ */
1314
+ declare function deriveLineage(ownItemId: string, ownRound: number, existingItems: readonly ExistingSzenenItem[]): DerivedLineage;
1315
+ /**
1316
+ * Leitet aus einer ausgewählten Runde das Item ab.
1317
+ *
1318
+ * Gibt `rejected` zurück, wo ein Item fachlich nicht entstehen darf — und wirft
1319
+ * nicht: Der Aufrufer soll den Grund in eine HTTP-Antwort übersetzen können,
1320
+ * ohne einen Ausnahmetext zu zerlegen.
1321
+ */
1322
+ declare function deriveItemFromRun(input: DeriveItemInput): ItemDerivationResult;
1323
+
1324
+ /** Nutzlast von `imageGenerationStarted` — geschrieben vor dem Provideraufruf. */
1325
+ interface ImageGenerationStartedPayload {
1326
+ generation_batch_id: string;
1327
+ prompt_run_id: string;
1328
+ /** Nur `generated_in_app`: ein externer Import braucht kein `started` (D-119). */
1329
+ source_kind: 'generated_in_app';
1330
+ request: {
1331
+ image_count: number;
1332
+ aspect_ratio?: string;
1333
+ seeds?: readonly number[];
1334
+ callable_model_id: string;
1335
+ };
1336
+ created_at: string;
1337
+ }
1338
+ /** Nutzlast von `imageGenerationFinished` — geschrieben nach der Batch-Persistenz. */
1339
+ interface ImageGenerationFinishedPayload {
1340
+ generation_batch_id: string;
1341
+ status: 'succeeded' | 'partial' | 'failed';
1342
+ /** Gesetzt bei `succeeded`/`partial`; bei `failed` gibt es kein Item (D-111). */
1343
+ item_id?: string;
1344
+ produced_count: number;
1345
+ diagnostic?: string;
1346
+ finished_at: string;
1347
+ }
1348
+ /**
1349
+ * Der Auftrag, wie ein Leser ihn sieht — die Faltung von `started` und dem
1350
+ * (ggf. noch fehlenden) `finished`.
1351
+ *
1352
+ * `status: 'started'` deckt sowohl „laeuft gerade" als auch „zwischen den
1353
+ * beiden Ereignissen abgebrochen" ab — aus dem Log allein ist das nicht
1354
+ * unterscheidbar, und genau das ist beabsichtigt (D-119): Es gibt **keinen**
1355
+ * automatischen Retry, der diese Unterscheidung bräuchte. Die Ansicht darf den
1356
+ * Zustand als „gestartet/unterbrochen" beschriften; der Nutzer entscheidet
1357
+ * sichtbar über einen neuen Versuch.
1358
+ */
1359
+ interface ImageGenerationOrder {
1360
+ generation_batch_id: string;
1361
+ prompt_run_id: string;
1362
+ source_kind: 'generated_in_app';
1363
+ request: ImageGenerationStartedPayload['request'];
1364
+ created_at: string;
1365
+ status: 'started' | 'succeeded' | 'partial' | 'failed';
1366
+ item_id?: string;
1367
+ produced_count?: number;
1368
+ diagnostic?: string;
1369
+ finished_at?: string;
1370
+ }
1371
+ /**
1372
+ * Liest alle Bildgenerierungsauftraege aus dem Ereignislog.
1373
+ *
1374
+ * Wie bei `collectPromptRuns`: bewusst ohne Reducer-Zustandsmaschine. Ein
1375
+ * zweites `started` zur selben `generation_batch_id` ist ein Datenfehler und
1376
+ * wird nicht stillschweigend ueberschrieben — das erste gilt. Ein `finished`
1377
+ * ohne passendes `started` wird ignoriert: Fuer `generated_in_app` ist
1378
+ * `started` durch D-119 zwingend vorgeschaltet, und ein Ereignis ohne
1379
+ * Gegenstueck waere kein gueltiger Auftrag, den diese Projektion erfinden
1380
+ * duerfte.
1381
+ */
1382
+ declare function collectImageGenerationOrders(events: readonly ElementEvent[]): readonly ImageGenerationOrder[];
1383
+ /** Alle Auftraege eines Prompt-Laufs, in Erfassungsreihenfolge. */
1384
+ declare function ordersForPromptRun(events: readonly ElementEvent[], runId: string): readonly ImageGenerationOrder[];
1385
+ /** Ein einzelner Auftrag, oder `null`. */
1386
+ declare function findImageGenerationOrder(events: readonly ElementEvent[], batchId: string): ImageGenerationOrder | null;
1387
+
1388
+ /**
1389
+ * Zugang zum Event-Kanal. Bewusst schmal: lesen und anhängen.
1390
+ *
1391
+ * Der HF-Kanal kennt weder Transaktionen noch Preconditions — das ist keine
1392
+ * Lücke dieser Schnittstelle, sondern die Eigenschaft, um die herum der
1393
+ * Reducer gebaut ist.
1394
+ */
1395
+ interface ElementEventChannel {
1396
+ /** Alle Szenen-Events. Reihenfolge egal, der Reducer sortiert selbst. */
1397
+ readEvents(): Promise<readonly ElementEvent[]>;
1398
+ /** Hängt ein Event an. Der Kanal vergibt `clientId` und `ts`. */
1399
+ appendEvent(type: string, payload: unknown): Promise<void>;
1400
+ }
1401
+ /** Erzeugt Kennungen. Injizierbar, damit Tests deterministisch bleiben. */
1402
+ interface IdFactory {
1403
+ newId(): string;
1404
+ }
1405
+ interface CreateHfElementStoreOptions {
1406
+ channel: ElementEventChannel;
1407
+ ids?: IdFactory;
1408
+ /**
1409
+ * Die wirksame Kontextkette — Stufe 3, S1b.
1410
+ *
1411
+ * Wird sie übergeben, kann der Publish-Pfad P-17 tatsächlich prüfen. Fehlt
1412
+ * sie, bleibt die Regel **ungeprüft** und besteht nicht still. Ein Host ohne
1413
+ * Kontextgraph (Flow-FA Pure) lässt sie weg; der Server reicht seinen Adapter
1414
+ * über `contexts/context_inheritance` herein.
1415
+ */
1416
+ contexts?: ContextChainPort;
1417
+ /**
1418
+ * Wie lange ein gelesener Zustand wiederverwendet werden darf, in
1419
+ * Millisekunden. `0` liest bei jedem Zugriff neu. Der Cache ist reine
1420
+ * Beschleunigung und **niemals** Grundlage einer Konfliktentscheidung —
1421
+ * vor jedem Schreibversuch wird frisch gelesen.
1422
+ */
1423
+ cacheMs?: number;
1424
+ now?: () => number;
1425
+ }
1426
+ /**
1427
+ * Prüfungen, die dieser Port strukturell nicht leisten kann — **heute keine**.
1428
+ *
1429
+ * Bis D-58 stand hier P-01…P-16, mit der Begründung, sie bräuchten Graph- und
1430
+ * Datenbankzugriff. Seitdem laufen sie wirklich, über den `ReferenceResolver`,
1431
+ * den beide Speicher erfüllen; die Konstante ist leer und bleibt als leeres
1432
+ * Rückgabefeld erhalten.
1433
+ *
1434
+ * Was in einem **konkreten** Lauf nicht anwendbar war, steht nicht hier,
1435
+ * sondern in `PublishCheckResult.unchecked` — und nur dort ist es wahr. Die
1436
+ * Konstante als Antwortfeld auszugeben war der Gegenprüffund P3: ein toter
1437
+ * Pfad, der aussah wie eine Aussage.
1438
+ */
1439
+ declare const UNCHECKED_PUBLISH_RULES: readonly string[];
1440
+ /**
1441
+ * Baut den HF-Elementspeicher.
1442
+ *
1443
+ * Erfüllt `SzenenElementStore` vollständig — dieselbe Schnittstelle, die der
1444
+ * MySQL-Port in Stufe 1d erfüllen muss (Contract-Test, Plan §7).
1445
+ *
1446
+ * Seit D-62 ist dieser Speicher der **autoritative**: HF ist der einzige
1447
+ * Untergrund, den alle drei Hosts haben, und damit der einzige, in dem die eine
1448
+ * fachliche Wahrheit liegen kann. Der Rückgabetyp sagt das jetzt.
1449
+ */
1450
+ declare function createHfElementStore(options: CreateHfElementStoreOptions): AuthoritativeSzenenStore & ChainQueries;
1451
+
1452
+ interface CreateHfEventChannelOptions {
1453
+ /** HF-Namespace mit abschließendem Schrägstrich, wie in `hfStateService`. */
1454
+ namespace: string;
1455
+ token: string;
1456
+ /**
1457
+ * Nur Events ab diesem Zeitpunkt lesen. Vorgabe `0` — der vollständige Log.
1458
+ *
1459
+ * Ein Snapshot-Mechanismus wie `loadHFState` für Bilder gibt es für Elemente
1460
+ * noch nicht; solange bleibt der volle Log die einzige Wahrheit. Das ist der
1461
+ * Punkt, an dem der Server später beschleunigt (R-2), ohne die einzige
1462
+ * Stelle zu werden, an der eine Invariante gilt.
1463
+ */
1464
+ sinceTs?: number;
1465
+ }
1466
+ /**
1467
+ * Baut einen `ElementEventChannel` auf dem HF-Dataset.
1468
+ *
1469
+ * Erfordert nur einen HF-Token — kein Server, keine Datenbank. Das ist die
1470
+ * Zusage von R-2 für Flow-FA Pure.
1471
+ */
1472
+ declare function createHfEventChannel(options: CreateHfEventChannelOptions): ElementEventChannel;
1473
+
1474
+ interface InMemoryEventChannel extends ElementEventChannel {
1475
+ /** Der rohe Log, für Prüfungen. */
1476
+ readonly events: readonly ElementEvent[];
1477
+ /** Hängt ein Fremdevent an — der HF-Kanal wird von mehreren Domains geteilt. */
1478
+ appendRaw(event: ElementEvent): void;
1479
+ /** Ein zweiter Client auf demselben Log. */
1480
+ withClient(clientId: string): InMemoryEventChannel;
1481
+ }
1482
+ interface CreateInMemoryEventChannelOptions {
1483
+ clientId?: string;
1484
+ /** Monoton steigender Zeitgeber. Der Vorgabewert genügt für Tests. */
1485
+ now?: () => number;
1486
+ /** Gemeinsamer Log, wenn mehrere Clients denselben Kanal teilen. */
1487
+ shared?: ElementEvent[];
1488
+ }
1489
+ declare function createInMemoryEventChannel(options?: CreateInMemoryEventChannelOptions): InMemoryEventChannel;
1490
+
1491
+ /** Ergebnis einer Eingabeprüfung. `null` heißt: in Ordnung. */
1492
+ type InputError = {
1493
+ kind: 'error';
1494
+ message: string;
1495
+ retryable: false;
1496
+ } | null;
1497
+ /**
1498
+ * Eine Revision, wie sie als Precondition taugt: ganzzahlig und nicht negativ.
1499
+ *
1500
+ * `NaN` ist der wichtigste Fall. `Number('abc')` ergibt ihn, und `NaN !== 0`
1501
+ * ist wahr — ohne diese Prüfung wurde daraus ein **Konflikt** statt eines
1502
+ * Eingabefehlers, gemeldet mit `expectedRevision: null`. Der Aufrufer bekam
1503
+ * die Auskunft, jemand anders habe geschrieben; wer daraufhin der
1504
+ * Konfliktregel folgte, scheiterte weiter.
1505
+ */
1506
+ declare function checkRevision(value: unknown, field: string): InputError;
1507
+ /** Ein Elementtyp aus dem Katalog der zwölf. */
1508
+ declare function checkElementType(value: unknown): InputError;
1509
+ /** Ein nicht leerer Titel. Reine Leerzeichen zählen nicht. */
1510
+ declare function checkTitle(value: unknown): InputError;
1511
+ /** Eine optionale Kennung: `null`, `undefined` oder ein nicht leerer Text. */
1512
+ declare function checkOptionalId(value: unknown, field: string): InputError;
1513
+ /** Eine Kennung, die gesetzt sein muss. */
1514
+ declare function checkRequiredId(value: unknown, field: string): InputError;
1515
+ /**
1516
+ * Die Parent-Liste einer Veröffentlichung.
1517
+ *
1518
+ * `parents: 'kaputt'` erzeugte zuvor einen `TypeError` aus dem eigenen Code
1519
+ * (`parents.map is not a function`), der als „Dienst nicht verfügbar" beim
1520
+ * Aufrufer ankam — samt interner Fehlermeldung.
1521
+ */
1522
+ declare function checkParents(value: unknown): InputError;
1523
+ /** Eine Payload, die überhaupt eine sein kann. */
1524
+ declare function checkPayloadPresent(value: unknown): InputError;
1525
+ /** Die erste greifende Prüfung, oder `null`. */
1526
+ declare function firstError(...checks: readonly InputError[]): InputError;
1527
+ declare function checkCreateElementInput(input: {
1528
+ type: unknown;
1529
+ title: unknown;
1530
+ subtype?: unknown;
1531
+ contextId?: unknown;
1532
+ }): InputError;
1533
+ declare function checkWriteDraftInput(input: {
1534
+ elementId: unknown;
1535
+ payload: unknown;
1536
+ expectedRevision: unknown;
1537
+ baseVersionId?: unknown;
1538
+ }): InputError;
1539
+ declare function checkPublishVersionInput(input: {
1540
+ elementId: unknown;
1541
+ payload: unknown;
1542
+ schemaVersion: unknown;
1543
+ parents?: unknown;
1544
+ publishedBy: unknown;
1545
+ }): InputError;
1546
+ declare function checkSetPreferredHeadInput(input: {
1547
+ elementId: unknown;
1548
+ contextId: unknown;
1549
+ versionId: unknown;
1550
+ expectedRevision: unknown;
1551
+ }): InputError;
1552
+ declare function checkReviseMetadataInput(input: {
1553
+ elementId: unknown;
1554
+ title: unknown;
1555
+ expectedRevision: unknown;
1556
+ }): InputError;
1557
+ /** Bequemlichkeit für Aufrufer, die den Typ eng brauchen. */
1558
+ declare const isKnownElementType: (value: unknown) => value is SzenenElementType;
1559
+
1560
+ /** Ein Schritt der verglichenen Befehlsfolge. */
1561
+ interface DifferentialStep {
1562
+ name: string;
1563
+ /** Führt den Schritt aus und gibt zurück, was verglichen werden soll. */
1564
+ run(store: SzenenElementStore, state: StepState): Promise<unknown>;
1565
+ }
1566
+ /** Zwischenergebnisse einer Folge — je Port eigene Kennungen. */
1567
+ interface StepState {
1568
+ elementId: string;
1569
+ versionIds: string[];
1570
+ draftId: string | null;
1571
+ }
1572
+ /** Ein Unterschied zwischen den beiden Läufen. */
1573
+ interface Divergence {
1574
+ step: string;
1575
+ left: string;
1576
+ right: string;
1577
+ }
1578
+ interface DifferentialResult {
1579
+ steps: number;
1580
+ divergences: readonly Divergence[];
1581
+ identical: boolean;
1582
+ }
1583
+ /** Die verglichene Befehlsfolge. Deckt Erfolg, Konflikt, Ablehnung und Lesen ab. */
1584
+ declare function differentialSteps(): readonly DifferentialStep[];
1585
+ /**
1586
+ * Fährt dieselbe Folge gegen zwei Speicher und vergleicht die Ergebnisse.
1587
+ *
1588
+ * @param left Fabrik für den ersten Speicher, frisch und leer.
1589
+ * @param right Fabrik für den zweiten.
1590
+ */
1591
+ declare function runStoreDifferential(left: () => Promise<SzenenElementStore> | SzenenElementStore, right: () => Promise<SzenenElementStore> | SzenenElementStore): Promise<DifferentialResult>;
1592
+
1593
+ /** Ein aufrufbares Bildmodell und seine Parametergrenzen. */
1594
+ interface CallableImageModel {
1595
+ callable_model_id: string;
1596
+ provider: string;
1597
+ max_images: number;
1598
+ aspect_ratios: readonly string[];
1599
+ supports_seed: boolean;
1600
+ }
1601
+ /** Die katalogisierte Zuordnung für einen `target_model.key`, oder `null`. */
1602
+ declare function callableImageModelFor(targetModelKey: string): CallableImageModel | null;
1603
+ /** Der Ausgang der Fähigkeitsauskunft (D-115). */
1604
+ type ImageGenerationCapability = {
1605
+ kind: 'supported';
1606
+ target_model_key: string;
1607
+ provider: string;
1608
+ callable_model_id: string;
1609
+ max_images: number;
1610
+ aspect_ratios: readonly string[];
1611
+ supports_seed: boolean;
1612
+ } | {
1613
+ kind: 'unsupported';
1614
+ target_model_key: string;
1615
+ reason: string;
1616
+ };
1617
+ /**
1618
+ * Ob **dieser Host** tatsächlich Zugang zu einem katalogisierten Bildmodell
1619
+ * hat — die einzige Stelle, an der Host-Wissen einfließen darf, und zwar als
1620
+ * Funktionsparameter, nicht als Verzweigung im gemeinsamen Code (R-1).
1621
+ */
1622
+ type ImageProviderAccessCheck = (model: CallableImageModel) => boolean;
1623
+ /**
1624
+ * Die Fähigkeitsauskunft: aus dem eingefrorenen `target_model` (D-103) und
1625
+ * der Zugangsauskunft des Hosts entsteht `supported` oder `unsupported`.
1626
+ *
1627
+ * `unsupported` ist kein Fehler und blockiert nichts (D-104.5) — der
1628
+ * Prompt-Lauf bleibt vollständig nutzbar und bekommt Ergebnisse über den
1629
+ * externen Importpfad (Teil D).
1630
+ */
1631
+ declare function capabilityForTargetModel(targetModel: unknown, hasAccess: ImageProviderAccessCheck): ImageGenerationCapability;
1632
+
1633
+ /** Ein tatsächlich vom Provider geliefertes Bild. */
1634
+ interface GeneratedImage {
1635
+ imageBase64: string;
1636
+ /** Nur gesetzt, wenn der Provider ihn tatsächlich zurückliefert — nie erfunden (D-107). */
1637
+ seed?: number;
1638
+ model?: string;
1639
+ width?: number;
1640
+ height?: number;
1641
+ }
1642
+ /** Die Eingabe an den tatsächlichen Provideraufruf — abgeleitet aus dem eingefrorenen Lauf. */
1643
+ interface ImageProviderInput {
1644
+ callableModelId: string;
1645
+ provider: string;
1646
+ positivePrompt: string;
1647
+ negativePrompt?: string | null;
1648
+ imageCount: number;
1649
+ aspectRatio?: string;
1650
+ seeds?: readonly number[];
1651
+ }
1652
+ /**
1653
+ * Der tatsächliche Bildprovider — liegt im Client, wo die Credentials sind
1654
+ * (D-116). Wirft bei einem technischen/Provider-Fehler; liefert bei einem
1655
+ * Teilerfolg weniger Bilder als angefordert, statt zu werfen.
1656
+ */
1657
+ interface ImageGenerationProviderPort {
1658
+ generate(input: ImageProviderInput): Promise<{
1659
+ images: readonly GeneratedImage[];
1660
+ }>;
1661
+ }
1662
+ /** Nur die Lesefähigkeit, die dieser Port braucht — kein voller Run-Port. */
1663
+ interface ImageGenerationRunReader {
1664
+ getRun(runId: string): Promise<QueryResult<PromptRunRecord | null>>;
1665
+ }
1666
+ /**
1667
+ * Die kanonische Persistenz eines fertigen Batches — beim React-Host ein
1668
+ * REST-Aufruf auf denselben Weg wie `SzenenImageBatchWritePort.importBatch`,
1669
+ * nur mit `source_kind: 'generated_in_app'` (Teil C).
1670
+ */
1671
+ interface ImageGenerationBatchPersistence {
1672
+ persist(input: {
1673
+ runId: string;
1674
+ generationBatchId: string;
1675
+ images: readonly GeneratedImage[];
1676
+ }): Promise<CommandResult<PromptImageBatch>>;
1677
+ }
1678
+ /** Was der Auftragskanal (D-119) braucht — lesen und anhängen, wie `RunEventChannel`. */
1679
+ interface ImageGenerationEventChannel {
1680
+ appendEvent(type: string, payload: unknown): Promise<void>;
1681
+ }
1682
+ interface StartImageGenerationInput {
1683
+ runId: string;
1684
+ /** Vom Aufrufer VOR dem Aufruf gebildet (D-113) — deterministisch mit dem Lauf verknüpft. */
1685
+ generationBatchId: string;
1686
+ imageCount: number;
1687
+ aspectRatio?: string;
1688
+ /** Je Bild, wenn das Modell Seeds kennt. */
1689
+ seeds?: readonly number[];
1690
+ }
1691
+ /** Die vier Ausgänge aus D-111, plus `rejected` für einen ungültigen Lauf. */
1692
+ type ImageGenerationResult = {
1693
+ kind: 'succeeded';
1694
+ batch: PromptImageBatch;
1695
+ } | {
1696
+ kind: 'partial';
1697
+ batch: PromptImageBatch;
1698
+ requested: number;
1699
+ produced: number;
1700
+ } | {
1701
+ kind: 'failed';
1702
+ message: string;
1703
+ } | {
1704
+ kind: 'unsupported';
1705
+ targetModelKey: string;
1706
+ reason: string;
1707
+ } | {
1708
+ kind: 'rejected';
1709
+ message: string;
1710
+ };
1711
+ interface SzenenImageGenerationPort {
1712
+ capabilityForRun(runId: string): Promise<QueryResult<ImageGenerationCapability>>;
1713
+ startFromPromptRun(input: StartImageGenerationInput): Promise<ImageGenerationResult>;
1714
+ }
1715
+ interface CreateImageGenerationPortOptions {
1716
+ runs: ImageGenerationRunReader;
1717
+ provider: ImageGenerationProviderPort;
1718
+ batches: ImageGenerationBatchPersistence;
1719
+ events: ImageGenerationEventChannel;
1720
+ /** Ob dieser Host Zugang zu einem katalogisierten Bildmodell hat (D-115). */
1721
+ hasAccess: ImageProviderAccessCheck;
1722
+ now?: () => Date;
1723
+ }
1724
+ /** Der gemeinsame Bildgenerierungs-Port. */
1725
+ declare function createImageGenerationPort(options: CreateImageGenerationPortOptions): SzenenImageGenerationPort;
1726
+
1727
+ /**
1728
+ * Ein Prompt-Lauf starten.
1729
+ *
1730
+ * Die View übergibt, was der Nutzer gewählt hat — nicht, was daraus folgt. Sie
1731
+ * baut **keinen** `RendererInput` und **keinen** Prompt: das tut
1732
+ * `runPromptDerivation()` hinter dem Port, in jedem Host derselbe Code (U20).
1733
+ */
1734
+ interface StartRunInput {
1735
+ /** Die veröffentlichte Shot-Version, für die der Lauf läuft. */
1736
+ shotVersionId: string;
1737
+ /** Freitext des Nutzers, optional — geht als Anweisung in den Lauf. */
1738
+ userInstruction?: string;
1739
+ /**
1740
+ * Arbeitskontext. Die wirksame Kette löst der Host über den
1741
+ * `ContextChainPort` auf; die View kennt sie nicht.
1742
+ */
1743
+ contextId?: string | null;
1744
+ }
1745
+ /** Lesen und Starten von Prompt-Läufen. */
1746
+ interface SzenenRunPort {
1747
+ /**
1748
+ * Alle Läufe einer Shot-Version, chronologisch.
1749
+ *
1750
+ * Die **Rundenzählung** macht der Aufrufer mit `roundOfRun()` aus
1751
+ * `itemDerivation.ts` — nicht dieser Port und nicht die View. Sonst gäbe es
1752
+ * zwei Zählungen, und U23 verlangt eine stabile.
1753
+ */
1754
+ listRunsForShot(shotVersionId: string): Promise<QueryResult<readonly PromptRunRecord[]>>;
1755
+ /** Ein einzelner Lauf, oder `null` bei unbekannter Kennung. */
1756
+ getRun(runId: string): Promise<QueryResult<PromptRunRecord | null>>;
1757
+ /** Startet einen Lauf und liefert das Protokoll des Ergebnisses. */
1758
+ startRun(input: StartRunInput): Promise<CommandResult<PromptRunRecord>>;
1759
+ /**
1760
+ * Startet einen Lauf aus einer **Draft-Kette** — Stufe 6.6, C3 (D-97/D-98).
1761
+ *
1762
+ * Bewusst eine eigene Operation statt eines diskriminierten `StartRunInput`:
1763
+ * Die Bruchwirkung für bestehende Hosts und Tests ist null, und fachlich
1764
+ * gehen beide Wege durch denselben Prompt-Use-Case — die Kette wird
1765
+ * eingefroren, dann läuft dieselbe Ableitung wie bei einer veröffentlichten
1766
+ * Version.
1767
+ *
1768
+ * Vor dem Provideraufruf wird eingefroren. Schlägt das fehl, gibt es **null**
1769
+ * Provideraufrufe.
1770
+ */
1771
+ startRunFromDraft(input: StartRunFromDraftInput): Promise<StartRunFromDraftResult>;
1772
+ /**
1773
+ * Die Läufe einer Draft-Kette.
1774
+ *
1775
+ * `listRunsForShot` bleibt unverändert für veröffentlichte Versionen; ein
1776
+ * Draft-Lauf hat keine, wäre dort also unauffindbar.
1777
+ */
1778
+ listRunsForChain(chainId: string): Promise<QueryResult<readonly PromptRunRecord[]>>;
1779
+ }
1780
+ /**
1781
+ * Warum ein Draft-Lauf nicht zustande kam — **drei** verschiedene Auskünfte.
1782
+ *
1783
+ * `CommandResult` kennt nur `error` mit `retryable`, und genau das hat am
1784
+ * 2026-08-13 auf dev zu einer Falschaussage geführt: Ein HF-`429` landete im
1785
+ * `error`-Zweig mit `retryable: true`, und die Ansicht meldete daraufhin „Ein
1786
+ * Entwurf der Kette wurde zwischenzeitlich geändert" — eine Ursache, die es
1787
+ * nicht gab.
1788
+ *
1789
+ * Deshalb sagt diese Operation, **was** los war:
1790
+ *
1791
+ * - `conflict` — ein Knoten hat sich während des Einfrierens geändert (D-97).
1792
+ * Beim nächsten Versuch weg.
1793
+ * - `rejected` — die Kette selbst ist mangelhaft (offenes Ende, fremde Kette,
1794
+ * unvollständiger Shot). Wiederholen hilft nicht, hier muss
1795
+ * jemand etwas ändern.
1796
+ * - `error` — technisch: Netz, Drosselung, Speicher nicht erreichbar. Der
1797
+ * Bestand ist in Ordnung.
1798
+ *
1799
+ * In **allen** Fehlerfällen gilt: Es wurde kein Modell gerufen (G23).
1800
+ */
1801
+ type StartRunFromDraftResult = {
1802
+ kind: 'ok';
1803
+ value: PromptRunRecord;
1804
+ } | {
1805
+ kind: 'unsupported';
1806
+ capability: string;
1807
+ } | {
1808
+ kind: 'conflict';
1809
+ message: string;
1810
+ node: {
1811
+ type: DerivableType;
1812
+ element_id: string;
1813
+ draft_id: string;
1814
+ };
1815
+ expectedRevision: number;
1816
+ actualRevision: number;
1817
+ } | {
1818
+ kind: 'rejected';
1819
+ message: string;
1820
+ } | {
1821
+ kind: 'error';
1822
+ message: string;
1823
+ retryable: boolean;
1824
+ };
1825
+ interface StartRunFromDraftInput {
1826
+ /** Das Shot-**Element** der Kette. Eine Version gibt es hier gerade nicht. */
1827
+ shotElementId: string;
1828
+ userInstruction?: string;
1829
+ contextId?: string | null;
1830
+ }
1831
+ /** Ein bereits gespeichertes Item zu einem Lauf. */
1832
+ interface RunItemReference {
1833
+ itemId: string;
1834
+ title: string;
1835
+ /** Der abgeleitete Stand, wie ihn Stufe 4 gespeichert hat. */
1836
+ item: DerivedItem | null;
1837
+ }
1838
+ interface SaveRunAsItemInput {
1839
+ runId: string;
1840
+ title?: string;
1841
+ notes?: string;
1842
+ rating?: number;
1843
+ fskLevel?: string;
1844
+ }
1845
+ /**
1846
+ * Runde als Item — **optional als Ganzes**.
1847
+ *
1848
+ * Flow-Pure hat keinen MySQL-Zugriff (E4-6) und lässt dieses Feld weg. Die View
1849
+ * zeigt die Aktion dann nicht an. Das ist der `unsupported`-Fall aus R-1 und
1850
+ * braucht in der View keine Zeile Sondercode (U26).
1851
+ */
1852
+ interface SzenenItemPort {
1853
+ /**
1854
+ * Das Item zu einem Lauf, ohne es anzulegen.
1855
+ *
1856
+ * Getrennt vom Speichern, weil U25 verlangt, ein bestehendes Item zu
1857
+ * **zeigen** — ein Aufruf, der nebenbei anlegt, könnte das nicht.
1858
+ * Die Kennung ist deterministisch (`itemIdForRun()`); dieser Port schlägt sie
1859
+ * nur nach und leitet nichts zweites ab.
1860
+ */
1861
+ getItemForRun(runId: string): Promise<QueryResult<RunItemReference | null>>;
1862
+ /**
1863
+ * Speichert eine erfolgreiche Runde als Item. Idempotent: eine Wiederholung
1864
+ * liefert dasselbe Item mit `created: false` (U25).
1865
+ */
1866
+ saveRunAsItem(input: SaveRunAsItemInput): Promise<CommandResult<{
1867
+ reference: RunItemReference;
1868
+ created: boolean;
1869
+ }>>;
1870
+ }
1871
+ /**
1872
+ * Eine Rekonstruktion starten — Stufe 6.5.
1873
+ *
1874
+ * Die View übergibt, was der Nutzer gewählt hat: Regel, Eingang, Text und
1875
+ * Bilder. Sie baut **keinen** Systemprompt und **keinen** Katalog — das tut
1876
+ * `runSceneDerivation()` hinter dem Port, in jedem Host derselbe Code.
1877
+ */
1878
+ interface StartDerivationInput {
1879
+ /** Die veröffentlichte `scene_derivation_policy`-Version. */
1880
+ policyVersionId: string;
1881
+ mode: DerivationInputMode;
1882
+ promptText?: string | null;
1883
+ /** Bilder mit Daten **und** Herkunft. Gespeichert wird nur die Herkunft (D-73). */
1884
+ images?: readonly DerivationImage[];
1885
+ contextId?: string | null;
1886
+ /**
1887
+ * Setzt einen Lauf fort (D-87/D-88) — Korrektur nach einem Fehlschlag oder
1888
+ * Ergänzung nach einem gelungenen Lauf. Ohne dieses Feld ist es ein erster
1889
+ * Lauf.
1890
+ *
1891
+ * Die vorige Antwort wird **nicht** mitgeschickt: Der Port liest sie aus dem
1892
+ * Vorgängerlauf. Zweimal übertragen hieße zwei Wahrheiten (R-2).
1893
+ */
1894
+ follows?: {
1895
+ runId: string;
1896
+ /** Was dem Modell vorgehalten wird — vom Menschen bearbeitbar (D-89). */
1897
+ note: string;
1898
+ /** Was nur der Mensch weiß. */
1899
+ userInstruction?: string | null;
1900
+ };
1901
+ }
1902
+ interface AdoptProposalInput {
1903
+ runId: string;
1904
+ type: DerivableType;
1905
+ title?: string;
1906
+ /**
1907
+ * Die veröffentlichte Vorgängerversion, auf die der Vorschlag zeigt.
1908
+ *
1909
+ * Pflicht für `scene_setup` und `shot`: `versionRef` verlangt eine
1910
+ * veröffentlichte Version (D-03), ein Entwurf genügt nicht (D-72).
1911
+ */
1912
+ referenceVersionId?: string;
1913
+ }
1914
+ /** Was aus einer Übernahme entsteht — ein **Draft**, nie eine Version. */
1915
+ interface AdoptedProposal {
1916
+ runId: string;
1917
+ type: DerivableType;
1918
+ elementId: string;
1919
+ }
1920
+ interface AdoptGraphInput {
1921
+ /**
1922
+ * Der Ursprung — **genau einer**. Ein Lauf oder eine geprüfte
1923
+ * Arbeitsfassung (D-99), nie beides: Zwei Quellen könnten sich
1924
+ * widersprechen, und dann wäre nicht mehr sagbar, woraus ein Knoten
1925
+ * entstanden ist.
1926
+ */
1927
+ runId?: string;
1928
+ recoveryId?: string;
1929
+ /**
1930
+ * Welche Typen übernommen werden sollen. Ohne Angabe: alle verwertbaren
1931
+ * Vorschläge des Ursprungs.
1932
+ */
1933
+ types?: readonly DerivableType[];
1934
+ /** Titel je Typ, sonst der Vorschlag des Modells (D-83), sonst der Fallback. */
1935
+ titles?: Partial<Record<DerivableType, string>>;
1936
+ }
1937
+ /** Ein Knoten der entstandenen Kette. */
1938
+ interface AdoptedGraphNode {
1939
+ type: DerivableType;
1940
+ elementId: string;
1941
+ draftId: string;
1942
+ revision: number;
1943
+ }
1944
+ /**
1945
+ * Das Ergebnis einer Graph-Übernahme.
1946
+ *
1947
+ * `missing` ist der ehrliche Teil: Die Speicherports bieten **keine**
1948
+ * Mehr-Element-Transaktion, und 6.6 täuscht deshalb keine Atomizität vor.
1949
+ * Bricht ein Schreibvorgang mitten im Graphen ab, werden die bereits
1950
+ * entstandenen Knoten genannt statt verschwiegen — sonst legte der nächste
1951
+ * Versuch stille Dubletten an.
1952
+ */
1953
+ interface AdoptedGraph {
1954
+ chainId: string;
1955
+ sourceRunId: string;
1956
+ sourceRecoveryId?: string;
1957
+ created: readonly AdoptedGraphNode[];
1958
+ /** Typen, die nicht entstanden sind, je mit Grund. */
1959
+ missing: readonly {
1960
+ type: DerivableType;
1961
+ reason: string;
1962
+ }[];
1963
+ /** `true`, wenn alle angeforderten Typen entstanden sind. */
1964
+ complete: boolean;
1965
+ }
1966
+ /**
1967
+ * Rekonstruktion — **optional als Ganzes**.
1968
+ *
1969
+ * Ein Host ohne Textgenerierungs-Port kann sie nicht anbieten und lässt das
1970
+ * Feld weg. Die View zeigt den Bereich dann gar nicht, statt ihn leer
1971
+ * darzustellen (R11). Das ist derselbe Mechanismus wie bei `items` und
1972
+ * `media` und braucht keine Zeile Sondercode.
1973
+ */
1974
+ interface SzenenDerivationPort {
1975
+ /** Die verfügbaren Regeln, aus denen der Nutzer wählt. */
1976
+ listPolicies(contextId?: string | null): Promise<QueryResult<readonly DerivationPolicyOption[]>>;
1977
+ getDerivation(runId: string): Promise<QueryResult<SceneDerivationRecord | null>>;
1978
+ startDerivation(input: StartDerivationInput): Promise<CommandResult<SceneDerivationRecord>>;
1979
+ /**
1980
+ * Übernimmt **einen** Vorschlag als regulären Draft. Kein Publish (6.5-D).
1981
+ *
1982
+ * Der Legacy-Einzelweg: Er verlangt für `scene_setup` und `shot` eine
1983
+ * veröffentlichte Vorgängerversion und spielt damit die Publish-Treppe nach.
1984
+ * Für den Normalfall gibt es seit 6.6 `adoptProposalGraph` — dieser hier
1985
+ * bleibt, weil eine einzelne Übernahme in einen bestehenden, längst
1986
+ * veröffentlichten Zusammenhang weiterhin sinnvoll ist.
1987
+ */
1988
+ adoptProposal(input: AdoptProposalInput): Promise<CommandResult<AdoptedProposal>>;
1989
+ /**
1990
+ * Übernimmt `scene`, `scene_setup` und `shot` als **eine** zusammenhängende
1991
+ * Draft-Kette (D-95/D-96) — der Hauptweg seit 6.6.
1992
+ *
1993
+ * Ein einzelner Nutzerklick darf die alte Publish-Treppe nicht intern
1994
+ * nachspielen. Deshalb ist das **eine** Fachoperation und keine Schleife über
1995
+ * `adoptProposal`: Alle Verträge werden vor dem ersten Schreibzugriff
1996
+ * geprüft, dann entsteht die Kette in einem Zug.
1997
+ */
1998
+ adoptProposalGraph(input: AdoptGraphInput): Promise<CommandResult<AdoptedGraph>>;
1999
+ /**
2000
+ * Prüft einen Text lokal gegen Regel und Katalog des Laufs, **ohne** ihn zu
2001
+ * speichern und **ohne** Provideraufruf.
2002
+ */
2003
+ assessRawOutput(input: AssessRawOutputInput): Promise<QueryResult<RecoveryAssessment>>;
2004
+ /** Speichert eine geprüfte Arbeitsfassung als unveränderlichen Datensatz. */
2005
+ recordRecovery(input: AssessRawOutputInput): Promise<CommandResult<SceneDerivationRecoveryRecord>>;
2006
+ getRecovery(recoveryId: string): Promise<QueryResult<SceneDerivationRecoveryRecord | null>>;
2007
+ /** Alle Arbeitsfassungen eines Laufs, in Anhängereihenfolge. */
2008
+ listRecoveries(runId: string): Promise<QueryResult<readonly SceneDerivationRecoveryRecord[]>>;
2009
+ }
2010
+ interface AssessRawOutputInput {
2011
+ runId: string;
2012
+ /**
2013
+ * Der zu prüfende Text.
2014
+ *
2015
+ * Fehlt er, wird der unveränderte `raw_output` des Laufs geprüft — der
2016
+ * häufigste erste Schritt: „Was ist an dem, was da steht, überhaupt dran?"
2017
+ */
2018
+ text?: string;
2019
+ }
2020
+ /**
2021
+ * Das Ergebnis einer lokalen Prüfung — dasselbe, was eine gespeicherte
2022
+ * Arbeitsfassung tragen würde, nur ohne `recovery_id` und `created_at`.
2023
+ *
2024
+ * Bewusst dieselbe Form: Wer erst prüft und dann speichert, soll nicht zwei
2025
+ * verschiedene Ergebnisse anzuschauen bekommen.
2026
+ */
2027
+ interface RecoveryAssessment {
2028
+ runId: string;
2029
+ source_text: string;
2030
+ edited: boolean;
2031
+ diagnostics: readonly DerivationDiagnostic[];
2032
+ /** Die verwertbaren Vorschläge. */
2033
+ proposals: readonly RecordedProposal[];
2034
+ /** Die nicht verwertbaren, je mit Begründung. */
2035
+ rejected: readonly UnusableProposal[];
2036
+ status: RecoveryStatus;
2037
+ }
2038
+ /** Eine wählbare Regel, so wie die Auswahl sie zeigt. */
2039
+ interface DerivationPolicyOption {
2040
+ elementId: string;
2041
+ versionId: string;
2042
+ title: string;
2043
+ inputModes: readonly DerivationInputMode[];
2044
+ produces: readonly DerivableType[];
2045
+ }
2046
+ /** Ein wählbares Bild aus dem Bestand. */
2047
+ interface LibraryImage {
2048
+ /**
2049
+ * Die **HF-Bildkennung** (D-93) — der Wert, unter dem das Bild als
2050
+ * `images/<mediaRef>.<ext>` liegt und auf den beide Hosts sich beziehen.
2051
+ *
2052
+ * Ausdrücklich **keine** hostlokale Kennung: Der Laufsatz liegt im
2053
+ * gemeinsamen Ereignislog (D-62), und ein Verweis, den nur die Hälfte der
2054
+ * Leser auflösen kann, ist kein Verweis.
2055
+ */
2056
+ mediaRef: string;
2057
+ title: string;
2058
+ mimeType: string;
2059
+ /** Anzeigbare Quelle für die Kachel, sofern der Host eine liefert. */
2060
+ thumbUrl?: string | null;
2061
+ }
2062
+ /**
2063
+ * Bilder wählen, auflösen und ablegen — **optional als Ganzes** (D-94).
2064
+ *
2065
+ * Dieselbe Bauform wie `items` und `media` (R11): Ein Host, der keinen
2066
+ * Bildbestand hat, liefert das Feld nicht, und die Ansicht bietet dann nur den
2067
+ * Upload an — sichtbar weniger, nicht stillschweigend kaputt.
2068
+ *
2069
+ * Beide heutigen Hosts liefern ihn: Flow schreibt direkt nach HF, React legt
2070
+ * ein Library-Item mit dem Tag `hf-sync` an, das der bestehende Sync trägt.
2071
+ */
2072
+ interface SzenenImageLibraryPort {
2073
+ /** Wählbare Bilder, neueste zuerst. */
2074
+ listImages(query?: {
2075
+ search?: string;
2076
+ limit?: number;
2077
+ }): Promise<QueryResult<readonly LibraryImage[]>>;
2078
+ /** Base64 **ohne** `data:`-Präfix und der MIME-Typ — die Modelleingabe. */
2079
+ resolveImage(mediaRef: string): Promise<QueryResult<{
2080
+ data: string;
2081
+ mime_type: string;
2082
+ }>>;
2083
+ /** Legt ein hochgeladenes Bild ab und gibt seine Kennung zurück (D-91). */
2084
+ putImage(input: {
2085
+ data: string;
2086
+ mime_type: string;
2087
+ title: string;
2088
+ }): Promise<CommandResult<LibraryImage>>;
2089
+ }
2090
+ interface VersionMedium {
2091
+ assetId: string;
2092
+ role: 'reference' | 'mask' | 'palette' | 'example';
2093
+ position: number;
2094
+ /** Anzeigbare Quelle, sofern der Host eine liefert. */
2095
+ url?: string | null;
2096
+ }
2097
+ interface ItemMedium {
2098
+ assetId: string;
2099
+ role: string;
2100
+ position: number;
2101
+ url?: string | null;
2102
+ }
2103
+ /**
2104
+ * Medien — **optional als Ganzes**, weil sie an Stufe 5 hängen.
2105
+ *
2106
+ * Der Port liest und ordnet zu. Er lädt nichts hoch und speichert keine Datei:
2107
+ * das bleibt die Medien-Fassade aus Stufe 5 (`mediaAssetService`), und §6.6
2108
+ * verbietet der UI ausdrücklich einen zweiten Upload-/Save-Weg.
2109
+ */
2110
+ interface SzenenMediaPort {
2111
+ listVersionMedia(versionId: string): Promise<QueryResult<readonly VersionMedium[]>>;
2112
+ listItemMedia(itemId: string): Promise<QueryResult<readonly ItemMedium[]>>;
2113
+ attachVersionMedium(input: {
2114
+ versionId: string;
2115
+ assetId: string;
2116
+ role: VersionMedium['role'];
2117
+ position?: number;
2118
+ }): Promise<CommandResult<VersionMedium>>;
2119
+ detachVersionMedium(input: {
2120
+ versionId: string;
2121
+ assetId: string;
2122
+ role: VersionMedium['role'];
2123
+ }): Promise<CommandResult<{
2124
+ removed: boolean;
2125
+ }>>;
2126
+ }
2127
+ /**
2128
+ * Ein Bild eines Batches, wie der Lesepfad es liefert.
2129
+ *
2130
+ * `asset_id` ist die fachlich stabile Identität, soweit im Host bekannt;
2131
+ * `media_ref` ist der im aktuellen Host auflösbare Locator (z. B. eine
2132
+ * HF-Transportkennung wie `${item_id}-${idx}`). `position` ist Reihenfolge,
2133
+ * keine Identität — sie ersetzt keins von beiden (D-118).
2134
+ */
2135
+ interface PromptBatchImageRef {
2136
+ asset_id?: string;
2137
+ media_ref: string;
2138
+ position: number;
2139
+ file?: string;
2140
+ model?: string | null;
2141
+ seed?: number | null;
2142
+ width?: number | null;
2143
+ height?: number | null;
2144
+ }
2145
+ /**
2146
+ * Ein Generierungsbatch, wie er aus der Library gelesen wird (D-105/D-114).
2147
+ *
2148
+ * Ein Lauf hat genau ein Item (D-113/D-121-Korrektur): wiederholte
2149
+ * „Bilder erzeugen“-Aufrufe desselben Laufs hängen ihre Bilder an dasselbe
2150
+ * Item an, statt eigene Items zu erzeugen. `generation_batch_ids` listet
2151
+ * darum alle bisherigen Provideraufrufe dieses Items, nicht nur den letzten.
2152
+ */
2153
+ interface PromptImageBatch {
2154
+ item_id: string;
2155
+ prompt_run_id: string;
2156
+ generation_batch_ids: readonly string[];
2157
+ source_kind: 'generated_in_app' | 'external_import';
2158
+ title: string;
2159
+ images: readonly PromptBatchImageRef[];
2160
+ }
2161
+ /**
2162
+ * Batch-**Historie lesen** — getrennt vom Schreiben (D-122).
2163
+ *
2164
+ * Eine Host-Grenze beim Library-Schreiben darf die Historie nicht mit
2165
+ * unsichtbar machen: ein Host ohne MySQL (Flow-Pure) liefert diesen Port
2166
+ * heute nicht — der reguläre `unsupported`-Fall, keine Zeile Sondercode
2167
+ * (D-115-Analogie: keine Host-Verzweigung im gemeinsamen Code).
2168
+ */
2169
+ interface SzenenImageBatchHistoryPort {
2170
+ /** Alle Batches eines Prompt-Laufs — gesucht über IDs, nicht über Titel/Zeit (D-109). */
2171
+ listBatchesForPromptRun(runId: string): Promise<QueryResult<readonly PromptImageBatch[]>>;
2172
+ /** Ein einzelner Batch über seine `generation_batch_id`, oder `null`. */
2173
+ getBatch(batchId: string): Promise<QueryResult<PromptImageBatch | null>>;
2174
+ /**
2175
+ * Die protokollierten Bildgenerierungsaufträge eines Laufs (D-119).
2176
+ *
2177
+ * Bewusst **getrennt** von `listBatchesForPromptRun`, und nicht dieselbe
2178
+ * Liste: Ein Batch ist ein gespeichertes Library-Item, ein Auftrag ist der
2179
+ * Prozessnachweis eines bezahlten Providerlaufs. Genau der Auftrag, der
2180
+ * zwischen `started` und `finished` abbrach, hat **kein** Item — er wäre in
2181
+ * der Batchliste unsichtbar, und das ist der Fall, für den D-119 existiert.
2182
+ *
2183
+ * Optional, weil ein Host den Library-Read tragen kann, ohne an den
2184
+ * autoritativen Ereignislog zu kommen. Fehlt die Operation, zeigt die
2185
+ * Ansicht die Batches und benennt die fehlende Auftragshistorie als
2186
+ * fehlende Fähigkeit — sie erfindet keine.
2187
+ */
2188
+ listOrdersForPromptRun?(runId: string): Promise<QueryResult<readonly ImageGenerationOrder[]>>;
2189
+ }
2190
+ /** Ein Bild für den externen Import — vom Nutzer bestätigte Metadaten, nie geraten (D-107/D-117). */
2191
+ interface ImportBatchImageInput {
2192
+ imageBase64: string;
2193
+ model?: string;
2194
+ seed?: number;
2195
+ aspectRatio?: string;
2196
+ resolution?: string;
2197
+ width?: number;
2198
+ height?: number;
2199
+ }
2200
+ interface ImportBatchInput {
2201
+ runId: string;
2202
+ /** Vor dem Aufruf vom Aufrufer gebildet (D-113) — deterministisch mit dem Lauf verknüpft. */
2203
+ generationBatchId: string;
2204
+ images: readonly ImportBatchImageInput[];
2205
+ title?: string;
2206
+ }
2207
+ interface AttachLibraryItemInput {
2208
+ runId: string;
2209
+ itemId: string;
2210
+ }
2211
+ /**
2212
+ * Der Ausgang einer Zuordnung — bewusst **kein** `CommandResult`: D-117
2213
+ * Punkt 6/7 verlangt, dass „gehört bereits zu einem anderen Lauf" ein
2214
+ * sichtbarer, benannter Ausgang ist, kein technischer Fehler und kein
2215
+ * stilles Umhängen.
2216
+ */
2217
+ type AttachLibraryItemResult = {
2218
+ kind: 'ok';
2219
+ value: PromptImageBatch;
2220
+ } | {
2221
+ kind: 'conflict';
2222
+ message: string;
2223
+ existingPromptRunId: string;
2224
+ } | {
2225
+ kind: 'unsupported';
2226
+ capability: string;
2227
+ } | {
2228
+ kind: 'error';
2229
+ message: string;
2230
+ retryable: boolean;
2231
+ };
2232
+ /**
2233
+ * Batch-**Schreiben** — getrennt vom Lesen (D-122), Teil D0-D2.
2234
+ *
2235
+ * Beide Operationen sind `generated_in_app` **nicht** gleichgestellt: Sie
2236
+ * rufen keinen Provider, sie legen bereits vorhandene Bilder ab oder
2237
+ * verknüpfen ein bestehendes Item. Ein Host ohne sicheren Batch-Schreibpfad
2238
+ * liefert diesen Port nicht — die Aktion „Externe Bilder zuordnen“ entfällt
2239
+ * dann sichtbar, statt eine Operation anzubieten, die verlorene Bilder
2240
+ * hinterließe.
2241
+ */
2242
+ interface SzenenImageBatchWritePort {
2243
+ /** Neue externe Bilder ablegen — derselbe kanonische Schreibweg wie In-App-Batches (D-117). */
2244
+ importBatch(input: ImportBatchInput): Promise<CommandResult<PromptImageBatch>>;
2245
+ /**
2246
+ * Ein bestehendes Library-Item einem Lauf zuordnen, ohne Bilder zu kopieren.
2247
+ * `conflict`, wenn das Item bereits zu einem **anderen** Lauf gehört — kein
2248
+ * stilles Umhängen (D-117 Punkt 6/7).
2249
+ */
2250
+ attachLibraryItem(input: AttachLibraryItemInput): Promise<AttachLibraryItemResult>;
2251
+ }
2252
+ /**
2253
+ * Alles, was die `SzenenView` von ihrem Host braucht.
2254
+ *
2255
+ * `elements` und `context` sind die **unveränderten** Verträge aus Stufe 1–3.
2256
+ * Sie werden hier nicht neu deklariert, sondern eingehängt: dieselben Typen,
2257
+ * dieselben Implementierungen, dieselben Contract-Tests.
2258
+ */
2259
+ interface SzenenViewPort {
2260
+ /** Elementspeicher — Queries und Commands aus Stufe 1. */
2261
+ elements: SzenenQueries & SzenenCommands;
2262
+ /** Wirksame Kontextkette — eigener Port, weil die Vererbung nicht uns gehört. */
2263
+ context: ContextChainPort;
2264
+ /** Prompt-Läufe — Stufe 3/4. */
2265
+ runs: SzenenRunPort;
2266
+ /** Runde als Item — fehlt in Flow-Pure. */
2267
+ items?: SzenenItemPort;
2268
+ /** Medien — fehlt, solange ein Host Stufe 5 nicht anbietet. */
2269
+ media?: SzenenMediaPort;
2270
+ /** Bildbestand — fehlt, wenn ein Host keinen hat (D-94). */
2271
+ imageLibrary?: SzenenImageLibraryPort;
2272
+ /** Rekonstruktion — fehlt ohne Textgenerierungs-Port (Stufe 6.5). */
2273
+ derivation?: SzenenDerivationPort;
2274
+ /** Bild-Batch-Historie — fehlt, solange ein Host keinen MySQL-Zugriff hat (D-122). */
2275
+ imageBatchHistory?: SzenenImageBatchHistoryPort;
2276
+ /** Bild-Batch-Schreiben — fehlt ohne sicheren Batch-Schreibpfad (D-122). */
2277
+ imageBatchWrite?: SzenenImageBatchWritePort;
2278
+ /**
2279
+ * Bildgenerierung aus einem Prompt-Lauf — fehlt, wenn Providerzugang
2280
+ * und/oder sicherer Batch-Schreibpfad fehlen (D-122/Teil F1). Ein Host mit
2281
+ * Provider, aber ohne kanonische Persistenz, darf keinen bezahlten
2282
+ * Bildlauf starten und das Ergebnis danach verlieren.
2283
+ */
2284
+ imageGeneration?: SzenenImageGenerationPort;
2285
+ }
2286
+ /**
2287
+ * Die Fähigkeiten eines Ports, wie die View sie abfragt.
2288
+ *
2289
+ * Bewusst **abgeleitet** und nicht gesetzt: es gibt kein Feld, das ein Host
2290
+ * falsch befüllen könnte. Wer `items` mitliefert, kann Items — wer nicht, kann
2291
+ * es nicht. Damit kann die Anzeige nie von der Wirklichkeit abweichen.
2292
+ */
2293
+ interface SzenenViewCapabilities {
2294
+ saveRunAsItem: boolean;
2295
+ setPreferredHead: boolean;
2296
+ reviseMetadata: boolean;
2297
+ retireElement: boolean;
2298
+ media: boolean;
2299
+ derivation: boolean;
2300
+ imageBatchHistory: boolean;
2301
+ /** Auftragshistorie (D-119) — kann fehlen, obwohl die Batchhistorie da ist. */
2302
+ imageOrderHistory: boolean;
2303
+ imageBatchWrite: boolean;
2304
+ imageGeneration: boolean;
2305
+ }
2306
+ declare function capabilitiesOf(port: SzenenViewPort): SzenenViewCapabilities;
2307
+ /**
2308
+ * Der Grund, den die View anzeigt, wenn eine Aktion fehlt.
2309
+ *
2310
+ * §8 verlangt: fehlende Capability wird als **nicht verfügbare Aktion erklärt**,
2311
+ * nicht als generischer Fehler. Und AGENTS.md Regel 8 verlangt konkrete
2312
+ * Meldungen — deshalb steht die Fähigkeit im Text.
2313
+ */
2314
+ declare function unsupportedReason(capability: string): string;
2315
+ /**
2316
+ * Hilfsform für optionale Commands: liefert `unsupported` statt zu werfen, wenn
2317
+ * der Host die Operation nicht hat.
2318
+ *
2319
+ * Damit steht der `unsupported`-Fall an genau einer Stelle, statt in jeder
2320
+ * aufrufenden Komponente als `if (!port.items)` aufzutauchen.
2321
+ */
2322
+ declare function callOptional<T>(capability: string, operation: (() => Promise<CommandResult<T>>) | undefined): Promise<CommandResult<T>>;
2323
+
2324
+ interface CreateHfImageLibraryOptions {
2325
+ namespace: string;
2326
+ token: string;
2327
+ /** Kennungen neuer Bilder. Ersetzbar, damit ein Test nicht würfelt. */
2328
+ newImageId?: () => string;
2329
+ /** Die Uhr — dieselbe Begründung. */
2330
+ now?: () => number;
2331
+ }
2332
+ declare function createHfImageLibrary(options: CreateHfImageLibraryOptions): SzenenImageLibraryPort;
2333
+
2334
+ interface CreateMemoryViewPortOptions {
2335
+ /**
2336
+ * Ob der Port Items anbietet. `false` bildet Flow-Pure nach: das Feld fehlt
2337
+ * dann ganz, statt eine Operation zu haben, die `unsupported` zurückgibt.
2338
+ * Der Unterschied ist der Punkt — U26 verlangt, dass die View damit ohne
2339
+ * Sondercode umgeht.
2340
+ */
2341
+ items?: boolean;
2342
+ /** Ob der Port Medien anbietet (Stufe 5 vorhanden). */
2343
+ media?: boolean;
2344
+ /**
2345
+ * Ob der Port einen Bildbestand anbietet (D-94).
2346
+ *
2347
+ * `false` bildet einen Host ohne ihn ab: Der Bereich zeigt dann nur den
2348
+ * Upload, und ein Folgelauf ohne Bild wird mit Grund abgelehnt.
2349
+ */
2350
+ imageLibrary?: boolean;
2351
+ /** Vorbelegte Bilder des Bestands. */
2352
+ images?: readonly LibraryImage[];
2353
+ /**
2354
+ * Ob der Port die Rekonstruktion anbietet (Stufe 6.5).
2355
+ *
2356
+ * `false` bildet einen Host ohne Textgenerierungs-Port ab. Der Bereich
2357
+ * „0 · Rekonstruktion" fehlt dann ganz, statt leer zu erscheinen (R11).
2358
+ */
2359
+ derivation?: boolean;
2360
+ /** Vorbelegte Regeln, aus denen die Auswahl liest. */
2361
+ policies?: readonly DerivationPolicyOption[];
2362
+ /** Erzeugt den Rekonstruktionslauf. Voreingestellt ein erfolgreicher. */
2363
+ deriveScene?: (input: StartDerivationInput, runId: string) => SceneDerivationRecord;
2364
+ /**
2365
+ * Erzeugt den Lauf. Voreingestellt ist ein erfolgreicher Lauf mit
2366
+ * erkennbarem Simulationsprovider — Pflichtnachweis 5 verlangt, dass eine
2367
+ * Simulation als solche sichtbar bleibt.
2368
+ */
2369
+ deriveRun?: (input: StartRunInput, runId: string) => PromptRunRecord;
2370
+ /** Vorbelegte Läufe. */
2371
+ runs?: readonly PromptRunRecord[];
2372
+ ids?: () => string;
2373
+ /**
2374
+ * Ob der Port Bild-Batch-Historie anbietet (Stufe 6.7, D-122).
2375
+ *
2376
+ * `false` bildet einen Host ohne MySQL-Zugriff ab (Flow-Pure): der
2377
+ * Bereich zeigt dann keine Batch-Historie, statt leer zu erscheinen (R11).
2378
+ */
2379
+ imageBatchHistory?: boolean;
2380
+ /** Vorbelegte Batches, aus denen `listBatchesForPromptRun`/`getBatch` lesen. */
2381
+ batches?: readonly PromptImageBatch[];
2382
+ /**
2383
+ * Ob der Port Bild-Batch-Schreiben anbietet (Stufe 6.7, D-122, Teil D0-D2).
2384
+ *
2385
+ * `false` bildet einen Host ohne sicheren Batch-Schreibpfad ab: „Externe
2386
+ * Bilder zuordnen" entfällt dann sichtbar, statt Bilder zu verlieren.
2387
+ */
2388
+ imageBatchWrite?: boolean;
2389
+ /**
2390
+ * Ob der Port Bildgenerierung anbietet (Stufe 6.7, Teil F1, D-122).
2391
+ *
2392
+ * `false` bildet einen Host ohne Providerzugang und/oder ohne sicheren
2393
+ * Batch-Schreibpfad ab: „Bilder erzeugen" entfällt dann sichtbar.
2394
+ */
2395
+ imageGeneration?: boolean;
2396
+ /** Simulierter Provideraufruf — Voreinstellung liefert `imageCount` Bilder. */
2397
+ imageProvider?: ImageGenerationProviderPort;
2398
+ /** Ob der simulierte Host Zugang zum katalogisierten Zielmodell hat. Default: immer. */
2399
+ imageProviderHasAccess?: ImageProviderAccessCheck;
2400
+ }
2401
+ declare function createMemoryViewPort(options?: CreateMemoryViewPortOptions): SzenenViewPort;
2402
+
2403
+ interface CreateFlowSzenenViewPortOptions {
2404
+ /**
2405
+ * Der Textzugang des Flow-SDK. Entfaellt, wenn `textPort` gesetzt ist — ein
2406
+ * Browser ausserhalb von Flow hat kein `Flow.generate.text`.
2407
+ */
2408
+ generateText?: FlowGenerateText;
2409
+ /**
2410
+ * Ein fertiger Textgenerierungs-Port statt des Flow-SDK.
2411
+ *
2412
+ * Der React-Client im Canvas hat kein `Flow.generate.text`, wohl aber einen
2413
+ * eigenen Zugang zum Modell. Er reicht seinen Port hier herein; alles
2414
+ * andere — Elementspeicher, Lauf, Protokoll — ist in beiden Clients derselbe
2415
+ * Code.
2416
+ */
2417
+ textPort?: TextGenerationPort;
2418
+ /** Existing channel for tests or embedded hosts. Otherwise HF credentials are required. */
2419
+ channel?: ElementEventChannel;
2420
+ namespace?: string;
2421
+ token?: string;
2422
+ context?: ContextChainPort;
2423
+ ids?: IdFactory;
2424
+ /**
2425
+ * Der Bildbestand (D-94). Ohne HF-Zugangsdaten gibt es keinen — dann fehlt
2426
+ * das Feld, und die Ansicht bietet nur den Upload an.
2427
+ */
2428
+ imageLibrary?: SzenenImageLibraryPort;
2429
+ newRunId?: () => string;
2430
+ now?: () => Date;
2431
+ }
2432
+ /**
2433
+ * Complete Flow adapter for the shared SzenenView: authoritative HF elements
2434
+ * and runs plus Flow.generate.text. Server-only item commands stay absent.
2435
+ */
2436
+ declare function createFlowSzenenViewPort(options: CreateFlowSzenenViewPortOptions): SzenenViewPort;
2437
+
2438
+ interface CreateBrowserTextGenerationPortOptions {
2439
+ /**
2440
+ * Der Google-Schlüssel des Clients, falls vorhanden.
2441
+ *
2442
+ * **Fehlen ist hier kein Fehler**, anders als im Serveradapter. Ohne
2443
+ * Schlüssel geht die Anfrage ohne `?key=` raus — das ist der Canvas-Modus,
2444
+ * und er ist der eigentliche Zweck dieses Ports. Ein Browser, der irrtümlich
2445
+ * ohne Schlüssel läuft, bekommt vom Provider ein HTTP 401 und damit einen
2446
+ * sichtbaren `provider_error`; still erfundene Antworten gibt es nicht.
2447
+ */
2448
+ apiKey?: string | null;
2449
+ modelId?: string;
2450
+ /** Für Tests. Vorgabe ist das `fetch` der Umgebung. */
2451
+ fetchImpl?: typeof fetch;
2452
+ }
2453
+ /** Baut den Textgenerierungs-Port für einen Browser mit Google-Zugang. */
2454
+ declare function createBrowserTextGenerationPort(options?: CreateBrowserTextGenerationPortOptions): TextGenerationPort;
2455
+
2456
+ /**
2457
+ * Der Speicher für Prompt-Läufe, host-neutral.
2458
+ *
2459
+ * Bewusst **kein** Ereigniskanal: Flow hat einen, React nicht. Ein
2460
+ * `appendEvent` im Vertrag hätte React gezwungen, eines nachzubauen, und den
2461
+ * REST-Weg zu einem Sonderfall gemacht. Was der Use-Case wirklich braucht, ist
2462
+ * schmaler — einen fertigen Record ablegen und Läufe wiederfinden.
2463
+ *
2464
+ * Der Port **interpretiert nichts**: Er baut keinen Record, liest keine
2465
+ * Providerantwort und leitet keine Runde ab. Er speichert, was er bekommt.
2466
+ */
2467
+ interface PromptRunPersistencePort {
2468
+ listForShot(shotVersionId: string): Promise<QueryResult<readonly PromptRunRecord[]>>;
2469
+ get(runId: string): Promise<QueryResult<PromptRunRecord | null>>;
2470
+ /** Legt den fertigen Lauf autoritativ ab. Ohne Bestätigung gibt es keinen Lauf. */
2471
+ record(record: PromptRunRecord): Promise<CommandResult<PromptRunRecord>>;
2472
+ /**
2473
+ * Die Läufe einer Draft-Kette — Stufe 6.6 (C3).
2474
+ *
2475
+ * Ein Draft-Lauf hat keine Shot-Version und wäre über `listForShot`
2476
+ * unauffindbar. Der bestehende Vertrag bleibt für veröffentlichte Versionen
2477
+ * unverändert.
2478
+ */
2479
+ listForChain(chainId: string): Promise<QueryResult<readonly PromptRunRecord[]>>;
2480
+ }
2481
+ /** Was der Eventlog-Adapter vom Kanal braucht — lesen und anhängen. */
2482
+ interface RunEventChannel {
2483
+ readEvents(): Promise<readonly ElementEvent[]>;
2484
+ appendEvent(type: string, payload: unknown): Promise<void>;
2485
+ }
2486
+ /**
2487
+ * Die Persistenz über das Ereignislog — der Weg, den Flow schon geht.
2488
+ *
2489
+ * Der Lauf ist append-only und unveränderlich; das Log trägt diese Form nativ
2490
+ * (`promptRunStore.ts`). Gelesen wird mit **derselben** Projektion wie überall,
2491
+ * damit ein zweiter Eintrag zur gleichen `run_id` hier nicht anders ausgelegt
2492
+ * wird als dort.
2493
+ */
2494
+ declare function createEventLogRunPersistence(channel: RunEventChannel): PromptRunPersistencePort;
2495
+ interface CreateClientRunPortOptions {
2496
+ /** Leseseite des Elementspeichers — für Auflösung und Kontextermittlung. */
2497
+ elements: SzenenQueries;
2498
+ context: ContextChainPort;
2499
+ text: TextGenerationPort;
2500
+ runs: PromptRunPersistencePort;
2501
+ newRunId?: () => string;
2502
+ now?: () => Date;
2503
+ }
2504
+ /** Der gemeinsame Prompt-Lauf als `SzenenRunPort`. */
2505
+ declare function createClientRunPort(options: CreateClientRunPortOptions): SzenenRunPort;
2506
+
2507
+ type IntegrityVerdict = {
2508
+ ok: true;
2509
+ } | {
2510
+ ok: false;
2511
+ message: string;
2512
+ };
2513
+ /**
2514
+ * Prüft einen eingereichten Prompt-Lauf.
2515
+ *
2516
+ * Die Meldung nennt das Feld, um das es geht — eine Ablehnung, die nur „ungültig"
2517
+ * sagt, lässt den Aufrufer raten (AGENTS.md Regel 8).
2518
+ */
2519
+ declare function checkPromptRunRecord(candidate: unknown): IntegrityVerdict;
2520
+ /**
2521
+ * Prüft einen eingereichten Rekonstruktionslauf.
2522
+ *
2523
+ * **Was hier nicht geprüft wird, und warum:** Ob die Vorschläge zur Aufgabe
2524
+ * passen, entscheidet `checkDerivationResponse()` — die braucht aber Regel *und*
2525
+ * Katalog, und beide stehen nicht im Record (D-73 friert die Eingabe ohne
2526
+ * Katalog ein). Sie nachträglich neu zu bilden hieße, gegen einen inzwischen
2527
+ * veränderten Bestand zu prüfen: dasselbe Ergebnis würde je nach Zeitpunkt
2528
+ * anders beurteilt. Deshalb prüft die Annahmestelle die Zusagen, die im Record
2529
+ * selbst nachweisbar sind — Struktur, Widerspruchsfreiheit, D-73 und D-82 —, und
2530
+ * behauptet nicht mehr, als sie wissen kann.
2531
+ */
2532
+ declare function checkSceneDerivationRecord(candidate: unknown): IntegrityVerdict;
2533
+ /**
2534
+ * Prüft eine eingereichte Arbeitsfassung — Stufe 6.6, A3 (D-99).
2535
+ *
2536
+ * **Was hier nicht geprüft wird, und warum:** Ob die Vorschläge zur Aufgabe
2537
+ * passen, kann die Annahmestelle so wenig entscheiden wie beim Lauf selbst —
2538
+ * dafür bräuchte sie Regel *und* Katalog von jetzt, und beide stehen nicht im
2539
+ * Datensatz. Geprüft wird deshalb, was im Datensatz nachweisbar ist: Struktur,
2540
+ * der Zusammenhang von `status` und `proposals`, und dass jeder Befund die
2541
+ * Form aus A1 hat.
2542
+ *
2543
+ * Ausdrücklich **nicht** geprüft wird, ob der Ursprungslauf existiert oder ob
2544
+ * er einen `raw_output` hatte. Das ist eine Bestandsfrage, keine Formfrage,
2545
+ * und sie gehört dorthin, wo der Bestand liegt — sonst prüfte diese Funktion
2546
+ * gegen etwas, das sie nicht sehen kann.
2547
+ */
2548
+ declare function checkSceneDerivationRecoveryRecord(candidate: unknown): IntegrityVerdict;
2549
+
2550
+ /** Welche Elementtypen als Katalogeintrag für einen Vorschlag taugen. */
2551
+ declare const CATALOGUE_TYPES: readonly ["camera_preset", "camera_pattern", "style", "shot_concept", "target_model"];
2552
+ /** Der Ausschnitt eines Element-Stores, den die Auflösung braucht. */
2553
+ interface PublishedHeadSource {
2554
+ listElements(filter: Record<string, unknown>): Promise<QueryResult<readonly {
2555
+ element_id: string;
2556
+ title?: string | null;
2557
+ }[]>>;
2558
+ getElement(elementId: string): Promise<QueryResult<{
2559
+ element: {
2560
+ context_id?: string | null;
2561
+ };
2562
+ metadata?: {
2563
+ title?: string | null;
2564
+ } | null;
2565
+ versions?: readonly {
2566
+ version_id: string;
2567
+ payload?: unknown;
2568
+ }[];
2569
+ preferredHeads?: readonly unknown[];
2570
+ } | null>>;
2571
+ }
2572
+ interface PublishedHead {
2573
+ type: string;
2574
+ element_id: string;
2575
+ version_id: string;
2576
+ title: string;
2577
+ payload: unknown;
2578
+ }
2579
+ interface CatalogueEntry {
2580
+ type: string;
2581
+ element_id: string;
2582
+ version_id: string;
2583
+ title: string;
2584
+ }
2585
+ /**
2586
+ * Die veröffentlichten Köpfe eines Elementtyps, mit Payload.
2587
+ *
2588
+ * Eine Stelle für zwei Aufrufer — den Katalog und die Regelauswahl. Die
2589
+ * Elementliste allein genügt für beides nicht: sie trägt Stammsätze ohne
2590
+ * Version und ohne Payload, und die Auflösung des Preferred Head ist eine
2591
+ * fachliche Entscheidung (D-36), die nicht zweimal nachgebaut werden darf.
2592
+ */
2593
+ declare function publishedHeadsOf(store: PublishedHeadSource, type: string, contextId?: string | null): Promise<PublishedHead[]>;
2594
+ /**
2595
+ * Baut den Katalog wählbarer Versionen für einen Kontext.
2596
+ *
2597
+ * Ohne ihn müsste das Modell Versionskennungen erfinden, und eine erfundene
2598
+ * UUID sieht aus wie eine echte. Es bekommt deshalb die Auswahl vorgelegt.
2599
+ */
2600
+ declare function catalogueFor(store: PublishedHeadSource, contextId?: string | null): Promise<CatalogueEntry[]>;
2601
+ /** Die Regelauswahl der Rekonstruktion — dieselbe Auflösung, anderer Typ. */
2602
+ declare function derivationPoliciesOf(store: PublishedHeadSource, contextId?: string | null): Promise<Array<{
2603
+ elementId: string;
2604
+ versionId: string;
2605
+ title: string;
2606
+ inputModes: readonly string[];
2607
+ produces: readonly DerivableType[];
2608
+ }>>;
2609
+
2610
+ /** Was dieser Port vom Elementspeicher braucht. */
2611
+ interface ClientDerivationStore extends PublishedHeadSource {
2612
+ getVersion(versionId: string): Promise<QueryResult<{
2613
+ element_id: string;
2614
+ type: string;
2615
+ payload: Record<string, unknown>;
2616
+ visible?: boolean;
2617
+ } | null>>;
2618
+ createElement(input: {
2619
+ type: string;
2620
+ subtype: string | null;
2621
+ contextId: string | null;
2622
+ title: string;
2623
+ description?: string;
2624
+ }): Promise<CommandResult<{
2625
+ element_id: string;
2626
+ revision?: number;
2627
+ }>>;
2628
+ writeDraft(input: {
2629
+ elementId: string;
2630
+ payload: Record<string, unknown>;
2631
+ baseVersionId: string | null;
2632
+ expectedRevision: number;
2633
+ /** Kettenmetadaten (Stufe 6.6, D-96). Weggelassen laesst sie unveraendert. */
2634
+ chain?: DraftChainMeta | null;
2635
+ }): Promise<CommandResult<{
2636
+ draft_id: string;
2637
+ revision: number;
2638
+ }>>;
2639
+ }
2640
+ /**
2641
+ * Der Speicher für Rekonstruktionsläufe, host-neutral.
2642
+ *
2643
+ * Bewusst **kein** Ereigniskanal: Flow hat einen, React nicht — dort führt der
2644
+ * Weg über REST zum Node-Server, der anhängt und projiziert. Ein `appendEvent`
2645
+ * im Vertrag hätte React gezwungen, ein Log nachzubauen, und den REST-Weg zum
2646
+ * Sonderfall gemacht.
2647
+ *
2648
+ * Der Port **interpretiert nichts**: Er baut keinen Record, liest keine
2649
+ * Providerantwort und leitet keinen Draft ab. Er speichert, was er bekommt.
2650
+ */
2651
+ interface SceneDerivationPersistencePort {
2652
+ get(runId: string): Promise<QueryResult<SceneDerivationRecord | null>>;
2653
+ /** Legt den fertigen Lauf autoritativ ab. Ohne Bestätigung gibt es keinen Lauf. */
2654
+ record(record: SceneDerivationRecord): Promise<CommandResult<SceneDerivationRecord>>;
2655
+ /** Eine einzelne Arbeitsfassung, oder `null`. */
2656
+ getRecovery(recoveryId: string): Promise<QueryResult<SceneDerivationRecoveryRecord | null>>;
2657
+ /** Alle Arbeitsfassungen eines Laufs, in Anhängereihenfolge. */
2658
+ listRecoveries(runId: string): Promise<QueryResult<readonly SceneDerivationRecoveryRecord[]>>;
2659
+ /** Legt eine Arbeitsfassung autoritativ ab. Sie überschreibt nie den Lauf. */
2660
+ recordRecovery(record: SceneDerivationRecoveryRecord): Promise<CommandResult<SceneDerivationRecoveryRecord>>;
2661
+ }
2662
+ /** Was der Ereignislog-Adapter vom Kanal braucht — lesen und anhängen. */
2663
+ interface ClientDerivationChannel {
2664
+ readEvents(): Promise<readonly ElementEvent[]>;
2665
+ appendEvent(type: string, payload: unknown): Promise<void>;
2666
+ }
2667
+ /**
2668
+ * Die Persistenz über das Ereignislog — der Weg, den Flow geht.
2669
+ *
2670
+ * Gelesen wird mit **derselben** Projektion wie überall
2671
+ * (`collectSceneDerivations`), damit ein doppelter Eintrag zur gleichen `run_id`
2672
+ * hier nicht anders ausgelegt wird als dort.
2673
+ */
2674
+ declare function createEventLogDerivationPersistence(channel: ClientDerivationChannel): SceneDerivationPersistencePort;
2675
+ interface CreateClientDerivationPortOptions {
2676
+ store: ClientDerivationStore;
2677
+ derivations: SceneDerivationPersistencePort;
2678
+ text: TextGenerationPort;
2679
+ /**
2680
+ * Der Bildbestand (D-91/D-94). Fehlt er, bleibt alles beim Alten: Uploads
2681
+ * werden als `upload` eingefroren und sind nach der Sitzung weg.
2682
+ *
2683
+ * Ist er da, geht **jedes** hochgeladene Referenzbild vor dem Lauf in den
2684
+ * Bestand, und der Lauf verweist darauf. Erst dadurch ist ein Folgelauf
2685
+ * später überhaupt möglich (D-87).
2686
+ */
2687
+ images?: SzenenImageLibraryPort;
2688
+ newRunId?: () => string;
2689
+ now?: () => Date;
2690
+ }
2691
+ declare function createClientDerivationPort(options: CreateClientDerivationPortOptions): SzenenDerivationPort;
2692
+
2693
+ type SzenenAreaId = 'derive' | 'elements' | 'scene' | 'setup' | 'shot' | 'media';
2694
+ interface SzenenArea {
2695
+ id: SzenenAreaId;
2696
+ title: string;
2697
+ /** Was der Bereich leistet — auch die Erklärung, wenn er fehlt. */
2698
+ description: string;
2699
+ }
2700
+ /**
2701
+ * Die Bereiche, die dieser Host trägt.
2702
+ *
2703
+ * `media` und `derive` fallen weg, wenn der Port die zugehörige Fähigkeit nicht
2704
+ * hat — die einzigen Stellen, an denen ein Bereich verschwinden kann, und beide
2705
+ * lesen eine Fähigkeit, keinen Hostnamen. Alle anderen Bereiche gibt es immer:
2706
+ * ein Host ohne Elementspeicher wäre kein Szenen-Host.
2707
+ *
2708
+ * Ein leerer Bereich wäre die schlechtere Antwort: Er verspräche eine Aktion,
2709
+ * die dieser Host nicht ausführen kann, und der Nutzer suchte den Fehler bei
2710
+ * sich.
2711
+ */
2712
+ declare function areasFor(port: SzenenViewPort): readonly SzenenArea[];
2713
+ /** Ob eine gespeicherte Bereichswahl in diesem Host noch gilt. */
2714
+ declare function resolveArea(port: SzenenViewPort, gewuenscht: SzenenAreaId | null | undefined): SzenenAreaId;
2715
+ /**
2716
+ * Wie ein Kommandoergebnis dem Nutzer erklärt wird.
2717
+ *
2718
+ * §8 verlangt getrennte Darstellung: ein Konflikt ist kein Fehler, eine
2719
+ * abgelehnte Veröffentlichung ist kein Fehler, und eine fehlende Fähigkeit ist
2720
+ * erst recht keiner. Diese Funktion ist die eine Stelle, an der aus einem
2721
+ * Ergebnis ein Text wird — damit keine Komponente eigene Formulierungen und
2722
+ * eigene Einordnungen erfindet.
2723
+ */
2724
+ type NoticeTone = 'ok' | 'conflict' | 'rejected' | 'unsupported' | 'error';
2725
+ interface Notice {
2726
+ tone: NoticeTone;
2727
+ text: string;
2728
+ /** Einzelbefunde, etwa Publish-Regelverstöße — nie zu einem Satz verklebt. */
2729
+ details?: readonly string[];
2730
+ }
2731
+ declare function noticeFor(ergebnis: {
2732
+ kind: string;
2733
+ [k: string]: unknown;
2734
+ }, was: string): Notice;
2735
+
2736
+ interface SzenenViewProps {
2737
+ port: SzenenViewPort;
2738
+ /** Arbeitskontext. Die wirksame Kette löst der Port auf, nicht die View. */
2739
+ contextId?: string | null;
2740
+ /** Startbereich; eine ungültige Angabe fällt auf den ersten verfügbaren zurück. */
2741
+ initialArea?: SzenenAreaId;
2742
+ /** Meldet Bereichswechsel nach außen, damit der Host sie merken kann. */
2743
+ onAreaChange?: (area: SzenenAreaId) => void;
2744
+ }
2745
+ declare const SzenenView: React__default.FC<SzenenViewProps>;
2746
+
2747
+ export { AuthoritativeSzenenStore, CATALOGUE_TYPES, type CallableImageModel, CapabilityAnchorError, type CapabilityFlag, type CapabilityReason, type CapabilityReport, type CapabilityReportInput, type CapabilityScope, type CapabilityState, type ChainQueries, type ClientDerivationChannel, type ClientDerivationStore, ContextChainPort, type CreateBrowserTextGenerationPortOptions, type CreateClientDerivationPortOptions, type CreateClientRunPortOptions, type CreateFlowSzenenViewPortOptions, type CreateHfElementStoreOptions, type CreateHfEventChannelOptions, type CreateImageGenerationPortOptions, type CreateMemoryViewPortOptions, DerivableType, DerivationAssessment, DerivationConflict, DerivationDiagnostic, DerivationFailure, DerivationImage, DerivationInputMode, type DeriveItemInput, type DerivedItem, type DerivedLineage, type DerivedRelationship, type DerivedSzenenReference, type DifferentialResult, type DifferentialStep, type Divergence, DraftChainMeta, ELEMENT_VERSION_SCHEMA_FILE, type ElementEvent, type ElementEventChannel, ElementSnapshot, type ElementStoreState, type ExistingSzenenItem, FlowGenerateText, type FreezeDraftChainInput, type FreezeFailure, type FreezeResult, type FreezeSuccess, type FrozenChainNode, type GeneratedImage, type IdFactory, type ImageGenerationBatchPersistence, type ImageGenerationCapability, type ImageGenerationEventChannel, type ImageGenerationFinishedPayload, type ImageGenerationOrder, type ImageGenerationProviderPort, type ImageGenerationResult, type ImageGenerationRunReader, type ImageGenerationStartedPayload, ImageProvenance, type ImageProviderAccessCheck, type ImageProviderInput, type InMemoryEventChannel, type InputError, type IntegrityVerdict, type ItemDerivationFailure, type ItemDerivationFailureClass, type ItemDerivationResult, type ItemMedium, type LibraryImage, type NodeContribution, NotDerivable, type Notice, type NoticeTone, type PromptRunOutcome, type PromptRunOutput, type PromptRunPersistencePort, type PromptRunRecord, type PromptRunRecordedPayload, type ProviderCheckRecord, type ProviderCheckRecordedPayload, type ProviderCheckResult, PublishCheckResult, PublishFinding, RULES_WITHOUT_CAPABILITY_EFFECT, RULE_SCOPES, type RawSchema, type RecordedDerivationInput, type RecordedProposal, type RecoveryStatus, type ReducerFinding, ReferenceResolver, type RendererInput, type ResolveFailure, type ResolveResult, type ResolveShotInput, type ResolveShotPayloadInput, ResolveTechnicalError, type ResolvedCamera, type ResolvedNode, type ResolvedPlacement, type RunEventChannel, type RunFailure, type RunFailureClass, type RunItemReference, SZENEN_EVENT_PREFIX, SZENEN_EVENT_TYPES, SZENEN_ITEM_PREFIX, SZENEN_SCHEMAS, type SaveRunAsItemInput, type SceneDerivationPersistencePort, type SceneDerivationRecord, type SceneDerivationRecordedPayload, type SceneDerivationRecoveryRecord, type SceneDerivationRecoveryRecordedPayload, SchemaError, type StartImageGenerationInput, type StartRunInput, type StepState, type SzenenArea, type SzenenAreaId, type SzenenBatchOrigin, type SzenenBatchOriginFailure, type SzenenBatchOriginVerdict, SzenenCommands, SzenenElementStore, SzenenElementType, type SzenenImageGenerationPort as SzenenImageGenerationPortContract, type SzenenImageLibraryPort, type SzenenItemPort, type SzenenMediaPort, SzenenQueries, type SzenenRunPort, SzenenView, type SzenenViewCapabilities, type SzenenViewPort, type SzenenViewProps, TargetModelResolution, TextGenerationPort, UNCHECKED_PUBLISH_RULES, UnusableProposal, type VersionMedium, type VisibilityNode, areasFor, buildSystemInstruction, buildUserPrompt, callOptional, callableImageModelFor, capabilitiesOf, capabilityForTargetModel, capabilityGate, capabilityReport, catalogueFor, checkCreateElementInput, checkElementType, checkOptionalId, checkParents, checkPayloadPresent, checkPromptRunRecord, checkPublishVersionInput, checkRequiredId, checkReviseMetadataInput, checkRevision, checkRunResponse, checkSceneDerivationRecord, checkSceneDerivationRecoveryRecord, checkSetPreferredHeadInput, checkSzenenBatchOrigin, checkTitle, checkWriteDraftInput, collectImageGenerationOrders, collectPromptRuns, collectProviderChecks, collectSceneDerivationRecoveries, collectSceneDerivations, createBrowserTextGenerationPort, createClientDerivationPort, createClientRunPort, createEventLogDerivationPersistence, createEventLogRunPersistence, createFlowSzenenViewPort, createHfElementStore, createHfEventChannel, createHfImageLibrary, createImageGenerationPort, createInMemoryEventChannel, createMemoryViewPort, derivationPoliciesOf, deriveItemFromRun, deriveLineage, differentialSteps, draftRevisionOf, findImageGenerationOrder, findPromptRun, findProviderCheck, findSceneDerivation, findSceneDerivationRecovery, firstError, freezeDraftChain, hasPlacementCapability, isKnownElementType, isSzenenItemId, itemIdForRun, logRevisionOf, mergeSzenenBatchOrigin, noticeFor, ordersForPromptRun, parseRunResponse, preferredHeadRevisionOf, publishedHeadsOf, recoveriesForRun, recoveryStatusOf, reduceElementEvents, resolveArea, resolveShot, resolveShotPayload, roundOfRun, runPromptDerivation, runStoreDifferential, scopeOfPath, totalModelCalls, unclassifiedPublishRules, unsupportedReason };