@rslsp1/fa-app-tools 3.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -39,90 +39,6 @@ async function callOptional(capability, operation) {
39
39
  return operation();
40
40
  }
41
41
 
42
- // src/features/szenen/szenenViewModel.ts
43
- var ALLE_BEREICHE = [
44
- {
45
- id: "derive",
46
- title: "0 \xB7 Rekonstruktion",
47
- description: "Aus einem Bild oder Prompt einen Szenenentwurf vorschlagen lassen."
48
- },
49
- {
50
- id: "elements",
51
- title: "1 \xB7 Bausteine",
52
- description: "Figuren, Orte, Stile und Regeln f\xFCr sp\xE4tere Bildprompts pflegen."
53
- },
54
- {
55
- id: "scene",
56
- title: "2 \xB7 Szene",
57
- description: "Aus Bausteinen eine konkrete Szene und ihre Beziehungen bauen."
58
- },
59
- {
60
- id: "setup",
61
- title: "3 \xB7 Bildaufbau",
62
- description: "Stil, Komposition und Kamera f\xFCr das sp\xE4tere Bild festlegen."
63
- },
64
- {
65
- id: "shot",
66
- title: "4 \xB7 Prompt",
67
- description: "Bildprompt erzeugen, Varianten vergleichen und als Item speichern."
68
- },
69
- {
70
- id: "media",
71
- title: "Referenzen",
72
- description: "Referenzmedien einer Elementversion ansehen und zuordnen."
73
- }
74
- ];
75
- function areasFor(port) {
76
- const faehig = capabilitiesOf(port);
77
- return ALLE_BEREICHE.filter((bereich) => {
78
- if (bereich.id === "media") return faehig.media;
79
- if (bereich.id === "derive") return faehig.derivation;
80
- return true;
81
- });
82
- }
83
- function resolveArea(port, gewuenscht) {
84
- const verfuegbar = areasFor(port);
85
- if (gewuenscht && verfuegbar.some((b) => b.id === gewuenscht)) return gewuenscht;
86
- return verfuegbar.find((b) => b.id === "elements")?.id ?? verfuegbar[0].id;
87
- }
88
- function noticeFor(ergebnis, was) {
89
- switch (ergebnis.kind) {
90
- case "ok":
91
- return { tone: "ok", text: `${was}: erledigt.` };
92
- case "conflict": {
93
- const aktuell = ergebnis.actualRevision;
94
- return {
95
- tone: "conflict",
96
- text: `${was}: inzwischen von anderer Seite ge\xE4ndert` + (aktuell !== void 0 ? ` (aktueller Stand: Revision ${String(aktuell)})` : "") + ". Bitte neu laden und erneut versuchen."
97
- };
98
- }
99
- case "rejected": {
100
- const fehler4 = ergebnis.errors ?? [];
101
- const ungeprueft = ergebnis.unchecked ?? [];
102
- return {
103
- tone: "rejected",
104
- text: `${was}: abgelehnt \u2014 ${fehler4.length} Befund${fehler4.length === 1 ? "" : "e"}.`,
105
- details: [
106
- ...fehler4.map((f) => `${f.path ?? "(ohne Pfad)"}: ${f.message ?? "ohne Meldung"}`),
107
- // Nicht verschweigen: was nicht geprüft wurde, ist nicht in Ordnung,
108
- // sondern ungeprüft.
109
- ...ungeprueft.map((u) => `ungepr\xFCft: ${u}`)
110
- ]
111
- };
112
- }
113
- case "unsupported":
114
- return {
115
- tone: "unsupported",
116
- text: `${was}: von diesem Host nicht angeboten (${String(ergebnis.capability ?? was)}). Das ist kein Fehler und kein vor\xFCbergehender Zustand.`
117
- };
118
- default:
119
- return {
120
- tone: "error",
121
- text: `${was}: ${String(ergebnis.message ?? "unbekannter Fehler")}`
122
- };
123
- }
124
- }
125
-
126
42
  // src/lib/szenen/jsonSchema.ts
127
43
  var SUPPORTED_KEYWORDS = /* @__PURE__ */ new Set([
128
44
  "$ref",
@@ -3196,6 +3112,96 @@ function formatSchemaErrors(errors) {
3196
3112
  return errors.map((e) => `${e.instancePath || "/"} ${e.message}`).join("; ");
3197
3113
  }
3198
3114
 
3115
+ // src/features/szenen/szenenViewModel.ts
3116
+ var KEINE_BAUSTEINE = [
3117
+ "scene",
3118
+ "scene_setup",
3119
+ "shot"
3120
+ ];
3121
+ var BAUSTEIN_TYPES = SZENEN_ELEMENT_TYPES.filter((typ) => !KEINE_BAUSTEINE.includes(typ));
3122
+ var ALLE_BEREICHE = [
3123
+ {
3124
+ id: "derive",
3125
+ title: "0 \xB7 Rekonstruktion",
3126
+ description: "Aus einem Bild oder Prompt einen Szenenentwurf vorschlagen lassen."
3127
+ },
3128
+ {
3129
+ id: "elements",
3130
+ title: "1 \xB7 Bausteine",
3131
+ description: "Figuren, Orte, Stile und Regeln f\xFCr sp\xE4tere Bildprompts pflegen."
3132
+ },
3133
+ {
3134
+ id: "scene",
3135
+ title: "2 \xB7 Szene",
3136
+ description: "Aus Bausteinen eine konkrete Szene und ihre Beziehungen bauen."
3137
+ },
3138
+ {
3139
+ id: "setup",
3140
+ title: "3 \xB7 Bildaufbau",
3141
+ description: "Stil, Komposition und Kamera f\xFCr das sp\xE4tere Bild festlegen."
3142
+ },
3143
+ {
3144
+ id: "shot",
3145
+ title: "4 \xB7 Prompt",
3146
+ description: "Bildprompt erzeugen, Varianten vergleichen und als Item speichern."
3147
+ },
3148
+ {
3149
+ id: "media",
3150
+ title: "Referenzen",
3151
+ description: "Referenzmedien einer Elementversion ansehen und zuordnen."
3152
+ }
3153
+ ];
3154
+ function areasFor(port) {
3155
+ const faehig = capabilitiesOf(port);
3156
+ return ALLE_BEREICHE.filter((bereich) => {
3157
+ if (bereich.id === "media") return faehig.media;
3158
+ if (bereich.id === "derive") return faehig.derivation;
3159
+ return true;
3160
+ });
3161
+ }
3162
+ function resolveArea(port, gewuenscht) {
3163
+ const verfuegbar = areasFor(port);
3164
+ if (gewuenscht && verfuegbar.some((b) => b.id === gewuenscht)) return gewuenscht;
3165
+ return verfuegbar.find((b) => b.id === "elements")?.id ?? verfuegbar[0].id;
3166
+ }
3167
+ function noticeFor(ergebnis, was) {
3168
+ switch (ergebnis.kind) {
3169
+ case "ok":
3170
+ return { tone: "ok", text: `${was}: erledigt.` };
3171
+ case "conflict": {
3172
+ const aktuell = ergebnis.actualRevision;
3173
+ return {
3174
+ tone: "conflict",
3175
+ text: `${was}: inzwischen von anderer Seite ge\xE4ndert` + (aktuell !== void 0 ? ` (aktueller Stand: Revision ${String(aktuell)})` : "") + ". Bitte neu laden und erneut versuchen."
3176
+ };
3177
+ }
3178
+ case "rejected": {
3179
+ const fehler4 = ergebnis.errors ?? [];
3180
+ const ungeprueft = ergebnis.unchecked ?? [];
3181
+ return {
3182
+ tone: "rejected",
3183
+ text: `${was}: abgelehnt \u2014 ${fehler4.length} Befund${fehler4.length === 1 ? "" : "e"}.`,
3184
+ details: [
3185
+ ...fehler4.map((f) => `${f.path ?? "(ohne Pfad)"}: ${f.message ?? "ohne Meldung"}`),
3186
+ // Nicht verschweigen: was nicht geprüft wurde, ist nicht in Ordnung,
3187
+ // sondern ungeprüft.
3188
+ ...ungeprueft.map((u) => `ungepr\xFCft: ${u}`)
3189
+ ]
3190
+ };
3191
+ }
3192
+ case "unsupported":
3193
+ return {
3194
+ tone: "unsupported",
3195
+ text: `${was}: von diesem Host nicht angeboten (${String(ergebnis.capability ?? was)}). Das ist kein Fehler und kein vor\xFCbergehender Zustand.`
3196
+ };
3197
+ default:
3198
+ return {
3199
+ tone: "error",
3200
+ text: `${was}: ${String(ergebnis.message ?? "unbekannter Fehler")}`
3201
+ };
3202
+ }
3203
+ }
3204
+
3199
3205
  // src/lib/szenen/contextVisibility.ts
3200
3206
  var isObject2 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
3201
3207
  function zerlegeKette(contextChain) {
@@ -3378,6 +3384,22 @@ function checkImageExecutionProfile(profile) {
3378
3384
  }
3379
3385
  return befunde;
3380
3386
  }
3387
+ function checkImageExecutionProfiles(profiles) {
3388
+ const anzahlJeKennung = /* @__PURE__ */ new Map();
3389
+ for (const profil of profiles ?? []) {
3390
+ if (!isObject3(profil) || !istText(profil.profile_id)) continue;
3391
+ anzahlJeKennung.set(profil.profile_id, (anzahlJeKennung.get(profil.profile_id) ?? 0) + 1);
3392
+ }
3393
+ return (profiles ?? []).map((profil) => {
3394
+ const befunde = [...checkImageExecutionProfile(profil)];
3395
+ if (isObject3(profil) && istText(profil.profile_id) && (anzahlJeKennung.get(profil.profile_id) ?? 0) > 1) {
3396
+ befunde.push(
3397
+ `Die profile_id "${profil.profile_id}" kommt in diesem Zielmodell mehrfach vor \u2014 die Auswahl waere nicht mehr eindeutig aufloesbar.`
3398
+ );
3399
+ }
3400
+ return befunde;
3401
+ });
3402
+ }
3381
3403
  function executableImageModels(promptTargetModelKey, targets, capability) {
3382
3404
  const models = [];
3383
3405
  const invalid = [];
@@ -3391,8 +3413,9 @@ function executableImageModels(promptTargetModelKey, targets, capability) {
3391
3413
  };
3392
3414
  }
3393
3415
  for (const target of targets ?? []) {
3394
- for (const roh of target.executionProfiles ?? []) {
3395
- const befunde = checkImageExecutionProfile(roh);
3416
+ const profilBefunde = checkImageExecutionProfiles(target.executionProfiles ?? []);
3417
+ for (const [index, roh] of (target.executionProfiles ?? []).entries()) {
3418
+ const befunde = profilBefunde[index] ?? [];
3396
3419
  if (befunde.length > 0) {
3397
3420
  const kennung = isObject3(roh) && istText(roh.profile_id) ? roh.profile_id : "(ohne profile_id)";
3398
3421
  invalid.push(`${target.key}/${kennung}: ${befunde.join(" ")}`);
@@ -3401,13 +3424,20 @@ function executableImageModels(promptTargetModelKey, targets, capability) {
3401
3424
  const profil = roh;
3402
3425
  if (!profil.enabled) continue;
3403
3426
  if (!profil.environments.includes(capability.environment_id)) continue;
3404
- if (!capability.execution_paths.includes(profil.execution_path)) continue;
3427
+ const weg = capability.execution_paths.find((r) => r.execution_path === profil.execution_path);
3428
+ if (!weg) continue;
3429
+ if (target.provider !== weg.provider) {
3430
+ invalid.push(
3431
+ `${target.key}/${profil.profile_id}: Das Zielmodell nennt den Anbieter ${target.provider === null ? "(keinen)" : `"${target.provider}"`}, der Aufrufweg "${weg.execution_path}" fuehrt aber zu "${weg.provider}".`
3432
+ );
3433
+ continue;
3434
+ }
3405
3435
  models.push({
3406
3436
  selection_id: `${target.key}#${profil.profile_id}`,
3407
3437
  target_model_key: target.key,
3408
3438
  ...target.versionId ? { target_model_version_id: target.versionId } : {},
3409
3439
  display_name: target.title,
3410
- provider: target.provider ?? "(ohne provider)",
3440
+ provider: weg.provider,
3411
3441
  profile_id: profil.profile_id,
3412
3442
  environment_id: capability.environment_id,
3413
3443
  execution_path: profil.execution_path,
@@ -3426,7 +3456,7 @@ function executableImageModels(promptTargetModelKey, targets, capability) {
3426
3456
  models: [],
3427
3457
  default_selection_id: null,
3428
3458
  invalid_profiles: invalid,
3429
- reason: `In dieser Umgebung (${capability.environment_id}) traegt kein sichtbares Zielmodell ein aktives Ausfuehrungsprofil fuer einen Aufrufweg dieses Hosts (${capability.execution_paths.join(", ") || "keiner"}).`
3459
+ reason: `In dieser Umgebung (${capability.environment_id}) traegt kein sichtbares Zielmodell ein aktives Ausfuehrungsprofil fuer einen Aufrufweg dieses Hosts (${capability.execution_paths.map((r) => r.execution_path).join(", ") || "keiner"}).`
3430
3460
  };
3431
3461
  }
3432
3462
  const passend = models.find((m) => m.is_prompt_target);
@@ -4260,6 +4290,96 @@ function finish(report) {
4260
4290
  };
4261
4291
  }
4262
4292
 
4293
+ // src/lib/szenen/promptOperation.ts
4294
+ var PROMPT_RULE_EFFECT = {
4295
+ "P-01": "diagnostic",
4296
+ // Kamera-ID im Rig nicht auflösbar → ohne Kamera weiter
4297
+ "P-02": "diagnostic",
4298
+ // mehrdeutige Kamera-ID → erklären, nicht sperren
4299
+ "P-03": "diagnostic",
4300
+ // Abstammungsintegrität einer camera_id — Publish-Frage
4301
+ "P-04": "diagnostic",
4302
+ // referenzierte Version nicht veröffentlicht/sichtbar
4303
+ "P-05": "diagnostic",
4304
+ // Node-Referenz nicht auflösbar → Teil auslassen
4305
+ "P-06": "diagnostic",
4306
+ // Placement-Node mehrdeutig → ohne exakte Platzierung
4307
+ "P-07": "diagnostic",
4308
+ // spatial Pattern ohne can_place → Pattern weglassen
4309
+ "P-08": "diagnostic",
4310
+ // unvollständige Pattern-Bindings
4311
+ "P-09": "not_applicable",
4312
+ // reine Publish-/Prozessregel für sequence
4313
+ "P-10": "diagnostic",
4314
+ // Zyklus: Blocker nur, wenn keine endliche Auflösung bleibt
4315
+ "P-11": "diagnostic",
4316
+ // Override-Disziplin, schon bisher advisory
4317
+ "P-12": "not_applicable",
4318
+ // Laufzeitregel der Auflösung, keine Bedingung
4319
+ "P-13": "diagnostic",
4320
+ // pattern_derived ohne Pattern-Platzierung
4321
+ "P-14": "diagnostic",
4322
+ // Bildgrößen-/Optik-Plausibilität, erklärte Absicht gewinnt
4323
+ "P-15": "diagnostic",
4324
+ // vertikaler look_at ohne up_hint — Rollwinkel ist Spezialpräzision
4325
+ "P-16": "diagnostic",
4326
+ // Placements ohne Koordinatensystem
4327
+ "P-17": "diagnostic"
4328
+ // Target Model nicht auflösbar → generischer Prompt
4329
+ };
4330
+ function rulesWithoutPromptEffect(alleRegeln) {
4331
+ return alleRegeln.filter((rule) => !(rule in PROMPT_RULE_EFFECT));
4332
+ }
4333
+ function diagnosticOfFinding(finding) {
4334
+ return {
4335
+ code: finding.rule,
4336
+ origin: "rule",
4337
+ path: finding.path,
4338
+ message: finding.message
4339
+ };
4340
+ }
4341
+ function diagnosticOfSchemaError(error, where) {
4342
+ return {
4343
+ code: "schema",
4344
+ origin: "schema",
4345
+ path: error.instancePath || "/",
4346
+ message: `${where}: ${error.message}`
4347
+ };
4348
+ }
4349
+ function promptDiagnosticsOf(checks) {
4350
+ const befunde = [];
4351
+ for (const finding of checks.findings) {
4352
+ if (PROMPT_RULE_EFFECT[finding.rule] === "not_applicable") continue;
4353
+ befunde.push(diagnosticOfFinding(finding));
4354
+ }
4355
+ return befunde;
4356
+ }
4357
+ var isObject7 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
4358
+ var asArray2 = (v) => Array.isArray(v) ? v : [];
4359
+ var istText2 = (v) => typeof v === "string" && v.trim().length > 0;
4360
+ function describableContent(scenePayload) {
4361
+ if (!isObject7(scenePayload)) {
4362
+ return {
4363
+ ok: false,
4364
+ message: `Die Szene ist kein Objekt, sondern ${Array.isArray(scenePayload) ? "ein Array" : typeof scenePayload}. Daraus laesst sich kein Textauftrag herstellen.`
4365
+ };
4366
+ }
4367
+ const nodes = asArray2(scenePayload.nodes);
4368
+ for (const node of nodes) {
4369
+ if (!isObject7(node)) continue;
4370
+ const semantic = isObject7(node.semantic) ? node.semantic : null;
4371
+ if (semantic && istText2(semantic.description)) return { ok: true };
4372
+ if (asArray2(node.component_refs).length > 0) return { ok: true };
4373
+ }
4374
+ const environment = isObject7(scenePayload.environment) ? scenePayload.environment : null;
4375
+ if (environment && istText2(environment.text)) return { ok: true };
4376
+ if (environment && asArray2(environment.component_refs).length > 0) return { ok: true };
4377
+ return {
4378
+ ok: false,
4379
+ message: nodes.length === 0 ? "Die Szene hat keine Knoten und keinen Umgebungstext. Ohne beschreibbaren Inhalt gibt es nichts, woraus ein Prompt entstehen koennte." : `Keiner der ${nodes.length} Knoten traegt eine Beschreibung oder eine Komponentenreferenz, und es gibt keinen Umgebungstext. Ein Prompt daraus waere eine leere Behauptung.`
4380
+ };
4381
+ }
4382
+
4263
4383
  // src/lib/szenen/capabilities.ts
4264
4384
  var CapabilityAnchorError = class extends Error {
4265
4385
  };
@@ -4302,9 +4422,9 @@ var FLAG_OF_SCOPE = {
4302
4422
  // die Vererbung an die beiden anderen weitergereicht.
4303
4423
  global: "can_describe_scene"
4304
4424
  };
4305
- var isObject7 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
4425
+ var isObject8 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
4306
4426
  function nodeCountOf(scenePayload) {
4307
- if (!isObject7(scenePayload)) return 0;
4427
+ if (!isObject8(scenePayload)) return 0;
4308
4428
  return Array.isArray(scenePayload.nodes) ? scenePayload.nodes.length : 0;
4309
4429
  }
4310
4430
  async function capabilityReport(input) {
@@ -4329,7 +4449,7 @@ async function capabilityReport(input) {
4329
4449
  reason: "Payload verletzt das Schema \u2014 die Publish-Regeln wurden nicht ausgefuehrt"
4330
4450
  }))
4331
4451
  } : await runPublishChecks({ type, payload: setupPayload, elementId, parents, resolver });
4332
- if (!isObject7(setupPayload)) {
4452
+ if (!isObject8(setupPayload)) {
4333
4453
  const vorgefunden = Array.isArray(setupPayload) ? "array" : typeof setupPayload;
4334
4454
  const reasons = [
4335
4455
  {
@@ -4339,10 +4459,14 @@ async function capabilityReport(input) {
4339
4459
  ];
4340
4460
  return {
4341
4461
  can_describe_scene: { state: "no", reasons },
4462
+ // Auch fuer den Promptpfad ein echter Blocker: Eine Payload, die kein
4463
+ // Objekt ist, ist technisch unlesbar (Schritt 07, Klasse A/C) — nicht
4464
+ // bloss fachlich unvollstaendig.
4342
4465
  can_render_prompt: { state: "no", reasons },
4343
4466
  can_place: { state: "no", reasons },
4344
4467
  checks,
4345
- schemaErrors
4468
+ schemaErrors,
4469
+ promptDiagnostics: []
4346
4470
  };
4347
4471
  }
4348
4472
  const blockedByScope = /* @__PURE__ */ new Map();
@@ -4378,6 +4502,8 @@ async function capabilityReport(input) {
4378
4502
  };
4379
4503
  const base = forFlag("can_describe_scene");
4380
4504
  let describe;
4505
+ let szenenPayload = null;
4506
+ let sceneVersionId = null;
4381
4507
  if (base.blocked.length > 0) {
4382
4508
  describe = { state: "no", reasons: base.blocked };
4383
4509
  } else if (schemaErrors.length > 0) {
@@ -4403,9 +4529,10 @@ async function capabilityReport(input) {
4403
4529
  ]
4404
4530
  };
4405
4531
  } else {
4406
- const sceneRef = isObject7(setupPayload.scene_ref) ? setupPayload.scene_ref : null;
4407
- const sceneVersionId = typeof sceneRef?.version_id === "string" ? sceneRef.version_id : null;
4532
+ const sceneRef = isObject8(setupPayload.scene_ref) ? setupPayload.scene_ref : null;
4533
+ sceneVersionId = typeof sceneRef?.version_id === "string" ? sceneRef.version_id : null;
4408
4534
  const scene = chainScene !== void 0 ? { payload: chainScene } : sceneVersionId ? await resolver.getVersion(sceneVersionId) : null;
4535
+ if (scene) szenenPayload = { payload: scene.payload };
4409
4536
  const nodes = nodeCountOf(scene?.payload);
4410
4537
  if (nodes === 0) {
4411
4538
  describe = {
@@ -4452,15 +4579,38 @@ async function capabilityReport(input) {
4452
4579
  if (own.unchecked.length > 0) return { state: "unknown", reasons: own.unchecked };
4453
4580
  return { state: "yes", reasons: [] };
4454
4581
  };
4582
+ const promptFlag = (() => {
4583
+ if (!szenenPayload) {
4584
+ return {
4585
+ state: "unknown",
4586
+ reasons: [
4587
+ {
4588
+ kind: "structure",
4589
+ message: `Die Szene ${sceneVersionId ?? "(ohne version_id)"} wurde nicht gelesen; ob beschreibbarer Inhalt vorliegt, ist damit offen \u2014 keine Absage.`
4590
+ }
4591
+ ]
4592
+ };
4593
+ }
4594
+ const inhalt = describableContent(szenenPayload.payload);
4595
+ if (!inhalt.ok) {
4596
+ return { state: "no", reasons: [{ kind: "structure", message: inhalt.message }] };
4597
+ }
4598
+ return { state: "yes", reasons: [] };
4599
+ })();
4600
+ const promptDiagnostics = [
4601
+ ...schemaErrors.map((e) => diagnosticOfSchemaError(e, `Scene Setup ${elementId}`)),
4602
+ ...promptDiagnosticsOf(checks)
4603
+ ];
4455
4604
  return {
4456
4605
  can_describe_scene: describe,
4457
- can_render_prompt: derived("can_render_prompt"),
4606
+ can_render_prompt: promptFlag,
4458
4607
  can_place: derived("can_place", {
4459
4608
  ok: hasPlacementCapability(setupPayload),
4460
4609
  message: "Das Scene Setup traegt kein coordinate_system und ist damit nicht platzierbar (D-65)."
4461
4610
  }),
4462
4611
  checks,
4463
- schemaErrors
4612
+ schemaErrors,
4613
+ promptDiagnostics
4464
4614
  };
4465
4615
  }
4466
4616
  function unclassifiedPublishRules() {
@@ -4468,6 +4618,27 @@ function unclassifiedPublishRules() {
4468
4618
  (rule) => !(rule in RULE_SCOPES) && !(rule in RULES_WITHOUT_CAPABILITY_EFFECT)
4469
4619
  );
4470
4620
  }
4621
+ function sceneOnlyCapabilities(scenePayload) {
4622
+ const knoten = nodeCountOf(scenePayload);
4623
+ const inhalt = describableContent(scenePayload);
4624
+ return {
4625
+ can_describe_scene: knoten > 0 ? { state: "yes", reasons: [] } : {
4626
+ state: "no",
4627
+ reasons: [{
4628
+ kind: "structure",
4629
+ message: "Die Szene hat keine Knoten. Ohne Knoten gibt es nichts zu beschreiben."
4630
+ }]
4631
+ },
4632
+ can_render_prompt: inhalt.ok ? { state: "yes", reasons: [] } : { state: "no", reasons: [{ kind: "structure", message: inhalt.message }] },
4633
+ can_place: {
4634
+ state: "no",
4635
+ reasons: [{
4636
+ kind: "structure",
4637
+ message: "Zu dieser Szene gehoert kein Scene Setup. Weltplatzierung und coordinate_system liegen ausschliesslich dort (D-39/D-65) \u2014 es gibt also keine belastbaren Koordinaten."
4638
+ }]
4639
+ }
4640
+ };
4641
+ }
4471
4642
 
4472
4643
  // src/lib/szenen/szenenPorts.ts
4473
4644
  function resolverFromQueries(queries, contexts) {
@@ -4525,13 +4696,13 @@ function isSzenenItemId(itemId) {
4525
4696
  return itemId.startsWith(SZENEN_ITEM_PREFIX);
4526
4697
  }
4527
4698
  function checkSzenenBatchOrigin(candidate) {
4528
- if (!istText2(candidate.prompt_run_id)) {
4699
+ if (!istText3(candidate.prompt_run_id)) {
4529
4700
  return {
4530
4701
  kind: "rejected",
4531
4702
  failure: { field: "prompt_run_id", message: '"prompt_run_id" fehlt oder ist leer.' }
4532
4703
  };
4533
4704
  }
4534
- if (!istText2(candidate.generation_batch_id)) {
4705
+ if (!istText3(candidate.generation_batch_id)) {
4535
4706
  return {
4536
4707
  kind: "rejected",
4537
4708
  failure: {
@@ -4574,7 +4745,7 @@ function mergeSzenenBatchOrigin(bestehend, neu) {
4574
4745
  };
4575
4746
  }
4576
4747
  var DEFAULT_FSK_LEVEL = "FSK16";
4577
- var istText2 = (v) => typeof v === "string" && v.trim().length > 0;
4748
+ var istText3 = (v) => typeof v === "string" && v.trim().length > 0;
4578
4749
  function roundOfRun(run, runsOfShot) {
4579
4750
  return runsOfShot.findIndex((kandidat) => kandidat.run_id === run.run_id) + 1;
4580
4751
  }
@@ -4610,7 +4781,7 @@ function deriveItemFromRun(input) {
4610
4781
  }
4611
4782
  };
4612
4783
  }
4613
- if (!run.output || !istText2(run.output.positive)) {
4784
+ if (!run.output || !istText3(run.output.positive)) {
4614
4785
  return {
4615
4786
  kind: "rejected",
4616
4787
  failure: {
@@ -4631,8 +4802,8 @@ function deriveItemFromRun(input) {
4631
4802
  }
4632
4803
  const item_id = itemIdForRun(run.run_id);
4633
4804
  const lineage = deriveLineage(item_id, round, existingItems);
4634
- const negative = istText2(run.output.negative) ? run.output.negative : null;
4635
- const title = istText2(input.title) ? input.title : istText2(input.shotTitle) ? `${input.shotTitle} \xB7 Runde ${round}` : `Szenen-Lauf ${round}`;
4805
+ const negative = istText3(run.output.negative) ? run.output.negative : null;
4806
+ const title = istText3(input.title) ? input.title : istText3(input.shotTitle) ? `${input.shotTitle} \xB7 Runde ${round}` : `Szenen-Lauf ${round}`;
4636
4807
  return {
4637
4808
  kind: "ok",
4638
4809
  value: {
@@ -4642,9 +4813,9 @@ function deriveItemFromRun(input) {
4642
4813
  negative_prompt: negative,
4643
4814
  // `feedback` ist Pflicht (D-55) und ist genau die Erlaeuterung fuer den
4644
4815
  // Menschen — also gehoert sie in das Feld fuer Notizen.
4645
- notes: istText2(input.notes) ? input.notes : run.output.feedback,
4816
+ notes: istText3(input.notes) ? input.notes : run.output.feedback,
4646
4817
  rating: typeof input.rating === "number" ? input.rating : 0,
4647
- fsk_level: istText2(input.fskLevel) ? input.fskLevel : DEFAULT_FSK_LEVEL,
4818
+ fsk_level: istText3(input.fskLevel) ? input.fskLevel : DEFAULT_FSK_LEVEL,
4648
4819
  tags: [],
4649
4820
  szenen: {
4650
4821
  prompt_run_id: run.run_id,
@@ -5518,7 +5689,7 @@ function validateDerivationInput(input) {
5518
5689
  if (input.policy.produces.length === 0) return "Die Regel erzeugt keinen einzigen Vorschlag.";
5519
5690
  return null;
5520
5691
  }
5521
- var isObject8 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
5692
+ var isObject9 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
5522
5693
  var MAX_PROPOSAL_TITLE_LENGTH = 120;
5523
5694
  function fallbackProposalTitle(type) {
5524
5695
  return `Rekonstruktion ${type}`;
@@ -5544,7 +5715,7 @@ function resolveJsonPointer(wurzel, pointer) {
5544
5715
  aktuell = aktuell[index];
5545
5716
  continue;
5546
5717
  }
5547
- if (!isObject8(aktuell) || !(schluessel in aktuell)) {
5718
+ if (!isObject9(aktuell) || !(schluessel in aktuell)) {
5548
5719
  return { found: false, value: void 0 };
5549
5720
  }
5550
5721
  aktuell = aktuell[schluessel];
@@ -5558,7 +5729,7 @@ function collectVersionRefs2(value) {
5558
5729
  knoten.forEach(besuchen);
5559
5730
  return;
5560
5731
  }
5561
- if (!isObject8(knoten)) return;
5732
+ if (!isObject9(knoten)) return;
5562
5733
  if (typeof knoten.element_id === "string" && typeof knoten.version_id === "string") {
5563
5734
  gefunden.push({ element_id: knoten.element_id, version_id: knoten.version_id });
5564
5735
  }
@@ -5624,7 +5795,7 @@ function assessDerivationResponse(value, input) {
5624
5795
  envelope: null,
5625
5796
  contract_ok: false
5626
5797
  });
5627
- if (!isObject8(value)) {
5798
+ if (!isObject9(value)) {
5628
5799
  befund({
5629
5800
  code: "response.not_object",
5630
5801
  severity: "error",
@@ -5642,7 +5813,7 @@ function assessDerivationResponse(value, input) {
5642
5813
  });
5643
5814
  }
5644
5815
  const rohProposals = value.proposals;
5645
- const proposalsLesbar = isObject8(rohProposals);
5816
+ const proposalsLesbar = isObject9(rohProposals);
5646
5817
  if (!proposalsLesbar) {
5647
5818
  befund({
5648
5819
  code: "envelope.proposals_missing",
@@ -5652,7 +5823,7 @@ function assessDerivationResponse(value, input) {
5652
5823
  });
5653
5824
  }
5654
5825
  const roh = proposalsLesbar ? rohProposals : {};
5655
- const rohGaps = isObject8(value.gaps) ? value.gaps : {};
5826
+ const rohGaps = isObject9(value.gaps) ? value.gaps : {};
5656
5827
  const gapsUngefragt = Object.keys(rohGaps).filter(
5657
5828
  (t) => !input.policy.produces.includes(t)
5658
5829
  );
@@ -5664,7 +5835,7 @@ function assessDerivationResponse(value, input) {
5664
5835
  pointer: "/gaps"
5665
5836
  });
5666
5837
  }
5667
- const fehlend = input.policy.produces.filter((t) => !isObject8(roh[t]));
5838
+ const fehlend = input.policy.produces.filter((t) => !isObject9(roh[t]));
5668
5839
  if (fehlend.length > 0 && proposalsLesbar) {
5669
5840
  const d = befund({
5670
5841
  code: "envelope.proposals_missing_types",
@@ -5685,10 +5856,10 @@ function assessDerivationResponse(value, input) {
5685
5856
  pointer: "/proposals"
5686
5857
  });
5687
5858
  }
5688
- const rohTitles = isObject8(value.titles) ? value.titles : {};
5859
+ const rohTitles = isObject9(value.titles) ? value.titles : {};
5689
5860
  const umgebucht = [];
5690
5861
  for (const type of input.policy.produces) {
5691
- if (!isObject8(roh[type])) continue;
5862
+ if (!isObject9(roh[type])) continue;
5692
5863
  const payload = roh[type];
5693
5864
  const eigene = [];
5694
5865
  const bezug = REFERENCE_FIELD[type];
@@ -5724,7 +5895,7 @@ function assessDerivationResponse(value, input) {
5724
5895
  const bezugPointer = bezug ? `/${bezug.field}` : null;
5725
5896
  let gapFehler = false;
5726
5897
  for (const eintrag of benannt) {
5727
- if (!isObject8(eintrag) || typeof eintrag.pointer !== "string" || typeof eintrag.reason !== "string" || !eintrag.reason.trim()) {
5898
+ if (!isObject9(eintrag) || typeof eintrag.pointer !== "string" || typeof eintrag.reason !== "string" || !eintrag.reason.trim()) {
5728
5899
  eigene.push(befund({
5729
5900
  code: "proposal.gap_entry_invalid",
5730
5901
  severity: "error",
@@ -5800,7 +5971,7 @@ function assessDerivationResponse(value, input) {
5800
5971
  });
5801
5972
  } else {
5802
5973
  for (const eintrag of value.not_derivable) {
5803
- if (!isObject8(eintrag) || typeof eintrag.field !== "string" || typeof eintrag.reason !== "string") {
5974
+ if (!isObject9(eintrag) || typeof eintrag.field !== "string" || typeof eintrag.reason !== "string") {
5804
5975
  befund({
5805
5976
  code: "envelope.not_derivable_entry_invalid",
5806
5977
  severity: "error",
@@ -5825,7 +5996,7 @@ function assessDerivationResponse(value, input) {
5825
5996
  });
5826
5997
  } else {
5827
5998
  for (const eintrag of value.conflicts) {
5828
- if (!isObject8(eintrag) || typeof eintrag.field !== "string" || typeof eintrag.from_image !== "string" || typeof eintrag.from_prompt !== "string") {
5999
+ if (!isObject9(eintrag) || typeof eintrag.field !== "string" || typeof eintrag.from_image !== "string" || typeof eintrag.from_prompt !== "string") {
5829
6000
  befund({
5830
6001
  code: "envelope.conflicts_entry_invalid",
5831
6002
  severity: "error",
@@ -6012,10 +6183,10 @@ async function runSceneDerivation(input, port, userPrompt) {
6012
6183
  }
6013
6184
 
6014
6185
  // src/features/szenen/SzenenView.tsx
6015
- import { useMemo as useMemo3, useState as useState15 } from "react";
6186
+ import { useMemo as useMemo3, useState as useState16 } from "react";
6016
6187
 
6017
6188
  // src/features/szenen/areas/ElementsArea.tsx
6018
- import { useState as useState10 } from "react";
6189
+ import { useState as useState11 } from "react";
6019
6190
 
6020
6191
  // src/features/szenen/areas/usePortQuery.ts
6021
6192
  import { useEffect, useRef, useState } from "react";
@@ -6049,6 +6220,32 @@ function usePortQuery(frage, abhaengigkeiten) {
6049
6220
  // src/features/szenen/areas/ElementDetail.tsx
6050
6221
  import { useEffect as useEffect3, useMemo as useMemo2, useState as useState9 } from "react";
6051
6222
 
6223
+ // src/features/szenen/elementLabels.ts
6224
+ var LABELS = {
6225
+ scene_component: { singular: "Szenenbaustein", plural: "Szenenbausteine" },
6226
+ scene: { singular: "Szene", plural: "Szenen" },
6227
+ shot_concept: { singular: "Prompt-Idee", plural: "Prompt-Ideen" },
6228
+ camera_preset: { singular: "Kamera", plural: "Kameras" },
6229
+ camera_pattern: { singular: "Kamera-Muster", plural: "Kamera-Muster" },
6230
+ style: { singular: "Stil", plural: "Stile" },
6231
+ scene_setup: { singular: "Bildaufbau", plural: "Bildaufbauten" },
6232
+ shot: { singular: "Prompt", plural: "Prompts" },
6233
+ prompt_policy: { singular: "Prompt-Regel", plural: "Prompt-Regeln" },
6234
+ prompt_fragment: { singular: "Prompt-Baustein", plural: "Prompt-Bausteine" },
6235
+ target_model: { singular: "Zielmodell", plural: "Zielmodelle" },
6236
+ sequence: { singular: "Sequenz", plural: "Sequenzen" },
6237
+ scene_derivation_policy: {
6238
+ singular: "Rekonstruktions-Regel",
6239
+ plural: "Rekonstruktions-Regeln"
6240
+ }
6241
+ };
6242
+ function elementTypLabel(typ) {
6243
+ return LABELS[typ]?.singular ?? typ;
6244
+ }
6245
+ function elementTypPlural(typ) {
6246
+ return LABELS[typ]?.plural ?? typ;
6247
+ }
6248
+
6052
6249
  // src/features/szenen/schemaForm.ts
6053
6250
  var FORM_JE_REF = {
6054
6251
  "common.schema.json#/$defs/slug": "slug",
@@ -6344,7 +6541,7 @@ var SEMANTIK = {
6344
6541
  function feldSemantik(type, pfad) {
6345
6542
  return SEMANTIK[`${type}.${pfad}`] ?? null;
6346
6543
  }
6347
- var LABELS = {
6544
+ var LABELS2 = {
6348
6545
  key: "Kennung",
6349
6546
  name: "Name",
6350
6547
  text: "Text",
@@ -6389,13 +6586,13 @@ var LABELS = {
6389
6586
  properties: "Zusatzangaben"
6390
6587
  };
6391
6588
  function feldLabel(type, pfad, name) {
6392
- return feldSemantik(type, pfad)?.label ?? LABELS[name] ?? name;
6589
+ return feldSemantik(type, pfad)?.label ?? LABELS2[name] ?? name;
6393
6590
  }
6394
6591
 
6395
6592
  // src/features/szenen/areas/SchemaFields.tsx
6396
6593
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6397
- var isObject9 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
6398
- var istVersionRef = (v) => isObject9(v) && typeof v.element_id === "string" && typeof v.version_id === "string";
6594
+ var isObject10 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
6595
+ var istVersionRef = (v) => isObject10(v) && typeof v.element_id === "string" && typeof v.version_id === "string";
6399
6596
  function leseJson(wert) {
6400
6597
  if (!wert || wert === NULL_MARKER) return null;
6401
6598
  try {
@@ -6623,13 +6820,13 @@ var VersionRefListeFeld = ({ port, kontextkette, feld, wert, onChange, readOnly,
6623
6820
  }
6624
6821
  const schreiben = (neu) => onChange(
6625
6822
  feld.path,
6626
- schreibListe(neu.map((eintrag, i) => isObject9(eintrag) && mitRolle ? { ...eintrag, rank: i } : eintrag))
6823
+ schreibListe(neu.map((eintrag, i) => isObject10(eintrag) && mitRolle ? { ...eintrag, rank: i } : eintrag))
6627
6824
  );
6628
6825
  return /* @__PURE__ */ jsxs("div", { className: "szenen-feld__reflist", "data-testid": `reflist-${feld.path}`, children: [
6629
6826
  liste.length === 0 && /* @__PURE__ */ jsx("p", { "data-testid": `reflist-${feld.path}-leer`, children: "Keine Eintr\xE4ge." }),
6630
6827
  /* @__PURE__ */ jsx("ol", { children: liste.map((eintrag, index) => /* @__PURE__ */ jsxs("li", { "data-testid": `reflist-${feld.path}-${index}`, children: [
6631
6828
  istVersionRef(eintrag) ? /* @__PURE__ */ jsx(RefAnzeige, { port, ref_: eintrag, testId: `reflist-${feld.path}-${index}-ref` }) : /* @__PURE__ */ jsx("code", { children: JSON.stringify(eintrag) }),
6632
- mitRolle === "styleRole" && isObject9(eintrag) && /* @__PURE__ */ jsxs(
6829
+ mitRolle === "styleRole" && isObject10(eintrag) && /* @__PURE__ */ jsxs(
6633
6830
  "select",
6634
6831
  {
6635
6832
  "data-testid": `reflist-${feld.path}-${index}-role`,
@@ -6642,7 +6839,7 @@ var VersionRefListeFeld = ({ port, kontextkette, feld, wert, onChange, readOnly,
6642
6839
  ]
6643
6840
  }
6644
6841
  ),
6645
- mitRolle === "frei" && isObject9(eintrag) && /* @__PURE__ */ jsx(
6842
+ mitRolle === "frei" && isObject10(eintrag) && /* @__PURE__ */ jsx(
6646
6843
  "input",
6647
6844
  {
6648
6845
  "data-testid": `reflist-${feld.path}-${index}-role`,
@@ -6652,7 +6849,7 @@ var VersionRefListeFeld = ({ port, kontextkette, feld, wert, onChange, readOnly,
6652
6849
  onChange: (e) => schreiben(liste.map((x, i) => i === index ? { ...x, role: e.target.value } : x))
6653
6850
  }
6654
6851
  ),
6655
- mitGewicht && isObject9(eintrag) && /* @__PURE__ */ jsx(
6852
+ mitGewicht && isObject10(eintrag) && /* @__PURE__ */ jsx(
6656
6853
  "input",
6657
6854
  {
6658
6855
  "data-testid": `reflist-${feld.path}-${index}-weight`,
@@ -6883,7 +7080,7 @@ var KameraFeld = ({
6883
7080
  if (phase.status !== "ready" || !phase.value) return [];
6884
7081
  const cameras = valueAtPath(phase.value.payload, "camera_rig.cameras");
6885
7082
  if (!Array.isArray(cameras)) return [];
6886
- return cameras.filter(isObject9).map((c) => ({
7083
+ return cameras.filter(isObject10).map((c) => ({
6887
7084
  id: typeof c.camera_id === "string" ? c.camera_id : null,
6888
7085
  name: typeof c.name === "string" ? c.name : null
6889
7086
  })).filter((c) => c.id !== null);
@@ -7028,11 +7225,11 @@ var MediaRefListeFeld = ({ feld, wert, onChange, readOnly }) => {
7028
7225
  }
7029
7226
  const schreiben = (neu) => onChange(
7030
7227
  feld.path,
7031
- schreibListe(neu.map((e, i) => isObject9(e) ? { ...e, position: i } : e))
7228
+ schreibListe(neu.map((e, i) => isObject10(e) ? { ...e, position: i } : e))
7032
7229
  );
7033
7230
  return /* @__PURE__ */ jsxs("div", { className: "szenen-feld__liste", "data-testid": `feld-${feld.path}`, children: [
7034
7231
  liste.map((eintrag, index) => {
7035
- const objekt = isObject9(eintrag) ? eintrag : {};
7232
+ const objekt = isObject10(eintrag) ? eintrag : {};
7036
7233
  return /* @__PURE__ */ jsxs("div", { className: "szenen-feld__liste-zeile", children: [
7037
7234
  /* @__PURE__ */ jsx(
7038
7235
  "input",
@@ -7041,7 +7238,7 @@ var MediaRefListeFeld = ({ feld, wert, onChange, readOnly }) => {
7041
7238
  value: typeof objekt.asset_id === "string" ? objekt.asset_id : "",
7042
7239
  readOnly,
7043
7240
  placeholder: "asset_id (UUID)",
7044
- onChange: (e) => schreiben(liste.map((x, i) => i === index ? { ...isObject9(x) ? x : {}, asset_id: e.target.value } : x))
7241
+ onChange: (e) => schreiben(liste.map((x, i) => i === index ? { ...isObject10(x) ? x : {}, asset_id: e.target.value } : x))
7045
7242
  }
7046
7243
  ),
7047
7244
  /* @__PURE__ */ jsxs(
@@ -7050,7 +7247,7 @@ var MediaRefListeFeld = ({ feld, wert, onChange, readOnly }) => {
7050
7247
  "data-testid": `feld-${feld.path}-${index}-rolle`,
7051
7248
  value: typeof objekt.role === "string" ? objekt.role : "",
7052
7249
  disabled: readOnly,
7053
- onChange: (e) => schreiben(liste.map((x, i) => i === index ? { ...isObject9(x) ? x : {}, role: e.target.value } : x)),
7250
+ onChange: (e) => schreiben(liste.map((x, i) => i === index ? { ...isObject10(x) ? x : {}, role: e.target.value } : x)),
7054
7251
  children: [
7055
7252
  /* @__PURE__ */ jsx("option", { value: "", children: "(Rolle w\xE4hlen)" }),
7056
7253
  rollen.map((r) => /* @__PURE__ */ jsx("option", { value: r, children: r }, r))
@@ -7093,9 +7290,10 @@ var LEERES_PROFIL = {
7093
7290
  var listeAus = (text) => text.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
7094
7291
  var AusfuehrungsprofileFeld = ({ feld, wert, onChange, readOnly }) => {
7095
7292
  const gelesen = leseListe(wert);
7096
- const profile = (gelesen ?? []).filter(isObject9);
7293
+ const profile = (gelesen ?? []).filter(isObject10);
7097
7294
  const unlesbar = gelesen === null;
7098
7295
  const schreibe = (neu) => onChange(feld.path, schreibListe(neu));
7296
+ const alleBefunde = checkImageExecutionProfiles(profile);
7099
7297
  const aendere = (index, patch) => schreibe(profile.map((p, i) => i === index ? { ...p, ...patch } : p));
7100
7298
  if (unlesbar) {
7101
7299
  return /* @__PURE__ */ jsx("p", { role: "alert", "data-testid": `feld-${feld.path}-unlesbar`, children: "Der gespeicherte Wert ist keine Profilliste. Er bleibt unver\xE4ndert stehen; bitte an der Quelle korrigieren." });
@@ -7103,7 +7301,7 @@ var AusfuehrungsprofileFeld = ({ feld, wert, onChange, readOnly }) => {
7103
7301
  return /* @__PURE__ */ jsxs("div", { className: "szenen-feld__profile", "data-testid": `feld-${feld.path}`, children: [
7104
7302
  profile.length === 0 && /* @__PURE__ */ jsx("p", { "data-testid": `feld-${feld.path}-keine`, children: "Dieses Zielmodell wird f\xFCr die Prompt-Optimierung verwendet und ist derzeit nicht direkt aus der App aufrufbar." }),
7105
7303
  profile.map((profil, index) => {
7106
- const befunde = checkImageExecutionProfile(profil);
7304
+ const befunde = alleBefunde[index] ?? [];
7107
7305
  const text = (schluessel) => typeof profil[schluessel] === "string" ? profil[schluessel] : "";
7108
7306
  const liste = (schluessel) => Array.isArray(profil[schluessel]) ? profil[schluessel].join(", ") : "";
7109
7307
  return /* @__PURE__ */ jsxs("fieldset", { "data-testid": `profil-${index}`, className: "szenen-feld__profil", children: [
@@ -7854,60 +8052,72 @@ var CapabilityPanel = ({ port, elementId, setupPayload }) => {
7854
8052
  ] });
7855
8053
  };
7856
8054
 
7857
- // src/features/szenen/areas/ChainPromptAction.tsx
8055
+ // src/features/szenen/areas/PromptStartAction.tsx
7858
8056
  import { useState as useState6 } from "react";
7859
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
7860
- var ChainPromptAction = ({
8057
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
8058
+ var PromptStartAction = ({
7861
8059
  port,
7862
- shotElementId
8060
+ source,
8061
+ hinweise = [],
8062
+ blocker = null,
8063
+ onLauf
7863
8064
  }) => {
7864
8065
  const [lauf, setLauf] = useState6(null);
7865
8066
  const [meldung, setMeldung] = useState6(null);
7866
8067
  const [ausgang, setAusgang] = useState6(null);
7867
8068
  const [laeuft, setLaeuft] = useState6(false);
7868
8069
  const runs = port.runs;
8070
+ const ausKette = source.kind === "draft_chain";
8071
+ const id = (name) => ausKette ? `kette-${name}` : `szene-${name}`;
7869
8072
  async function erzeugen() {
7870
8073
  setLaeuft(true);
7871
8074
  setMeldung(null);
7872
8075
  setAusgang(null);
7873
8076
  try {
7874
- const ergebnis = await runs.startRunFromDraft({ shotElementId });
8077
+ const ergebnis = source.kind === "draft_chain" ? await runs.startRunFromDraft({ shotElementId: source.shotElementId }) : await runs.startRunFromScene({ sceneElementId: source.sceneElementId });
7875
8078
  if (ergebnis.kind !== "ok") {
7876
8079
  setMeldung(ergebnis.kind === "unsupported" ? `Dieser Host kann "${ergebnis.capability}" nicht.` : ergebnis.message);
7877
8080
  setAusgang(ergebnis.kind === "unsupported" ? "error" : ergebnis.kind);
7878
8081
  return;
7879
8082
  }
7880
8083
  setLauf(ergebnis.value);
8084
+ onLauf?.();
7881
8085
  } finally {
7882
8086
  setLaeuft(false);
7883
8087
  }
7884
8088
  }
7885
- return /* @__PURE__ */ jsxs5("section", { className: "szenen-kette", "data-testid": "kette-prompt-aktion", children: [
7886
- /* @__PURE__ */ jsx5("h5", { children: "Prompt aus der Draft-Kette" }),
7887
- /* @__PURE__ */ jsxs5("p", { className: "szenen-area__lead", children: [
8089
+ return /* @__PURE__ */ jsxs5("section", { className: "szenen-kette", "data-testid": id("prompt-aktion"), children: [
8090
+ /* @__PURE__ */ jsx5("h5", { children: ausKette ? "Prompt aus der Draft-Kette" : "Prompt aus dieser Szene" }),
8091
+ /* @__PURE__ */ jsx5("p", { className: "szenen-area__lead", children: ausKette ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
7888
8092
  "Dieser Shot geh\xF6rt zu einer Draft-Kette. Der Lauf friert Szene, Aufbau und Shot in dem Stand ein, den er gerade vorfindet \u2014",
7889
8093
  " ",
7890
8094
  /* @__PURE__ */ jsx5("strong", { children: "ohne" }),
7891
8095
  " dass etwas ver\xF6ffentlicht werden muss."
7892
- ] }),
8096
+ ] }) : /* @__PURE__ */ jsxs5(Fragment2, { children: [
8097
+ "Der Lauf friert diese Szene in dem Stand ein, den er gerade vorfindet. Bildaufbau, Kamera und Zielmodell sind ",
8098
+ /* @__PURE__ */ jsx5("strong", { children: "nicht n\xF6tig" }),
8099
+ " \u2014 was fehlt, wird weggelassen und am Lauf festgehalten, nicht erg\xE4nzt."
8100
+ ] }) }),
8101
+ hinweise.length > 0 && /* @__PURE__ */ jsx5("ul", { className: "szenen-detail__hint", "data-testid": id("hinweise"), role: "status", children: hinweise.map((hinweis, i) => /* @__PURE__ */ jsx5("li", { children: hinweis }, i)) }),
8102
+ blocker && /* @__PURE__ */ jsx5("p", { className: "szenen-error", role: "alert", "data-testid": id("blocker"), children: blocker }),
7893
8103
  /* @__PURE__ */ jsx5(
7894
8104
  "button",
7895
8105
  {
7896
8106
  type: "button",
7897
- disabled: laeuft,
8107
+ disabled: laeuft || blocker !== null,
7898
8108
  onClick: () => void erzeugen(),
7899
- "data-testid": "kette-prompt",
7900
- children: laeuft ? "Pr\xFCft und erzeugt \u2026" : "Draft-Kette pr\xFCfen und Prompt erzeugen (kostet einen Modellaufruf)"
8109
+ "data-testid": id("prompt"),
8110
+ children: laeuft ? "Pr\xFCft und erzeugt \u2026" : ausKette ? "Draft-Kette pr\xFCfen und Prompt erzeugen (kostet einen Modellaufruf)" : "Prompt erzeugen (kostet einen Modellaufruf)"
7901
8111
  }
7902
8112
  ),
7903
- meldung && /* @__PURE__ */ jsxs5("div", { className: "szenen-error", role: "alert", "data-testid": "kette-meldung", children: [
8113
+ meldung && /* @__PURE__ */ jsxs5("div", { className: "szenen-error", role: "alert", "data-testid": id("meldung"), children: [
7904
8114
  /* @__PURE__ */ jsx5("p", { children: meldung }),
7905
- /* @__PURE__ */ jsx5("p", { "data-testid": "kette-kein-modell", children: /* @__PURE__ */ jsx5("strong", { children: "Es wurde kein Modell gerufen." }) }),
7906
- ausgang === "conflict" && /* @__PURE__ */ jsx5("p", { "data-testid": "kette-konflikt", children: "Ein Entwurf der Kette wurde zwischenzeitlich ge\xE4ndert. Ein erneuter Versuch friert den aktuellen Stand ein." }),
7907
- ausgang === "rejected" && /* @__PURE__ */ jsx5("p", { "data-testid": "kette-mangel", children: "Die Kette selbst ist noch nicht vollst\xE4ndig. Ein erneuter Versuch \xE4ndert daran nichts \u2014 die Entw\xFCrfe m\xFCssen zuerst erg\xE4nzt werden." }),
7908
- ausgang === "error" && /* @__PURE__ */ jsx5("p", { "data-testid": "kette-technisch", children: "Das war ein technisches Problem beim Zugriff, kein Mangel der Kette. Ein erneuter Versuch ist sinnvoll." })
8115
+ /* @__PURE__ */ jsx5("p", { "data-testid": id("kein-modell"), children: /* @__PURE__ */ jsx5("strong", { children: "Es wurde kein Modell gerufen." }) }),
8116
+ ausgang === "conflict" && /* @__PURE__ */ jsx5("p", { "data-testid": id("konflikt"), children: ausKette ? "Ein Entwurf der Kette wurde zwischenzeitlich ge\xE4ndert. Ein erneuter Versuch friert den aktuellen Stand ein." : "Die Szene wurde zwischenzeitlich ge\xE4ndert. Ein erneuter Versuch friert den aktuellen Stand ein." }),
8117
+ ausgang === "rejected" && /* @__PURE__ */ jsx5("p", { "data-testid": id("mangel"), children: ausKette ? "Die Kette selbst ist noch nicht vollst\xE4ndig. Ein erneuter Versuch \xE4ndert daran nichts \u2014 die Entw\xFCrfe m\xFCssen zuerst erg\xE4nzt werden." : "Aus diesem Stand l\xE4sst sich kein Auftrag herstellen. Ein erneuter Versuch \xE4ndert daran nichts \u2014 die Szene muss zuerst Inhalt bekommen." }),
8118
+ ausgang === "error" && /* @__PURE__ */ jsx5("p", { "data-testid": id("technisch"), children: "Das war ein technisches Problem beim Zugriff, kein fachlicher Mangel. Ein erneuter Versuch ist sinnvoll." })
7909
8119
  ] }),
7910
- lauf && /* @__PURE__ */ jsxs5("div", { className: "szenen-run", "data-testid": "kette-lauf", children: [
8120
+ lauf && /* @__PURE__ */ jsxs5("div", { className: "szenen-run", "data-testid": id("lauf"), children: [
7911
8121
  /* @__PURE__ */ jsxs5("h5", { children: [
7912
8122
  "Prompt-Lauf ",
7913
8123
  lauf.status === "succeeded" ? "gelungen" : "gescheitert"
@@ -7919,7 +8129,7 @@ var ChainPromptAction = ({
7919
8129
  /* @__PURE__ */ jsx5("code", { children: lauf.model_id }),
7920
8130
  "."
7921
8131
  ] }),
7922
- lauf.status === "succeeded" && lauf.output && /* @__PURE__ */ jsx5("pre", { className: "szenen-proposal__payload", "data-testid": "kette-prompt-text", children: lauf.output.positive }),
8132
+ lauf.status === "succeeded" && lauf.output && /* @__PURE__ */ jsx5("pre", { className: "szenen-proposal__payload", "data-testid": id("prompt-text"), children: lauf.output.positive }),
7923
8133
  lauf.status === "failed" && /* @__PURE__ */ jsxs5("p", { className: "szenen-error", children: [
7924
8134
  lauf.failure?.class,
7925
8135
  " \u2014 ",
@@ -8051,7 +8261,7 @@ import { useState as useState8 } from "react";
8051
8261
 
8052
8262
  // src/features/szenen/areas/RunImagesPanel.tsx
8053
8263
  import { useState as useState7 } from "react";
8054
- import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
8264
+ import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
8055
8265
  var AUFTRAG_TEXT = {
8056
8266
  // „gestartet/unterbrochen" in einem: Aus dem Log allein ist beides nicht
8057
8267
  // unterscheidbar, und genau das ist beabsichtigt — es gibt keinen
@@ -8089,12 +8299,27 @@ var RunImagesPanel = ({ port, lauf }) => {
8089
8299
  "Lauf ",
8090
8300
  /* @__PURE__ */ jsx7("code", { "data-testid": `eingang-lauf-${lauf.run_id}`, children: lauf.run_id })
8091
8301
  ] }),
8092
- quelle.kind === "published" ? /* @__PURE__ */ jsxs7("span", { "data-testid": `eingang-herkunft-${lauf.run_id}`, children: [
8302
+ quelle.kind === "published" && /* @__PURE__ */ jsxs7("span", { "data-testid": `eingang-herkunft-${lauf.run_id}`, children: [
8093
8303
  "ver\xF6ffentlichte Shot-Version ",
8094
8304
  /* @__PURE__ */ jsx7("code", { children: quelle.shot_version_id })
8095
- ] }) : /* @__PURE__ */ jsxs7("span", { "data-testid": `eingang-herkunft-${lauf.run_id}`, children: [
8305
+ ] }),
8306
+ quelle.kind === "draft_chain" && /* @__PURE__ */ jsxs7("span", { "data-testid": `eingang-herkunft-${lauf.run_id}`, children: [
8096
8307
  "Draft-Kette ",
8097
8308
  /* @__PURE__ */ jsx7("code", { children: quelle.chain_id })
8309
+ ] }),
8310
+ quelle.kind === "scene_direct" && /* @__PURE__ */ jsxs7("span", { "data-testid": `eingang-herkunft-${lauf.run_id}`, children: [
8311
+ "Szene ",
8312
+ /* @__PURE__ */ jsx7("code", { children: quelle.scene.element_id }),
8313
+ quelle.scene.draft_id ? /* @__PURE__ */ jsxs7(Fragment3, { children: [
8314
+ " \xB7 Entwurf ",
8315
+ /* @__PURE__ */ jsx7("code", { children: quelle.scene.draft_id }),
8316
+ " (Revision ",
8317
+ quelle.scene.revision,
8318
+ ")"
8319
+ ] }) : /* @__PURE__ */ jsxs7(Fragment3, { children: [
8320
+ " \xB7 Version ",
8321
+ /* @__PURE__ */ jsx7("code", { children: quelle.scene.version_id })
8322
+ ] })
8098
8323
  ] })
8099
8324
  ] }),
8100
8325
  quelle.kind === "draft_chain" && quelle.derivation_run_id ? /* @__PURE__ */ jsx7(
@@ -8319,7 +8544,7 @@ var ErzeugenAktion = ({ port, lauf, wahl, wahlFehler, onFertig }) => {
8319
8544
  return (
8320
8545
  // Kein Fehler und kein Grund, den Lauf zu sperren: Der externe
8321
8546
  // Importweg bleibt daneben stehen (D-104.5).
8322
- /* @__PURE__ */ jsxs7(Fragment2, { children: [
8547
+ /* @__PURE__ */ jsxs7(Fragment3, { children: [
8323
8548
  /* @__PURE__ */ jsxs7("p", { "data-testid": `erzeugen-unsupported-modell-${lauf.run_id}`, children: [
8324
8549
  "Hier kann derzeit kein Bild erzeugt werden:",
8325
8550
  " ",
@@ -8377,7 +8602,7 @@ var ErzeugenAktion = ({ port, lauf, wahl, wahlFehler, onFertig }) => {
8377
8602
  return /* @__PURE__ */ jsxs7("div", { className: "szenen-bilder__aktion", "data-testid": `erzeugen-${lauf.run_id}`, children: [
8378
8603
  /* @__PURE__ */ jsx7("h5", { children: "Bilder aus diesem Prompt erzeugen" }),
8379
8604
  /* @__PURE__ */ jsx7(ProfilBefunde, { wahl, runId: lauf.run_id }),
8380
- /* @__PURE__ */ jsx7("p", { "data-testid": `erzeugen-zielmodell-${lauf.run_id}`, children: wahl.prompt_target_model_key ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
8605
+ /* @__PURE__ */ jsx7("p", { "data-testid": `erzeugen-zielmodell-${lauf.run_id}`, children: wahl.prompt_target_model_key ? /* @__PURE__ */ jsxs7(Fragment3, { children: [
8381
8606
  "Prompt optimiert f\xFCr ",
8382
8607
  /* @__PURE__ */ jsx7("code", { children: wahl.prompt_target_model_key })
8383
8608
  ] }) : "Dieser Lauf tr\xE4gt keine Optimierungsabsicht (kein target_model)." }),
@@ -8561,7 +8786,7 @@ var ZuordnenAktion = ({ port, lauf, onFertig }) => {
8561
8786
  }
8562
8787
  )
8563
8788
  ] }),
8564
- dateien.length > 0 && /* @__PURE__ */ jsxs7(Fragment2, { children: [
8789
+ dateien.length > 0 && /* @__PURE__ */ jsxs7(Fragment3, { children: [
8565
8790
  /* @__PURE__ */ jsxs7("label", { children: [
8566
8791
  "Modell (f\xFCr alle Bilder, leer = unbekannt)",
8567
8792
  /* @__PURE__ */ jsx7(
@@ -8660,9 +8885,13 @@ var RunsPanel = ({ port, source, contextId }) => {
8660
8885
  const [notiz, setNotiz] = useState8(null);
8661
8886
  const [nachladen, setNachladen] = useState8(0);
8662
8887
  const faehig = capabilitiesOf(port);
8663
- const quellSchluessel = source.kind === "published" ? source.shotVersionId : source.chainId;
8888
+ const quellSchluessel = source.kind === "published" ? source.shotVersionId : source.kind === "draft_chain" ? source.chainId : source.sceneElementId;
8664
8889
  const [phase, neuLaden] = usePortQuery(
8665
- () => source.kind === "published" ? port.runs.listRunsForShot(source.shotVersionId) : port.runs.listRunsForChain(source.chainId),
8890
+ () => {
8891
+ if (source.kind === "published") return port.runs.listRunsForShot(source.shotVersionId);
8892
+ if (source.kind === "draft_chain") return port.runs.listRunsForChain(source.chainId);
8893
+ return port.runs.listRunsForScene(source.sceneElementId);
8894
+ },
8666
8895
  [port, source.kind, quellSchluessel, nachladen]
8667
8896
  );
8668
8897
  const starten = async () => {
@@ -8701,7 +8930,7 @@ var RunsPanel = ({ port, source, contextId }) => {
8701
8930
  "L\xE4ufe konnten nicht geladen werden: ",
8702
8931
  phase.message
8703
8932
  ] }),
8704
- phase.status === "ready" && laeufe.length === 0 && /* @__PURE__ */ jsx8("p", { "data-testid": "keine-laeufe", children: source.kind === "published" ? "F\xFCr diese Shot-Version gibt es noch keinen Lauf." : "F\xFCr diese Draft-Kette gibt es noch keinen Lauf." }),
8933
+ phase.status === "ready" && laeufe.length === 0 && /* @__PURE__ */ jsx8("p", { "data-testid": "keine-laeufe", children: source.kind === "published" ? "F\xFCr diese Shot-Version gibt es noch keinen Lauf." : source.kind === "draft_chain" ? "F\xFCr diese Draft-Kette gibt es noch keinen Lauf." : "F\xFCr diese Szene gibt es noch keinen direkten Lauf." }),
8705
8934
  /* @__PURE__ */ jsx8("ol", { "data-testid": "runden-liste", children: laeufe.map((lauf) => /* @__PURE__ */ jsx8(
8706
8935
  RundenEintrag,
8707
8936
  {
@@ -8794,7 +9023,7 @@ var RundenEintrag = ({ port, lauf, runde, itemMoeglich, onItemGespeichert }) =>
8794
9023
  };
8795
9024
 
8796
9025
  // src/features/szenen/areas/ElementDetail.tsx
8797
- import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
9026
+ import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
8798
9027
  var STRUKTURELL_BEDIENT = {
8799
9028
  scene: ["nodes", "relations"]
8800
9029
  };
@@ -8906,6 +9135,23 @@ var ElementDetail = ({
8906
9135
  if (!kette2) return null;
8907
9136
  return kette2.links[0]?.field ?? null;
8908
9137
  }, [schnappschuss?.draft?.chain]);
9138
+ const laufStand = useMemo2(() => {
9139
+ if (!schnappschuss || schnappschuss.element.type !== "scene") return null;
9140
+ if (schnappschuss.draft) return schnappschuss.draft.payload;
9141
+ const kopf = usableHeadVersionId(kopfAufloesung);
9142
+ if (!kopf) return null;
9143
+ return schnappschuss.versions.find((v) => v.version_id === kopf)?.payload ?? null;
9144
+ }, [schnappschuss, kopfAufloesung]);
9145
+ const szenenBlocker = useMemo2(() => {
9146
+ if (!schnappschuss || schnappschuss.element.type !== "scene") return null;
9147
+ if (laufStand === null) {
9148
+ return schnappschuss.versions.length > 0 ? "Diese Szene hat keinen Entwurf und in diesem Kontext keinen bevorzugten Kopf. Welcher Stand gilt, entscheidet keine Reihenfolge (D-36) \u2014 bitte oben eine Version als bevorzugt setzen." : "Diese Szene hat noch keinen gespeicherten Stand. Ein Lauf friert ein, was gespeichert ist \u2014 bitte zuerst den Entwurf speichern.";
9149
+ }
9150
+ const flag = sceneOnlyCapabilities(laufStand).can_render_prompt;
9151
+ if (flag.state === "yes") return null;
9152
+ const grund = flag.reasons[0];
9153
+ return grund && "message" in grund ? grund.message : "Kein Lauf moeglich.";
9154
+ }, [schnappschuss, laufStand]);
8909
9155
  const vorschau = useMemo2(() => {
8910
9156
  if (!schnappschuss) return null;
8911
9157
  try {
@@ -9039,8 +9285,7 @@ var ElementDetail = ({
9039
9285
  /* @__PURE__ */ jsxs9("header", { children: [
9040
9286
  /* @__PURE__ */ jsx9("h3", { children: schnappschuss.metadata?.title ?? "(ohne Titel)" }),
9041
9287
  /* @__PURE__ */ jsxs9("p", { className: "szenen-detail__ids", children: [
9042
- /* @__PURE__ */ jsx9("span", { children: typ }),
9043
- /* @__PURE__ */ jsx9("code", { children: schnappschuss.element.element_id }),
9288
+ /* @__PURE__ */ jsx9("span", { "data-testid": "element-typ", children: elementTypLabel(typ) }),
9044
9289
  schnappschuss.element.retired && /* @__PURE__ */ jsx9("span", { "data-testid": "ist-stillgelegt", children: "stillgelegt" })
9045
9290
  ] })
9046
9291
  ] }),
@@ -9084,10 +9329,10 @@ var ElementDetail = ({
9084
9329
  /* @__PURE__ */ jsxs9("p", { children: [
9085
9330
  "Es gibt bereits einen Entwurf (Revision ",
9086
9331
  draft.revision,
9087
- draft.base_version_id ? /* @__PURE__ */ jsxs9(Fragment3, { children: [
9332
+ draft.base_version_id ? /* @__PURE__ */ jsxs9(Fragment4, { children: [
9088
9333
  " auf Basis ",
9089
9334
  /* @__PURE__ */ jsx9("code", { children: draft.base_version_id })
9090
- ] }) : /* @__PURE__ */ jsx9(Fragment3, { children: " ohne Basis" }),
9335
+ ] }) : /* @__PURE__ */ jsx9(Fragment4, { children: " ohne Basis" }),
9091
9336
  "). Ihn auf Version ",
9092
9337
  /* @__PURE__ */ jsx9("code", { children: basiswechsel }),
9093
9338
  " neu aufzusetzen",
@@ -9119,13 +9364,13 @@ var ElementDetail = ({
9119
9364
  )
9120
9365
  ] }),
9121
9366
  /* @__PURE__ */ jsxs9("section", { className: "szenen-detail__draft", "data-testid": "draft-bereich", children: [
9122
- /* @__PURE__ */ jsx9("h4", { children: bearbeitbar ? /* @__PURE__ */ jsxs9(Fragment3, { children: [
9367
+ /* @__PURE__ */ jsx9("h4", { children: bearbeitbar ? /* @__PURE__ */ jsxs9(Fragment4, { children: [
9123
9368
  "Entwurf",
9124
9369
  draft && /* @__PURE__ */ jsxs9("span", { children: [
9125
9370
  " \xB7 Revision ",
9126
9371
  draft.revision
9127
9372
  ] })
9128
- ] }) : /* @__PURE__ */ jsx9(Fragment3, { children: "Ver\xF6ffentlichte Version \u2014 nur Ansicht" }) }),
9373
+ ] }) : /* @__PURE__ */ jsx9(Fragment4, { children: "Ver\xF6ffentlichte Version \u2014 nur Ansicht" }) }),
9129
9374
  angezeigt.kind === "keiner" && /* @__PURE__ */ jsxs9("p", { "data-testid": "nichts-angezeigt", children: [
9130
9375
  "Es ist kein Stand ausgew\xE4hlt. Oben eine Version anzeigen oder \xFCber ",
9131
9376
  /* @__PURE__ */ jsx9("strong", { children: "als Grundlage bearbeiten" }),
@@ -9136,7 +9381,7 @@ var ElementDetail = ({
9136
9381
  /* @__PURE__ */ jsx9("strong", { children: "als Grundlage bearbeiten" }),
9137
9382
  " w\xE4hlen \u2014 das erzeugt einen Entwurf mit genau dieser Version als Basis."
9138
9383
  ] }),
9139
- angezeigt.kind !== "keiner" && /* @__PURE__ */ jsxs9(Fragment3, { children: [
9384
+ angezeigt.kind !== "keiner" && /* @__PURE__ */ jsxs9(Fragment4, { children: [
9140
9385
  typ === "scene" && /* @__PURE__ */ jsx9(
9141
9386
  SceneEditor,
9142
9387
  {
@@ -9216,12 +9461,15 @@ var ElementDetail = ({
9216
9461
  // einer Draft-Kette, fuehrt der Weg ueber das Einfrieren —
9217
9462
  // der alte Satz „setzen eine veroeffentlichte Version
9218
9463
  // voraus" gilt nur noch fuer den Einzel-Shot.
9219
- draft?.chain ? /* @__PURE__ */ jsxs9(Fragment3, { children: [
9464
+ draft?.chain ? /* @__PURE__ */ jsxs9(Fragment4, { children: [
9220
9465
  /* @__PURE__ */ jsx9(
9221
- ChainPromptAction,
9466
+ PromptStartAction,
9222
9467
  {
9223
9468
  port,
9224
- shotElementId: schnappschuss.element.element_id
9469
+ source: {
9470
+ kind: "draft_chain",
9471
+ shotElementId: schnappschuss.element.element_id
9472
+ }
9225
9473
  }
9226
9474
  ),
9227
9475
  /* @__PURE__ */ jsx9(
@@ -9241,15 +9489,39 @@ var ElementDetail = ({
9241
9489
  source: { kind: "published", shotVersionId: laufVersionId }
9242
9490
  }
9243
9491
  ) : /* @__PURE__ */ jsx9("p", { "data-testid": "laufquelle-unklar", children: "Dieser Shot hat mehrere ver\xF6ffentlichte Versionen und keinen bevorzugten Kopf in diesem Kontext. Welche davon einen Lauf tr\xE4gt, entscheidet keine Reihenfolge \u2014 bitte oben eine Version anzeigen oder als bevorzugt setzen." })),
9244
- typ === "scene_setup" && /* @__PURE__ */ jsx9(
9245
- CapabilityPanel,
9246
- {
9247
- port,
9248
- elementId,
9249
- setupPayload: payloadAusFormular()
9250
- }
9251
- ),
9252
- notiz && /* @__PURE__ */ jsxs9(
9492
+ typ === "scene" && /* @__PURE__ */ jsxs9(Fragment4, { children: [
9493
+ /* @__PURE__ */ jsx9(
9494
+ PromptStartAction,
9495
+ {
9496
+ port,
9497
+ source: { kind: "scene", sceneElementId: schnappschuss.element.element_id },
9498
+ hinweise: [
9499
+ "Kein Bildaufbau und keine Kamera \u2014 der Prompt wird ohne Kameravorgabe erzeugt.",
9500
+ "Kein Zielmodell \u2014 generische Promptableitung ohne Modelloptimierung.",
9501
+ schnappschuss.draft ? "Eingefroren wird der gespeicherte Entwurf. Nicht gespeicherte Aenderungen im Formular gehen nicht mit." : "Eingefroren wird die wirksame veroeffentlichte Version."
9502
+ ],
9503
+ blocker: szenenBlocker,
9504
+ onLauf: () => setNachladen((n) => n + 1)
9505
+ }
9506
+ ),
9507
+ /* @__PURE__ */ jsx9(
9508
+ RunsPanel,
9509
+ {
9510
+ port,
9511
+ contextId,
9512
+ source: { kind: "scene", sceneElementId: schnappschuss.element.element_id }
9513
+ }
9514
+ )
9515
+ ] }),
9516
+ typ === "scene_setup" && /* @__PURE__ */ jsx9(
9517
+ CapabilityPanel,
9518
+ {
9519
+ port,
9520
+ elementId,
9521
+ setupPayload: payloadAusFormular()
9522
+ }
9523
+ ),
9524
+ notiz && /* @__PURE__ */ jsxs9(
9253
9525
  "div",
9254
9526
  {
9255
9527
  className: `szenen-detail__notice szenen-detail__notice--${notiz.tone}`,
@@ -9265,6 +9537,26 @@ var ElementDetail = ({
9265
9537
  ] });
9266
9538
  };
9267
9539
 
9540
+ // src/features/szenen/areas/useSchmalesDisplay.ts
9541
+ import { useEffect as useEffect4, useState as useState10 } from "react";
9542
+ var SCHMALE_ANSICHT = "(max-width: 760px)";
9543
+ function messen(abfrage) {
9544
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
9545
+ return window.matchMedia(abfrage).matches;
9546
+ }
9547
+ function useSchmalesDisplay(abfrage = SCHMALE_ANSICHT) {
9548
+ const [schmal, setSchmal] = useState10(() => messen(abfrage));
9549
+ useEffect4(() => {
9550
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
9551
+ const liste = window.matchMedia(abfrage);
9552
+ const aktualisieren = () => setSchmal(liste.matches);
9553
+ aktualisieren();
9554
+ liste.addEventListener?.("change", aktualisieren);
9555
+ return () => liste.removeEventListener?.("change", aktualisieren);
9556
+ }, [abfrage]);
9557
+ return schmal;
9558
+ }
9559
+
9268
9560
  // src/features/szenen/areas/ElementsArea.tsx
9269
9561
  import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
9270
9562
  var ElementsArea = ({
@@ -9273,18 +9565,31 @@ var ElementsArea = ({
9273
9565
  author = "szenen-view",
9274
9566
  restrictToTypes,
9275
9567
  allTypesLabel,
9568
+ listTitle,
9276
9569
  onSelect
9277
9570
  }) => {
9278
9571
  const auswahlTypen = restrictToTypes ?? SZENEN_ELEMENT_TYPES;
9279
- const [typ, setTyp] = useState10(
9280
- restrictToTypes && restrictToTypes.length === 1 ? restrictToTypes[0] : ""
9281
- );
9282
- const [zeigeStillgelegte, setZeigeStillgelegte] = useState10(false);
9283
- const [gewaehlt, setGewaehlt] = useState10(null);
9284
- const [neuerTitel, setNeuerTitel] = useState10("");
9285
- const [neuerTyp, setNeuerTyp] = useState10(auswahlTypen[0]);
9286
- const [notiz, setNotiz] = useState10(null);
9287
- const [anlegend, setAnlegend] = useState10(false);
9572
+ const einzelTyp = auswahlTypen.length === 1 ? auswahlTypen[0] : null;
9573
+ const gemischt = auswahlTypen.length > 1;
9574
+ const ueberschrift = listTitle ?? (einzelTyp ? elementTypPlural(einzelTyp) : "Bausteine");
9575
+ const einzahl = einzelTyp ? elementTypLabel(einzelTyp) : "Objekt";
9576
+ const [typ, setTyp] = useState11(einzelTyp ?? "");
9577
+ const [zeigeStillgelegte, setZeigeStillgelegte] = useState11(false);
9578
+ const [gewaehlt, setGewaehlt] = useState11(null);
9579
+ const [neuerTitel, setNeuerTitel] = useState11("");
9580
+ const [neuerTyp, setNeuerTyp] = useState11(auswahlTypen[0]);
9581
+ const [notiz, setNotiz] = useState11(null);
9582
+ const [anlegend, setAnlegend] = useState11(false);
9583
+ const [anlageOffen, setAnlageOffen] = useState11(false);
9584
+ const schmal = useSchmalesDisplay();
9585
+ const [ansicht, setAnsicht] = useState11("liste");
9586
+ const zeigeListe = !schmal || ansicht === "liste";
9587
+ const zeigeDetail = !schmal || ansicht === "detail";
9588
+ const waehle = (elementId) => {
9589
+ setGewaehlt(elementId);
9590
+ setAnsicht("detail");
9591
+ onSelect?.(elementId);
9592
+ };
9288
9593
  const [phase, neuLaden] = usePortQuery(
9289
9594
  () => port.elements.listElements({
9290
9595
  contextId,
@@ -9293,128 +9598,199 @@ var ElementsArea = ({
9293
9598
  }),
9294
9599
  [port, contextId, typ, zeigeStillgelegte]
9295
9600
  );
9296
- return /* @__PURE__ */ jsxs10("div", { className: "szenen-elements", "data-testid": "bereich-elemente", children: [
9297
- /* @__PURE__ */ jsxs10("div", { className: "szenen-elements__filter", children: [
9298
- /* @__PURE__ */ jsxs10("label", { children: [
9299
- "Typ",
9300
- /* @__PURE__ */ jsxs10(
9301
- "select",
9302
- {
9303
- "data-testid": "filter-typ",
9304
- value: typ,
9305
- onChange: (e) => setTyp(e.target.value),
9306
- children: [
9307
- (!restrictToTypes || restrictToTypes.length > 1) && /* @__PURE__ */ jsx10("option", { value: "", children: allTypesLabel ?? "alle Typen" }),
9308
- auswahlTypen.map((t) => /* @__PURE__ */ jsx10("option", { value: t, children: t }, t))
9309
- ]
9310
- }
9311
- )
9312
- ] }),
9313
- /* @__PURE__ */ jsxs10("label", { children: [
9314
- /* @__PURE__ */ jsx10(
9315
- "input",
9316
- {
9317
- type: "checkbox",
9318
- "data-testid": "filter-stillgelegt",
9319
- checked: zeigeStillgelegte,
9320
- onChange: (e) => setZeigeStillgelegte(e.target.checked)
9321
- }
9322
- ),
9323
- "stillgelegte Elemente einblenden"
9324
- ] }),
9325
- /* @__PURE__ */ jsx10("button", { type: "button", "data-testid": "neu-laden", onClick: neuLaden, children: "neu laden" })
9326
- ] }),
9327
- /* @__PURE__ */ jsxs10(
9328
- "form",
9329
- {
9330
- className: "szenen-elements__create",
9331
- "data-testid": "element-anlegen",
9332
- onSubmit: async (e) => {
9333
- e.preventDefault();
9334
- if (!neuerTitel.trim()) return;
9335
- setAnlegend(true);
9336
- const ergebnis = await port.elements.createElement({
9337
- type: neuerTyp,
9338
- title: neuerTitel.trim(),
9339
- contextId
9340
- });
9341
- setNotiz(noticeFor(ergebnis, `Element \u201E${neuerTitel.trim()}" anlegen`));
9342
- setAnlegend(false);
9343
- if (ergebnis.kind === "ok") {
9344
- setNeuerTitel("");
9345
- setGewaehlt(ergebnis.value.element_id);
9346
- onSelect?.(ergebnis.value.element_id);
9347
- neuLaden();
9348
- }
9349
- },
9350
- children: [
9351
- /* @__PURE__ */ jsx10(
9352
- "input",
9601
+ const anlageSchliessen = () => {
9602
+ setAnlageOffen(false);
9603
+ setNeuerTitel("");
9604
+ };
9605
+ return /* @__PURE__ */ jsxs10(
9606
+ "div",
9607
+ {
9608
+ className: "szenen-elements",
9609
+ "data-testid": "bereich-elemente",
9610
+ "data-ansicht": schmal ? ansicht : "beide",
9611
+ children: [
9612
+ zeigeListe && /* @__PURE__ */ jsxs10("div", { className: "szenen-elements__master", "data-testid": "elemente-master", children: [
9613
+ /* @__PURE__ */ jsxs10("div", { className: "szenen-elements__toolbar", children: [
9614
+ /* @__PURE__ */ jsx10("h3", { className: "szenen-elements__heading", children: ueberschrift }),
9615
+ /* @__PURE__ */ jsx10(
9616
+ "button",
9617
+ {
9618
+ type: "button",
9619
+ className: "szenen-elements__new",
9620
+ "data-testid": "neu-oeffnen",
9621
+ "aria-expanded": anlageOffen,
9622
+ onClick: () => {
9623
+ setNotiz(null);
9624
+ if (anlageOffen) anlageSchliessen();
9625
+ else setAnlageOffen(true);
9626
+ },
9627
+ children: "+ Neu"
9628
+ }
9629
+ )
9630
+ ] }),
9631
+ gemischt && /* @__PURE__ */ jsxs10("label", { className: "szenen-elements__scope", children: [
9632
+ "Art",
9633
+ /* @__PURE__ */ jsxs10(
9634
+ "select",
9635
+ {
9636
+ "data-testid": "filter-typ",
9637
+ value: typ,
9638
+ onChange: (e) => setTyp(e.target.value),
9639
+ children: [
9640
+ /* @__PURE__ */ jsx10("option", { value: "", children: allTypesLabel ?? "alle Typen" }),
9641
+ auswahlTypen.map((t) => /* @__PURE__ */ jsx10("option", { value: t, children: elementTypPlural(t) }, t))
9642
+ ]
9643
+ }
9644
+ )
9645
+ ] }),
9646
+ anlageOffen && /* @__PURE__ */ jsxs10(
9647
+ "form",
9353
9648
  {
9354
- "data-testid": "neuer-titel",
9355
- value: neuerTitel,
9356
- placeholder: "Titel des neuen Elements",
9357
- onChange: (e) => setNeuerTitel(e.target.value)
9649
+ className: "szenen-elements__create",
9650
+ "data-testid": "element-anlegen",
9651
+ onSubmit: async (e) => {
9652
+ e.preventDefault();
9653
+ if (!neuerTitel.trim()) return;
9654
+ setAnlegend(true);
9655
+ const gewuenschterTyp = einzelTyp ?? neuerTyp;
9656
+ const titel = neuerTitel.trim();
9657
+ const ergebnis = await port.elements.createElement({
9658
+ type: gewuenschterTyp,
9659
+ title: titel,
9660
+ contextId
9661
+ });
9662
+ setNotiz(noticeFor(
9663
+ ergebnis,
9664
+ `${elementTypLabel(gewuenschterTyp)} \u201E${titel}" anlegen`
9665
+ ));
9666
+ setAnlegend(false);
9667
+ if (ergebnis.kind === "ok") {
9668
+ anlageSchliessen();
9669
+ waehle(ergebnis.value.element_id);
9670
+ neuLaden();
9671
+ }
9672
+ },
9673
+ children: [
9674
+ /* @__PURE__ */ jsxs10("label", { className: "szenen-elements__create-title", children: [
9675
+ einzelTyp ? `Neue ${einzahl}` : "Titel",
9676
+ /* @__PURE__ */ jsx10(
9677
+ "input",
9678
+ {
9679
+ "data-testid": "neuer-titel",
9680
+ value: neuerTitel,
9681
+ autoFocus: true,
9682
+ placeholder: einzelTyp ? `Titel der neuen ${einzahl}` : "Titel",
9683
+ onChange: (e) => setNeuerTitel(e.target.value)
9684
+ }
9685
+ )
9686
+ ] }),
9687
+ gemischt && /* @__PURE__ */ jsxs10("label", { className: "szenen-elements__create-type", children: [
9688
+ "Art",
9689
+ /* @__PURE__ */ jsx10(
9690
+ "select",
9691
+ {
9692
+ "data-testid": "neuer-typ",
9693
+ value: neuerTyp,
9694
+ onChange: (e) => setNeuerTyp(e.target.value),
9695
+ children: auswahlTypen.map((t) => /* @__PURE__ */ jsx10("option", { value: t, children: elementTypLabel(t) }, t))
9696
+ }
9697
+ )
9698
+ ] }),
9699
+ /* @__PURE__ */ jsxs10("div", { className: "szenen-elements__create-actions", children: [
9700
+ /* @__PURE__ */ jsx10(
9701
+ "button",
9702
+ {
9703
+ type: "submit",
9704
+ "data-testid": "anlegen",
9705
+ disabled: anlegend || !neuerTitel.trim(),
9706
+ children: "anlegen"
9707
+ }
9708
+ ),
9709
+ /* @__PURE__ */ jsx10(
9710
+ "button",
9711
+ {
9712
+ type: "button",
9713
+ "data-testid": "anlegen-abbrechen",
9714
+ onClick: anlageSchliessen,
9715
+ children: "abbrechen"
9716
+ }
9717
+ )
9718
+ ] })
9719
+ ]
9358
9720
  }
9359
9721
  ),
9360
- /* @__PURE__ */ jsx10(
9361
- "select",
9722
+ notiz && /* @__PURE__ */ jsx10("p", { "data-testid": "anlegen-notiz", "data-tone": notiz.tone, children: notiz.text }),
9723
+ phase.status === "loading" && /* @__PURE__ */ jsx10("p", { "data-testid": "elemente-laden", children: "Elemente werden geladen \u2026" }),
9724
+ phase.status === "error" && /* @__PURE__ */ jsxs10("p", { "data-testid": "elemente-fehler", role: "alert", children: [
9725
+ "Elemente konnten nicht geladen werden: ",
9726
+ phase.message,
9727
+ phase.retryable && " \u2014 ein erneuter Versuch kann helfen."
9728
+ ] }),
9729
+ phase.status === "ready" && phase.value.length === 0 && /* @__PURE__ */ jsxs10("p", { "data-testid": "elemente-leer", children: [
9730
+ typ ? `Keine ${elementTypPlural(typ)} in diesem Kontext.` : "Nichts in diesem Kontext.",
9731
+ " ",
9732
+ 'Mit \u201E+ Neu" anlegen.'
9733
+ ] }),
9734
+ phase.status === "ready" && phase.value.length > 0 && /* @__PURE__ */ jsx10("ul", { className: "szenen-elements__list", "data-testid": "elemente-liste", children: phase.value.map((element) => /* @__PURE__ */ jsx10("li", { "data-element-id": element.element_id, children: /* @__PURE__ */ jsxs10(
9735
+ "button",
9362
9736
  {
9363
- "data-testid": "neuer-typ",
9364
- value: neuerTyp,
9365
- onChange: (e) => setNeuerTyp(e.target.value),
9366
- children: auswahlTypen.map((t) => /* @__PURE__ */ jsx10("option", { value: t, children: t }, t))
9737
+ type: "button",
9738
+ "data-testid": `element-waehlen-${element.element_id}`,
9739
+ "aria-current": element.element_id === gewaehlt,
9740
+ className: element.element_id === gewaehlt ? "is-selected" : void 0,
9741
+ onClick: () => waehle(element.element_id),
9742
+ children: [
9743
+ /* @__PURE__ */ jsx10("strong", { className: "szenen-elements__title", children: element.title || "Unbenanntes Element" }),
9744
+ gemischt && /* @__PURE__ */ jsx10("span", { className: "szenen-elements__type", children: elementTypLabel(element.type) }),
9745
+ element.subtype && /* @__PURE__ */ jsx10("span", { className: "szenen-elements__subtype", children: element.subtype }),
9746
+ element.retired && /* @__PURE__ */ jsx10("span", { className: "szenen-elements__retired", children: "stillgelegt" })
9747
+ ]
9748
+ }
9749
+ ) }, element.element_id)) }),
9750
+ /* @__PURE__ */ jsxs10("details", { className: "szenen-elements__options", "data-testid": "listen-optionen", children: [
9751
+ /* @__PURE__ */ jsx10("summary", { children: "Listenoptionen" }),
9752
+ /* @__PURE__ */ jsxs10("div", { className: "szenen-elements__filter", children: [
9753
+ /* @__PURE__ */ jsxs10("label", { children: [
9754
+ /* @__PURE__ */ jsx10(
9755
+ "input",
9756
+ {
9757
+ type: "checkbox",
9758
+ "data-testid": "filter-stillgelegt",
9759
+ checked: zeigeStillgelegte,
9760
+ onChange: (e) => setZeigeStillgelegte(e.target.checked)
9761
+ }
9762
+ ),
9763
+ "stillgelegte Elemente einblenden"
9764
+ ] }),
9765
+ /* @__PURE__ */ jsx10("button", { type: "button", "data-testid": "neu-laden", onClick: neuLaden, children: "neu laden" })
9766
+ ] })
9767
+ ] })
9768
+ ] }),
9769
+ zeigeDetail && /* @__PURE__ */ jsxs10("div", { className: "szenen-elements__detail", "data-testid": "elemente-detail-spalte", children: [
9770
+ schmal && /* @__PURE__ */ jsx10(
9771
+ "button",
9772
+ {
9773
+ type: "button",
9774
+ className: "szenen-elements__back",
9775
+ "data-testid": "zurueck-zur-liste",
9776
+ onClick: () => setAnsicht("liste"),
9777
+ children: "\u2190 Zur\xFCck zur Liste"
9367
9778
  }
9368
9779
  ),
9369
- /* @__PURE__ */ jsx10("button", { type: "submit", "data-testid": "anlegen", disabled: anlegend || !neuerTitel.trim(), children: "anlegen" })
9370
- ]
9371
- }
9372
- ),
9373
- notiz && /* @__PURE__ */ jsx10("p", { "data-testid": "anlegen-notiz", "data-tone": notiz.tone, children: notiz.text }),
9374
- phase.status === "loading" && /* @__PURE__ */ jsx10("p", { "data-testid": "elemente-laden", children: "Elemente werden geladen \u2026" }),
9375
- phase.status === "error" && /* @__PURE__ */ jsxs10("p", { "data-testid": "elemente-fehler", role: "alert", children: [
9376
- "Elemente konnten nicht geladen werden: ",
9377
- phase.message,
9378
- phase.retryable && " \u2014 ein erneuter Versuch kann helfen."
9379
- ] }),
9380
- phase.status === "ready" && phase.value.length === 0 && /* @__PURE__ */ jsxs10("p", { "data-testid": "elemente-leer", children: [
9381
- "Keine Elemente in diesem Kontext",
9382
- typ ? ` mit Typ \u201E${typ}"` : "",
9383
- "."
9384
- ] }),
9385
- phase.status === "ready" && phase.value.length > 0 && /* @__PURE__ */ jsx10("ul", { className: "szenen-elements__list", "data-testid": "elemente-liste", children: phase.value.map((element) => /* @__PURE__ */ jsx10("li", { "data-element-id": element.element_id, children: /* @__PURE__ */ jsxs10(
9386
- "button",
9387
- {
9388
- type: "button",
9389
- "aria-current": element.element_id === gewaehlt,
9390
- className: element.element_id === gewaehlt ? "is-selected" : void 0,
9391
- onClick: () => {
9392
- setGewaehlt(element.element_id);
9393
- onSelect?.(element.element_id);
9394
- },
9395
- children: [
9396
- /* @__PURE__ */ jsx10("strong", { className: "szenen-elements__title", children: element.title || "Unbenanntes Element" }),
9397
- /* @__PURE__ */ jsx10("span", { className: "szenen-elements__type", children: element.type }),
9398
- element.subtype && /* @__PURE__ */ jsx10("span", { className: "szenen-elements__subtype", children: element.subtype }),
9399
- /* @__PURE__ */ jsxs10("span", { className: "szenen-elements__technical", children: [
9400
- "ID ",
9401
- /* @__PURE__ */ jsx10("code", { className: "szenen-elements__id", children: element.element_id })
9402
- ] }),
9403
- element.retired && /* @__PURE__ */ jsx10("span", { className: "szenen-elements__retired", children: "stillgelegt" })
9404
- ]
9405
- }
9406
- ) }, element.element_id)) }),
9407
- gewaehlt && /* @__PURE__ */ jsx10(
9408
- ElementDetail,
9409
- {
9410
- port,
9411
- elementId: gewaehlt,
9412
- contextId,
9413
- author,
9414
- onChanged: neuLaden
9415
- }
9416
- )
9417
- ] });
9780
+ gewaehlt ? /* @__PURE__ */ jsx10(
9781
+ ElementDetail,
9782
+ {
9783
+ port,
9784
+ elementId: gewaehlt,
9785
+ contextId,
9786
+ author,
9787
+ onChanged: neuLaden
9788
+ }
9789
+ ) : /* @__PURE__ */ jsx10("p", { className: "szenen-elements__empty-detail", "data-testid": "keine-auswahl", children: "Nichts ausgew\xE4hlt. Ein Eintrag aus der Liste \xF6ffnet die Bearbeitung." })
9790
+ ] })
9791
+ ]
9792
+ }
9793
+ );
9418
9794
  };
9419
9795
 
9420
9796
  // src/features/szenen/areas/SceneArea.tsx
@@ -9427,14 +9803,15 @@ var SceneArea = ({ port, contextId }) => /* @__PURE__ */ jsxs11("div", { classNa
9427
9803
  // src/features/szenen/areas/SetupArea.tsx
9428
9804
  import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
9429
9805
  var SetupArea = ({ port, contextId }) => /* @__PURE__ */ jsxs12("div", { className: "szenen-setup", "data-testid": "bereich-setup", children: [
9430
- /* @__PURE__ */ jsx12("p", { className: "szenen-area__lead", children: "Scene Setups und Camera Rigs dieses Kontexts." }),
9806
+ /* @__PURE__ */ jsx12("p", { className: "szenen-area__lead", children: "Bildaufbauten, Kameras und Stile dieses Kontexts." }),
9431
9807
  /* @__PURE__ */ jsx12(
9432
9808
  ElementsArea,
9433
9809
  {
9434
9810
  port,
9435
9811
  contextId,
9436
9812
  restrictToTypes: ["scene_setup", "camera_preset", "camera_pattern", "style"],
9437
- allTypesLabel: "alle Bildaufbau-Typen"
9813
+ allTypesLabel: "alle Bildaufbau-Typen",
9814
+ listTitle: "Bildaufbau"
9438
9815
  }
9439
9816
  )
9440
9817
  ] });
@@ -9442,34 +9819,35 @@ var SetupArea = ({ port, contextId }) => /* @__PURE__ */ jsxs12("div", { classNa
9442
9819
  // src/features/szenen/areas/ShotArea.tsx
9443
9820
  import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
9444
9821
  var ShotArea = ({ port, contextId }) => /* @__PURE__ */ jsxs13("div", { className: "szenen-shot", "data-testid": "bereich-shot", children: [
9445
- /* @__PURE__ */ jsx13("p", { className: "szenen-area__lead", children: "Shots dieses Kontexts. Auswahl zeigt Runden und startet Prompt-L\xE4ufe." }),
9822
+ /* @__PURE__ */ jsx13("p", { className: "szenen-area__lead", children: "Prompts dieses Kontexts. Auswahl zeigt Runden und startet Prompt-L\xE4ufe." }),
9446
9823
  /* @__PURE__ */ jsx13(
9447
9824
  ElementsArea,
9448
9825
  {
9449
9826
  port,
9450
9827
  contextId,
9451
9828
  restrictToTypes: ["shot", "shot_concept", "target_model"],
9452
- allTypesLabel: "alle Prompt-Typen"
9829
+ allTypesLabel: "alle Prompt-Typen",
9830
+ listTitle: "Prompts"
9453
9831
  }
9454
9832
  )
9455
9833
  ] });
9456
9834
 
9457
9835
  // src/features/szenen/areas/MediaArea.tsx
9458
- import { useState as useState11 } from "react";
9836
+ import { useState as useState12 } from "react";
9459
9837
  import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
9460
9838
  var leer = async () => ({ kind: "ok", value: [] });
9461
9839
  var MediaArea = ({ port }) => {
9462
9840
  const media = port.media;
9463
- const [versionInput, setVersionInput] = useState11("");
9464
- const [versionId, setVersionId] = useState11("");
9465
- const [itemInput, setItemInput] = useState11("");
9466
- const [itemId, setItemId] = useState11("");
9467
- const [assetId, setAssetId] = useState11("");
9468
- const [role, setRole] = useState11("reference");
9469
- const [position, setPosition] = useState11("0");
9470
- const [notiz, setNotiz] = useState11(null);
9471
- const [busy, setBusy] = useState11(false);
9472
- const [refresh, setRefresh] = useState11(0);
9841
+ const [versionInput, setVersionInput] = useState12("");
9842
+ const [versionId, setVersionId] = useState12("");
9843
+ const [itemInput, setItemInput] = useState12("");
9844
+ const [itemId, setItemId] = useState12("");
9845
+ const [assetId, setAssetId] = useState12("");
9846
+ const [role, setRole] = useState12("reference");
9847
+ const [position, setPosition] = useState12("0");
9848
+ const [notiz, setNotiz] = useState12(null);
9849
+ const [busy, setBusy] = useState12(false);
9850
+ const [refresh, setRefresh] = useState12(0);
9473
9851
  const [versionPhase] = usePortQuery(
9474
9852
  () => versionId ? media.listVersionMedia(versionId) : leer(),
9475
9853
  [media, versionId, refresh]
@@ -9595,24 +9973,24 @@ var MediaArea = ({ port }) => {
9595
9973
  };
9596
9974
 
9597
9975
  // src/features/szenen/areas/DeriveArea.tsx
9598
- import { useRef as useRef2, useState as useState14 } from "react";
9976
+ import { useRef as useRef2, useState as useState15 } from "react";
9599
9977
 
9600
9978
  // src/features/szenen/areas/RecoveryPanel.tsx
9601
- import { useState as useState12 } from "react";
9602
- import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
9979
+ import { useState as useState13 } from "react";
9980
+ import { Fragment as Fragment5, jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
9603
9981
  var Diagnosen = ({ befunde, testId }) => {
9604
9982
  if (befunde.length === 0) return null;
9605
9983
  return /* @__PURE__ */ jsx15("ul", { className: "szenen-diagnose__liste", "data-testid": testId, children: befunde.map((d, i) => /* @__PURE__ */ jsxs15("li", { "data-severity": d.severity, children: [
9606
9984
  /* @__PURE__ */ jsx15("code", { children: d.code }),
9607
- d.proposal_type && /* @__PURE__ */ jsxs15(Fragment4, { children: [
9985
+ d.proposal_type && /* @__PURE__ */ jsxs15(Fragment5, { children: [
9608
9986
  " \xB7 ",
9609
9987
  /* @__PURE__ */ jsx15("strong", { children: d.proposal_type })
9610
9988
  ] }),
9611
- d.pointer && /* @__PURE__ */ jsxs15(Fragment4, { children: [
9989
+ d.pointer && /* @__PURE__ */ jsxs15(Fragment5, { children: [
9612
9990
  " \xB7 ",
9613
9991
  /* @__PURE__ */ jsx15("code", { children: d.pointer })
9614
9992
  ] }),
9615
- typeof d.line === "number" && /* @__PURE__ */ jsxs15(Fragment4, { children: [
9993
+ typeof d.line === "number" && /* @__PURE__ */ jsxs15(Fragment5, { children: [
9616
9994
  " \xB7 Zeile ",
9617
9995
  d.line,
9618
9996
  ", Spalte ",
@@ -9627,7 +10005,7 @@ var Ausbeute = ({ bewertung }) => /* @__PURE__ */ jsxs15("div", { className: "sz
9627
10005
  bewertung.status === "partial" && "Diese Fassung ist teilweise verwertbar \u2014 nicht alles kommt durch.",
9628
10006
  bewertung.status === "invalid" && "Aus dieser Fassung ist nichts zu \xFCbernehmen."
9629
10007
  ] }),
9630
- bewertung.proposals.length > 0 && /* @__PURE__ */ jsxs15(Fragment4, { children: [
10008
+ bewertung.proposals.length > 0 && /* @__PURE__ */ jsxs15(Fragment5, { children: [
9631
10009
  /* @__PURE__ */ jsx15("h5", { children: "Verwertbar" }),
9632
10010
  /* @__PURE__ */ jsx15("ul", { "data-testid": "rettung-verwertbar", children: bewertung.proposals.map((p) => /* @__PURE__ */ jsxs15("li", { "data-testid": `rettung-verwertbar-${p.type}`, children: [
9633
10011
  /* @__PURE__ */ jsx15("strong", { children: p.type }),
@@ -9640,7 +10018,7 @@ var Ausbeute = ({ bewertung }) => /* @__PURE__ */ jsxs15("div", { className: "sz
9640
10018
  ] }, i)) })
9641
10019
  ] }, p.type)) })
9642
10020
  ] }),
9643
- bewertung.rejected.length > 0 && /* @__PURE__ */ jsxs15(Fragment4, { children: [
10021
+ bewertung.rejected.length > 0 && /* @__PURE__ */ jsxs15(Fragment5, { children: [
9644
10022
  /* @__PURE__ */ jsx15("h5", { children: "Nicht verwertbar" }),
9645
10023
  /* @__PURE__ */ jsx15("ul", { "data-testid": "rettung-abgelehnt", children: bewertung.rejected.map((r) => /* @__PURE__ */ jsxs15("li", { "data-testid": `rettung-abgelehnt-${r.type}`, children: [
9646
10024
  /* @__PURE__ */ jsx15("strong", { children: r.type }),
@@ -9649,11 +10027,11 @@ var Ausbeute = ({ bewertung }) => /* @__PURE__ */ jsxs15("div", { className: "sz
9649
10027
  ] })
9650
10028
  ] });
9651
10029
  var RecoveryPanel = ({ port, lauf }) => {
9652
- const [arbeitskopie, setArbeitskopie] = useState12(null);
9653
- const [bewertung, setBewertung] = useState12(null);
9654
- const [gesichert, setGesichert] = useState12(null);
9655
- const [meldung, setMeldung] = useState12(null);
9656
- const [laeuft, setLaeuft] = useState12(false);
10030
+ const [arbeitskopie, setArbeitskopie] = useState13(null);
10031
+ const [bewertung, setBewertung] = useState13(null);
10032
+ const [gesichert, setGesichert] = useState13(null);
10033
+ const [meldung, setMeldung] = useState13(null);
10034
+ const [laeuft, setLaeuft] = useState13(false);
9657
10035
  if (!port.derivation) return null;
9658
10036
  if (typeof lauf.raw_output !== "string" || lauf.raw_output.length === 0) return null;
9659
10037
  const derivation = port.derivation;
@@ -9776,12 +10154,12 @@ var RecoveryPanel = ({ port, lauf }) => {
9776
10154
  };
9777
10155
 
9778
10156
  // src/features/szenen/areas/ChainActions.tsx
9779
- import { useState as useState13 } from "react";
9780
- import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
10157
+ import { useState as useState14 } from "react";
10158
+ import { Fragment as Fragment6, jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
9781
10159
  var ChainActions = ({ port, runId, recoveryId }) => {
9782
- const [graph, setGraph] = useState13(null);
9783
- const [meldung, setMeldung] = useState13(null);
9784
- const [laeuft, setLaeuft] = useState13(false);
10160
+ const [graph, setGraph] = useState14(null);
10161
+ const [meldung, setMeldung] = useState14(null);
10162
+ const [laeuft, setLaeuft] = useState14(false);
9785
10163
  if (!port.derivation) return null;
9786
10164
  const derivation = port.derivation;
9787
10165
  const runs = port.runs;
@@ -9845,23 +10223,29 @@ var ChainActions = ({ port, runId, recoveryId }) => {
9845
10223
  ] }, m.type)) })
9846
10224
  ] })
9847
10225
  ] }),
9848
- shotKnoten && /* @__PURE__ */ jsxs16(Fragment5, { children: [
10226
+ shotKnoten && /* @__PURE__ */ jsxs16(Fragment6, { children: [
9849
10227
  /* @__PURE__ */ jsx16("p", { children: 'Die Entw\xFCrfe lassen sich jetzt unter \u201E1 \xB7 Bausteine" \xE4ndern. Der Prompt-Lauf friert den Stand ein, den er dabei vorfindet \u2014 dieselbe Aktion steht auch am Shot selbst, unter \u201E4 \xB7 Prompt".' }),
9850
- /* @__PURE__ */ jsx16(ChainPromptAction, { port, shotElementId: shotKnoten.elementId })
10228
+ /* @__PURE__ */ jsx16(
10229
+ PromptStartAction,
10230
+ {
10231
+ port,
10232
+ source: { kind: "draft_chain", shotElementId: shotKnoten.elementId }
10233
+ }
10234
+ )
9851
10235
  ] }),
9852
10236
  meldung && /* @__PURE__ */ jsx16("p", { className: "szenen-error", role: "alert", "data-testid": "kette-meldung", children: meldung })
9853
10237
  ] });
9854
10238
  };
9855
10239
 
9856
10240
  // src/features/szenen/areas/DeriveArea.tsx
9857
- import { Fragment as Fragment6, jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
10241
+ import { Fragment as Fragment7, jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
9858
10242
  var MODUS_TEXT = {
9859
10243
  prompt: "Nur Prompt",
9860
10244
  image: "Nur Bild",
9861
10245
  image_prompt: "Bild und Prompt"
9862
10246
  };
9863
10247
  var BelegFeld = ({ titel, text, testId, offen }) => {
9864
- const [kopiert, setKopiert] = useState14(false);
10248
+ const [kopiert, setKopiert] = useState15(false);
9865
10249
  const feld = useRef2(null);
9866
10250
  async function kopieren() {
9867
10251
  try {
@@ -9958,7 +10342,7 @@ function readAsBase642(datei) {
9958
10342
  });
9959
10343
  }
9960
10344
  var BildWaehler = ({ port, gewaehlt, onWaehlen, onEntfernen }) => {
9961
- const [suche, setSuche] = useState14("");
10345
+ const [suche, setSuche] = useState15("");
9962
10346
  const [bilder] = usePortQuery(
9963
10347
  () => port.imageLibrary.listImages({ search: suche.trim() || void 0, limit: 60 }),
9964
10348
  [port, suche]
@@ -10016,19 +10400,19 @@ async function digestOf(datei) {
10016
10400
  return [...new Uint8Array(hash)].map((b) => b.toString(16).padStart(2, "0")).join("");
10017
10401
  }
10018
10402
  var DeriveArea = ({ port, contextId }) => {
10019
- const [policyVersionId, setPolicyVersionId] = useState14("");
10020
- const [modus, setModus] = useState14("prompt");
10021
- const [promptText, setPromptText] = useState14("");
10022
- const [dateien, setDateien] = useState14([]);
10023
- const [bestandsbilder, setBestandsbilder] = useState14([]);
10024
- const [laeuft, setLaeuft] = useState14(false);
10025
- const [lauf, setLauf] = useState14(null);
10026
- const [meldung, setMeldung] = useState14(null);
10027
- const [uebernommen, setUebernommen] = useState14({});
10028
- const [titel, setTitel] = useState14({});
10029
- const [referenzen, setReferenzen] = useState14({});
10030
- const [beanstandung, setBeanstandung] = useState14(null);
10031
- const [zusatz, setZusatz] = useState14("");
10403
+ const [policyVersionId, setPolicyVersionId] = useState15("");
10404
+ const [modus, setModus] = useState15("prompt");
10405
+ const [promptText, setPromptText] = useState15("");
10406
+ const [dateien, setDateien] = useState15([]);
10407
+ const [bestandsbilder, setBestandsbilder] = useState15([]);
10408
+ const [laeuft, setLaeuft] = useState15(false);
10409
+ const [lauf, setLauf] = useState15(null);
10410
+ const [meldung, setMeldung] = useState15(null);
10411
+ const [uebernommen, setUebernommen] = useState15({});
10412
+ const [titel, setTitel] = useState15({});
10413
+ const [referenzen, setReferenzen] = useState15({});
10414
+ const [beanstandung, setBeanstandung] = useState15(null);
10415
+ const [zusatz, setZusatz] = useState15("");
10032
10416
  const [regeln] = usePortQuery(
10033
10417
  () => port.derivation.listPolicies(contextId),
10034
10418
  [port, contextId]
@@ -10242,7 +10626,7 @@ ${teile.map((t) => `- ${t}`).join("\n")}`;
10242
10626
  }
10243
10627
  )
10244
10628
  ] }),
10245
- modus !== "prompt" && /* @__PURE__ */ jsxs17(Fragment6, { children: [
10629
+ modus !== "prompt" && /* @__PURE__ */ jsxs17(Fragment7, { children: [
10246
10630
  port.imageLibrary && /* @__PURE__ */ jsx17(
10247
10631
  BildWaehler,
10248
10632
  {
@@ -10344,7 +10728,7 @@ ${teile.map((t) => `- ${t}`).join("\n")}`;
10344
10728
  )
10345
10729
  ] }),
10346
10730
  /* @__PURE__ */ jsx17("pre", { className: "szenen-proposal__payload", children: JSON.stringify(vorschlag.payload, null, 2) }),
10347
- bezug && !fertig && /* @__PURE__ */ jsxs17(Fragment6, { children: [
10731
+ bezug && !fertig && /* @__PURE__ */ jsxs17(Fragment7, { children: [
10348
10732
  /* @__PURE__ */ jsx17(
10349
10733
  ReferencePicker,
10350
10734
  {
@@ -10414,7 +10798,7 @@ var SzenenView = ({
10414
10798
  }) => {
10415
10799
  const bereiche = useMemo3(() => areasFor(port), [port]);
10416
10800
  const faehig = useMemo3(() => capabilitiesOf(port), [port]);
10417
- const [aktiv, setAktiv] = useState15(() => resolveArea(port, initialArea));
10801
+ const [aktiv, setAktiv] = useState16(() => resolveArea(port, initialArea));
10418
10802
  const wechsle = (id) => {
10419
10803
  setAktiv(id);
10420
10804
  onAreaChange?.(id);
@@ -10445,7 +10829,16 @@ var SzenenView = ({
10445
10829
  )) }),
10446
10830
  /* @__PURE__ */ jsxs18("section", { className: "szenen-view__area", "aria-label": aktuellerBereich.title, children: [
10447
10831
  aktiv === "derive" && port.derivation && /* @__PURE__ */ jsx18(DeriveArea, { port, contextId }),
10448
- aktiv === "elements" && /* @__PURE__ */ jsx18(ElementsArea, { port, contextId }),
10832
+ aktiv === "elements" && /* @__PURE__ */ jsx18(
10833
+ ElementsArea,
10834
+ {
10835
+ port,
10836
+ contextId,
10837
+ restrictToTypes: BAUSTEIN_TYPES,
10838
+ allTypesLabel: "alle Bausteine",
10839
+ listTitle: "Bausteine"
10840
+ }
10841
+ ),
10449
10842
  aktiv === "scene" && /* @__PURE__ */ jsx18(SceneArea, { port, contextId }),
10450
10843
  aktiv === "setup" && /* @__PURE__ */ jsx18(SetupArea, { port, contextId }),
10451
10844
  aktiv === "shot" && /* @__PURE__ */ jsx18(ShotArea, { port, contextId }),
@@ -11226,7 +11619,7 @@ var CHAIN_EDGES = {
11226
11619
  scene_ref: { from: "scene_setup", to: "scene" },
11227
11620
  scene_setup_ref: { from: "shot", to: "scene_setup" }
11228
11621
  };
11229
- function istText3(wert) {
11622
+ function istText4(wert) {
11230
11623
  return typeof wert === "string" && wert.trim().length > 0;
11231
11624
  }
11232
11625
  function checkDraftChainMeta(meta, type) {
@@ -11237,14 +11630,14 @@ function checkDraftChainMeta(meta, type) {
11237
11630
  };
11238
11631
  }
11239
11632
  const m = meta;
11240
- if (!istText3(m.chain_id)) return { ok: false, message: '"chain_id" fehlt oder ist leer.' };
11241
- if (!istText3(m.source_run_id)) {
11633
+ if (!istText4(m.chain_id)) return { ok: false, message: '"chain_id" fehlt oder ist leer.' };
11634
+ if (!istText4(m.source_run_id)) {
11242
11635
  return {
11243
11636
  ok: false,
11244
11637
  message: '"source_run_id" fehlt oder ist leer \u2014 ohne sie ist die Herkunft eines Kettenknotens nicht rekonstruierbar (D-96/B3).'
11245
11638
  };
11246
11639
  }
11247
- if (m.source_recovery_id !== void 0 && !istText3(m.source_recovery_id)) {
11640
+ if (m.source_recovery_id !== void 0 && !istText4(m.source_recovery_id)) {
11248
11641
  return { ok: false, message: '"source_recovery_id" ist gesetzt, aber leer.' };
11249
11642
  }
11250
11643
  if (!Array.isArray(m.links)) {
@@ -11269,7 +11662,7 @@ function checkDraftChainMeta(meta, type) {
11269
11662
  message: `"${l.field}" gehoert an einen ${kante.from}, nicht an einen ${type}.`
11270
11663
  };
11271
11664
  }
11272
- if (!istText3(l.target_element_id) || !istText3(l.target_draft_id)) {
11665
+ if (!istText4(l.target_element_id) || !istText4(l.target_draft_id)) {
11273
11666
  return {
11274
11667
  ok: false,
11275
11668
  message: `"links[${index}]" braucht target_element_id und target_draft_id.`
@@ -11917,12 +12310,12 @@ function createHfEventChannel(options) {
11917
12310
  // src/lib/szenen/resolve.ts
11918
12311
  var ResolveTechnicalError = class extends Error {
11919
12312
  };
11920
- var isObject10 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
11921
- var asArray2 = (v) => Array.isArray(v) ? v : [];
12313
+ var isObject11 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
12314
+ var asArray3 = (v) => Array.isArray(v) ? v : [];
11922
12315
  var str = (v) => typeof v === "string" ? v : null;
11923
12316
  var num = (v) => typeof v === "number" ? v : null;
11924
12317
  async function refOf(resolver, ref, expected, path) {
11925
- const versionId = isObject10(ref) ? str(ref.version_id) : null;
12318
+ const versionId = isObject11(ref) ? str(ref.version_id) : null;
11926
12319
  if (!versionId) {
11927
12320
  return {
11928
12321
  ok: false,
@@ -11974,8 +12367,11 @@ async function refOf(resolver, ref, expected, path) {
11974
12367
  }
11975
12368
  return { ok: true, version };
11976
12369
  }
12370
+ function ausgelassen(diagnostics, code, path, message) {
12371
+ diagnostics.push({ code, origin: "resolution", path, message });
12372
+ }
11977
12373
  function entraeumlichtePlatzierung(placement, assumptions) {
11978
- if (!isObject10(placement)) return null;
12374
+ if (!isObject11(placement)) return null;
11979
12375
  if (placement.mode !== "pattern") {
11980
12376
  assumptions.push(
11981
12377
  `Die Kameraplatzierung (mode "${str(placement.mode) ?? "unbekannt"}") ist metrisch und entfaellt ohne can_place. Der Renderer darf daraus keine Position ableiten.`
@@ -11990,7 +12386,7 @@ function entraeumlichtePlatzierung(placement, assumptions) {
11990
12386
  const entfallen = [];
11991
12387
  if (placement.offsets !== void 0) entfallen.push("offsets");
11992
12388
  const height = placement.height;
11993
- if (isObject10(height)) {
12389
+ if (isObject11(height)) {
11994
12390
  if (height.mode === "anchor") {
11995
12391
  const behalteneHoehe = {
11996
12392
  mode: "anchor",
@@ -12069,142 +12465,328 @@ async function resolveShotPayload(input) {
12069
12465
  chain
12070
12466
  } = input;
12071
12467
  const assumptions = [];
12072
- const shotVersion = {
12073
- version_id: shotVersionId,
12074
- element_id: shotElementId,
12075
- payload: shotPayload
12076
- };
12077
- const shotErrors = ohneKettenReferenz(
12078
- validatePayload("shot", shotVersion.payload).errors,
12079
- chain ? "scene_setup_ref" : null
12080
- );
12081
- if (shotErrors.length > 0) {
12468
+ const diagnostics = [];
12469
+ if (!isObject11(shotPayload)) {
12082
12470
  return {
12083
12471
  kind: "rejected",
12084
12472
  failure: {
12085
12473
  class: "schema",
12086
12474
  where: "shot",
12087
- message: `Die Shot-Payload verletzt das Schema (${shotErrors.length} Befunde). Es wurde keine ihrer Referenzen aufgeloest.`,
12088
- errors: shotErrors
12475
+ message: `Die Shot-Payload ist kein Objekt, sondern ${Array.isArray(shotPayload) ? "ein Array" : typeof shotPayload}. Daraus laesst sich kein Auftrag herstellen.`,
12476
+ errors: []
12477
+ }
12478
+ };
12479
+ }
12480
+ const shot = shotPayload;
12481
+ for (const fehler4 of ohneKettenReferenz(
12482
+ validatePayload("shot", shotPayload).errors,
12483
+ chain ? "scene_setup_ref" : null
12484
+ )) {
12485
+ diagnostics.push(diagnosticOfSchemaError(fehler4, `Shot ${shotElementId}`));
12486
+ }
12487
+ let setup = null;
12488
+ let report = null;
12489
+ let canPlace = false;
12490
+ let capabilities;
12491
+ let scene;
12492
+ const nenntSetup = chain !== void 0 || shot.scene_setup_ref !== void 0;
12493
+ if (!nenntSetup) {
12494
+ return {
12495
+ kind: "rejected",
12496
+ failure: {
12497
+ class: "no_content",
12498
+ message: `Der Shot ${shotElementId} nennt kein scene_setup_ref und fuehrt keine Draft-Kette. Ohne Setup gibt es keinen Weg zu einer Szene und damit keinen beschreibbaren Inhalt.`
12089
12499
  }
12090
12500
  };
12091
12501
  }
12092
- const shot = shotVersion.payload;
12093
12502
  const setupRef = chain ? { ok: true, version: chain.setup } : await refOf(resolver, shot.scene_setup_ref, "scene_setup", "/scene_setup_ref");
12094
12503
  if (!setupRef.ok) return { kind: "rejected", failure: setupRef.failure };
12095
- const setupErrors = ohneKettenReferenz(
12096
- validatePayload("scene_setup", setupRef.version.payload).errors,
12097
- chain ? "scene_ref" : null
12098
- );
12099
- if (setupErrors.length > 0) {
12504
+ if (!isObject11(setupRef.version.payload)) {
12100
12505
  return {
12101
12506
  kind: "rejected",
12102
12507
  failure: {
12103
12508
  class: "schema",
12104
12509
  where: "scene_setup",
12105
- message: `Die Scene-Setup-Payload verletzt das Schema (${setupErrors.length} Befunde). Weder ihre Referenzen noch der Faehigkeitsbericht wurden mit einem Resolver gefahren.`,
12106
- errors: setupErrors
12510
+ message: `Die Scene-Setup-Payload ist kein Objekt, sondern ${Array.isArray(setupRef.version.payload) ? "ein Array" : typeof setupRef.version.payload}.`,
12511
+ errors: []
12107
12512
  }
12108
12513
  };
12109
12514
  }
12110
- const setup = setupRef.version.payload;
12111
- const report = await capabilityReport({
12515
+ setup = {
12516
+ element_id: setupRef.version.element_id,
12517
+ version_id: setupRef.version.version_id,
12518
+ payload: setupRef.version.payload
12519
+ };
12520
+ report = await capabilityReport({
12112
12521
  type: "scene_setup",
12113
- setupPayload: setup,
12114
- elementId: setupRef.version.element_id,
12522
+ setupPayload: setup.payload,
12523
+ elementId: setup.element_id,
12115
12524
  resolver,
12116
12525
  // Bei einer Draft-Kette kommt die Szene von hier, nicht aus `scene_ref`
12117
12526
  // (C1). Dasselbe Regelwerk, ein anderer Weg zur selben Szene.
12118
12527
  ...chain ? { chainScene: chain.scene.payload } : {}
12119
12528
  });
12120
- const gate = capabilityGate(report, "can_render_prompt");
12121
- if (gate) return { kind: "rejected", failure: gate };
12122
- const placeGate = capabilityGate(report, "can_place");
12123
- if (placeGate && placeGate.class === "capability_undetermined") {
12124
- return { kind: "rejected", failure: placeGate };
12125
- }
12126
- const canPlace = report.can_place.state === "yes";
12529
+ diagnostics.push(...report.promptDiagnostics);
12530
+ canPlace = report.can_place.state === "yes";
12127
12531
  if (!canPlace) {
12128
12532
  assumptions.push(
12129
- "can_place ist nicht erfuellt \u2014 alle Platzierungen bleiben null. Der Renderer darf daraus keine Koordinaten ableiten (D-47)."
12533
+ `can_place ist "${report.can_place.state}" \u2014 alle Platzierungen bleiben null. Der Renderer darf daraus keine Koordinaten ableiten (D-47).`
12130
12534
  );
12131
12535
  }
12132
- const sceneRef = chain ? { ok: true, version: chain.scene } : await refOf(resolver, setup.scene_ref, "scene", "/scene_ref");
12536
+ capabilities = {
12537
+ can_describe_scene: report.can_describe_scene.state,
12538
+ can_render_prompt: report.can_render_prompt.state,
12539
+ can_place: report.can_place.state
12540
+ };
12541
+ const sceneRef = chain ? { ok: true, version: chain.scene } : await refOf(resolver, setup.payload.scene_ref, "scene", "/scene_ref");
12133
12542
  if (!sceneRef.ok) return { kind: "rejected", failure: sceneRef.failure };
12134
- const scene = sceneRef.version.payload;
12135
- const cameraId = str(shot.camera_id) ?? "";
12136
- const rig = isObject10(setup.camera_rig) ? setup.camera_rig : {};
12137
- const cameras = asArray2(rig.cameras);
12138
- const cameraIndex = cameras.findIndex(
12139
- (camera2) => isObject10(camera2) && camera2.camera_id === cameraId
12140
- );
12141
- if (cameraIndex < 0) {
12543
+ if (!isObject11(sceneRef.version.payload)) {
12142
12544
  return {
12143
12545
  kind: "rejected",
12144
12546
  failure: {
12145
- class: "reference_unresolvable",
12146
- message: `Die aktive camera_id "${cameraId}" kommt im Rig der Scene-Setup-Version ${setupRef.version.version_id} nicht vor (P-01).`,
12147
- versionId: setupRef.version.version_id,
12148
- path: "/camera_id",
12149
- reason: "unknown"
12547
+ class: "schema",
12548
+ where: "scene",
12549
+ message: `Die Szenen-Payload ist kein Objekt, sondern ${Array.isArray(sceneRef.version.payload) ? "ein Array" : typeof sceneRef.version.payload}.`,
12550
+ errors: []
12551
+ }
12552
+ };
12553
+ }
12554
+ scene = {
12555
+ element_id: sceneRef.version.element_id,
12556
+ version_id: sceneRef.version.version_id,
12557
+ payload: sceneRef.version.payload
12558
+ };
12559
+ return komponiere({
12560
+ shot: { element_id: shotElementId, version_id: shotVersionId, payload: shot },
12561
+ setup,
12562
+ scene,
12563
+ report,
12564
+ capabilities,
12565
+ canPlace,
12566
+ resolver,
12567
+ contextChain,
12568
+ userInstruction,
12569
+ assumptions,
12570
+ diagnostics
12571
+ });
12572
+ }
12573
+ async function resolveScenePayload(input) {
12574
+ const {
12575
+ scenePayload,
12576
+ sceneElementId,
12577
+ sceneVersionId = "",
12578
+ resolver,
12579
+ contextChain,
12580
+ userInstruction
12581
+ } = input;
12582
+ if (!isObject11(scenePayload)) {
12583
+ return {
12584
+ kind: "rejected",
12585
+ failure: {
12586
+ class: "schema",
12587
+ where: "scene",
12588
+ message: `Die Szenen-Payload ist kein Objekt, sondern ${Array.isArray(scenePayload) ? "ein Array" : typeof scenePayload}.`,
12589
+ errors: []
12150
12590
  }
12151
12591
  };
12152
12592
  }
12153
- const camera = cameras[cameraIndex];
12154
- const presetRef = await refOf(
12593
+ const assumptions = [
12594
+ "Kein Scene Setup, kein Shot: Der Lauf entsteht aus der Szene allein. Bildaufbau, Kamera und Zielmodell wurden nicht ergaenzt, sondern sind nicht vorhanden (D-135)."
12595
+ ];
12596
+ const diagnostics = [];
12597
+ for (const fehler4 of validatePayload("scene", scenePayload).errors) {
12598
+ diagnostics.push(diagnosticOfSchemaError(fehler4, `Szene ${sceneElementId}`));
12599
+ }
12600
+ const faehig = sceneOnlyCapabilities(scenePayload);
12601
+ return komponiere({
12602
+ shot: null,
12603
+ setup: null,
12604
+ scene: { element_id: sceneElementId, version_id: sceneVersionId, payload: scenePayload },
12605
+ report: null,
12606
+ capabilities: {
12607
+ can_describe_scene: faehig.can_describe_scene.state,
12608
+ can_render_prompt: faehig.can_render_prompt.state,
12609
+ can_place: faehig.can_place.state
12610
+ },
12611
+ canPlace: false,
12155
12612
  resolver,
12156
- camera.preset_ref,
12157
- "camera_preset",
12158
- `/camera_rig/cameras/${cameraIndex}/preset_ref`
12159
- );
12160
- if (!presetRef.ok) return { kind: "rejected", failure: presetRef.failure };
12161
- let pattern = null;
12162
- const placementSpec = isObject10(camera.placement) ? camera.placement : null;
12163
- if (placementSpec && isObject10(placementSpec.pattern_ref)) {
12164
- const patternRef = await refOf(
12165
- resolver,
12166
- placementSpec.pattern_ref,
12167
- "camera_pattern",
12168
- `/camera_rig/cameras/${cameraIndex}/placement/pattern_ref`
12613
+ contextChain,
12614
+ userInstruction,
12615
+ assumptions,
12616
+ diagnostics
12617
+ });
12618
+ }
12619
+ async function komponiere(z) {
12620
+ const {
12621
+ shot,
12622
+ setup,
12623
+ scene,
12624
+ report,
12625
+ capabilities,
12626
+ canPlace,
12627
+ resolver,
12628
+ contextChain,
12629
+ userInstruction,
12630
+ assumptions,
12631
+ diagnostics
12632
+ } = z;
12633
+ const inhalt = describableContent(scene.payload);
12634
+ if (!inhalt.ok) {
12635
+ return {
12636
+ kind: "rejected",
12637
+ failure: {
12638
+ class: "no_content",
12639
+ message: `Szene ${scene.element_id}: ${inhalt.message}`
12640
+ }
12641
+ };
12642
+ }
12643
+ const eingefroreneFaehigkeiten = {
12644
+ ...capabilities,
12645
+ can_render_prompt: "yes"
12646
+ };
12647
+ const shotOverrides = shot && isObject11(shot.payload.overrides) ? shot.payload.overrides : {};
12648
+ const settings = shot && isObject11(shot.payload.prompt_render_settings) ? shot.payload.prompt_render_settings : {};
12649
+ let camera = null;
12650
+ if (shot && setup) {
12651
+ const cameraId = str(shot.payload.camera_id);
12652
+ const rig = isObject11(setup.payload.camera_rig) ? setup.payload.camera_rig : {};
12653
+ const cameras = asArray3(rig.cameras);
12654
+ const cameraIndex = cameraId === null ? -1 : cameras.findIndex((c) => isObject11(c) && c.camera_id === cameraId);
12655
+ if (cameraId === null) {
12656
+ ausgelassen(
12657
+ diagnostics,
12658
+ "P-01",
12659
+ "/camera_id",
12660
+ `Der Shot ${shot.element_id} nennt keine camera_id. Der Prompt entsteht ohne Kameravorgabe; eine Kamera wird nicht erfunden (D-75).`
12661
+ );
12662
+ } else if (cameraIndex < 0) {
12663
+ ausgelassen(
12664
+ diagnostics,
12665
+ "P-01",
12666
+ "/camera_id",
12667
+ `Die aktive camera_id "${cameraId}" kommt im Rig der Scene-Setup-Version ${setup.version_id} nicht vor. Der Prompt entsteht ohne Kameravorgabe.`
12668
+ );
12669
+ } else {
12670
+ const rohKamera = cameras[cameraIndex];
12671
+ let preset = null;
12672
+ const presetRef = await refOf(
12673
+ resolver,
12674
+ rohKamera.preset_ref,
12675
+ "camera_preset",
12676
+ `/camera_rig/cameras/${cameraIndex}/preset_ref`
12677
+ );
12678
+ if (presetRef.ok) preset = presetRef.version.payload;
12679
+ else {
12680
+ ausgelassen(
12681
+ diagnostics,
12682
+ "P-04",
12683
+ `/camera_rig/cameras/${cameraIndex}/preset_ref`,
12684
+ `${presetRef.failure.message} Die Kamera geht ohne Preset in den Prompt.`
12685
+ );
12686
+ }
12687
+ let pattern = null;
12688
+ const placementSpec = isObject11(rohKamera.placement) ? rohKamera.placement : null;
12689
+ if (placementSpec && isObject11(placementSpec.pattern_ref)) {
12690
+ const patternRef = await refOf(
12691
+ resolver,
12692
+ placementSpec.pattern_ref,
12693
+ "camera_pattern",
12694
+ `/camera_rig/cameras/${cameraIndex}/placement/pattern_ref`
12695
+ );
12696
+ if (patternRef.ok) pattern = patternRef.version.payload;
12697
+ else {
12698
+ ausgelassen(
12699
+ diagnostics,
12700
+ "P-04",
12701
+ `/camera_rig/cameras/${cameraIndex}/placement/pattern_ref`,
12702
+ `${patternRef.failure.message} Das Kameramuster entfaellt im Prompt.`
12703
+ );
12704
+ }
12705
+ }
12706
+ const cameraPlacement = canPlace ? rohKamera.placement ?? null : entraeumlichtePlatzierung(rohKamera.placement, assumptions);
12707
+ camera = {
12708
+ camera_id: cameraId,
12709
+ name: str(rohKamera.name),
12710
+ preset,
12711
+ placement: cameraPlacement,
12712
+ orientation: rohKamera.orientation ?? null,
12713
+ // Der Shot darf Bildgroesse und Fokus ueberschreiben (D-40) — das ist
12714
+ // die oberste Stufe der Vorrangkette.
12715
+ framing: shotOverrides.framing ?? rohKamera.framing ?? null,
12716
+ focus: shotOverrides.focus !== void 0 ? shotOverrides.focus : rohKamera.focus ?? null,
12717
+ pattern
12718
+ };
12719
+ }
12720
+ } else if (shot && !setup) {
12721
+ ausgelassen(
12722
+ diagnostics,
12723
+ "P-01",
12724
+ "/camera_id",
12725
+ "Ohne Scene Setup gibt es kein Camera Rig. Der Prompt entsteht ohne Kameravorgabe."
12169
12726
  );
12170
- if (!patternRef.ok) return { kind: "rejected", failure: patternRef.failure };
12171
- pattern = patternRef.version.payload;
12172
12727
  }
12173
12728
  let shotConcept = null;
12174
- if (isObject10(shot.shot_concept_ref)) {
12729
+ if (shot && isObject11(shot.payload.shot_concept_ref)) {
12175
12730
  const conceptRef = await refOf(
12176
12731
  resolver,
12177
- shot.shot_concept_ref,
12732
+ shot.payload.shot_concept_ref,
12178
12733
  "shot_concept",
12179
12734
  "/shot_concept_ref"
12180
12735
  );
12181
- if (!conceptRef.ok) return { kind: "rejected", failure: conceptRef.failure };
12182
- shotConcept = conceptRef.version.payload;
12736
+ if (conceptRef.ok) shotConcept = conceptRef.version.payload;
12737
+ else {
12738
+ ausgelassen(
12739
+ diagnostics,
12740
+ "P-04",
12741
+ "/shot_concept_ref",
12742
+ `${conceptRef.failure.message} Das Shot Concept entfaellt im Prompt.`
12743
+ );
12744
+ }
12183
12745
  }
12184
12746
  const styles = [];
12185
12747
  for (const [ebene, refs] of [
12186
- ["scene_setup", asArray2(setup.style_refs)],
12187
- ["shot", asArray2(shot.style_refs)]
12748
+ ["scene_setup", setup ? asArray3(setup.payload.style_refs) : []],
12749
+ ["shot", shot ? asArray3(shot.payload.style_refs) : []]
12188
12750
  ]) {
12189
12751
  for (const [i, ref] of refs.entries()) {
12190
12752
  const resolved = await refOf(resolver, ref, "style", `/${ebene}/style_refs/${i}`);
12191
- if (!resolved.ok) return { kind: "rejected", failure: resolved.failure };
12753
+ if (!resolved.ok) {
12754
+ ausgelassen(
12755
+ diagnostics,
12756
+ "P-04",
12757
+ `/${ebene}/style_refs/${i}`,
12758
+ `${resolved.failure.message} Dieser Stil entfaellt im Prompt.`
12759
+ );
12760
+ continue;
12761
+ }
12192
12762
  const payload = resolved.version.payload;
12193
12763
  styles.push({
12194
- role: str(isObject10(ref) ? ref.role : null) ?? str(payload.role) ?? "unspecified",
12195
- rank: num(isObject10(ref) ? ref.rank : null) ?? 0,
12196
- weight: num(isObject10(ref) ? ref.weight : null),
12764
+ role: str(isObject11(ref) ? ref.role : null) ?? str(payload.role) ?? "unspecified",
12765
+ rank: num(isObject11(ref) ? ref.rank : null) ?? 0,
12766
+ weight: num(isObject11(ref) ? ref.weight : null),
12197
12767
  text: str(payload.text) ?? "",
12198
12768
  locale: str(payload.locale)
12199
12769
  });
12200
12770
  }
12201
12771
  }
12202
12772
  styles.sort((a, b) => a.rank - b.rank);
12203
- const settings = isObject10(shot.prompt_render_settings) ? shot.prompt_render_settings : {};
12204
12773
  const policies = [];
12205
- for (const [i, ref] of asArray2(settings.policy_refs).entries()) {
12206
- const resolved = await refOf(resolver, ref, "prompt_policy", `/prompt_render_settings/policy_refs/${i}`);
12207
- if (!resolved.ok) return { kind: "rejected", failure: resolved.failure };
12774
+ for (const [i, ref] of asArray3(settings.policy_refs).entries()) {
12775
+ const resolved = await refOf(
12776
+ resolver,
12777
+ ref,
12778
+ "prompt_policy",
12779
+ `/prompt_render_settings/policy_refs/${i}`
12780
+ );
12781
+ if (!resolved.ok) {
12782
+ ausgelassen(
12783
+ diagnostics,
12784
+ "P-04",
12785
+ `/prompt_render_settings/policy_refs/${i}`,
12786
+ `${resolved.failure.message} Diese Policy entfaellt im Prompt.`
12787
+ );
12788
+ continue;
12789
+ }
12208
12790
  const payload = resolved.version.payload;
12209
12791
  policies.push({
12210
12792
  subtype: str(payload.subtype) ?? "general",
@@ -12215,14 +12797,22 @@ async function resolveShotPayload(input) {
12215
12797
  }
12216
12798
  policies.sort((a, b) => a.rank - b.rank);
12217
12799
  const fragments = [];
12218
- for (const [i, ref] of asArray2(settings.fragment_refs).entries()) {
12800
+ for (const [i, ref] of asArray3(settings.fragment_refs).entries()) {
12219
12801
  const resolved = await refOf(
12220
12802
  resolver,
12221
12803
  ref,
12222
12804
  "prompt_fragment",
12223
12805
  `/prompt_render_settings/fragment_refs/${i}`
12224
12806
  );
12225
- if (!resolved.ok) return { kind: "rejected", failure: resolved.failure };
12807
+ if (!resolved.ok) {
12808
+ ausgelassen(
12809
+ diagnostics,
12810
+ "P-04",
12811
+ `/prompt_render_settings/fragment_refs/${i}`,
12812
+ `${resolved.failure.message} Dieses Fragment entfaellt im Prompt.`
12813
+ );
12814
+ continue;
12815
+ }
12226
12816
  const payload = resolved.version.payload;
12227
12817
  fragments.push({
12228
12818
  channel: str(payload.channel) ?? "positive",
@@ -12232,83 +12822,102 @@ async function resolveShotPayload(input) {
12232
12822
  });
12233
12823
  }
12234
12824
  fragments.sort((a, b) => a.rank - b.rank);
12235
- const key = str(settings.target_model_id);
12236
- if (!key) {
12237
- return {
12238
- kind: "rejected",
12239
- failure: {
12240
- class: "target_model_unresolvable",
12241
- message: "Der Shot nennt kein target_model_id.",
12242
- resolution: { kind: "not_found", key: "", chain: contextChain }
12243
- }
12244
- };
12245
- }
12246
- if (!resolver.resolveTargetModel) {
12825
+ let targetModelPayload = null;
12826
+ let targetModelResolution = null;
12827
+ const key = shot ? str(settings.target_model_id) : null;
12828
+ if (key === null) {
12829
+ ausgelassen(
12830
+ diagnostics,
12831
+ "P-17",
12832
+ "/prompt_render_settings/target_model_id",
12833
+ shot ? `Der Shot ${shot.element_id} nennt kein target_model_id. Der Prompt wird generisch abgeleitet, ohne Modelloptimierung.` : "Ohne Shot gibt es kein target_model_id. Der Prompt wird generisch abgeleitet, ohne Modelloptimierung."
12834
+ );
12835
+ } else if (!resolver.resolveTargetModel) {
12247
12836
  throw new ResolveTechnicalError(
12248
12837
  `Der Resolver bietet keine Zielmodellsuche an (kein ContextChainPort). Ein Lauf ohne Kontextkette wuerde ein Zielmodell melden, das nicht das gesuchte ist.`
12249
12838
  );
12250
- }
12251
- const targetModel = await resolver.resolveTargetModel(key, shotVersion.element_id);
12252
- if (targetModel.kind !== "resolved") {
12253
- return {
12254
- kind: "rejected",
12255
- failure: {
12256
- class: "target_model_unresolvable",
12257
- message: describeTargetModelFailure(targetModel),
12258
- resolution: targetModel
12839
+ } else {
12840
+ const targetModel = await resolver.resolveTargetModel(key, shot.element_id);
12841
+ if (targetModel.kind !== "resolved") {
12842
+ ausgelassen(
12843
+ diagnostics,
12844
+ "P-17",
12845
+ "/prompt_render_settings/target_model_id",
12846
+ `${describeTargetModelFailure(targetModel)} Der Prompt wird generisch abgeleitet, ohne Modelloptimierung.`
12847
+ );
12848
+ } else {
12849
+ targetModelPayload = targetModel.payload;
12850
+ targetModelResolution = {
12851
+ element_id: targetModel.elementId,
12852
+ version_id: targetModel.versionId,
12853
+ chain_index: targetModel.chainIndex,
12854
+ head: targetModel.head,
12855
+ shadowed_retired: targetModel.shadowedRetired.map((entry) => ({
12856
+ element_id: entry.elementId,
12857
+ context_id: entry.contextId
12858
+ }))
12859
+ };
12860
+ for (const uebergangen of targetModel.shadowedRetired) {
12861
+ assumptions.push(
12862
+ `Ein stillgelegtes target_model (${uebergangen.elementId}, Kontext ${uebergangen.contextId ?? "global"}) wurde uebergangen; verwendet wird ${targetModel.elementId} von Kettenglied ${targetModel.chainIndex}.`
12863
+ );
12259
12864
  }
12260
- };
12261
- }
12262
- for (const uebergangen of targetModel.shadowedRetired) {
12263
- assumptions.push(
12264
- `Ein stillgelegtes target_model (${uebergangen.elementId}, Kontext ${uebergangen.contextId ?? "global"}) wurde uebergangen; verwendet wird ${targetModel.elementId} von Kettenglied ${targetModel.chainIndex}.`
12265
- );
12266
- }
12267
- if (targetModel.head.kind === "selected" && targetModel.head.stale) {
12268
- assumptions.push(
12269
- `Die Auswahl des Zielmodell-Heads (${targetModel.versionId}) ist veraltet \u2014 es gibt neuere Heads. Die Auswahl gilt, weil sie getroffen wurde (D-36).`
12270
- );
12865
+ if (targetModel.head.kind === "selected" && targetModel.head.stale) {
12866
+ assumptions.push(
12867
+ `Die Auswahl des Zielmodell-Heads (${targetModel.versionId}) ist veraltet \u2014 es gibt neuere Heads. Die Auswahl gilt, weil sie getroffen wurde (D-36).`
12868
+ );
12869
+ }
12870
+ }
12271
12871
  }
12272
12872
  const overrides = /* @__PURE__ */ new Map();
12273
- for (const entry of asArray2(setup.node_overrides)) {
12274
- if (isObject10(entry) && typeof entry.node_id === "string") overrides.set(entry.node_id, entry);
12873
+ for (const entry of setup ? asArray3(setup.payload.node_overrides) : []) {
12874
+ if (isObject11(entry) && typeof entry.node_id === "string") overrides.set(entry.node_id, entry);
12275
12875
  }
12276
12876
  const placements = /* @__PURE__ */ new Map();
12277
- for (const entry of asArray2(setup.placements)) {
12278
- if (!isObject10(entry) || typeof entry.node_id !== "string") continue;
12877
+ for (const entry of setup ? asArray3(setup.payload.placements) : []) {
12878
+ if (!isObject11(entry) || typeof entry.node_id !== "string") continue;
12279
12879
  placements.set(entry.node_id, {
12280
- position: asArray2(entry.position),
12281
- ...entry.rotation_euler_deg ? { rotation_euler_deg: asArray2(entry.rotation_euler_deg) } : {},
12282
- ...entry.scale ? { scale: asArray2(entry.scale) } : {}
12880
+ position: asArray3(entry.position),
12881
+ ...entry.rotation_euler_deg ? { rotation_euler_deg: asArray3(entry.rotation_euler_deg) } : {},
12882
+ ...entry.scale ? { scale: asArray3(entry.scale) } : {}
12283
12883
  });
12284
12884
  }
12285
- const shotOverrides = isObject10(shot.overrides) ? shot.overrides : {};
12286
- const hidden = new Set(asArray2(shotOverrides.hidden_nodes).filter((v) => typeof v === "string"));
12885
+ const hidden = new Set(
12886
+ asArray3(shotOverrides.hidden_nodes).filter((v) => typeof v === "string")
12887
+ );
12287
12888
  const nodes = [];
12288
- for (const raw of asArray2(scene.nodes)) {
12289
- if (!isObject10(raw) || typeof raw.node_id !== "string") continue;
12889
+ for (const raw of asArray3(scene.payload.nodes)) {
12890
+ if (!isObject11(raw) || typeof raw.node_id !== "string") continue;
12290
12891
  const nodeId = raw.node_id;
12291
12892
  const contributions = [];
12292
- for (const [i, ref] of asArray2(raw.component_refs).entries()) {
12893
+ for (const [i, ref] of asArray3(raw.component_refs).entries()) {
12293
12894
  const resolved = await refOf(
12294
12895
  resolver,
12295
12896
  ref,
12296
12897
  "scene_component",
12297
12898
  `/nodes/${nodeId}/component_refs/${i}`
12298
12899
  );
12299
- if (!resolved.ok) return { kind: "rejected", failure: resolved.failure };
12900
+ if (!resolved.ok) {
12901
+ ausgelassen(
12902
+ diagnostics,
12903
+ "P-05",
12904
+ `/nodes/${nodeId}/component_refs/${i}`,
12905
+ `${resolved.failure.message} Dieser Beitrag entfaellt; der Knoten bleibt mit seinen uebrigen Beitraegen im Prompt.`
12906
+ );
12907
+ continue;
12908
+ }
12300
12909
  const payload = resolved.version.payload;
12301
12910
  contributions.push({
12302
12911
  source: "component",
12303
12912
  element_id: resolved.version.element_id,
12304
12913
  version_id: resolved.version.version_id,
12305
- role: str(isObject10(ref) ? ref.role : null),
12306
- rank: num(isObject10(ref) ? ref.rank : null) ?? 0,
12914
+ role: str(isObject11(ref) ? ref.role : null),
12915
+ rank: num(isObject11(ref) ? ref.rank : null) ?? 0,
12307
12916
  locale: str(payload.locale),
12308
12917
  text: str(payload.text) ?? ""
12309
12918
  });
12310
12919
  }
12311
- const semantic = isObject10(raw.semantic) ? raw.semantic : null;
12920
+ const semantic = isObject11(raw.semantic) ? raw.semantic : null;
12312
12921
  if (semantic && str(semantic.description)) {
12313
12922
  contributions.push({
12314
12923
  source: "node_semantic",
@@ -12322,12 +12931,12 @@ async function resolveShotPayload(input) {
12322
12931
  });
12323
12932
  }
12324
12933
  const override = overrides.get(nodeId);
12325
- const overrideSemantic = override && isObject10(override.semantic) ? override.semantic : null;
12326
- if (overrideSemantic && str(overrideSemantic.description)) {
12934
+ const overrideSemantic = override && isObject11(override.semantic) ? override.semantic : null;
12935
+ if (overrideSemantic && str(overrideSemantic.description) && setup) {
12327
12936
  contributions.push({
12328
12937
  source: "setup_override",
12329
- element_id: setupRef.version.element_id,
12330
- version_id: setupRef.version.version_id,
12938
+ element_id: setup.element_id,
12939
+ version_id: setup.version_id,
12331
12940
  role: null,
12332
12941
  rank: Number.MAX_SAFE_INTEGER,
12333
12942
  locale: null,
@@ -12336,8 +12945,8 @@ async function resolveShotPayload(input) {
12336
12945
  }
12337
12946
  contributions.sort((a, b) => a.rank - b.rank);
12338
12947
  const properties = {
12339
- ...isObject10(semantic?.properties) ? semantic.properties : {},
12340
- ...isObject10(overrideSemantic?.properties) ? overrideSemantic.properties : {}
12948
+ ...isObject11(semantic?.properties) ? semantic.properties : {},
12949
+ ...isObject11(overrideSemantic?.properties) ? overrideSemantic.properties : {}
12341
12950
  };
12342
12951
  nodes.push({
12343
12952
  node_id: nodeId,
@@ -12348,9 +12957,6 @@ async function resolveShotPayload(input) {
12348
12957
  hidden: hidden.has(nodeId)
12349
12958
  });
12350
12959
  }
12351
- const cameraPlacement = canPlace ? camera.placement ?? null : entraeumlichtePlatzierung(camera.placement, assumptions);
12352
- const framing = shotOverrides.framing ?? camera.framing;
12353
- const focus = shotOverrides.focus !== void 0 ? shotOverrides.focus : camera.focus ?? null;
12354
12960
  const shotInstruction = str(settings.user_instruction);
12355
12961
  if (userInstruction && shotInstruction && userInstruction !== shotInstruction) {
12356
12962
  assumptions.push(
@@ -12364,56 +12970,37 @@ async function resolveShotPayload(input) {
12364
12970
  kind: "resolved",
12365
12971
  report,
12366
12972
  input: {
12367
- shot: {
12368
- version_id: shotVersion.version_id,
12369
- element_id: shotVersion.element_id,
12370
- camera_id: cameraId,
12973
+ shot: shot ? {
12974
+ version_id: shot.version_id,
12975
+ element_id: shot.element_id,
12976
+ camera_id: camera ? camera.camera_id : null,
12371
12977
  shot_concept: shotConcept,
12372
12978
  // Der Aufrufer darf die im Shot hinterlegte Anweisung ueberschreiben
12373
12979
  // (§4.1). Beide Herkuenfte sind unterschiedliche Sachverhalte, deshalb
12374
12980
  // wird der Fall in `assumptions` benannt statt still ersetzt.
12375
- user_instruction: userInstruction ?? str(settings.user_instruction),
12981
+ user_instruction: userInstruction ?? shotInstruction,
12376
12982
  text_override: str(shotOverrides.text)
12377
- },
12983
+ } : null,
12984
+ setup: setup ? { version_id: setup.version_id, element_id: setup.element_id } : null,
12378
12985
  scene: {
12379
- version_id: sceneRef.version.version_id,
12986
+ element_id: scene.element_id,
12987
+ version_id: scene.version_id,
12380
12988
  nodes,
12381
- relations: asArray2(scene.relations),
12382
- environment: scene.environment ?? null,
12383
- unit_system: scene.unit_system ?? null
12384
- },
12385
- camera: {
12386
- camera_id: cameraId,
12387
- name: str(camera.name),
12388
- preset: presetRef.version.payload,
12389
- placement: cameraPlacement,
12390
- orientation: camera.orientation ?? null,
12391
- framing: framing ?? null,
12392
- focus,
12393
- pattern
12989
+ relations: asArray3(scene.payload.relations),
12990
+ environment: scene.payload.environment ?? null,
12991
+ unit_system: scene.payload.unit_system ?? null
12394
12992
  },
12993
+ camera,
12395
12994
  styles,
12396
12995
  policies,
12397
12996
  fragments,
12398
- target_model: targetModel.payload,
12997
+ target_model: targetModelPayload,
12399
12998
  localization_notes: [],
12400
12999
  assumptions,
12401
- capabilities: {
12402
- can_describe_scene: report.can_describe_scene.state,
12403
- can_render_prompt: report.can_render_prompt.state,
12404
- can_place: report.can_place.state
12405
- },
13000
+ diagnostics,
13001
+ capabilities: eingefroreneFaehigkeiten,
12406
13002
  context_chain: [...contextChain],
12407
- target_model_resolution: {
12408
- element_id: targetModel.elementId,
12409
- version_id: targetModel.versionId,
12410
- chain_index: targetModel.chainIndex,
12411
- head: targetModel.head,
12412
- shadowed_retired: targetModel.shadowedRetired.map((entry) => ({
12413
- element_id: entry.elementId,
12414
- context_id: entry.contextId
12415
- }))
12416
- }
13003
+ target_model_resolution: targetModelResolution
12417
13004
  }
12418
13005
  };
12419
13006
  }
@@ -12585,9 +13172,117 @@ async function freezeDraftChain(input) {
12585
13172
  ...shot.chain.source_recovery_id ? { sourceRecoveryId: shot.chain.source_recovery_id } : {}
12586
13173
  };
12587
13174
  }
13175
+ function ladeSzene(sicht, elementId, contextChain) {
13176
+ const gelesen = sicht.getElement(elementId);
13177
+ if (gelesen.kind !== "ok") {
13178
+ return {
13179
+ fehler: gelesen.message ?? `Element ${elementId} konnte nicht gelesen werden.`,
13180
+ technisch: true
13181
+ };
13182
+ }
13183
+ const snapshot = gelesen.value;
13184
+ if (!snapshot) return { fehler: `Element ${elementId} ist unbekannt.` };
13185
+ if (snapshot.element.type !== "scene") {
13186
+ return {
13187
+ fehler: `Element ${elementId} ist vom Typ "${snapshot.element.type}", erwartet "scene".`
13188
+ };
13189
+ }
13190
+ if (snapshot.draftFork) {
13191
+ return {
13192
+ fehler: `Element ${elementId} hat parallele Entwuerfe. Solange sie nicht aufgeloest sind, gibt es keinen eindeutigen Arbeitsstand (D-29).`
13193
+ };
13194
+ }
13195
+ if (snapshot.draft) {
13196
+ return {
13197
+ element_id: elementId,
13198
+ draft_id: snapshot.draft.draft_id,
13199
+ revision: snapshot.draft.revision,
13200
+ version_id: null,
13201
+ payload: snapshot.draft.payload
13202
+ };
13203
+ }
13204
+ const versionen = snapshot.versions ?? [];
13205
+ if (versionen.length === 0) {
13206
+ return {
13207
+ fehler: `Element ${elementId} hat weder einen Entwurf noch eine veroeffentlichte Version. Es gibt nichts einzufrieren.`
13208
+ };
13209
+ }
13210
+ const kopf = effectivePreferredHeadSafe(
13211
+ { element: snapshot.element, versions: versionen, preferredHeads: snapshot.preferredHeads },
13212
+ contextChain
13213
+ );
13214
+ if (kopf.kind === "dag_fehler") {
13215
+ return { fehler: `Der Versionsgraph von Element ${elementId} ist nicht aufbaubar: ${kopf.message}` };
13216
+ }
13217
+ const versionId = usableHeadVersionId(resolutionOf(kopf));
13218
+ if (!versionId) {
13219
+ return {
13220
+ fehler: `Element ${elementId} hat mehrere veroeffentlichte Koepfe und in diesem Kontext keine Auswahl. Welcher Stand gilt, entscheidet keine Reihenfolge (D-36) \u2014 bitte einen bevorzugten Kopf setzen.`
13221
+ };
13222
+ }
13223
+ const version = versionen.find((v) => v.version_id === versionId);
13224
+ if (!version) {
13225
+ return {
13226
+ fehler: `Die wirksame Version ${versionId} von Element ${elementId} steht nicht in der gelesenen Momentaufnahme.`
13227
+ };
13228
+ }
13229
+ return {
13230
+ element_id: elementId,
13231
+ draft_id: null,
13232
+ revision: null,
13233
+ version_id: versionId,
13234
+ payload: version.payload
13235
+ };
13236
+ }
13237
+ async function freezeSceneWorkingState(input) {
13238
+ const { sceneElementId, store, resolver, contextChain, userInstruction } = input;
13239
+ const a = await store.readSnapshot({ fresh: false });
13240
+ const szene = ladeSzene(a, sceneElementId, contextChain);
13241
+ if ("fehler" in szene) return ausfallErgebnis(szene);
13242
+ const b = await store.readSnapshot({ fresh: true });
13243
+ const erneut = ladeSzene(b, sceneElementId, contextChain);
13244
+ if ("fehler" in erneut) return ausfallErgebnis(erneut);
13245
+ if (erneut.draft_id !== szene.draft_id || erneut.revision !== szene.revision || erneut.version_id !== szene.version_id) {
13246
+ return {
13247
+ kind: "conflict",
13248
+ message: `Der Arbeitsstand der Szene ${sceneElementId} hat sich waehrend des Einfrierens geaendert (erwartet ${szene.draft_id ? `Entwurf ${szene.draft_id}, Revision ${szene.revision}` : `Version ${szene.version_id}`}, vorhanden ${erneut.draft_id ? `Entwurf ${erneut.draft_id}, Revision ${erneut.revision}` : `Version ${erneut.version_id}`}). Es wurde kein Modell gerufen.`,
13249
+ node: { type: "scene", element_id: sceneElementId, draft_id: szene.draft_id ?? "" },
13250
+ expectedRevision: szene.revision ?? 0,
13251
+ actualRevision: erneut.revision ?? 0
13252
+ };
13253
+ }
13254
+ const aufgeloest = await resolveScenePayload({
13255
+ scenePayload: szene.payload,
13256
+ sceneElementId: szene.element_id,
13257
+ // Ein Entwurf hat keine Version — und bekommt hier auch keine erfundene
13258
+ // (D-98/D-75).
13259
+ sceneVersionId: szene.version_id ?? "",
13260
+ resolver,
13261
+ contextChain,
13262
+ userInstruction
13263
+ });
13264
+ if (aufgeloest.kind !== "resolved") {
13265
+ return {
13266
+ kind: "rejected",
13267
+ message: aufgeloest.failure.message,
13268
+ failure: aufgeloest.failure
13269
+ };
13270
+ }
13271
+ return {
13272
+ kind: "ok",
13273
+ scene: {
13274
+ element_id: szene.element_id,
13275
+ draft_id: szene.draft_id,
13276
+ revision: szene.revision,
13277
+ version_id: szene.version_id
13278
+ },
13279
+ input: aufgeloest.input
13280
+ };
13281
+ }
12588
13282
 
12589
13283
  // src/lib/szenen/promptRun.ts
12590
13284
  function buildSystemInstruction2(input) {
13285
+ const ohneZielmodell = input.target_model === null || input.target_model === void 0;
12591
13286
  const model = input.target_model ?? {};
12592
13287
  const sprache = typeof model.prompt_language === "string" ? model.prompt_language : "en";
12593
13288
  const negativ = model.supports_negative_prompt === true;
@@ -12608,7 +13303,11 @@ function buildSystemInstruction2(input) {
12608
13303
  "",
12609
13304
  `Der Prompt wird in der Sprache "${sprache}" formuliert.`
12610
13305
  ];
12611
- if (!negativ) {
13306
+ if (ohneZielmodell) {
13307
+ zeilen.push(
13308
+ 'Es ist KEIN Zielmodell angegeben. Formuliere einen generischen Prompt und richte ihn nicht an einer bestimmten Bildmodell-Syntax aus. "negative" bleibt null, weil kein Modell zugesagt hat, ein Negativfeld zu fuehren; was mit negativen Fragmenten geschehen ist, gehoert in "notes".'
13309
+ );
13310
+ } else if (!negativ) {
12612
13311
  zeilen.push(
12613
13312
  'Das Zielmodell kennt KEIN Negativ-Prompt-Feld. "negative" bleibt null; was mit negativen Fragmenten geschehen ist, gehoert in "notes".'
12614
13313
  );
@@ -12637,6 +13336,14 @@ function buildSystemInstruction2(input) {
12637
13336
  'Widersprechen sie einander, nenne den Widerspruch mit beiden Quellen in "notes" \u2014',
12638
13337
  "waehle nicht still eine Seite."
12639
13338
  );
13339
+ if (input.camera === null) {
13340
+ zeilen.push(
13341
+ "",
13342
+ "Es ist KEINE Kamera angegeben. Erfinde keine Brennweite, keinen Bildausschnitt",
13343
+ "und keine Kameraposition. Wo eine Kameraaussage noetig waere, formuliere sie",
13344
+ 'als Annahme und nenne sie in "notes".'
13345
+ );
13346
+ }
12640
13347
  if (input.capabilities.can_place !== "yes") {
12641
13348
  zeilen.push(
12642
13349
  "",
@@ -12650,7 +13357,7 @@ function buildSystemInstruction2(input) {
12650
13357
  function buildUserPrompt2(input) {
12651
13358
  return JSON.stringify(input, null, 2);
12652
13359
  }
12653
- var isObject11 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
13360
+ var isObject12 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
12654
13361
  function parseRunResponse(raw) {
12655
13362
  const text = raw.trim().replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/, "").trim();
12656
13363
  if (text.length === 0) return { ok: false, message: "Die Antwort war leer." };
@@ -12664,7 +13371,7 @@ function parseRunResponse(raw) {
12664
13371
  }
12665
13372
  }
12666
13373
  function checkRunResponse(value, input) {
12667
- if (!isObject11(value)) {
13374
+ if (!isObject12(value)) {
12668
13375
  return { ok: false, message: `Die Antwort ist kein Objekt, sondern ${Array.isArray(value) ? "array" : typeof value}.` };
12669
13376
  }
12670
13377
  if (typeof value.positive !== "string" || value.positive.trim().length === 0) {
@@ -12682,11 +13389,11 @@ function checkRunResponse(value, input) {
12682
13389
  if (negative !== null && !negativErlaubt) {
12683
13390
  return {
12684
13391
  ok: false,
12685
- message: `Das Zielmodell fuehrt kein Negativ-Prompt-Feld (supports_negative_prompt = false), die Antwort liefert aber eines.`
13392
+ message: input.target_model ? `Das Zielmodell fuehrt kein Negativ-Prompt-Feld (supports_negative_prompt = false), die Antwort liefert aber eines.` : `Dieser Lauf hat kein Zielmodell (generische Ableitung); ein Negativ-Prompt-Feld ist damit nicht zugesagt, die Antwort liefert aber eines.`
12686
13393
  };
12687
13394
  }
12688
13395
  const visibility = value.visibility;
12689
- if (!isObject11(visibility)) {
13396
+ if (!isObject12(visibility)) {
12690
13397
  return { ok: false, message: '"visibility" fehlt \u2014 die Pflichtdiagnosen aus D-21.' };
12691
13398
  }
12692
13399
  if (typeof visibility.basis !== "string") {
@@ -12698,7 +13405,7 @@ function checkRunResponse(value, input) {
12698
13405
  const genannt = /* @__PURE__ */ new Set();
12699
13406
  const nodes = [];
12700
13407
  for (const eintrag of visibility.nodes) {
12701
- if (!isObject11(eintrag) || typeof eintrag.node_id !== "string" || typeof eintrag.state !== "string") {
13408
+ if (!isObject12(eintrag) || typeof eintrag.node_id !== "string" || typeof eintrag.state !== "string") {
12702
13409
  return { ok: false, message: 'Ein Eintrag in "visibility.nodes" hat keine node_id oder keinen state.' };
12703
13410
  }
12704
13411
  genannt.add(eintrag.node_id);
@@ -12843,6 +13550,23 @@ function createEventLogRunPersistence(channel) {
12843
13550
  return queryError(error, `Laeufe der Kette ${chainId} konnten nicht gelesen werden`);
12844
13551
  }
12845
13552
  },
13553
+ async listForScene(sceneElementId) {
13554
+ try {
13555
+ const events = await channel.readEvents();
13556
+ return {
13557
+ kind: "ok",
13558
+ value: collectPromptRuns(events).filter((run) => {
13559
+ const quelle = sourceOf(run);
13560
+ return quelle.kind === "scene_direct" && quelle.scene.element_id === sceneElementId;
13561
+ })
13562
+ };
13563
+ } catch (error) {
13564
+ return queryError(
13565
+ error,
13566
+ `Laeufe der Szene ${sceneElementId} konnten nicht gelesen werden`
13567
+ );
13568
+ }
13569
+ },
12846
13570
  async record(record) {
12847
13571
  try {
12848
13572
  await channel.appendEvent(SZENEN_EVENT_TYPES.promptRunRecorded, record);
@@ -12929,13 +13653,21 @@ function createClientRunPort(options) {
12929
13653
  return { kind: "error", message: resolved.failure.message, retryable: false };
12930
13654
  }
12931
13655
  const outcome = await runPromptDerivation(resolved.input, text);
13656
+ if (!resolved.input.shot) {
13657
+ return {
13658
+ kind: "error",
13659
+ message: `Die Aufloesung der Shot-Version ${input.shotVersionId} lieferte eine Eingabe ohne Shot. Das ist ein Programmfehler, kein Lauf.`,
13660
+ retryable: false
13661
+ };
13662
+ }
12932
13663
  const record = {
12933
13664
  run_id: newRunId(),
12934
13665
  shot_version_id: input.shotVersionId,
12935
13666
  shot_element_id: resolved.input.shot.element_id,
12936
13667
  scene_setup_version_id: resolved.input.scene.version_id,
12937
- camera_id: resolved.input.shot.camera_id,
12938
- target_model_version_id: resolved.input.target_model_resolution.version_id,
13668
+ // Leer heisst „kein Wert", nicht „Wert unbekannt" (D-75/D-135).
13669
+ camera_id: resolved.input.shot.camera_id ?? "",
13670
+ target_model_version_id: resolved.input.target_model_resolution?.version_id ?? "",
12939
13671
  provider: outcome.provider,
12940
13672
  model_id: outcome.model_id,
12941
13673
  system_prompt: outcome.system_prompt,
@@ -13007,8 +13739,8 @@ function createClientRunPort(options) {
13007
13739
  shot_version_id: "",
13008
13740
  shot_element_id: input.shotElementId,
13009
13741
  scene_setup_version_id: "",
13010
- camera_id: eingefroren.input.shot.camera_id,
13011
- target_model_version_id: eingefroren.input.target_model_resolution.version_id,
13742
+ camera_id: eingefroren.input.shot?.camera_id ?? "",
13743
+ target_model_version_id: eingefroren.input.target_model_resolution?.version_id ?? "",
13012
13744
  provider: outcome.provider,
13013
13745
  model_id: outcome.model_id,
13014
13746
  system_prompt: outcome.system_prompt,
@@ -13042,6 +13774,95 @@ function createClientRunPort(options) {
13042
13774
  async listRunsForChain(chainId) {
13043
13775
  const alle = await runs.listForChain(chainId);
13044
13776
  return alle;
13777
+ },
13778
+ // ── Der Lauf direkt aus einer Szene (D-135) ───────────────────────────
13779
+ //
13780
+ // Bewusst **derselbe** Ablauf wie oben: Kontext ermitteln, Kette
13781
+ // aufloesen, einfrieren, dann erst rufen. Was sich unterscheidet, ist
13782
+ // ausschliesslich, **was** eingefroren wird — ein Szenen-Arbeitsstand
13783
+ // statt einer Drei-Knoten-Kette.
13784
+ async startRunFromScene(input) {
13785
+ try {
13786
+ let contextId = input.contextId;
13787
+ if (contextId === void 0) {
13788
+ const element = await elements.getElement(input.sceneElementId);
13789
+ if (element.kind !== "ok") {
13790
+ return { kind: "error", message: element.message, retryable: element.retryable };
13791
+ }
13792
+ if (element.value === null) {
13793
+ return {
13794
+ kind: "error",
13795
+ message: `Element ${input.sceneElementId} ist unbekannt.`,
13796
+ retryable: false
13797
+ };
13798
+ }
13799
+ contextId = element.value.element.context_id;
13800
+ }
13801
+ const chain = await context.chainFor(contextId ?? null);
13802
+ if (chain.kind !== "ok") {
13803
+ return { kind: "error", message: chain.message, retryable: chain.retryable };
13804
+ }
13805
+ const eingefroren = await freezeSceneWorkingState({
13806
+ sceneElementId: input.sceneElementId,
13807
+ store: elements,
13808
+ resolver,
13809
+ contextChain: chain.value,
13810
+ userInstruction: input.userInstruction ?? null
13811
+ });
13812
+ if (eingefroren.kind === "conflict") {
13813
+ return {
13814
+ kind: "conflict",
13815
+ message: eingefroren.message,
13816
+ node: eingefroren.node,
13817
+ expectedRevision: eingefroren.expectedRevision,
13818
+ actualRevision: eingefroren.actualRevision
13819
+ };
13820
+ }
13821
+ if (eingefroren.kind === "error") {
13822
+ return { kind: "error", message: eingefroren.message, retryable: eingefroren.retryable };
13823
+ }
13824
+ if (eingefroren.kind !== "ok") {
13825
+ return { kind: "rejected", message: eingefroren.message };
13826
+ }
13827
+ const outcome = await runPromptDerivation(eingefroren.input, text);
13828
+ const record = {
13829
+ run_id: newRunId(),
13830
+ // Keine fingierten Kennungen (D-98/D-75). Was es nicht gibt, bleibt
13831
+ // leer — die Herkunft steht in `source`.
13832
+ shot_version_id: "",
13833
+ shot_element_id: "",
13834
+ scene_setup_version_id: "",
13835
+ camera_id: "",
13836
+ target_model_version_id: eingefroren.input.target_model_resolution?.version_id ?? "",
13837
+ provider: outcome.provider,
13838
+ model_id: outcome.model_id,
13839
+ system_prompt: outcome.system_prompt,
13840
+ input_payload: eingefroren.input,
13841
+ status: outcome.status,
13842
+ failure: outcome.status === "failed" ? outcome.failure : null,
13843
+ output: outcome.status === "succeeded" ? outcome.output : null,
13844
+ raw_output: outcome.raw_output,
13845
+ source: { kind: "scene_direct", scene: eingefroren.scene },
13846
+ created_at: now().toISOString()
13847
+ };
13848
+ return await runs.record(record);
13849
+ } catch (error) {
13850
+ return {
13851
+ kind: "error",
13852
+ message: `Prompt-Lauf aus der Szene ${input.sceneElementId} ist fehlgeschlagen: ${error instanceof Error ? error.message : String(error)}`,
13853
+ retryable: true
13854
+ };
13855
+ }
13856
+ },
13857
+ async listRunsForScene(sceneElementId) {
13858
+ try {
13859
+ return await runs.listForScene(sceneElementId);
13860
+ } catch (error) {
13861
+ return queryError(
13862
+ error,
13863
+ `Laeufe der Szene ${sceneElementId} konnten nicht gelesen werden`
13864
+ );
13865
+ }
13045
13866
  }
13046
13867
  };
13047
13868
  }
@@ -13346,7 +14167,7 @@ function createFlowImageProvider(generateImage) {
13346
14167
  }
13347
14168
 
13348
14169
  // src/lib/szenen/imageGenerationOrderStore.ts
13349
- function istText4(wert) {
14170
+ function istText5(wert) {
13350
14171
  return typeof wert === "string" && wert.trim().length > 0;
13351
14172
  }
13352
14173
  function collectImageGenerationOrders(events) {
@@ -13354,7 +14175,7 @@ function collectImageGenerationOrders(events) {
13354
14175
  for (const event of events) {
13355
14176
  if (event.type !== SZENEN_EVENT_TYPES.imageGenerationStarted) continue;
13356
14177
  const payload = event.payload;
13357
- if (!payload || !istText4(payload.generation_batch_id) || !istText4(payload.prompt_run_id)) continue;
14178
+ if (!payload || !istText5(payload.generation_batch_id) || !istText5(payload.prompt_run_id)) continue;
13358
14179
  if (byBatchId.has(payload.generation_batch_id)) continue;
13359
14180
  byBatchId.set(payload.generation_batch_id, {
13360
14181
  generation_batch_id: payload.generation_batch_id,
@@ -13368,7 +14189,7 @@ function collectImageGenerationOrders(events) {
13368
14189
  for (const event of events) {
13369
14190
  if (event.type !== SZENEN_EVENT_TYPES.imageGenerationFinished) continue;
13370
14191
  const payload = event.payload;
13371
- if (!payload || !istText4(payload.generation_batch_id)) continue;
14192
+ if (!payload || !istText5(payload.generation_batch_id)) continue;
13372
14193
  const auftrag = byBatchId.get(payload.generation_batch_id);
13373
14194
  if (!auftrag) continue;
13374
14195
  if (auftrag.status !== "started") continue;
@@ -13392,18 +14213,18 @@ function findImageGenerationOrder(events, batchId) {
13392
14213
  }
13393
14214
 
13394
14215
  // src/lib/szenen/imageBatchStore.ts
13395
- var istText5 = (wert) => typeof wert === "string" && wert.trim().length > 0;
14216
+ var istText6 = (wert) => typeof wert === "string" && wert.trim().length > 0;
13396
14217
  function alsBilder(rohe) {
13397
14218
  if (!Array.isArray(rohe)) return [];
13398
- return rohe.filter((b) => !!b && typeof b === "object").filter((b) => istText5(b.media_ref) && typeof b.position === "number").map((b) => ({
14219
+ return rohe.filter((b) => !!b && typeof b === "object").filter((b) => istText6(b.media_ref) && typeof b.position === "number").map((b) => ({
13399
14220
  media_ref: b.media_ref,
13400
14221
  position: b.position,
13401
- ...istText5(b.asset_id) ? { asset_id: b.asset_id } : {},
14222
+ ...istText6(b.asset_id) ? { asset_id: b.asset_id } : {},
13402
14223
  // Der bestätigte MIME-Typ (Review 2026-08-18 §5 P2) muss durch das
13403
14224
  // Rücklesen hindurch: Genau hier braucht ihn der Lesepfad, um den
13404
14225
  // Dateipfad `images/<id>.<ext>` zu bilden, statt ihn zu erraten. Nur
13405
14226
  // gesetzt, wenn er im Ereignis steht — ältere Batches tragen ihn nicht.
13406
- ...istText5(b.mime_type) ? { mime_type: b.mime_type } : {},
14227
+ ...istText6(b.mime_type) ? { mime_type: b.mime_type } : {},
13407
14228
  model: b.model ?? null,
13408
14229
  seed: b.seed ?? null,
13409
14230
  width: b.width ?? null,
@@ -13415,7 +14236,7 @@ function collectImageBatches(events) {
13415
14236
  for (const event of events) {
13416
14237
  if (event.type !== SZENEN_EVENT_TYPES.imageBatchPersisted) continue;
13417
14238
  const payload = event.payload;
13418
- if (!payload || !istText5(payload.item_id) || !istText5(payload.prompt_run_id) || !istText5(payload.generation_batch_id)) continue;
14239
+ if (!payload || !istText6(payload.item_id) || !istText6(payload.prompt_run_id) || !istText6(payload.generation_batch_id)) continue;
13419
14240
  if (payload.source_kind !== "generated_in_app" && payload.source_kind !== "external_import") continue;
13420
14241
  const bestehend = byItemId.get(payload.item_id);
13421
14242
  if (bestehend?.generation_batch_ids.includes(payload.generation_batch_id)) continue;
@@ -13426,7 +14247,7 @@ function collectImageBatches(events) {
13426
14247
  prompt_run_id: payload.prompt_run_id,
13427
14248
  generation_batch_ids: [payload.generation_batch_id],
13428
14249
  source_kind: payload.source_kind,
13429
- title: istText5(payload.title) ? payload.title : `Batch aus Lauf ${payload.prompt_run_id}`,
14250
+ title: istText6(payload.title) ? payload.title : `Batch aus Lauf ${payload.prompt_run_id}`,
13430
14251
  images: bilder
13431
14252
  });
13432
14253
  continue;
@@ -13903,7 +14724,7 @@ function createFlowSzenenViewPort(options) {
13903
14724
  ...options.now ? { now: options.now } : {}
13904
14725
  }) : void 0;
13905
14726
  const bildProvider = options.imageProvider ?? (options.generateImage ? createFlowImageProvider(options.generateImage) : void 0);
13906
- const bildFaehigkeit = options.imageCapability ?? { environment_id: "flow", execution_paths: [FLOW_EXECUTION_PATH] };
14727
+ const bildFaehigkeit = options.imageCapability ?? { environment_id: "flow", execution_paths: [{ execution_path: FLOW_EXECUTION_PATH, provider: "google" }] };
13907
14728
  const imageGeneration = bildProvider && imageBatchWrite ? createImageGenerationPort({
13908
14729
  runs: { async getRun(runId) {
13909
14730
  return runs.getRun(runId);
@@ -13946,9 +14767,6 @@ export {
13946
14767
  capabilitiesOf,
13947
14768
  unsupportedReason,
13948
14769
  callOptional,
13949
- areasFor,
13950
- resolveArea,
13951
- noticeFor,
13952
14770
  UnsupportedSchemaError,
13953
14771
  compileSchemas,
13954
14772
  validateAgainst,
@@ -13959,8 +14777,12 @@ export {
13959
14777
  validateElementVersion,
13960
14778
  validatePayload,
13961
14779
  formatSchemaErrors,
14780
+ areasFor,
14781
+ resolveArea,
14782
+ noticeFor,
13962
14783
  selectableTargetModels,
13963
14784
  checkImageExecutionProfile,
14785
+ checkImageExecutionProfiles,
13964
14786
  executableImageModels,
13965
14787
  findExecutableImageModel,
13966
14788
  checkImageModelParameters,
@@ -13970,12 +14792,19 @@ export {
13970
14792
  describeTargetModelFailure,
13971
14793
  ALL_PUBLISH_RULES,
13972
14794
  runPublishChecks,
14795
+ PROMPT_RULE_EFFECT,
14796
+ rulesWithoutPromptEffect,
14797
+ diagnosticOfFinding,
14798
+ diagnosticOfSchemaError,
14799
+ promptDiagnosticsOf,
14800
+ describableContent,
13973
14801
  CapabilityAnchorError,
13974
14802
  RULE_SCOPES,
13975
14803
  RULES_WITHOUT_CAPABILITY_EFFECT,
13976
14804
  scopeOfPath,
13977
14805
  capabilityReport,
13978
14806
  unclassifiedPublishRules,
14807
+ sceneOnlyCapabilities,
13979
14808
  resolverFromQueries,
13980
14809
  isProjectionCurrent,
13981
14810
  isOk,
@@ -14053,8 +14882,10 @@ export {
14053
14882
  ResolveTechnicalError,
14054
14883
  resolveShot,
14055
14884
  resolveShotPayload,
14885
+ resolveScenePayload,
14056
14886
  capabilityGate,
14057
14887
  freezeDraftChain,
14888
+ freezeSceneWorkingState,
14058
14889
  buildSystemInstruction2,
14059
14890
  buildUserPrompt2,
14060
14891
  parseRunResponse,