@rslsp1/fa-app-tools 7.4.0 → 9.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.
@@ -443,7 +443,10 @@ function capabilitiesOf(port) {
443
443
  imageOrderHistory: typeof port.imageBatchHistory?.listOrdersForPromptRun === "function",
444
444
  imageBatchWrite: typeof port.imageBatchWrite?.importBatch === "function",
445
445
  imageGeneration: typeof port.imageGeneration?.startFromPromptRun === "function",
446
- imageJobs: typeof port.imageJobs?.claimAndRun === "function"
446
+ imageJobs: typeof port.imageJobs?.claimAndRun === "function",
447
+ // P1-A: die herkunftsuebergreifende Prompt-Sicht. Ein Host ohne sie
448
+ // verliert nur diesen Bereich — nicht die drei bestehenden Einstiege.
449
+ promptOverview: typeof port.runs.listAllRuns === "function"
447
450
  };
448
451
  }
449
452
  function unsupportedReason(capability) {
@@ -3530,37 +3533,52 @@ function formatSchemaErrors(errors) {
3530
3533
  }
3531
3534
 
3532
3535
  // src/features/szenen/szenenViewModel.ts
3533
- var KEINE_BAUSTEINE = [
3534
- "scene",
3536
+ var BAUSTEIN_TYPES = [
3537
+ "scene_component",
3538
+ "style",
3539
+ "shot_concept",
3540
+ "prompt_fragment",
3541
+ "prompt_policy"
3542
+ ];
3543
+ var ERWEITERT_REIHENFOLGE = [
3535
3544
  "scene_setup",
3536
- "shot"
3545
+ "shot",
3546
+ "camera_preset",
3547
+ "camera_pattern",
3548
+ "target_model",
3549
+ "scene_derivation_policy",
3550
+ "sequence"
3537
3551
  ];
3538
- var BAUSTEIN_TYPES = SZENEN_ELEMENT_TYPES.filter((typ) => !KEINE_BAUSTEINE.includes(typ));
3552
+ var ERWEITERT_TYPES = (() => {
3553
+ const gehoertHierher = (typ) => typ !== "scene" && !BAUSTEIN_TYPES.includes(typ);
3554
+ const bekannt = ERWEITERT_REIHENFOLGE.filter(
3555
+ (typ) => SZENEN_ELEMENT_TYPES.includes(typ) && gehoertHierher(typ)
3556
+ );
3557
+ const rest = SZENEN_ELEMENT_TYPES.filter(
3558
+ (typ) => gehoertHierher(typ) && !bekannt.includes(typ)
3559
+ );
3560
+ return [...bekannt, ...rest];
3561
+ })();
3539
3562
  var ALLE_BEREICHE = [
3540
3563
  {
3541
- id: "derive",
3542
- title: "0 \xB7 Rekonstruktion",
3543
- description: "Aus einem Bild oder Prompt einen Szenenentwurf vorschlagen lassen."
3544
- },
3545
- {
3546
- id: "elements",
3547
- title: "1 \xB7 Bausteine",
3548
- description: "Figuren, Orte, Stile und Regeln f\xFCr sp\xE4tere Bildprompts pflegen."
3564
+ id: "scene",
3565
+ title: "Szenen",
3566
+ description: "Szenen anlegen, aus Bild oder Text ableiten und daraus Prompts starten."
3549
3567
  },
3550
3568
  {
3551
- id: "scene",
3552
- title: "2 \xB7 Szene",
3553
- description: "Aus Bausteinen eine konkrete Szene und ihre Beziehungen bauen."
3569
+ id: "prompts",
3570
+ title: "Prompts",
3571
+ description: "Alle erzeugten Prompts mit ihren Bildern \u2014 unabhaengig davon, ueber welchen Weg sie entstanden sind."
3554
3572
  },
3555
3573
  {
3556
- id: "setup",
3557
- title: "3 \xB7 Bildaufbau",
3558
- description: "Stil, Komposition und Kamera f\xFCr das sp\xE4tere Bild festlegen."
3574
+ id: "elements",
3575
+ title: "Bausteine",
3576
+ description: "Figuren, Orte, Stile, Prompt-Bausteine und Prompt-Regeln pflegen."
3559
3577
  },
3560
3578
  {
3561
- id: "shot",
3562
- title: "4 \xB7 Prompt",
3563
- description: "Bildprompt erzeugen, Varianten vergleichen und als Item speichern."
3579
+ id: "advanced",
3580
+ title: "Erweitert",
3581
+ description: "Optionale Pr\xE4zisierung: Bildaufbau, Shot, Kameras, Zielmodelle, Regeln, Sequenzen."
3564
3582
  },
3565
3583
  {
3566
3584
  id: "media",
@@ -3570,16 +3588,12 @@ var ALLE_BEREICHE = [
3570
3588
  ];
3571
3589
  function areasFor(port) {
3572
3590
  const faehig = capabilitiesOf(port);
3573
- return ALLE_BEREICHE.filter((bereich) => {
3574
- if (bereich.id === "media") return faehig.media;
3575
- if (bereich.id === "derive") return faehig.derivation;
3576
- return true;
3577
- });
3591
+ return ALLE_BEREICHE.filter((bereich) => bereich.id !== "media" || faehig.media);
3578
3592
  }
3579
3593
  function resolveArea(port, gewuenscht) {
3580
3594
  const verfuegbar = areasFor(port);
3581
3595
  if (gewuenscht && verfuegbar.some((b) => b.id === gewuenscht)) return gewuenscht;
3582
- return verfuegbar.find((b) => b.id === "elements")?.id ?? verfuegbar[0].id;
3596
+ return verfuegbar.find((b) => b.id === "scene")?.id ?? verfuegbar[0].id;
3583
3597
  }
3584
3598
  function noticeFor(ergebnis, was) {
3585
3599
  switch (ergebnis.kind) {
@@ -5104,158 +5118,6 @@ function resolverFromQueries(queries, contexts) {
5104
5118
  var isProjectionCurrent = (state) => state.status === "current";
5105
5119
  var isOk = (result) => result.kind === "ok";
5106
5120
 
5107
- // src/lib/szenen/itemDerivation.ts
5108
- var SZENEN_ITEM_PREFIX = "szn-";
5109
- function itemIdForRun(runId) {
5110
- return `${SZENEN_ITEM_PREFIX}${runId}`;
5111
- }
5112
- function isSzenenItemId(itemId) {
5113
- return itemId.startsWith(SZENEN_ITEM_PREFIX);
5114
- }
5115
- function checkSzenenBatchOrigin(candidate) {
5116
- if (!istText3(candidate.prompt_run_id)) {
5117
- return {
5118
- kind: "rejected",
5119
- failure: { field: "prompt_run_id", message: '"prompt_run_id" fehlt oder ist leer.' }
5120
- };
5121
- }
5122
- if (!istText3(candidate.generation_batch_id)) {
5123
- return {
5124
- kind: "rejected",
5125
- failure: {
5126
- field: "generation_batch_id",
5127
- message: '"generation_batch_id" fehlt oder ist leer.'
5128
- }
5129
- };
5130
- }
5131
- if (candidate.source_kind !== "generated_in_app" && candidate.source_kind !== "external_import") {
5132
- return {
5133
- kind: "rejected",
5134
- failure: {
5135
- field: "source_kind",
5136
- message: `"source_kind" ist unbekannt: ${JSON.stringify(candidate.source_kind)}. Erlaubt: generated_in_app, external_import.`
5137
- }
5138
- };
5139
- }
5140
- const round = typeof candidate.round === "number" && Number.isInteger(candidate.round) ? candidate.round : void 0;
5141
- return {
5142
- kind: "ok",
5143
- value: {
5144
- prompt_run_id: candidate.prompt_run_id,
5145
- generation_batch_ids: [candidate.generation_batch_id],
5146
- source_kind: candidate.source_kind,
5147
- ...round !== void 0 ? { round } : {}
5148
- }
5149
- };
5150
- }
5151
- function mergeSzenenBatchOrigin(bestehend, neu) {
5152
- if (!bestehend) return neu;
5153
- const ids = [...bestehend.generation_batch_ids];
5154
- for (const id of neu.generation_batch_ids) {
5155
- if (!ids.includes(id)) ids.push(id);
5156
- }
5157
- return {
5158
- prompt_run_id: bestehend.prompt_run_id,
5159
- generation_batch_ids: ids,
5160
- source_kind: bestehend.source_kind,
5161
- ...bestehend.round !== void 0 ? { round: bestehend.round } : {}
5162
- };
5163
- }
5164
- var DEFAULT_FSK_LEVEL = "FSK16";
5165
- var istText3 = (v) => typeof v === "string" && v.trim().length > 0;
5166
- function roundOfRun(run, runsOfShot) {
5167
- return runsOfShot.findIndex((kandidat) => kandidat.run_id === run.run_id) + 1;
5168
- }
5169
- function deriveLineage(ownItemId, ownRound, existingItems) {
5170
- const kandidaten = existingItems.filter((item) => item.valid && item.item_id !== ownItemId).sort((a, b) => a.sequence - b.sequence);
5171
- const elternteil = kandidaten[kandidaten.length - 1];
5172
- if (!elternteil) {
5173
- return {
5174
- parent_item_id: null,
5175
- lineage_root_id: ownItemId,
5176
- generation: 0,
5177
- out_of_order: false
5178
- };
5179
- }
5180
- return {
5181
- parent_item_id: elternteil.item_id,
5182
- lineage_root_id: elternteil.lineage_root_id,
5183
- generation: elternteil.generation + 1,
5184
- // Der Elternteil kommt aus einer spaeteren Runde: rueckwaerts gespeichert.
5185
- // Kein Fehler, aber nichts, was stillschweigend passieren darf.
5186
- out_of_order: elternteil.round >= ownRound
5187
- };
5188
- }
5189
- function deriveItemFromRun(input) {
5190
- const { run, runsOfShot, existingItems, savedAt } = input;
5191
- if (run.status === "failed") {
5192
- return {
5193
- kind: "rejected",
5194
- failure: {
5195
- class: "run_failed",
5196
- message: `Der Lauf ${run.run_id} ist gescheitert (${run.failure ? run.failure.class : "unbekannt"}) und traegt keinen Prompt. Aus einem Fehlerlauf entsteht kein Item.`,
5197
- run_failure: run.failure
5198
- }
5199
- };
5200
- }
5201
- if (!run.output || !istText3(run.output.positive)) {
5202
- return {
5203
- kind: "rejected",
5204
- failure: {
5205
- class: "run_without_output",
5206
- message: `Der Lauf ${run.run_id} ist als erfolgreich protokolliert, traegt aber keinen positiven Prompt. Das ist ein Datenfehler im Lauf, kein Item.`
5207
- }
5208
- };
5209
- }
5210
- const round = roundOfRun(run, runsOfShot);
5211
- if (round === 0) {
5212
- return {
5213
- kind: "rejected",
5214
- failure: {
5215
- class: "run_not_among_siblings",
5216
- message: `Der Lauf ${run.run_id} ist unter den ${runsOfShot.length} Laeufen des Shots ${run.shot_version_id} nicht enthalten. Ohne seinen Platz gaebe es keine Rundennummer.`
5217
- }
5218
- };
5219
- }
5220
- const item_id = itemIdForRun(run.run_id);
5221
- const lineage = deriveLineage(item_id, round, existingItems);
5222
- const negative = istText3(run.output.negative) ? run.output.negative : null;
5223
- const title = istText3(input.title) ? input.title : istText3(input.shotTitle) ? `${input.shotTitle} \xB7 Runde ${round}` : `Szenen-Lauf ${round}`;
5224
- return {
5225
- kind: "ok",
5226
- value: {
5227
- item_id,
5228
- title,
5229
- content: run.output.positive,
5230
- negative_prompt: negative,
5231
- // `feedback` ist Pflicht (D-55) und ist genau die Erlaeuterung fuer den
5232
- // Menschen — also gehoert sie in das Feld fuer Notizen.
5233
- notes: istText3(input.notes) ? input.notes : run.output.feedback,
5234
- rating: typeof input.rating === "number" ? input.rating : 0,
5235
- fsk_level: istText3(input.fskLevel) ? input.fskLevel : DEFAULT_FSK_LEVEL,
5236
- tags: [],
5237
- szenen: {
5238
- prompt_run_id: run.run_id,
5239
- shot_version_id: run.shot_version_id,
5240
- shot_element_id: run.shot_element_id,
5241
- scene_setup_version_id: run.scene_setup_version_id,
5242
- camera_id: run.camera_id,
5243
- target_model_version_id: run.target_model_version_id,
5244
- provider: run.provider,
5245
- model_id: run.model_id,
5246
- run_created_at: run.created_at,
5247
- round,
5248
- created_from_draft_id: null,
5249
- saved_at: savedAt
5250
- },
5251
- lineage,
5252
- // Bestandsformat: `LibraryTab` baut den Baum aus `metadata.relationships`.
5253
- // Ein Szenen-Item ohne diese Kante waere im Baum unsichtbar.
5254
- relationships: lineage.parent_item_id ? [{ type: "parent", id: lineage.parent_item_id, role: "source_A" }] : []
5255
- }
5256
- };
5257
- }
5258
-
5259
5121
  // src/lib/szenen/elementEvents.ts
5260
5122
  var SZENEN_EVENT_PREFIX = "szenen.";
5261
5123
  var SZENEN_EVENT_TYPES = {
@@ -5694,84 +5556,321 @@ function collectPromptRuns(events) {
5694
5556
  function findPromptRun(events, runId) {
5695
5557
  return collectPromptRuns(events).find((run) => run.run_id === runId) ?? null;
5696
5558
  }
5697
-
5698
- // src/lib/szenen/seedListe.ts
5699
- var DEFAULT_SEED_VORLAGE = {
5700
- name: "Default",
5701
- seeds: "1; 10; 100; 1000",
5702
- builtin: true
5703
- };
5704
- function parseSeedListe(eingabe) {
5705
- if (!eingabe) return [];
5706
- return eingabe.split(/[,;]/).map((teil) => teil.trim()).filter((teil) => teil.length > 0);
5707
- }
5708
- function formatSeedListe(tokens) {
5709
- return tokens.join("; ");
5559
+ var istKennung = (wert) => typeof wert === "string" && wert.trim().length > 0;
5560
+ function groupOf(run) {
5561
+ const quelle = sourceOf(run);
5562
+ if (quelle.kind === "published") {
5563
+ return istKennung(quelle.shot_version_id) ? {
5564
+ kind: "published",
5565
+ key: `published:${quelle.shot_version_id}`,
5566
+ shot_version_id: quelle.shot_version_id
5567
+ } : {
5568
+ kind: "unresolved",
5569
+ key: `run:${run.run_id}`,
5570
+ reason: `Der Lauf ${run.run_id} gilt als ver\xF6ffentlichte Herkunft, tr\xE4gt aber keine shot_version_id. Er steht deshalb f\xFCr sich; eine Zuordnung w\xE4re geraten.`
5571
+ };
5572
+ }
5573
+ if (quelle.kind === "draft_chain") {
5574
+ return istKennung(quelle.chain_id) ? { kind: "draft_chain", key: `chain:${quelle.chain_id}`, chain_id: quelle.chain_id } : {
5575
+ kind: "unresolved",
5576
+ key: `run:${run.run_id}`,
5577
+ reason: `Der Lauf ${run.run_id} stammt aus einer Draft-Kette ohne chain_id. Er steht deshalb f\xFCr sich; eine Zuordnung w\xE4re geraten.`
5578
+ };
5579
+ }
5580
+ const elementId = quelle.scene?.element_id;
5581
+ return istKennung(elementId) ? { kind: "scene_direct", key: `scene:${elementId}`, scene_element_id: elementId } : {
5582
+ kind: "unresolved",
5583
+ key: `run:${run.run_id}`,
5584
+ reason: `Der Lauf ${run.run_id} entstand direkt aus einer Szene, nennt aber kein Szenen-Element. Er steht deshalb f\xFCr sich; eine Zuordnung w\xE4re geraten.`
5585
+ };
5710
5586
  }
5711
- var GANZZAHL = /^-?\d+$/;
5712
- function ordneSeedsZu(eingabe, anzahl) {
5713
- const tokens = Array.isArray(eingabe) ? [...eingabe] : parseSeedListe(eingabe);
5714
- const eintraege = [];
5715
- for (let position = 0; position < anzahl; position++) {
5716
- const roh = tokens[position] ?? null;
5717
- if (roh === null) {
5718
- eintraege.push({ position, roh: null, seed: null, ungueltig: false });
5587
+ function groupKeyOf(run) {
5588
+ return groupOf(run).key;
5589
+ }
5590
+ function siblingsOf(run, alle) {
5591
+ const schluessel = groupKeyOf(run);
5592
+ return alle.filter((kandidat) => groupKeyOf(kandidat) === schluessel);
5593
+ }
5594
+ function namingElementOf(run) {
5595
+ const quelle = sourceOf(run);
5596
+ if (quelle.kind === "scene_direct") {
5597
+ return istKennung(quelle.scene?.element_id) ? quelle.scene.element_id : null;
5598
+ }
5599
+ if (quelle.kind === "draft_chain") {
5600
+ const szene = (quelle.nodes ?? []).find((knoten) => knoten?.type === "scene");
5601
+ if (szene && istKennung(szene.element_id)) return szene.element_id;
5602
+ const shot = (quelle.nodes ?? []).find((knoten) => knoten?.type === "shot");
5603
+ if (shot && istKennung(shot.element_id)) return shot.element_id;
5604
+ }
5605
+ return istKennung(run.shot_element_id) ? run.shot_element_id : null;
5606
+ }
5607
+ function contextOfRun(run) {
5608
+ const kette = run.input_payload?.context_chain;
5609
+ if (!Array.isArray(kette) || kette.length === 0) return void 0;
5610
+ const erstes = kette[0];
5611
+ if (erstes === null) return null;
5612
+ return istKennung(erstes) ? erstes : void 0;
5613
+ }
5614
+ function selectPromptRuns(alle, filter = {}) {
5615
+ const status = filter.status ?? "succeeded";
5616
+ const nachKontext = filter.contextId !== void 0;
5617
+ const runs = [];
5618
+ let hiddenByStatus = 0;
5619
+ let hiddenByContext = 0;
5620
+ let withoutContext = 0;
5621
+ for (const run of alle) {
5622
+ if (status !== "all" && run.status !== status) {
5623
+ hiddenByStatus += 1;
5719
5624
  continue;
5720
5625
  }
5721
- const zahl = GANZZAHL.test(roh) ? Number(roh) : Number.NaN;
5722
- const gueltig = Number.isSafeInteger(zahl);
5723
- eintraege.push({
5724
- position,
5725
- roh,
5726
- seed: gueltig ? zahl : null,
5727
- ungueltig: !gueltig
5728
- });
5626
+ if (nachKontext) {
5627
+ const kontext = contextOfRun(run);
5628
+ if (kontext === void 0) {
5629
+ withoutContext += 1;
5630
+ continue;
5631
+ }
5632
+ if (kontext !== filter.contextId) {
5633
+ hiddenByContext += 1;
5634
+ continue;
5635
+ }
5636
+ }
5637
+ runs.push(run);
5729
5638
  }
5730
- return {
5731
- eintraege,
5732
- ungueltige: eintraege.filter((e) => e.ungueltig),
5733
- ueberzaehlig: Math.max(0, tokens.length - anzahl)
5734
- };
5735
- }
5736
- function seedFehlerText(ungueltige) {
5737
- const teile = ungueltige.map((e) => `Bild ${e.position + 1}: "${e.roh}"`);
5738
- return `Die Seedliste enth\xE4lt keine ganze Zahl an ${teile.length === 1 ? "Position" : "Positionen"} \u2014 ${teile.join(", ")}. Kein Bild wurde importiert.`;
5739
- }
5740
- function mitDefaultVorlage(custom) {
5741
- return [DEFAULT_SEED_VORLAGE, ...custom.filter((v) => !v.builtin)];
5639
+ return { runs, hiddenByStatus, hiddenByContext, withoutContext };
5742
5640
  }
5743
5641
 
5744
- // src/lib/szenen/zipBilder.ts
5745
- var BILD_ENDUNGEN = {
5746
- png: "image/png",
5747
- jpg: "image/jpeg",
5748
- jpeg: "image/jpeg",
5749
- webp: "image/webp"
5750
- };
5751
- var UPLOAD_MAX_BYTES = 45 * 1024 * 1024;
5752
- function byteLaenge(base64) {
5753
- const fuellzeichen = base64.endsWith("==") ? 2 : base64.endsWith("=") ? 1 : 0;
5754
- return Math.floor(base64.length * 3 / 4) - fuellzeichen;
5755
- }
5756
- function angekuendigteGroesse(eintrag) {
5757
- const roh = eintrag._data?.uncompressedSize;
5758
- return typeof roh === "number" && Number.isFinite(roh) && roh >= 0 ? roh : null;
5759
- }
5760
- function bildGroesseVerdikt(archiv, pfad, bytes) {
5761
- if (bytes === null || bytes <= UPLOAD_MAX_BYTES) return null;
5762
- return `${archiv}: Das Bild ${pfad} ist entpackt ${mb(bytes)} MB gro\xDF \u2014 die Grenze f\xFCr eine einzelne Bilddatei liegt bei ${UPLOAD_MAX_BYTES / 1024 / 1024} MB. Kein Bild wurde importiert.`;
5763
- }
5764
- function mb(bytes) {
5765
- return (bytes / 1024 / 1024).toFixed(1);
5766
- }
5767
- function istZipDatei(datei) {
5768
- return /\.zip$/i.test(datei.name);
5642
+ // src/lib/szenen/itemDerivation.ts
5643
+ var SZENEN_ITEM_PREFIX = "szn-";
5644
+ function itemIdForRun(runId) {
5645
+ return `${SZENEN_ITEM_PREFIX}${runId}`;
5769
5646
  }
5770
- function endungVon(pfad) {
5771
- const punkt = pfad.lastIndexOf(".");
5772
- return punkt >= 0 ? pfad.slice(punkt + 1).toLowerCase() : "";
5647
+ function isSzenenItemId(itemId) {
5648
+ return itemId.startsWith(SZENEN_ITEM_PREFIX);
5773
5649
  }
5774
- function istImportierbar(pfad, istVerzeichnis) {
5650
+ function checkSzenenBatchOrigin(candidate) {
5651
+ if (!istText3(candidate.prompt_run_id)) {
5652
+ return {
5653
+ kind: "rejected",
5654
+ failure: { field: "prompt_run_id", message: '"prompt_run_id" fehlt oder ist leer.' }
5655
+ };
5656
+ }
5657
+ if (!istText3(candidate.generation_batch_id)) {
5658
+ return {
5659
+ kind: "rejected",
5660
+ failure: {
5661
+ field: "generation_batch_id",
5662
+ message: '"generation_batch_id" fehlt oder ist leer.'
5663
+ }
5664
+ };
5665
+ }
5666
+ if (candidate.source_kind !== "generated_in_app" && candidate.source_kind !== "external_import") {
5667
+ return {
5668
+ kind: "rejected",
5669
+ failure: {
5670
+ field: "source_kind",
5671
+ message: `"source_kind" ist unbekannt: ${JSON.stringify(candidate.source_kind)}. Erlaubt: generated_in_app, external_import.`
5672
+ }
5673
+ };
5674
+ }
5675
+ const round = typeof candidate.round === "number" && Number.isInteger(candidate.round) ? candidate.round : void 0;
5676
+ return {
5677
+ kind: "ok",
5678
+ value: {
5679
+ prompt_run_id: candidate.prompt_run_id,
5680
+ generation_batch_ids: [candidate.generation_batch_id],
5681
+ source_kind: candidate.source_kind,
5682
+ ...round !== void 0 ? { round } : {}
5683
+ }
5684
+ };
5685
+ }
5686
+ function mergeSzenenBatchOrigin(bestehend, neu) {
5687
+ if (!bestehend) return neu;
5688
+ const ids = [...bestehend.generation_batch_ids];
5689
+ for (const id of neu.generation_batch_ids) {
5690
+ if (!ids.includes(id)) ids.push(id);
5691
+ }
5692
+ return {
5693
+ prompt_run_id: bestehend.prompt_run_id,
5694
+ generation_batch_ids: ids,
5695
+ source_kind: bestehend.source_kind,
5696
+ ...bestehend.round !== void 0 ? { round: bestehend.round } : {}
5697
+ };
5698
+ }
5699
+ var DEFAULT_FSK_LEVEL = "FSK16";
5700
+ var istText3 = (v) => typeof v === "string" && v.trim().length > 0;
5701
+ function roundOfRun(run, runsOfShot) {
5702
+ return runsOfShot.findIndex((kandidat) => kandidat.run_id === run.run_id) + 1;
5703
+ }
5704
+ function deriveLineage(ownItemId, ownRound, existingItems) {
5705
+ const kandidaten = existingItems.filter((item) => item.valid && item.item_id !== ownItemId).sort((a, b) => a.sequence - b.sequence);
5706
+ const elternteil = kandidaten[kandidaten.length - 1];
5707
+ if (!elternteil) {
5708
+ return {
5709
+ parent_item_id: null,
5710
+ lineage_root_id: ownItemId,
5711
+ generation: 0,
5712
+ out_of_order: false
5713
+ };
5714
+ }
5715
+ return {
5716
+ parent_item_id: elternteil.item_id,
5717
+ lineage_root_id: elternteil.lineage_root_id,
5718
+ generation: elternteil.generation + 1,
5719
+ // Der Elternteil kommt aus einer spaeteren Runde: rueckwaerts gespeichert.
5720
+ // Kein Fehler, aber nichts, was stillschweigend passieren darf.
5721
+ out_of_order: elternteil.round >= ownRound
5722
+ };
5723
+ }
5724
+ function deriveItemFromRun(input) {
5725
+ const { run, runsOfShot, existingItems, savedAt } = input;
5726
+ if (run.status === "failed") {
5727
+ return {
5728
+ kind: "rejected",
5729
+ failure: {
5730
+ class: "run_failed",
5731
+ message: `Der Lauf ${run.run_id} ist gescheitert (${run.failure ? run.failure.class : "unbekannt"}) und traegt keinen Prompt. Aus einem Fehlerlauf entsteht kein Item.`,
5732
+ run_failure: run.failure
5733
+ }
5734
+ };
5735
+ }
5736
+ if (!run.output || !istText3(run.output.positive)) {
5737
+ return {
5738
+ kind: "rejected",
5739
+ failure: {
5740
+ class: "run_without_output",
5741
+ message: `Der Lauf ${run.run_id} ist als erfolgreich protokolliert, traegt aber keinen positiven Prompt. Das ist ein Datenfehler im Lauf, kein Item.`
5742
+ }
5743
+ };
5744
+ }
5745
+ const round = roundOfRun(run, runsOfShot);
5746
+ if (round === 0) {
5747
+ return {
5748
+ kind: "rejected",
5749
+ failure: {
5750
+ class: "run_not_among_siblings",
5751
+ // Regel 11: Die Meldung nennt die **Bezugsgruppe**, nicht ein Feld,
5752
+ // das bei einem shotlosen Lauf leer ist. „des Shots ''" war keine
5753
+ // Auskunft (P1-B).
5754
+ message: `Der Lauf ${run.run_id} ist unter den ${runsOfShot.length} Laeufen seiner Bezugsgruppe ${groupKeyOf(run)} nicht enthalten. Ohne seinen Platz gaebe es keine Rundennummer.`
5755
+ }
5756
+ };
5757
+ }
5758
+ const item_id = itemIdForRun(run.run_id);
5759
+ const lineage = deriveLineage(item_id, round, existingItems);
5760
+ const negative = istText3(run.output.negative) ? run.output.negative : null;
5761
+ const title = istText3(input.title) ? input.title : istText3(input.shotTitle) ? `${input.shotTitle} \xB7 Runde ${round}` : `Szenen-Lauf ${round}`;
5762
+ return {
5763
+ kind: "ok",
5764
+ value: {
5765
+ item_id,
5766
+ title,
5767
+ content: run.output.positive,
5768
+ negative_prompt: negative,
5769
+ // `feedback` ist Pflicht (D-55) und ist genau die Erlaeuterung fuer den
5770
+ // Menschen — also gehoert sie in das Feld fuer Notizen.
5771
+ notes: istText3(input.notes) ? input.notes : run.output.feedback,
5772
+ rating: typeof input.rating === "number" ? input.rating : 0,
5773
+ fsk_level: istText3(input.fskLevel) ? input.fskLevel : DEFAULT_FSK_LEVEL,
5774
+ tags: [],
5775
+ szenen: {
5776
+ prompt_run_id: run.run_id,
5777
+ shot_version_id: run.shot_version_id,
5778
+ shot_element_id: run.shot_element_id,
5779
+ scene_setup_version_id: run.scene_setup_version_id,
5780
+ camera_id: run.camera_id,
5781
+ target_model_version_id: run.target_model_version_id,
5782
+ provider: run.provider,
5783
+ model_id: run.model_id,
5784
+ run_created_at: run.created_at,
5785
+ round,
5786
+ created_from_draft_id: null,
5787
+ saved_at: savedAt
5788
+ },
5789
+ lineage,
5790
+ // Bestandsformat: `LibraryTab` baut den Baum aus `metadata.relationships`.
5791
+ // Ein Szenen-Item ohne diese Kante waere im Baum unsichtbar.
5792
+ relationships: lineage.parent_item_id ? [{ type: "parent", id: lineage.parent_item_id, role: "source_A" }] : []
5793
+ }
5794
+ };
5795
+ }
5796
+
5797
+ // src/lib/szenen/seedListe.ts
5798
+ var DEFAULT_SEED_VORLAGE = {
5799
+ name: "Default",
5800
+ seeds: "1; 10; 100; 1000",
5801
+ builtin: true
5802
+ };
5803
+ function parseSeedListe(eingabe) {
5804
+ if (!eingabe) return [];
5805
+ return eingabe.split(/[,;]/).map((teil) => teil.trim()).filter((teil) => teil.length > 0);
5806
+ }
5807
+ function formatSeedListe(tokens) {
5808
+ return tokens.join("; ");
5809
+ }
5810
+ var GANZZAHL = /^-?\d+$/;
5811
+ function ordneSeedsZu(eingabe, anzahl) {
5812
+ const tokens = Array.isArray(eingabe) ? [...eingabe] : parseSeedListe(eingabe);
5813
+ const eintraege = [];
5814
+ for (let position = 0; position < anzahl; position++) {
5815
+ const roh = tokens[position] ?? null;
5816
+ if (roh === null) {
5817
+ eintraege.push({ position, roh: null, seed: null, ungueltig: false });
5818
+ continue;
5819
+ }
5820
+ const zahl = GANZZAHL.test(roh) ? Number(roh) : Number.NaN;
5821
+ const gueltig = Number.isSafeInteger(zahl);
5822
+ eintraege.push({
5823
+ position,
5824
+ roh,
5825
+ seed: gueltig ? zahl : null,
5826
+ ungueltig: !gueltig
5827
+ });
5828
+ }
5829
+ return {
5830
+ eintraege,
5831
+ ungueltige: eintraege.filter((e) => e.ungueltig),
5832
+ ueberzaehlig: Math.max(0, tokens.length - anzahl)
5833
+ };
5834
+ }
5835
+ function seedFehlerText(ungueltige) {
5836
+ const teile = ungueltige.map((e) => `Bild ${e.position + 1}: "${e.roh}"`);
5837
+ return `Die Seedliste enth\xE4lt keine ganze Zahl an ${teile.length === 1 ? "Position" : "Positionen"} \u2014 ${teile.join(", ")}. Kein Bild wurde importiert.`;
5838
+ }
5839
+ function mitDefaultVorlage(custom) {
5840
+ return [DEFAULT_SEED_VORLAGE, ...custom.filter((v) => !v.builtin)];
5841
+ }
5842
+
5843
+ // src/lib/szenen/zipBilder.ts
5844
+ var BILD_ENDUNGEN = {
5845
+ png: "image/png",
5846
+ jpg: "image/jpeg",
5847
+ jpeg: "image/jpeg",
5848
+ webp: "image/webp"
5849
+ };
5850
+ var UPLOAD_MAX_BYTES = 45 * 1024 * 1024;
5851
+ function byteLaenge(base64) {
5852
+ const fuellzeichen = base64.endsWith("==") ? 2 : base64.endsWith("=") ? 1 : 0;
5853
+ return Math.floor(base64.length * 3 / 4) - fuellzeichen;
5854
+ }
5855
+ function angekuendigteGroesse(eintrag) {
5856
+ const roh = eintrag._data?.uncompressedSize;
5857
+ return typeof roh === "number" && Number.isFinite(roh) && roh >= 0 ? roh : null;
5858
+ }
5859
+ function bildGroesseVerdikt(archiv, pfad, bytes) {
5860
+ if (bytes === null || bytes <= UPLOAD_MAX_BYTES) return null;
5861
+ return `${archiv}: Das Bild ${pfad} ist entpackt ${mb(bytes)} MB gro\xDF \u2014 die Grenze f\xFCr eine einzelne Bilddatei liegt bei ${UPLOAD_MAX_BYTES / 1024 / 1024} MB. Kein Bild wurde importiert.`;
5862
+ }
5863
+ function mb(bytes) {
5864
+ return (bytes / 1024 / 1024).toFixed(1);
5865
+ }
5866
+ function istZipDatei(datei) {
5867
+ return /\.zip$/i.test(datei.name);
5868
+ }
5869
+ function endungVon(pfad) {
5870
+ const punkt = pfad.lastIndexOf(".");
5871
+ return punkt >= 0 ? pfad.slice(punkt + 1).toLowerCase() : "";
5872
+ }
5873
+ function istImportierbar(pfad, istVerzeichnis) {
5775
5874
  if (istVerzeichnis) return false;
5776
5875
  if (pfad.startsWith("__MACOSX/")) return false;
5777
5876
  const datei = pfad.slice(pfad.lastIndexOf("/") + 1);
@@ -6804,10 +6903,10 @@ async function runSceneDerivation(input, port, userPrompt) {
6804
6903
  }
6805
6904
 
6806
6905
  // src/features/szenen/SzenenView.tsx
6807
- import { useMemo as useMemo4, useState as useState17 } from "react";
6906
+ import { useMemo as useMemo5, useState as useState20 } from "react";
6808
6907
 
6809
6908
  // src/features/szenen/areas/ElementsArea.tsx
6810
- import { useState as useState12 } from "react";
6909
+ import { useState as useState13 } from "react";
6811
6910
 
6812
6911
  // src/features/szenen/areas/usePortQuery.ts
6813
6912
  import { useEffect, useRef, useState } from "react";
@@ -6839,7 +6938,7 @@ function usePortQuery(frage, abhaengigkeiten) {
6839
6938
  }
6840
6939
 
6841
6940
  // src/features/szenen/areas/ElementDetail.tsx
6842
- import { useEffect as useEffect6, useMemo as useMemo2, useState as useState10 } from "react";
6941
+ import { useEffect as useEffect7, useMemo as useMemo2, useState as useState11 } from "react";
6843
6942
 
6844
6943
  // src/features/szenen/elementLabels.ts
6845
6944
  var LABELS = {
@@ -8931,13 +9030,57 @@ var VersionNavigator = ({
8931
9030
  };
8932
9031
 
8933
9032
  // src/features/szenen/areas/RunsPanel.tsx
8934
- import { useEffect as useEffect5, useRef as useRef3, useState as useState9 } from "react";
9033
+ import { useEffect as useEffect6, useRef as useRef3, useState as useState10 } from "react";
9034
+
9035
+ // src/features/szenen/areas/useLaufTitel.ts
9036
+ import { useEffect as useEffect3, useState as useState7 } from "react";
9037
+ function useLaufTitel(port, laeufe) {
9038
+ const [titelJeElement, setTitelJeElement] = useState7(
9039
+ () => /* @__PURE__ */ new Map()
9040
+ );
9041
+ const gebraucht = [...new Set(
9042
+ laeufe.map(namingElementOf).filter((id) => id !== null)
9043
+ )].sort();
9044
+ const schluessel = gebraucht.join(",");
9045
+ useEffect3(() => {
9046
+ let abgemeldet = false;
9047
+ const offen = gebraucht.filter((id) => !titelJeElement.has(id));
9048
+ if (offen.length === 0) return void 0;
9049
+ void (async () => {
9050
+ const gelesen = /* @__PURE__ */ new Map();
9051
+ for (const id of offen) {
9052
+ try {
9053
+ const ergebnis = await port.elements.getElement(id);
9054
+ gelesen.set(
9055
+ id,
9056
+ ergebnis.kind === "ok" && ergebnis.value ? ergebnis.value.metadata?.title ?? null : null
9057
+ );
9058
+ } catch {
9059
+ gelesen.set(id, null);
9060
+ }
9061
+ }
9062
+ if (abgemeldet) return;
9063
+ setTitelJeElement((bisher) => new Map([...bisher, ...gelesen]));
9064
+ })();
9065
+ return () => {
9066
+ abgemeldet = true;
9067
+ };
9068
+ }, [port, schluessel]);
9069
+ const jeLauf = /* @__PURE__ */ new Map();
9070
+ for (const lauf of laeufe) {
9071
+ const elementId = namingElementOf(lauf);
9072
+ if (!elementId) continue;
9073
+ const titel = titelJeElement.get(elementId);
9074
+ if (titel) jeLauf.set(lauf.run_id, titel);
9075
+ }
9076
+ return jeLauf;
9077
+ }
8935
9078
 
8936
9079
  // src/features/szenen/areas/RunImagesPanel.tsx
8937
- import React7, { useEffect as useEffect4, useRef as useRef2, useState as useState8 } from "react";
9080
+ import React7, { useEffect as useEffect5, useRef as useRef2, useState as useState9 } from "react";
8938
9081
 
8939
9082
  // src/features/szenen/areas/Bildbausteine.tsx
8940
- import { useCallback, useEffect as useEffect3, useState as useState7 } from "react";
9083
+ import { useCallback, useEffect as useEffect4, useState as useState8 } from "react";
8941
9084
  import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
8942
9085
  var Kachel = ({
8943
9086
  quelle,
@@ -8958,7 +9101,7 @@ var BildViewer = ({
8958
9101
  if (anzahl === 0) return;
8959
9102
  onWechseln((position + schritt + anzahl) % anzahl);
8960
9103
  }, [anzahl, position, onWechseln]);
8961
- useEffect3(() => {
9104
+ useEffect4(() => {
8962
9105
  const taste = (e) => {
8963
9106
  if (e.key === "Escape") onSchliessen();
8964
9107
  else if (e.key === "ArrowLeft") blaettern(-1);
@@ -9041,8 +9184,8 @@ var BildViewer = ({
9041
9184
  );
9042
9185
  };
9043
9186
  var BildGalerie = ({ bilder, testId, satzTitel }) => {
9044
- const [offen, setOffen] = useState7(null);
9045
- useEffect3(() => {
9187
+ const [offen, setOffen] = useState8(null);
9188
+ useEffect4(() => {
9046
9189
  setOffen((vorher) => vorher !== null && vorher >= bilder.length ? null : vorher);
9047
9190
  }, [bilder.length]);
9048
9191
  if (bilder.length === 0) return null;
@@ -9098,11 +9241,11 @@ var AUFTRAG_TEXT = {
9098
9241
  };
9099
9242
  var RunImagesPanel = ({ port, lauf }) => {
9100
9243
  const faehig = capabilitiesOf(port);
9101
- const [nachladen, setNachladen] = useState8(0);
9244
+ const [nachladen, setNachladen] = useState9(0);
9102
9245
  const neuLesen = () => setNachladen((n) => n + 1);
9103
- const [erzeugenOffen, setErzeugenOffen] = useState8(null);
9104
- const [zuordnenOffen, setZuordnenOffen] = useState8(null);
9105
- const [chatAuftraegeOffen, setChatAuftraegeOffen] = useState8(null);
9246
+ const [erzeugenOffen, setErzeugenOffen] = useState9(null);
9247
+ const [zuordnenOffen, setZuordnenOffen] = useState9(null);
9248
+ const [chatAuftraegeOffen, setChatAuftraegeOffen] = useState9(null);
9106
9249
  const quelle = sourceOf(lauf);
9107
9250
  const [wahlPhase] = usePortQuery(
9108
9251
  () => port.imageGeneration ? port.imageGeneration.imageModelChoiceForRun(lauf.run_id) : Promise.resolve({ kind: "ok", value: null }),
@@ -9416,12 +9559,12 @@ var BestandsBild = ({ port, mediaRef }) => {
9416
9559
  ] });
9417
9560
  };
9418
9561
  function useBildQuellen(port, bilder) {
9419
- const [stand, setStand] = useState8(() => ({ quellen: /* @__PURE__ */ new Map(), fehler: /* @__PURE__ */ new Map() }));
9562
+ const [stand, setStand] = useState9(() => ({ quellen: /* @__PURE__ */ new Map(), fehler: /* @__PURE__ */ new Map() }));
9420
9563
  const gehalten = useRef2(/* @__PURE__ */ new Map());
9421
9564
  const gescheitert = useRef2(/* @__PURE__ */ new Map());
9422
- const [versuch, setVersuch] = useState8(0);
9565
+ const [versuch, setVersuch] = useState9(0);
9423
9566
  const schluessel = bilder.map((b) => `${b.media_ref}|${b.mime_type ?? ""}`).join(" ");
9424
- useEffect4(() => {
9567
+ useEffect5(() => {
9425
9568
  const bestand = port.imageLibrary;
9426
9569
  if (!bestand) return void 0;
9427
9570
  let abgebrochen = false;
@@ -9586,11 +9729,11 @@ var ProfilBefunde = ({ wahl, runId }) => {
9586
9729
  ] });
9587
9730
  };
9588
9731
  var ErzeugenAktion = ({ port, lauf, wahl, wahlFehler, onFertig }) => {
9589
- const [modellWahl, setModellWahl] = useState8(null);
9590
- const [anzahlText, setAnzahlText] = useState8("1");
9591
- const [seitenverhaeltnis, setSeitenverhaeltnis] = useState8("");
9592
- const [laeuft, setLaeuft] = useState8(false);
9593
- const [notiz, setNotiz] = useState8(null);
9732
+ const [modellWahl, setModellWahl] = useState9(null);
9733
+ const [anzahlText, setAnzahlText] = useState9("1");
9734
+ const [seitenverhaeltnis, setSeitenverhaeltnis] = useState9("");
9735
+ const [laeuft, setLaeuft] = useState9(false);
9736
+ const [notiz, setNotiz] = useState9(null);
9594
9737
  if (!port.imageGeneration) {
9595
9738
  return /* @__PURE__ */ jsx8("p", { "data-testid": `erzeugen-unsupported-${lauf.run_id}`, children: "Dieser Host erzeugt keine Bilder \u2014 entweder fehlt der Providerzugang oder der gesicherte Speicherweg. Externe Bilder lassen sich trotzdem zuordnen." });
9596
9739
  }
@@ -9767,23 +9910,23 @@ var ErzeugenAktion = ({ port, lauf, wahl, wahlFehler, onFertig }) => {
9767
9910
  };
9768
9911
  var DEFAULT_VORLAGE_KEY = "__default__";
9769
9912
  var ZuordnenAktion = ({ port, lauf, onFertig }) => {
9770
- const [dateien, setDateien] = useState8([]);
9771
- const [seeds, setSeeds] = useState8({});
9772
- const [zip, setZip] = useState8(null);
9773
- const [zipLaedt, setZipLaedt] = useState8(false);
9774
- const [seedListe, setSeedListe] = useState8("");
9775
- const [vorlagen, setVorlagen] = useState8([DEFAULT_SEED_VORLAGE]);
9776
- const [vorlageKey, setVorlageKey] = useState8(DEFAULT_VORLAGE_KEY);
9777
- const [vorlagenStand, setVorlagenStand] = useState8(0);
9778
- const [vorlageBenennen, setVorlageBenennen] = useState8(false);
9779
- const [vorlageName, setVorlageName] = useState8("");
9780
- const [modell, setModell] = useState8("");
9781
- const [itemId, setItemId] = useState8("");
9782
- const [laeuft, setLaeuft] = useState8(false);
9783
- const [notiz, setNotiz] = useState8(null);
9913
+ const [dateien, setDateien] = useState9([]);
9914
+ const [seeds, setSeeds] = useState9({});
9915
+ const [zip, setZip] = useState9(null);
9916
+ const [zipLaedt, setZipLaedt] = useState9(false);
9917
+ const [seedListe, setSeedListe] = useState9("");
9918
+ const [vorlagen, setVorlagen] = useState9([DEFAULT_SEED_VORLAGE]);
9919
+ const [vorlageKey, setVorlageKey] = useState9(DEFAULT_VORLAGE_KEY);
9920
+ const [vorlagenStand, setVorlagenStand] = useState9(0);
9921
+ const [vorlageBenennen, setVorlageBenennen] = useState9(false);
9922
+ const [vorlageName, setVorlageName] = useState9("");
9923
+ const [modell, setModell] = useState9("");
9924
+ const [itemId, setItemId] = useState9("");
9925
+ const [laeuft, setLaeuft] = useState9(false);
9926
+ const [notiz, setNotiz] = useState9(null);
9784
9927
  const auswahlMarke = useRef2(0);
9785
9928
  const zipAktiv = zip !== null;
9786
- useEffect4(() => {
9929
+ useEffect5(() => {
9787
9930
  if (!zipAktiv) return;
9788
9931
  let abgebrochen = false;
9789
9932
  void (async () => {
@@ -10243,8 +10386,8 @@ var ChatAuftraegeAktion = ({
10243
10386
  laedt,
10244
10387
  onFertig
10245
10388
  }) => {
10246
- const [laufend, setLaufend] = useState8(null);
10247
- const [notiz, setNotiz] = useState8(null);
10389
+ const [laufend, setLaufend] = useState9(null);
10390
+ const [notiz, setNotiz] = useState9(null);
10248
10391
  async function uebernehmen(jobId) {
10249
10392
  if (!port.imageJobs) return;
10250
10393
  setLaufend(jobId);
@@ -10323,12 +10466,12 @@ var ChatAuftraegeAktion = ({
10323
10466
  // src/features/szenen/areas/RunsPanel.tsx
10324
10467
  import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
10325
10468
  var RunsPanel = ({ port, source, contextId }) => {
10326
- const [anweisung, setAnweisung] = useState9("");
10327
- const [laeuft, setLaeuft] = useState9(false);
10328
- const [notiz, setNotiz] = useState9(null);
10329
- const [nachladen, setNachladen] = useState9(0);
10330
- const faehig = capabilitiesOf(port);
10331
- const quellSchluessel = source.kind === "published" ? source.shotVersionId : source.kind === "draft_chain" ? source.chainId : source.sceneElementId;
10469
+ const [anweisung, setAnweisung] = useState10("");
10470
+ const [laeuft, setLaeuft] = useState10(false);
10471
+ const [notiz, setNotiz] = useState10(null);
10472
+ const [nachladen, setNachladen] = useState10(0);
10473
+ const faehig = capabilitiesOf(port);
10474
+ const quellSchluessel = source.kind === "published" ? source.shotVersionId : source.kind === "draft_chain" ? source.chainId : source.sceneElementId;
10332
10475
  const aktuelleQuelle = useRef3({ kind: source.kind, id: quellSchluessel });
10333
10476
  aktuelleQuelle.current = { kind: source.kind, id: quellSchluessel };
10334
10477
  const [phase, neuLaden] = usePortQuery(
@@ -10357,10 +10500,11 @@ var RunsPanel = ({ port, source, contextId }) => {
10357
10500
  neuLaden();
10358
10501
  };
10359
10502
  const laeufe = phase.status === "ready" ? phase.value : [];
10360
- const [gewaehlteRunde, setGewaehlteRunde] = useState9(void 0);
10503
+ const titel = useLaufTitel(port, laeufe);
10504
+ const [gewaehlteRunde, setGewaehlteRunde] = useState10(void 0);
10361
10505
  const neueste = laeufe.length > 0 ? laeufe[laeufe.length - 1].run_id : null;
10362
10506
  const offeneRunde = gewaehlteRunde === void 0 ? neueste : gewaehlteRunde;
10363
- useEffect5(() => {
10507
+ useEffect6(() => {
10364
10508
  setGewaehlteRunde(void 0);
10365
10509
  setAnweisung("");
10366
10510
  setNotiz(null);
@@ -10395,6 +10539,7 @@ var RunsPanel = ({ port, source, contextId }) => {
10395
10539
  port,
10396
10540
  lauf,
10397
10541
  runde: roundOfRun(lauf, laeufe),
10542
+ titel: titel.get(lauf.run_id) ?? null,
10398
10543
  offen: lauf.run_id === offeneRunde,
10399
10544
  onUmschalten: () => setGewaehlteRunde(
10400
10545
  lauf.run_id === offeneRunde ? null : lauf.run_id
@@ -10419,7 +10564,7 @@ var STATUS_TEXT = {
10419
10564
  };
10420
10565
  var LANGER_TEXT = 240;
10421
10566
  var Sekundaertext = ({ titel, text, testId }) => {
10422
- const [ganz, setGanz] = useState9(false);
10567
+ const [ganz, setGanz] = useState10(false);
10423
10568
  const lang = text.length > LANGER_TEXT;
10424
10569
  return /* @__PURE__ */ jsxs9("section", { className: "szenen-runs__sekundaer", children: [
10425
10570
  /* @__PURE__ */ jsx9("h5", { children: titel }),
@@ -10438,7 +10583,7 @@ var Sekundaertext = ({ titel, text, testId }) => {
10438
10583
  };
10439
10584
  var LISTE_ANFANG = 3;
10440
10585
  var SekundaerListe = ({ titel, eintraege, testId, className }) => {
10441
- const [alle, setAlle] = useState9(false);
10586
+ const [alle, setAlle] = useState10(false);
10442
10587
  const lang = eintraege.length > LISTE_ANFANG;
10443
10588
  const gezeigt = lang && !alle ? eintraege.slice(0, LISTE_ANFANG) : eintraege;
10444
10589
  return /* @__PURE__ */ jsxs9("section", { className: "szenen-runs__sekundaer", children: [
@@ -10456,10 +10601,10 @@ var SekundaerListe = ({ titel, eintraege, testId, className }) => {
10456
10601
  )
10457
10602
  ] });
10458
10603
  };
10459
- var RundenEintrag = ({ port, lauf, runde, offen, onUmschalten, itemMoeglich, onItemGespeichert }) => {
10460
- const [notiz, setNotiz] = useState9(null);
10461
- const [laeuft, setLaeuft] = useState9(false);
10462
- const [nachladen, setNachladen] = useState9(0);
10604
+ var RundenEintrag = ({ port, lauf, runde, titel, offen, onUmschalten, itemMoeglich, onItemGespeichert }) => {
10605
+ const [notiz, setNotiz] = useState10(null);
10606
+ const [laeuft, setLaeuft] = useState10(false);
10607
+ const [nachladen, setNachladen] = useState10(0);
10463
10608
  const [itemPhase] = usePortQuery(
10464
10609
  () => offen && port.items ? port.items.getItemForRun(lauf.run_id) : Promise.resolve({ kind: "ok", value: null }),
10465
10610
  [port, lauf.run_id, nachladen, offen]
@@ -10487,10 +10632,7 @@ var RundenEintrag = ({ port, lauf, runde, offen, onUmschalten, itemMoeglich, onI
10487
10632
  "aria-expanded": offen,
10488
10633
  "data-testid": `runde-umschalten-${lauf.run_id}`,
10489
10634
  children: [
10490
- /* @__PURE__ */ jsxs9("span", { className: "szenen-runs__marke", children: [
10491
- "Runde ",
10492
- runde
10493
- ] }),
10635
+ /* @__PURE__ */ jsx9("span", { className: "szenen-runs__marke", "data-testid": `titel-${lauf.run_id}`, children: titel ? `${titel} \xB7 Runde ${runde}` : `Runde ${runde}` }),
10494
10636
  /* @__PURE__ */ jsx9(
10495
10637
  "span",
10496
10638
  {
@@ -10614,16 +10756,16 @@ var ElementDetail = ({
10614
10756
  author,
10615
10757
  onChanged
10616
10758
  }) => {
10617
- const [nachladen, setNachladen] = useState10(0);
10759
+ const [nachladen, setNachladen] = useState11(0);
10618
10760
  const [phase] = usePortQuery(
10619
10761
  () => port.elements.getElement(elementId),
10620
10762
  [port, elementId, nachladen]
10621
10763
  );
10622
- const [entwurf, setEntwurf] = useState10({});
10623
- const [notiz, setNotiz] = useState10(null);
10624
- const [laeuft, setLaeuft] = useState10(false);
10625
- const [wahl, setWahl] = useState10(null);
10626
- const [basiswechsel, setBasiswechsel] = useState10(null);
10764
+ const [entwurf, setEntwurf] = useState11({});
10765
+ const [notiz, setNotiz] = useState11(null);
10766
+ const [laeuft, setLaeuft] = useState11(false);
10767
+ const [wahl, setWahl] = useState11(null);
10768
+ const [basiswechsel, setBasiswechsel] = useState11(null);
10627
10769
  const [kettenPhase] = usePortQuery(
10628
10770
  () => port.context.chainFor(contextId),
10629
10771
  [port, contextId]
@@ -10645,7 +10787,7 @@ var ElementDetail = ({
10645
10787
  () => schnappschuss ? fieldsForType(schnappschuss.element.type) : [],
10646
10788
  [schnappschuss?.element.type]
10647
10789
  );
10648
- useEffect6(() => {
10790
+ useEffect7(() => {
10649
10791
  setWahl(null);
10650
10792
  setBasiswechsel(null);
10651
10793
  setNotiz(null);
@@ -10676,7 +10818,7 @@ var ElementDetail = ({
10676
10818
  return {};
10677
10819
  }, [schnappschuss, angezeigt]);
10678
10820
  const anzeigeSchluessel = angezeigt.kind === "version" ? `v:${angezeigt.versionId}` : angezeigt.kind;
10679
- useEffect6(() => {
10821
+ useEffect7(() => {
10680
10822
  if (!schnappschuss) return;
10681
10823
  setEntwurf(formFromPayload(felder, angezeigtePayload));
10682
10824
  }, [
@@ -11108,15 +11250,15 @@ var ElementDetail = ({
11108
11250
  };
11109
11251
 
11110
11252
  // src/features/szenen/areas/useSchmalesDisplay.ts
11111
- import { useEffect as useEffect7, useState as useState11 } from "react";
11253
+ import { useEffect as useEffect8, useState as useState12 } from "react";
11112
11254
  var SCHMALE_ANSICHT = "(max-width: 760px)";
11113
11255
  function messen(abfrage) {
11114
11256
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
11115
11257
  return window.matchMedia(abfrage).matches;
11116
11258
  }
11117
11259
  function useSchmalesDisplay(abfrage = SCHMALE_ANSICHT) {
11118
- const [schmal, setSchmal] = useState11(() => messen(abfrage));
11119
- useEffect7(() => {
11260
+ const [schmal, setSchmal] = useState12(() => messen(abfrage));
11261
+ useEffect8(() => {
11120
11262
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
11121
11263
  const liste = window.matchMedia(abfrage);
11122
11264
  const aktualisieren = () => setSchmal(liste.matches);
@@ -11143,16 +11285,16 @@ var ElementsArea = ({
11143
11285
  const gemischt = auswahlTypen.length > 1;
11144
11286
  const ueberschrift = listTitle ?? (einzelTyp ? elementTypPlural(einzelTyp) : "Bausteine");
11145
11287
  const einzahl = einzelTyp ? elementTypLabel(einzelTyp) : "Objekt";
11146
- const [typ, setTyp] = useState12(einzelTyp ?? "");
11147
- const [zeigeStillgelegte, setZeigeStillgelegte] = useState12(false);
11148
- const [gewaehlt, setGewaehlt] = useState12(null);
11149
- const [neuerTitel, setNeuerTitel] = useState12("");
11150
- const [neuerTyp, setNeuerTyp] = useState12(auswahlTypen[0]);
11151
- const [notiz, setNotiz] = useState12(null);
11152
- const [anlegend, setAnlegend] = useState12(false);
11153
- const [anlageOffen, setAnlageOffen] = useState12(false);
11288
+ const [typ, setTyp] = useState13(einzelTyp ?? "");
11289
+ const [zeigeStillgelegte, setZeigeStillgelegte] = useState13(false);
11290
+ const [gewaehlt, setGewaehlt] = useState13(null);
11291
+ const [neuerTitel, setNeuerTitel] = useState13("");
11292
+ const [neuerTyp, setNeuerTyp] = useState13(auswahlTypen[0]);
11293
+ const [notiz, setNotiz] = useState13(null);
11294
+ const [anlegend, setAnlegend] = useState13(false);
11295
+ const [anlageOffen, setAnlageOffen] = useState13(false);
11154
11296
  const schmal = useSchmalesDisplay();
11155
- const [ansicht, setAnsicht] = useState12("liste");
11297
+ const [ansicht, setAnsicht] = useState13("liste");
11156
11298
  const zeigeListe = !schmal || ansicht === "liste";
11157
11299
  const zeigeDetail = !schmal || ansicht === "detail";
11158
11300
  const waehle = (elementId) => {
@@ -11364,235 +11506,59 @@ var ElementsArea = ({
11364
11506
  };
11365
11507
 
11366
11508
  // src/features/szenen/areas/SceneArea.tsx
11367
- import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
11368
- var SceneArea = ({ port, contextId }) => /* @__PURE__ */ jsxs12("div", { className: "szenen-scene", "data-testid": "bereich-szene", children: [
11369
- /* @__PURE__ */ jsx12("p", { className: "szenen-area__lead", children: "Szenen dieses Kontexts. Auswahl \xF6ffnet die Bearbeitung der Nodes und Beziehungen." }),
11370
- /* @__PURE__ */ jsx12(ElementsArea, { port, contextId, restrictToTypes: ["scene"] })
11371
- ] });
11372
-
11373
- // src/features/szenen/areas/SetupArea.tsx
11374
- import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
11375
- var SetupArea = ({ port, contextId }) => /* @__PURE__ */ jsxs13("div", { className: "szenen-setup", "data-testid": "bereich-setup", children: [
11376
- /* @__PURE__ */ jsx13("p", { className: "szenen-area__lead", children: "Bildaufbauten, Kameras und Stile dieses Kontexts." }),
11377
- /* @__PURE__ */ jsx13(
11378
- ElementsArea,
11379
- {
11380
- port,
11381
- contextId,
11382
- restrictToTypes: ["scene_setup", "camera_preset", "camera_pattern", "style"],
11383
- allTypesLabel: "alle Bildaufbau-Typen",
11384
- listTitle: "Bildaufbau"
11385
- }
11386
- )
11387
- ] });
11388
-
11389
- // src/features/szenen/areas/ShotArea.tsx
11390
- import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
11391
- var ShotArea = ({ port, contextId }) => /* @__PURE__ */ jsxs14("div", { className: "szenen-shot", "data-testid": "bereich-shot", children: [
11392
- /* @__PURE__ */ jsx14("p", { className: "szenen-area__lead", children: "Prompts dieses Kontexts. Auswahl zeigt Runden und startet Prompt-L\xE4ufe." }),
11393
- /* @__PURE__ */ jsx14(
11394
- ElementsArea,
11395
- {
11396
- port,
11397
- contextId,
11398
- restrictToTypes: ["shot", "shot_concept", "target_model"],
11399
- allTypesLabel: "alle Prompt-Typen",
11400
- listTitle: "Prompts"
11401
- }
11402
- )
11403
- ] });
11404
-
11405
- // src/features/szenen/areas/MediaArea.tsx
11406
- import { useState as useState13 } from "react";
11407
- import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
11408
- var leer = async () => ({ kind: "ok", value: [] });
11409
- var MediaArea = ({ port }) => {
11410
- const media = port.media;
11411
- const [versionInput, setVersionInput] = useState13("");
11412
- const [versionId, setVersionId] = useState13("");
11413
- const [itemInput, setItemInput] = useState13("");
11414
- const [itemId, setItemId] = useState13("");
11415
- const [assetId, setAssetId] = useState13("");
11416
- const [role, setRole] = useState13("reference");
11417
- const [position, setPosition] = useState13("0");
11418
- const [notiz, setNotiz] = useState13(null);
11419
- const [busy, setBusy] = useState13(false);
11420
- const [refresh, setRefresh] = useState13(0);
11421
- const [versionPhase] = usePortQuery(
11422
- () => versionId ? media.listVersionMedia(versionId) : leer(),
11423
- [media, versionId, refresh]
11424
- );
11425
- const [itemPhase] = usePortQuery(
11426
- () => itemId ? media.listItemMedia(itemId) : Promise.resolve({ kind: "ok", value: [] }),
11427
- [media, itemId, refresh]
11428
- );
11429
- const zuordnen = async () => {
11430
- if (!versionInput.trim() || !assetId.trim()) {
11431
- setNotiz({ tone: "error", text: "Version-ID und Asset-ID sind erforderlich." });
11432
- return;
11433
- }
11434
- const parsedPosition = Number(position);
11435
- if (!Number.isInteger(parsedPosition) || parsedPosition < 0) {
11436
- setNotiz({ tone: "error", text: `Position muss eine nicht-negative Ganzzahl sein, war ${JSON.stringify(position)}.` });
11437
- return;
11438
- }
11439
- setBusy(true);
11440
- const result = await media.attachVersionMedium({
11441
- versionId: versionInput.trim(),
11442
- assetId: assetId.trim(),
11443
- role,
11444
- position: parsedPosition
11445
- });
11446
- setNotiz(noticeFor(result, "Referenzmedium zuordnen"));
11447
- if (result.kind === "ok") {
11448
- setVersionId(versionInput.trim());
11449
- setRefresh((value) => value + 1);
11450
- }
11451
- setBusy(false);
11452
- };
11453
- const entfernen = async (medium) => {
11454
- setBusy(true);
11455
- const result = await media.detachVersionMedium({
11456
- versionId,
11457
- assetId: medium.assetId,
11458
- role: medium.role
11459
- });
11460
- setNotiz(noticeFor(result, "Referenzmedium entfernen"));
11461
- if (result.kind === "ok") setRefresh((value) => value + 1);
11462
- setBusy(false);
11463
- };
11464
- const versionMedien = versionPhase.status === "ready" ? versionPhase.value : [];
11465
- const itemMedien = itemPhase.status === "ready" ? itemPhase.value : [];
11466
- return /* @__PURE__ */ jsxs15("div", { className: "szenen-media", "data-testid": "bereich-medien", children: [
11467
- /* @__PURE__ */ jsx15("p", { className: "szenen-area__lead", children: "Bereits vorhandene Medien-Assets einer Elementversion zuordnen. Hochgeladen wird hier nichts \u2014 Medien entstehen \xFCber den bestehenden Speicherweg aus Stufe 5." }),
11468
- /* @__PURE__ */ jsxs15("section", { children: [
11469
- /* @__PURE__ */ jsx15("h3", { children: "Version" }),
11470
- /* @__PURE__ */ jsxs15("div", { className: "szenen-media__lookup", children: [
11471
- /* @__PURE__ */ jsxs15("label", { children: [
11472
- "Version-ID",
11473
- /* @__PURE__ */ jsx15("input", { value: versionInput, onChange: (event) => setVersionInput(event.target.value) })
11474
- ] }),
11475
- /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => setVersionId(versionInput.trim()), children: "Medien laden" })
11476
- ] }),
11477
- /* @__PURE__ */ jsxs15("div", { className: "szenen-media__attach", children: [
11478
- /* @__PURE__ */ jsxs15("label", { children: [
11479
- "Asset-ID",
11480
- /* @__PURE__ */ jsx15("input", { value: assetId, onChange: (event) => setAssetId(event.target.value) })
11481
- ] }),
11482
- /* @__PURE__ */ jsxs15("label", { children: [
11483
- "Rolle",
11484
- /* @__PURE__ */ jsxs15("select", { value: role, onChange: (event) => setRole(event.target.value), children: [
11485
- /* @__PURE__ */ jsx15("option", { value: "reference", children: "reference" }),
11486
- /* @__PURE__ */ jsx15("option", { value: "mask", children: "mask" }),
11487
- /* @__PURE__ */ jsx15("option", { value: "palette", children: "palette" }),
11488
- /* @__PURE__ */ jsx15("option", { value: "example", children: "example" })
11489
- ] })
11490
- ] }),
11491
- /* @__PURE__ */ jsxs15("label", { children: [
11492
- "Position",
11493
- /* @__PURE__ */ jsx15("input", { type: "number", min: "0", value: position, onChange: (event) => setPosition(event.target.value) })
11494
- ] }),
11495
- /* @__PURE__ */ jsx15("button", { type: "button", disabled: busy, onClick: zuordnen, children: "zuordnen" })
11496
- ] }),
11497
- versionPhase.status === "loading" && versionId && /* @__PURE__ */ jsx15("p", { children: "Versionsmedien werden geladen \u2026" }),
11498
- versionPhase.status === "error" && /* @__PURE__ */ jsxs15("p", { role: "alert", children: [
11499
- "Versionsmedien konnten nicht geladen werden: ",
11500
- versionPhase.message
11501
- ] }),
11502
- versionPhase.status === "ready" && versionId && versionMedien.length === 0 && /* @__PURE__ */ jsxs15("p", { children: [
11503
- "Version ",
11504
- versionId,
11505
- " hat keine Medien."
11506
- ] }),
11507
- /* @__PURE__ */ jsx15("ul", { className: "szenen-media__list", children: versionMedien.map((medium) => /* @__PURE__ */ jsxs15("li", { children: [
11508
- /* @__PURE__ */ jsx15("code", { children: medium.assetId }),
11509
- /* @__PURE__ */ jsxs15("span", { children: [
11510
- medium.role,
11511
- " \xB7 Position ",
11512
- medium.position
11513
- ] }),
11514
- medium.url && /* @__PURE__ */ jsx15("a", { href: medium.url, target: "_blank", rel: "noreferrer", children: "\xF6ffnen" }),
11515
- /* @__PURE__ */ jsx15("button", { type: "button", disabled: busy, onClick: () => entfernen(medium), children: "entfernen" })
11516
- ] }, `${medium.assetId}:${medium.role}`)) })
11517
- ] }),
11518
- /* @__PURE__ */ jsxs15("section", { children: [
11519
- /* @__PURE__ */ jsx15("h3", { children: "Item-Medien" }),
11520
- /* @__PURE__ */ jsxs15("div", { className: "szenen-media__lookup", children: [
11521
- /* @__PURE__ */ jsxs15("label", { children: [
11522
- "Item-ID",
11523
- /* @__PURE__ */ jsx15("input", { value: itemInput, onChange: (event) => setItemInput(event.target.value) })
11524
- ] }),
11525
- /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => setItemId(itemInput.trim()), children: "Item-Medien laden" })
11526
- ] }),
11527
- itemPhase.status === "error" && /* @__PURE__ */ jsxs15("p", { role: "alert", children: [
11528
- "Item-Medien konnten nicht geladen werden: ",
11529
- itemPhase.message
11530
- ] }),
11531
- /* @__PURE__ */ jsx15("ul", { className: "szenen-media__list", children: itemMedien.map((medium) => /* @__PURE__ */ jsxs15("li", { children: [
11532
- /* @__PURE__ */ jsx15("code", { children: medium.assetId }),
11533
- /* @__PURE__ */ jsxs15("span", { children: [
11534
- medium.role,
11535
- " \xB7 Position ",
11536
- medium.position
11537
- ] }),
11538
- medium.url && /* @__PURE__ */ jsx15("a", { href: medium.url, target: "_blank", rel: "noreferrer", children: "\xF6ffnen" })
11539
- ] }, `${medium.assetId}:${medium.role}:${medium.position}`)) })
11540
- ] }),
11541
- notiz && /* @__PURE__ */ jsx15("p", { role: notiz.tone === "error" ? "alert" : "status", "data-tone": notiz.tone, children: notiz.text })
11542
- ] });
11543
- };
11509
+ import { useState as useState17 } from "react";
11544
11510
 
11545
11511
  // src/features/szenen/areas/DeriveArea.tsx
11546
- import { useEffect as useEffect8, useMemo as useMemo3, useRef as useRef4, useState as useState16 } from "react";
11512
+ import { useEffect as useEffect9, useMemo as useMemo3, useRef as useRef4, useState as useState16 } from "react";
11547
11513
 
11548
11514
  // src/features/szenen/areas/RecoveryPanel.tsx
11549
11515
  import { useState as useState14 } from "react";
11550
- import { Fragment as Fragment6, jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
11516
+ import { Fragment as Fragment6, jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
11551
11517
  var Diagnosen = ({ befunde, testId }) => {
11552
11518
  if (befunde.length === 0) return null;
11553
- return /* @__PURE__ */ jsx16("ul", { className: "szenen-diagnose__liste", "data-testid": testId, children: befunde.map((d, i) => /* @__PURE__ */ jsxs16("li", { "data-severity": d.severity, children: [
11554
- /* @__PURE__ */ jsx16("code", { children: d.code }),
11555
- d.proposal_type && /* @__PURE__ */ jsxs16(Fragment6, { children: [
11519
+ return /* @__PURE__ */ jsx12("ul", { className: "szenen-diagnose__liste", "data-testid": testId, children: befunde.map((d, i) => /* @__PURE__ */ jsxs12("li", { "data-severity": d.severity, children: [
11520
+ /* @__PURE__ */ jsx12("code", { children: d.code }),
11521
+ d.proposal_type && /* @__PURE__ */ jsxs12(Fragment6, { children: [
11556
11522
  " \xB7 ",
11557
- /* @__PURE__ */ jsx16("strong", { children: d.proposal_type })
11523
+ /* @__PURE__ */ jsx12("strong", { children: d.proposal_type })
11558
11524
  ] }),
11559
- d.pointer && /* @__PURE__ */ jsxs16(Fragment6, { children: [
11525
+ d.pointer && /* @__PURE__ */ jsxs12(Fragment6, { children: [
11560
11526
  " \xB7 ",
11561
- /* @__PURE__ */ jsx16("code", { children: d.pointer })
11527
+ /* @__PURE__ */ jsx12("code", { children: d.pointer })
11562
11528
  ] }),
11563
- typeof d.line === "number" && /* @__PURE__ */ jsxs16(Fragment6, { children: [
11529
+ typeof d.line === "number" && /* @__PURE__ */ jsxs12(Fragment6, { children: [
11564
11530
  " \xB7 Zeile ",
11565
11531
  d.line,
11566
11532
  ", Spalte ",
11567
11533
  d.column
11568
11534
  ] }),
11569
- /* @__PURE__ */ jsx16("div", { children: d.message })
11535
+ /* @__PURE__ */ jsx12("div", { children: d.message })
11570
11536
  ] }, i)) });
11571
11537
  };
11572
- var Ausbeute = ({ bewertung }) => /* @__PURE__ */ jsxs16("div", { className: "szenen-diagnose", "data-testid": "rettung-ergebnis", children: [
11573
- /* @__PURE__ */ jsxs16("p", { "data-testid": "rettung-status", children: [
11538
+ var Ausbeute = ({ bewertung }) => /* @__PURE__ */ jsxs12("div", { className: "szenen-diagnose", "data-testid": "rettung-ergebnis", children: [
11539
+ /* @__PURE__ */ jsxs12("p", { "data-testid": "rettung-status", children: [
11574
11540
  bewertung.status === "usable" && "Diese Fassung ist vollst\xE4ndig verwertbar.",
11575
11541
  bewertung.status === "partial" && "Diese Fassung ist teilweise verwertbar \u2014 nicht alles kommt durch.",
11576
11542
  bewertung.status === "invalid" && "Aus dieser Fassung ist nichts zu \xFCbernehmen."
11577
11543
  ] }),
11578
- bewertung.proposals.length > 0 && /* @__PURE__ */ jsxs16(Fragment6, { children: [
11579
- /* @__PURE__ */ jsx16("h5", { children: "Verwertbar" }),
11580
- /* @__PURE__ */ jsx16("ul", { "data-testid": "rettung-verwertbar", children: bewertung.proposals.map((p) => /* @__PURE__ */ jsxs16("li", { "data-testid": `rettung-verwertbar-${p.type}`, children: [
11581
- /* @__PURE__ */ jsx16("strong", { children: p.type }),
11544
+ bewertung.proposals.length > 0 && /* @__PURE__ */ jsxs12(Fragment6, { children: [
11545
+ /* @__PURE__ */ jsx12("h5", { children: "Verwertbar" }),
11546
+ /* @__PURE__ */ jsx12("ul", { "data-testid": "rettung-verwertbar", children: bewertung.proposals.map((p) => /* @__PURE__ */ jsxs12("li", { "data-testid": `rettung-verwertbar-${p.type}`, children: [
11547
+ /* @__PURE__ */ jsx12("strong", { children: p.type }),
11582
11548
  " \u2014 ",
11583
11549
  p.status === "complete" ? "vollst\xE4ndig" : "teilweise; vor dem Ver\xF6ffentlichen zu erg\xE4nzen",
11584
- p.status === "partial" && p.gaps && p.gaps.length > 0 && /* @__PURE__ */ jsx16("ul", { children: p.gaps.map((l, i) => /* @__PURE__ */ jsxs16("li", { children: [
11585
- /* @__PURE__ */ jsx16("code", { children: l.pointer }),
11550
+ p.status === "partial" && p.gaps && p.gaps.length > 0 && /* @__PURE__ */ jsx12("ul", { children: p.gaps.map((l, i) => /* @__PURE__ */ jsxs12("li", { children: [
11551
+ /* @__PURE__ */ jsx12("code", { children: l.pointer }),
11586
11552
  ": ",
11587
11553
  l.reason
11588
11554
  ] }, i)) })
11589
11555
  ] }, p.type)) })
11590
11556
  ] }),
11591
- bewertung.rejected.length > 0 && /* @__PURE__ */ jsxs16(Fragment6, { children: [
11592
- /* @__PURE__ */ jsx16("h5", { children: "Nicht verwertbar" }),
11593
- /* @__PURE__ */ jsx16("ul", { "data-testid": "rettung-abgelehnt", children: bewertung.rejected.map((r) => /* @__PURE__ */ jsxs16("li", { "data-testid": `rettung-abgelehnt-${r.type}`, children: [
11594
- /* @__PURE__ */ jsx16("strong", { children: r.type }),
11595
- /* @__PURE__ */ jsx16(Diagnosen, { befunde: r.diagnostics, testId: `rettung-grund-${r.type}` })
11557
+ bewertung.rejected.length > 0 && /* @__PURE__ */ jsxs12(Fragment6, { children: [
11558
+ /* @__PURE__ */ jsx12("h5", { children: "Nicht verwertbar" }),
11559
+ /* @__PURE__ */ jsx12("ul", { "data-testid": "rettung-abgelehnt", children: bewertung.rejected.map((r) => /* @__PURE__ */ jsxs12("li", { "data-testid": `rettung-abgelehnt-${r.type}`, children: [
11560
+ /* @__PURE__ */ jsx12("strong", { children: r.type }),
11561
+ /* @__PURE__ */ jsx12(Diagnosen, { befunde: r.diagnostics, testId: `rettung-grund-${r.type}` })
11596
11562
  ] }, r.type)) })
11597
11563
  ] })
11598
11564
  ] });
@@ -11637,16 +11603,16 @@ var RecoveryPanel = ({ port, lauf }) => {
11637
11603
  setLaeuft(false);
11638
11604
  }
11639
11605
  }
11640
- return /* @__PURE__ */ jsxs16("section", { className: "szenen-rettung", "data-testid": "rettung", children: [
11641
- /* @__PURE__ */ jsx16("h4", { children: "Antwort retten" }),
11642
- /* @__PURE__ */ jsxs16("p", { className: "szenen-area__lead", children: [
11606
+ return /* @__PURE__ */ jsxs12("section", { className: "szenen-rettung", "data-testid": "rettung", children: [
11607
+ /* @__PURE__ */ jsx12("h4", { children: "Antwort retten" }),
11608
+ /* @__PURE__ */ jsxs12("p", { className: "szenen-area__lead", children: [
11643
11609
  "Der Lauf ist bezahlt und seine Antwort liegt vor. Sie l\xE4sst sich hier pr\xFCfen und korrigieren \u2014 ",
11644
- /* @__PURE__ */ jsx16("strong", { children: "ohne" }),
11610
+ /* @__PURE__ */ jsx12("strong", { children: "ohne" }),
11645
11611
  " einen weiteren Modellaufruf. Das Original bleibt unver\xE4ndert."
11646
11612
  ] }),
11647
- /* @__PURE__ */ jsxs16("label", { className: "szenen-field", children: [
11648
- /* @__PURE__ */ jsx16("span", { children: "Original der Modellantwort (unver\xE4nderlich)" }),
11649
- /* @__PURE__ */ jsx16(
11613
+ /* @__PURE__ */ jsxs12("label", { className: "szenen-field", children: [
11614
+ /* @__PURE__ */ jsx12("span", { children: "Original der Modellantwort (unver\xE4nderlich)" }),
11615
+ /* @__PURE__ */ jsx12(
11650
11616
  "textarea",
11651
11617
  {
11652
11618
  readOnly: true,
@@ -11657,12 +11623,12 @@ var RecoveryPanel = ({ port, lauf }) => {
11657
11623
  }
11658
11624
  )
11659
11625
  ] }),
11660
- /* @__PURE__ */ jsxs16("label", { className: "szenen-field", children: [
11661
- /* @__PURE__ */ jsxs16("span", { children: [
11626
+ /* @__PURE__ */ jsxs12("label", { className: "szenen-field", children: [
11627
+ /* @__PURE__ */ jsxs12("span", { children: [
11662
11628
  "Arbeitskopie",
11663
11629
  bearbeitet ? " (bearbeitet)" : ""
11664
11630
  ] }),
11665
- /* @__PURE__ */ jsx16(
11631
+ /* @__PURE__ */ jsx12(
11666
11632
  "textarea",
11667
11633
  {
11668
11634
  rows: 8,
@@ -11672,8 +11638,8 @@ var RecoveryPanel = ({ port, lauf }) => {
11672
11638
  }
11673
11639
  )
11674
11640
  ] }),
11675
- /* @__PURE__ */ jsxs16("div", { className: "szenen-rettung__aktionen", children: [
11676
- /* @__PURE__ */ jsx16(
11641
+ /* @__PURE__ */ jsxs12("div", { className: "szenen-rettung__aktionen", children: [
11642
+ /* @__PURE__ */ jsx12(
11677
11643
  "button",
11678
11644
  {
11679
11645
  type: "button",
@@ -11683,7 +11649,7 @@ var RecoveryPanel = ({ port, lauf }) => {
11683
11649
  children: "Arbeitskopie pr\xFCfen (kein Modellaufruf)"
11684
11650
  }
11685
11651
  ),
11686
- /* @__PURE__ */ jsx16(
11652
+ /* @__PURE__ */ jsx12(
11687
11653
  "button",
11688
11654
  {
11689
11655
  type: "button",
@@ -11693,7 +11659,7 @@ var RecoveryPanel = ({ port, lauf }) => {
11693
11659
  children: "Arbeitsfassung speichern"
11694
11660
  }
11695
11661
  ),
11696
- arbeitskopie !== null && /* @__PURE__ */ jsx16(
11662
+ arbeitskopie !== null && /* @__PURE__ */ jsx12(
11697
11663
  "button",
11698
11664
  {
11699
11665
  type: "button",
@@ -11708,15 +11674,15 @@ var RecoveryPanel = ({ port, lauf }) => {
11708
11674
  }
11709
11675
  )
11710
11676
  ] }),
11711
- meldung && /* @__PURE__ */ jsx16("p", { className: "szenen-error", role: "alert", "data-testid": "rettung-meldung", children: meldung }),
11712
- bewertung && /* @__PURE__ */ jsx16(Ausbeute, { bewertung }),
11713
- bewertung && bewertung.diagnostics.length > 0 && /* @__PURE__ */ jsxs16("div", { className: "szenen-diagnose", children: [
11714
- /* @__PURE__ */ jsx16("h5", { children: "Befunde an dieser Fassung" }),
11715
- /* @__PURE__ */ jsx16(Diagnosen, { befunde: bewertung.diagnostics, testId: "rettung-befunde" })
11677
+ meldung && /* @__PURE__ */ jsx12("p", { className: "szenen-error", role: "alert", "data-testid": "rettung-meldung", children: meldung }),
11678
+ bewertung && /* @__PURE__ */ jsx12(Ausbeute, { bewertung }),
11679
+ bewertung && bewertung.diagnostics.length > 0 && /* @__PURE__ */ jsxs12("div", { className: "szenen-diagnose", children: [
11680
+ /* @__PURE__ */ jsx12("h5", { children: "Befunde an dieser Fassung" }),
11681
+ /* @__PURE__ */ jsx12(Diagnosen, { befunde: bewertung.diagnostics, testId: "rettung-befunde" })
11716
11682
  ] }),
11717
- gesichert && /* @__PURE__ */ jsxs16("p", { "data-testid": "rettung-gesichert", children: [
11683
+ gesichert && /* @__PURE__ */ jsxs12("p", { "data-testid": "rettung-gesichert", children: [
11718
11684
  "Gespeichert als Arbeitsfassung ",
11719
- /* @__PURE__ */ jsx16("code", { children: gesichert.recovery_id }),
11685
+ /* @__PURE__ */ jsx12("code", { children: gesichert.recovery_id }),
11720
11686
  gesichert.edited ? " (bearbeitet)" : " (unver\xE4ndert)",
11721
11687
  ". Das Original des Laufs ist davon unber\xFChrt."
11722
11688
  ] })
@@ -11725,7 +11691,7 @@ var RecoveryPanel = ({ port, lauf }) => {
11725
11691
 
11726
11692
  // src/features/szenen/areas/ChainActions.tsx
11727
11693
  import { useState as useState15 } from "react";
11728
- import { Fragment as Fragment7, jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
11694
+ import { Fragment as Fragment7, jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
11729
11695
  var ChainActions = ({ port, runId, recoveryId }) => {
11730
11696
  const [graph, setGraph] = useState15(null);
11731
11697
  const [meldung, setMeldung] = useState15(null);
@@ -11751,14 +11717,14 @@ var ChainActions = ({ port, runId, recoveryId }) => {
11751
11717
  setLaeuft(false);
11752
11718
  }
11753
11719
  }
11754
- return /* @__PURE__ */ jsxs17("section", { className: "szenen-kette", "data-testid": "kette", children: [
11755
- /* @__PURE__ */ jsx17("h4", { children: "Draft-Kette" }),
11756
- /* @__PURE__ */ jsxs17("p", { className: "szenen-area__lead", children: [
11720
+ return /* @__PURE__ */ jsxs13("section", { className: "szenen-kette", "data-testid": "kette", children: [
11721
+ /* @__PURE__ */ jsx13("h4", { children: "Draft-Kette" }),
11722
+ /* @__PURE__ */ jsxs13("p", { className: "szenen-area__lead", children: [
11757
11723
  "Szene, Aufbau und Shot entstehen als zusammenh\xE4ngende Entw\xFCrfe. Daraus l\xE4sst sich sofort ein Prompt erzeugen \u2014 ",
11758
- /* @__PURE__ */ jsx17("strong", { children: "ohne" }),
11724
+ /* @__PURE__ */ jsx13("strong", { children: "ohne" }),
11759
11725
  " vorher etwas zu ver\xF6ffentlichen."
11760
11726
  ] }),
11761
- !graph && /* @__PURE__ */ jsx17(
11727
+ !graph && /* @__PURE__ */ jsx13(
11762
11728
  "button",
11763
11729
  {
11764
11730
  type: "button",
@@ -11768,34 +11734,34 @@ var ChainActions = ({ port, runId, recoveryId }) => {
11768
11734
  children: "Als Draft-Kette \xFCbernehmen"
11769
11735
  }
11770
11736
  ),
11771
- graph && /* @__PURE__ */ jsxs17("div", { "data-testid": "kette-ergebnis", children: [
11772
- /* @__PURE__ */ jsxs17("p", { children: [
11737
+ graph && /* @__PURE__ */ jsxs13("div", { "data-testid": "kette-ergebnis", children: [
11738
+ /* @__PURE__ */ jsxs13("p", { children: [
11773
11739
  "Kette ",
11774
- /* @__PURE__ */ jsx17("code", { children: graph.chainId }),
11740
+ /* @__PURE__ */ jsx13("code", { children: graph.chainId }),
11775
11741
  " angelegt. Kein Knoten ist ver\xF6ffentlicht."
11776
11742
  ] }),
11777
- /* @__PURE__ */ jsx17("ul", { "data-testid": "kette-knoten", children: graph.created.map((k) => /* @__PURE__ */ jsxs17("li", { "data-testid": `kette-knoten-${k.type}`, children: [
11778
- /* @__PURE__ */ jsx17("strong", { children: k.type }),
11743
+ /* @__PURE__ */ jsx13("ul", { "data-testid": "kette-knoten", children: graph.created.map((k) => /* @__PURE__ */ jsxs13("li", { "data-testid": `kette-knoten-${k.type}`, children: [
11744
+ /* @__PURE__ */ jsx13("strong", { children: k.type }),
11779
11745
  " \u2014 Element ",
11780
- /* @__PURE__ */ jsx17("code", { children: k.elementId }),
11746
+ /* @__PURE__ */ jsx13("code", { children: k.elementId }),
11781
11747
  ", Entwurf ",
11782
- /* @__PURE__ */ jsx17("code", { children: k.draftId }),
11748
+ /* @__PURE__ */ jsx13("code", { children: k.draftId }),
11783
11749
  " (Revision ",
11784
11750
  k.revision,
11785
11751
  ")"
11786
11752
  ] }, k.type)) }),
11787
- graph.missing.length > 0 && /* @__PURE__ */ jsxs17("div", { className: "szenen-diagnose", "data-testid": "kette-fehlend", children: [
11788
- /* @__PURE__ */ jsx17("h5", { children: "Unvollst\xE4ndig erzeugt" }),
11789
- /* @__PURE__ */ jsx17("ul", { children: graph.missing.map((m) => /* @__PURE__ */ jsxs17("li", { children: [
11790
- /* @__PURE__ */ jsx17("strong", { children: m.type }),
11753
+ graph.missing.length > 0 && /* @__PURE__ */ jsxs13("div", { className: "szenen-diagnose", "data-testid": "kette-fehlend", children: [
11754
+ /* @__PURE__ */ jsx13("h5", { children: "Unvollst\xE4ndig erzeugt" }),
11755
+ /* @__PURE__ */ jsx13("ul", { children: graph.missing.map((m) => /* @__PURE__ */ jsxs13("li", { children: [
11756
+ /* @__PURE__ */ jsx13("strong", { children: m.type }),
11791
11757
  ": ",
11792
11758
  m.reason
11793
11759
  ] }, m.type)) })
11794
11760
  ] })
11795
11761
  ] }),
11796
- shotKnoten && /* @__PURE__ */ jsxs17(Fragment7, { children: [
11797
- /* @__PURE__ */ jsx17("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".' }),
11798
- /* @__PURE__ */ jsx17(
11762
+ shotKnoten && /* @__PURE__ */ jsxs13(Fragment7, { children: [
11763
+ /* @__PURE__ */ jsx13("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".' }),
11764
+ /* @__PURE__ */ jsx13(
11799
11765
  PromptStartAction,
11800
11766
  {
11801
11767
  port,
@@ -11803,12 +11769,12 @@ var ChainActions = ({ port, runId, recoveryId }) => {
11803
11769
  }
11804
11770
  )
11805
11771
  ] }),
11806
- meldung && /* @__PURE__ */ jsx17("p", { className: "szenen-error", role: "alert", "data-testid": "kette-meldung", children: meldung })
11772
+ meldung && /* @__PURE__ */ jsx13("p", { className: "szenen-error", role: "alert", "data-testid": "kette-meldung", children: meldung })
11807
11773
  ] });
11808
11774
  };
11809
11775
 
11810
11776
  // src/features/szenen/areas/DeriveArea.tsx
11811
- import { Fragment as Fragment8, jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
11777
+ import { Fragment as Fragment8, jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
11812
11778
  var MODUS_TEXT = {
11813
11779
  prompt: "Nur Prompt",
11814
11780
  image: "Nur Bild",
@@ -11826,15 +11792,15 @@ var BelegFeld = ({ titel, text, testId, offen }) => {
11826
11792
  setKopiert(false);
11827
11793
  }
11828
11794
  }
11829
- return /* @__PURE__ */ jsxs18("details", { open: offen, "data-testid": `belege-${testId}`, children: [
11830
- /* @__PURE__ */ jsxs18("summary", { children: [
11795
+ return /* @__PURE__ */ jsxs14("details", { open: offen, "data-testid": `belege-${testId}`, children: [
11796
+ /* @__PURE__ */ jsxs14("summary", { children: [
11831
11797
  titel,
11832
11798
  " (",
11833
11799
  text.length,
11834
11800
  " Zeichen)"
11835
11801
  ] }),
11836
- /* @__PURE__ */ jsxs18("div", { className: "szenen-beleg__kopf", children: [
11837
- /* @__PURE__ */ jsx18(
11802
+ /* @__PURE__ */ jsxs14("div", { className: "szenen-beleg__kopf", children: [
11803
+ /* @__PURE__ */ jsx14(
11838
11804
  "button",
11839
11805
  {
11840
11806
  type: "button",
@@ -11843,9 +11809,9 @@ var BelegFeld = ({ titel, text, testId, offen }) => {
11843
11809
  children: "Kopieren"
11844
11810
  }
11845
11811
  ),
11846
- kopiert && /* @__PURE__ */ jsx18("span", { "data-testid": `kopiert-${testId}`, children: "Kopiert." })
11812
+ kopiert && /* @__PURE__ */ jsx14("span", { "data-testid": `kopiert-${testId}`, children: "Kopiert." })
11847
11813
  ] }),
11848
- /* @__PURE__ */ jsx18(
11814
+ /* @__PURE__ */ jsx14(
11849
11815
  "textarea",
11850
11816
  {
11851
11817
  ref: feld,
@@ -11859,8 +11825,8 @@ var BelegFeld = ({ titel, text, testId, offen }) => {
11859
11825
  )
11860
11826
  ] });
11861
11827
  };
11862
- var Belege = ({ lauf }) => /* @__PURE__ */ jsxs18("div", { className: "szenen-diagnose", "data-testid": "belege", children: [
11863
- lauf.raw_output ? /* @__PURE__ */ jsx18(
11828
+ var Belege = ({ lauf }) => /* @__PURE__ */ jsxs14("div", { className: "szenen-diagnose", "data-testid": "belege", children: [
11829
+ lauf.raw_output ? /* @__PURE__ */ jsx14(
11864
11830
  BelegFeld,
11865
11831
  {
11866
11832
  titel: "Rohantwort des Modells",
@@ -11871,9 +11837,9 @@ var Belege = ({ lauf }) => /* @__PURE__ */ jsxs18("div", { className: "szenen-di
11871
11837
  ) : (
11872
11838
  /* Kein Text ist auch eine Auskunft: Der Provider hat nichts geliefert,
11873
11839
  das Modell hat also nicht „falsch geantwortet". */
11874
- /* @__PURE__ */ jsx18("p", { "data-testid": "roh-antwort-fehlt", children: "Es gibt keine Rohantwort \u2014 der Lauf ist gescheitert, bevor ein Text ankam (etwa Netz, Sperre oder Providerfehler)." })
11840
+ /* @__PURE__ */ jsx14("p", { "data-testid": "roh-antwort-fehlt", children: "Es gibt keine Rohantwort \u2014 der Lauf ist gescheitert, bevor ein Text ankam (etwa Netz, Sperre oder Providerfehler)." })
11875
11841
  ),
11876
- /* @__PURE__ */ jsx18(
11842
+ /* @__PURE__ */ jsx14(
11877
11843
  BelegFeld,
11878
11844
  {
11879
11845
  titel: "Systemprompt dieses Laufs",
@@ -11885,18 +11851,18 @@ var Belege = ({ lauf }) => /* @__PURE__ */ jsxs18("div", { className: "szenen-di
11885
11851
  ] });
11886
11852
  var Herkunft = ({ lauf }) => {
11887
11853
  if (!lauf.follows) return null;
11888
- return /* @__PURE__ */ jsxs18("p", { className: "szenen-run__herkunft", "data-testid": "folgt-auf", children: [
11854
+ return /* @__PURE__ */ jsxs14("p", { className: "szenen-run__herkunft", "data-testid": "folgt-auf", children: [
11889
11855
  "Folgt auf Lauf ",
11890
- /* @__PURE__ */ jsx18("code", { children: lauf.follows.run_id }),
11856
+ /* @__PURE__ */ jsx14("code", { children: lauf.follows.run_id }),
11891
11857
  ".",
11892
11858
  lauf.status === "succeeded" && " Im Folgelauf gelungen."
11893
11859
  ] });
11894
11860
  };
11895
11861
  var Widerspruch = ({ lauf }) => {
11896
11862
  if (!lauf.reply) return null;
11897
- return /* @__PURE__ */ jsxs18("div", { className: "szenen-diagnose szenen-diagnose--antwort", "data-testid": "modell-antwort", children: [
11898
- /* @__PURE__ */ jsx18("h4", { children: "Das Modell antwortet auf die Beanstandung" }),
11899
- /* @__PURE__ */ jsx18("p", { children: lauf.reply })
11863
+ return /* @__PURE__ */ jsxs14("div", { className: "szenen-diagnose szenen-diagnose--antwort", "data-testid": "modell-antwort", children: [
11864
+ /* @__PURE__ */ jsx14("h4", { children: "Das Modell antwortet auf die Beanstandung" }),
11865
+ /* @__PURE__ */ jsx14("p", { children: lauf.reply })
11900
11866
  ] });
11901
11867
  };
11902
11868
  function readAsBase642(datei) {
@@ -11915,7 +11881,7 @@ var ERSTE_KACHELN = 12;
11915
11881
  function useSichtbareKacheln(alle, wurzel) {
11916
11882
  const [gesehen, setGesehen] = useState16([]);
11917
11883
  const schluessel = alle.join(" ");
11918
- useEffect8(() => {
11884
+ useEffect9(() => {
11919
11885
  const ziel = wurzel.current;
11920
11886
  if (!ziel || typeof IntersectionObserver === "undefined") return void 0;
11921
11887
  const beobachter = new IntersectionObserver((eintraege) => {
@@ -11937,7 +11903,7 @@ function useVorschauen(port, mediaRefs) {
11937
11903
  const gehalten = useRef4(/* @__PURE__ */ new Map());
11938
11904
  const ohneBild = useRef4(/* @__PURE__ */ new Set());
11939
11905
  const schluessel = mediaRefs.join(" ");
11940
- useEffect8(() => {
11906
+ useEffect9(() => {
11941
11907
  const bestand = port.imageLibrary;
11942
11908
  if (!bestand?.loadPreview) return void 0;
11943
11909
  const refs = schluessel ? schluessel.split(" ") : [];
@@ -12003,10 +11969,10 @@ var BildWaehler = ({ port, gewaehlt, onWaehlen, onEntfernen }) => {
12003
11969
  if (item.images.length === 1) onWaehlen(deckbild);
12004
11970
  else setFokus(item.itemRef === fokus ? null : item.itemRef);
12005
11971
  }
12006
- return /* @__PURE__ */ jsxs18("div", { className: "szenen-bildwahl", "data-testid": "bildwahl", children: [
12007
- /* @__PURE__ */ jsxs18("label", { className: "szenen-field", children: [
12008
- /* @__PURE__ */ jsx18("span", { children: "Bild aus dem Bestand" }),
12009
- /* @__PURE__ */ jsx18(
11972
+ return /* @__PURE__ */ jsxs14("div", { className: "szenen-bildwahl", "data-testid": "bildwahl", children: [
11973
+ /* @__PURE__ */ jsxs14("label", { className: "szenen-field", children: [
11974
+ /* @__PURE__ */ jsx14("span", { children: "Bild aus dem Bestand" }),
11975
+ /* @__PURE__ */ jsx14(
12010
11976
  "input",
12011
11977
  {
12012
11978
  type: "search",
@@ -12020,23 +11986,23 @@ var BildWaehler = ({ port, gewaehlt, onWaehlen, onEntfernen }) => {
12020
11986
  }
12021
11987
  )
12022
11988
  ] }),
12023
- items.status === "loading" && /* @__PURE__ */ jsx18("p", { children: "Bilder werden geladen \u2026" }),
12024
- items.status === "error" && /* @__PURE__ */ jsxs18("p", { className: "szenen-error", role: "alert", children: [
11989
+ items.status === "loading" && /* @__PURE__ */ jsx14("p", { children: "Bilder werden geladen \u2026" }),
11990
+ items.status === "error" && /* @__PURE__ */ jsxs14("p", { className: "szenen-error", role: "alert", children: [
12025
11991
  "Der Bildbestand ist nicht lesbar: ",
12026
11992
  items.message
12027
11993
  ] }),
12028
- items.status === "ready" && werke.length === 0 && /* @__PURE__ */ jsx18("p", { className: "szenen-empty", "data-testid": "bildwahl-leer", children: "Zu dieser Suche gibt es kein Bild. Ohne Treffer bleibt der Upload." }),
12029
- werke.length > 0 && /* @__PURE__ */ jsx18(
11994
+ items.status === "ready" && werke.length === 0 && /* @__PURE__ */ jsx14("p", { className: "szenen-empty", "data-testid": "bildwahl-leer", children: "Zu dieser Suche gibt es kein Bild. Ohne Treffer bleibt der Upload." }),
11995
+ werke.length > 0 && /* @__PURE__ */ jsx14(
12030
11996
  "div",
12031
11997
  {
12032
11998
  className: "szenen-bildwahl__browser",
12033
11999
  ref: browser,
12034
12000
  "data-testid": "bildwahl-werke",
12035
- children: /* @__PURE__ */ jsx18("ul", { className: "szenen-bildwahl__raster", children: werke.map((item) => {
12001
+ children: /* @__PURE__ */ jsx14("ul", { className: "szenen-bildwahl__raster", children: werke.map((item) => {
12036
12002
  const deckbild = item.images[0];
12037
12003
  if (!deckbild) return null;
12038
12004
  const fokussiert = item.itemRef === fokus;
12039
- return /* @__PURE__ */ jsx18("li", { "data-media-ref": deckbild.mediaRef, children: /* @__PURE__ */ jsxs18(
12005
+ return /* @__PURE__ */ jsx14("li", { "data-media-ref": deckbild.mediaRef, children: /* @__PURE__ */ jsxs14(
12040
12006
  "button",
12041
12007
  {
12042
12008
  type: "button",
@@ -12046,7 +12012,7 @@ var BildWaehler = ({ port, gewaehlt, onWaehlen, onEntfernen }) => {
12046
12012
  "data-testid": `item-waehlen-${item.itemRef}`,
12047
12013
  title: item.title,
12048
12014
  children: [
12049
- /* @__PURE__ */ jsx18(
12015
+ /* @__PURE__ */ jsx14(
12050
12016
  Kachel,
12051
12017
  {
12052
12018
  quelle: quelleVon(deckbild),
@@ -12054,7 +12020,7 @@ var BildWaehler = ({ port, gewaehlt, onWaehlen, onEntfernen }) => {
12054
12020
  ...gescheitert.has(deckbild.mediaRef) ? { leerText: "Vorschau fehlt" } : {}
12055
12021
  }
12056
12022
  ),
12057
- item.images.length > 1 && /* @__PURE__ */ jsxs18(
12023
+ item.images.length > 1 && /* @__PURE__ */ jsxs14(
12058
12024
  "span",
12059
12025
  {
12060
12026
  className: "szenen-bildwahl__anzahl",
@@ -12065,22 +12031,22 @@ var BildWaehler = ({ port, gewaehlt, onWaehlen, onEntfernen }) => {
12065
12031
  ]
12066
12032
  }
12067
12033
  ),
12068
- /* @__PURE__ */ jsx18("span", { className: "szenen-bildwahl__kacheltitel", children: item.title })
12034
+ /* @__PURE__ */ jsx14("span", { className: "szenen-bildwahl__kacheltitel", children: item.title })
12069
12035
  ]
12070
12036
  }
12071
12037
  ) }, item.itemRef);
12072
12038
  }) })
12073
12039
  }
12074
12040
  ),
12075
- werk && /* @__PURE__ */ jsxs18("section", { className: "szenen-bildwahl__inspector", "data-testid": "bildwahl-galerie", children: [
12076
- /* @__PURE__ */ jsxs18("header", { className: "szenen-bildwahl__inspektorkopf", children: [
12077
- /* @__PURE__ */ jsxs18("span", { className: "szenen-bildwahl__werktitel", "data-testid": "bildwahl-werktitel", children: [
12041
+ werk && /* @__PURE__ */ jsxs14("section", { className: "szenen-bildwahl__inspector", "data-testid": "bildwahl-galerie", children: [
12042
+ /* @__PURE__ */ jsxs14("header", { className: "szenen-bildwahl__inspektorkopf", children: [
12043
+ /* @__PURE__ */ jsxs14("span", { className: "szenen-bildwahl__werktitel", "data-testid": "bildwahl-werktitel", children: [
12078
12044
  werk.title,
12079
12045
  " \xB7 ",
12080
12046
  werk.images.length,
12081
12047
  " Bilder"
12082
12048
  ] }),
12083
- /* @__PURE__ */ jsx18(
12049
+ /* @__PURE__ */ jsx14(
12084
12050
  "button",
12085
12051
  {
12086
12052
  type: "button",
@@ -12091,7 +12057,7 @@ var BildWaehler = ({ port, gewaehlt, onWaehlen, onEntfernen }) => {
12091
12057
  }
12092
12058
  )
12093
12059
  ] }),
12094
- /* @__PURE__ */ jsx18("ul", { className: "szenen-bildwahl__streifen", children: werk.images.map((bild, position) => /* @__PURE__ */ jsx18("li", { children: /* @__PURE__ */ jsxs18(
12060
+ /* @__PURE__ */ jsx14("ul", { className: "szenen-bildwahl__streifen", children: werk.images.map((bild, position) => /* @__PURE__ */ jsx14("li", { children: /* @__PURE__ */ jsxs14(
12095
12061
  "button",
12096
12062
  {
12097
12063
  type: "button",
@@ -12101,7 +12067,7 @@ var BildWaehler = ({ port, gewaehlt, onWaehlen, onEntfernen }) => {
12101
12067
  "data-testid": `bild-waehlen-${bild.mediaRef}`,
12102
12068
  title: bild.title,
12103
12069
  children: [
12104
- /* @__PURE__ */ jsx18(
12070
+ /* @__PURE__ */ jsx14(
12105
12071
  Kachel,
12106
12072
  {
12107
12073
  quelle: quelleVon(bild),
@@ -12109,7 +12075,7 @@ var BildWaehler = ({ port, gewaehlt, onWaehlen, onEntfernen }) => {
12109
12075
  ...gescheitert.has(bild.mediaRef) ? { leerText: "Vorschau fehlt" } : {}
12110
12076
  }
12111
12077
  ),
12112
- /* @__PURE__ */ jsxs18("span", { className: "szenen-bildwahl__nummer", children: [
12078
+ /* @__PURE__ */ jsxs14("span", { className: "szenen-bildwahl__nummer", children: [
12113
12079
  "#",
12114
12080
  position + 1
12115
12081
  ] })
@@ -12117,10 +12083,10 @@ var BildWaehler = ({ port, gewaehlt, onWaehlen, onEntfernen }) => {
12117
12083
  }
12118
12084
  ) }, bild.mediaRef)) })
12119
12085
  ] }),
12120
- gewaehlt.length > 0 && /* @__PURE__ */ jsx18("ul", { className: "szenen-bildwahl__gewaehlt", "data-testid": "bilder-gewaehlt", children: gewaehlt.map((bild) => /* @__PURE__ */ jsxs18("li", { children: [
12121
- /* @__PURE__ */ jsx18(Kachel, { quelle: quelleVon(bild), alt: bild.title }),
12122
- /* @__PURE__ */ jsx18("span", { className: "szenen-bildwahl__kacheltitel", children: bild.title }),
12123
- /* @__PURE__ */ jsx18(
12086
+ gewaehlt.length > 0 && /* @__PURE__ */ jsx14("ul", { className: "szenen-bildwahl__gewaehlt", "data-testid": "bilder-gewaehlt", children: gewaehlt.map((bild) => /* @__PURE__ */ jsxs14("li", { children: [
12087
+ /* @__PURE__ */ jsx14(Kachel, { quelle: quelleVon(bild), alt: bild.title }),
12088
+ /* @__PURE__ */ jsx14("span", { className: "szenen-bildwahl__kacheltitel", children: bild.title }),
12089
+ /* @__PURE__ */ jsx14(
12124
12090
  "button",
12125
12091
  {
12126
12092
  type: "button",
@@ -12156,6 +12122,15 @@ var DeriveArea = ({ port, contextId }) => {
12156
12122
  () => port.derivation.listPolicies(contextId),
12157
12123
  [port, contextId]
12158
12124
  );
12125
+ const sortiert = useMemo3(() => regeln.status === "ready" ? [...regeln.value].sort((a, b) => {
12126
+ const szeneZuerst = Number(b.produces.includes("scene")) - Number(a.produces.includes("scene"));
12127
+ return szeneZuerst !== 0 ? szeneZuerst : a.title.localeCompare(b.title, "de");
12128
+ }) : [], [regeln]);
12129
+ useEffect9(() => {
12130
+ if (policyVersionId) return;
12131
+ const fuerSzene = sortiert.find((r) => r.produces.includes("scene"));
12132
+ if (fuerSzene) setPolicyVersionId(fuerSzene.versionId);
12133
+ }, [sortiert, policyVersionId]);
12159
12134
  const gewaehlt = regeln.status === "ready" ? regeln.value.find((r) => r.versionId === policyVersionId) ?? null : null;
12160
12135
  async function starten(folgt) {
12161
12136
  if (!gewaehlt) {
@@ -12230,12 +12205,12 @@ ${teile.map((t) => `- ${t}`).join("\n")}`;
12230
12205
  const text = beanstandung ?? vorgabeBeanstandung(satz);
12231
12206
  const bilderFehlen = satz.input.images.some((bild) => bild.kind !== "library");
12232
12207
  const bereit = Boolean(text.trim()) && !bilderFehlen && !laeuft;
12233
- return /* @__PURE__ */ jsxs18("div", { className: "szenen-folgelauf", "data-testid": "folgelauf", children: [
12234
- /* @__PURE__ */ jsx18("h4", { children: "Korrektur- oder Erg\xE4nzungslauf" }),
12235
- /* @__PURE__ */ jsx18("p", { className: "szenen-area__lead", children: satz.status === "failed" ? "Das Modell bekommt seine Antwort und die Beanstandung noch einmal vorgelegt." : "Das Ergebnis steht. Wenn etwas offen blieb, kann das Modell nachbessern." }),
12236
- /* @__PURE__ */ jsxs18("label", { className: "szenen-field", children: [
12237
- /* @__PURE__ */ jsx18("span", { children: "Beanstandung" }),
12238
- /* @__PURE__ */ jsx18(
12208
+ return /* @__PURE__ */ jsxs14("div", { className: "szenen-folgelauf", "data-testid": "folgelauf", children: [
12209
+ /* @__PURE__ */ jsx14("h4", { children: "Korrektur- oder Erg\xE4nzungslauf" }),
12210
+ /* @__PURE__ */ jsx14("p", { className: "szenen-area__lead", children: satz.status === "failed" ? "Das Modell bekommt seine Antwort und die Beanstandung noch einmal vorgelegt." : "Das Ergebnis steht. Wenn etwas offen blieb, kann das Modell nachbessern." }),
12211
+ /* @__PURE__ */ jsxs14("label", { className: "szenen-field", children: [
12212
+ /* @__PURE__ */ jsx14("span", { children: "Beanstandung" }),
12213
+ /* @__PURE__ */ jsx14(
12239
12214
  "textarea",
12240
12215
  {
12241
12216
  rows: 4,
@@ -12245,9 +12220,9 @@ ${teile.map((t) => `- ${t}`).join("\n")}`;
12245
12220
  }
12246
12221
  )
12247
12222
  ] }),
12248
- /* @__PURE__ */ jsxs18("label", { className: "szenen-field", children: [
12249
- /* @__PURE__ */ jsx18("span", { children: "Zus\xE4tzliche Anweisung (optional)" }),
12250
- /* @__PURE__ */ jsx18(
12223
+ /* @__PURE__ */ jsxs14("label", { className: "szenen-field", children: [
12224
+ /* @__PURE__ */ jsx14("span", { children: "Zus\xE4tzliche Anweisung (optional)" }),
12225
+ /* @__PURE__ */ jsx14(
12251
12226
  "textarea",
12252
12227
  {
12253
12228
  rows: 2,
@@ -12258,8 +12233,8 @@ ${teile.map((t) => `- ${t}`).join("\n")}`;
12258
12233
  }
12259
12234
  )
12260
12235
  ] }),
12261
- bilderFehlen && /* @__PURE__ */ jsx18("p", { className: "szenen-error", "data-testid": "folgelauf-ohne-bild", children: "Die Bilder dieses Laufs wurden nicht im Bestand abgelegt \u2014 er ist \xE4lter als diese M\xF6glichkeit. Ein Folgelauf ohne sie k\xF6nnte ein fehlendes Pflichtfeld nur erfinden. Starten Sie einen neuen Lauf mit dem Referenzbild; dessen Bilder bleiben dann erhalten." }),
12262
- /* @__PURE__ */ jsx18(
12236
+ bilderFehlen && /* @__PURE__ */ jsx14("p", { className: "szenen-error", "data-testid": "folgelauf-ohne-bild", children: "Die Bilder dieses Laufs wurden nicht im Bestand abgelegt \u2014 er ist \xE4lter als diese M\xF6glichkeit. Ein Folgelauf ohne sie k\xF6nnte ein fehlendes Pflichtfeld nur erfinden. Starten Sie einen neuen Lauf mit dem Referenzbild; dessen Bilder bleiben dann erhalten." }),
12237
+ /* @__PURE__ */ jsx14(
12263
12238
  "button",
12264
12239
  {
12265
12240
  type: "button",
@@ -12299,19 +12274,19 @@ ${teile.map((t) => `- ${t}`).join("\n")}`;
12299
12274
  setMeldung(ergebnis.message);
12300
12275
  }
12301
12276
  }
12302
- return /* @__PURE__ */ jsxs18("div", { className: "szenen-derive", "data-testid": "bereich-rekonstruktion", children: [
12303
- /* @__PURE__ */ jsx18("p", { className: "szenen-area__lead", children: "Aus einem Referenzbild, einem Prompt oder beidem einen Szenenentwurf vorschlagen lassen. Der Vorschlag wird nie ver\xF6ffentlicht \u2014 er wird ein Entwurf, den Sie pr\xFCfen und \xE4ndern." }),
12304
- regeln.status === "loading" && /* @__PURE__ */ jsx18("p", { children: "Regeln werden geladen \u2026" }),
12305
- regeln.status === "error" && /* @__PURE__ */ jsxs18("p", { className: "szenen-error", role: "alert", children: [
12277
+ return /* @__PURE__ */ jsxs14("div", { className: "szenen-derive", "data-testid": "bereich-rekonstruktion", children: [
12278
+ /* @__PURE__ */ jsx14("p", { className: "szenen-area__lead", children: "Aus einem Referenzbild, einem Prompt oder beidem einen Szenenentwurf vorschlagen lassen. Der Vorschlag wird nie ver\xF6ffentlicht \u2014 er wird ein Entwurf, den Sie pr\xFCfen und \xE4ndern." }),
12279
+ regeln.status === "loading" && /* @__PURE__ */ jsx14("p", { children: "Regeln werden geladen \u2026" }),
12280
+ regeln.status === "error" && /* @__PURE__ */ jsxs14("p", { className: "szenen-error", role: "alert", children: [
12306
12281
  "Die Regeln konnten nicht gelesen werden: ",
12307
12282
  regeln.message
12308
12283
  ] }),
12309
- regeln.status === "ready" && regeln.value.length === 0 && /* @__PURE__ */ jsxs18("p", { className: "szenen-empty", children: [
12284
+ regeln.status === "ready" && regeln.value.length === 0 && /* @__PURE__ */ jsxs14("p", { className: "szenen-empty", children: [
12310
12285
  "In diesem Kontext ist keine Rekonstruktionsregel (",
12311
- /* @__PURE__ */ jsx18("code", { children: "scene_derivation_policy" }),
12312
- ') ver\xF6ffentlicht. Ohne sie ist kein Lauf reproduzierbar \u2014 legen Sie hier eine unter \u201E1 \xB7 Bausteine" an, oder wechseln Sie in den Kontext, in dem Ihre Regel liegt. Regeln aus anderen Kontexten stehen hier bewusst nicht zur Auswahl.'
12286
+ /* @__PURE__ */ jsx14("code", { children: "scene_derivation_policy" }),
12287
+ ') ver\xF6ffentlicht. Ohne sie ist kein Lauf reproduzierbar \u2014 legen Sie eine unter \u201EErweitert" an, oder wechseln Sie in den Kontext, in dem Ihre Regel liegt. Regeln aus anderen Kontexten stehen hier bewusst nicht zur Auswahl.'
12313
12288
  ] }),
12314
- regeln.status === "ready" && regeln.value.length > 0 && /* @__PURE__ */ jsxs18(
12289
+ regeln.status === "ready" && regeln.value.length > 0 && /* @__PURE__ */ jsxs14(
12315
12290
  "form",
12316
12291
  {
12317
12292
  className: "szenen-form",
@@ -12320,17 +12295,17 @@ ${teile.map((t) => `- ${t}`).join("\n")}`;
12320
12295
  void starten();
12321
12296
  },
12322
12297
  children: [
12323
- /* @__PURE__ */ jsxs18("label", { className: "szenen-field", children: [
12324
- /* @__PURE__ */ jsx18("span", { children: "Regel" }),
12325
- /* @__PURE__ */ jsxs18(
12298
+ /* @__PURE__ */ jsxs14("label", { className: "szenen-field", children: [
12299
+ /* @__PURE__ */ jsx14("span", { children: "Regel" }),
12300
+ /* @__PURE__ */ jsxs14(
12326
12301
  "select",
12327
12302
  {
12328
12303
  value: policyVersionId,
12329
12304
  onChange: (e) => setPolicyVersionId(e.target.value),
12330
12305
  "data-testid": "regel-auswahl",
12331
12306
  children: [
12332
- /* @__PURE__ */ jsx18("option", { value: "", children: "\u2014 bitte w\xE4hlen \u2014" }),
12333
- regeln.value.map((regel) => /* @__PURE__ */ jsxs18("option", { value: regel.versionId, children: [
12307
+ /* @__PURE__ */ jsx14("option", { value: "", children: "\u2014 bitte w\xE4hlen \u2014" }),
12308
+ sortiert.map((regel) => /* @__PURE__ */ jsxs14("option", { value: regel.versionId, children: [
12334
12309
  regel.title,
12335
12310
  " (",
12336
12311
  regel.produces.join(", "),
@@ -12340,21 +12315,21 @@ ${teile.map((t) => `- ${t}`).join("\n")}`;
12340
12315
  }
12341
12316
  )
12342
12317
  ] }),
12343
- /* @__PURE__ */ jsxs18("label", { className: "szenen-field", children: [
12344
- /* @__PURE__ */ jsx18("span", { children: "Eingang" }),
12345
- /* @__PURE__ */ jsx18(
12318
+ /* @__PURE__ */ jsxs14("label", { className: "szenen-field", children: [
12319
+ /* @__PURE__ */ jsx14("span", { children: "Eingang" }),
12320
+ /* @__PURE__ */ jsx14(
12346
12321
  "select",
12347
12322
  {
12348
12323
  value: modus,
12349
12324
  onChange: (e) => setModus(e.target.value),
12350
12325
  "data-testid": "modus-auswahl",
12351
- children: (gewaehlt ? gewaehlt.inputModes : ["prompt", "image", "image_prompt"]).map((m) => /* @__PURE__ */ jsx18("option", { value: m, children: MODUS_TEXT[m] }, m))
12326
+ children: (gewaehlt ? gewaehlt.inputModes : ["prompt", "image", "image_prompt"]).map((m) => /* @__PURE__ */ jsx14("option", { value: m, children: MODUS_TEXT[m] }, m))
12352
12327
  }
12353
12328
  )
12354
12329
  ] }),
12355
- modus !== "image" && /* @__PURE__ */ jsxs18("label", { className: "szenen-field", children: [
12356
- /* @__PURE__ */ jsx18("span", { children: "Referenzprompt" }),
12357
- /* @__PURE__ */ jsx18(
12330
+ modus !== "image" && /* @__PURE__ */ jsxs14("label", { className: "szenen-field", children: [
12331
+ /* @__PURE__ */ jsx14("span", { children: "Referenzprompt" }),
12332
+ /* @__PURE__ */ jsx14(
12358
12333
  "textarea",
12359
12334
  {
12360
12335
  value: promptText,
@@ -12364,8 +12339,8 @@ ${teile.map((t) => `- ${t}`).join("\n")}`;
12364
12339
  }
12365
12340
  )
12366
12341
  ] }),
12367
- modus !== "prompt" && /* @__PURE__ */ jsxs18(Fragment8, { children: [
12368
- port.imageLibrary && /* @__PURE__ */ jsx18(
12342
+ modus !== "prompt" && /* @__PURE__ */ jsxs14(Fragment8, { children: [
12343
+ port.imageLibrary && /* @__PURE__ */ jsx14(
12369
12344
  BildWaehler,
12370
12345
  {
12371
12346
  port,
@@ -12374,9 +12349,9 @@ ${teile.map((t) => `- ${t}`).join("\n")}`;
12374
12349
  onEntfernen: (ref) => setBestandsbilder((v) => v.filter((b) => b.mediaRef !== ref))
12375
12350
  }
12376
12351
  ),
12377
- /* @__PURE__ */ jsxs18("label", { className: "szenen-field", children: [
12378
- /* @__PURE__ */ jsx18("span", { children: port.imageLibrary ? "Oder hochladen" : "Referenzbild" }),
12379
- /* @__PURE__ */ jsx18(
12352
+ /* @__PURE__ */ jsxs14("label", { className: "szenen-field", children: [
12353
+ /* @__PURE__ */ jsx14("span", { children: port.imageLibrary ? "Oder hochladen" : "Referenzbild" }),
12354
+ /* @__PURE__ */ jsx14(
12380
12355
  "input",
12381
12356
  {
12382
12357
  type: "file",
@@ -12386,143 +12361,467 @@ ${teile.map((t) => `- ${t}`).join("\n")}`;
12386
12361
  "data-testid": "bild-eingabe"
12387
12362
  }
12388
12363
  ),
12389
- port.imageLibrary && /* @__PURE__ */ jsx18("small", { "data-testid": "upload-hinweis", children: "Hochgeladene Bilder werden im Bestand abgelegt \u2014 nur so ist sp\xE4ter ein Folgelauf damit m\xF6glich." })
12364
+ port.imageLibrary && /* @__PURE__ */ jsx14("small", { "data-testid": "upload-hinweis", children: "Hochgeladene Bilder werden im Bestand abgelegt \u2014 nur so ist sp\xE4ter ein Folgelauf damit m\xF6glich." })
12390
12365
  ] })
12391
12366
  ] }),
12392
- /* @__PURE__ */ jsx18("button", { type: "submit", disabled: !gewaehlt || laeuft, "data-testid": "lauf-starten", children: laeuft ? "Rekonstruiert \u2026" : "Rekonstruieren" })
12367
+ /* @__PURE__ */ jsx14("button", { type: "submit", disabled: !gewaehlt || laeuft, "data-testid": "lauf-starten", children: laeuft ? "Rekonstruiert \u2026" : "Rekonstruieren" })
12393
12368
  ]
12394
12369
  }
12395
12370
  ),
12396
- meldung && /* @__PURE__ */ jsx18("p", { className: "szenen-error", role: "alert", "data-testid": "derive-meldung", children: meldung }),
12397
- lauf && lauf.status === "failed" && /* @__PURE__ */ jsxs18("section", { className: "szenen-run szenen-run--failed", "data-testid": "lauf-fehler", children: [
12398
- /* @__PURE__ */ jsx18("h3", { children: "Der Lauf ist gescheitert" }),
12399
- /* @__PURE__ */ jsxs18("p", { children: [
12400
- /* @__PURE__ */ jsx18("strong", { children: lauf.failure?.class }),
12371
+ meldung && /* @__PURE__ */ jsx14("p", { className: "szenen-error", role: "alert", "data-testid": "derive-meldung", children: meldung }),
12372
+ lauf && lauf.status === "failed" && /* @__PURE__ */ jsxs14("section", { className: "szenen-run szenen-run--failed", "data-testid": "lauf-fehler", children: [
12373
+ /* @__PURE__ */ jsx14("h3", { children: "Der Lauf ist gescheitert" }),
12374
+ /* @__PURE__ */ jsxs14("p", { children: [
12375
+ /* @__PURE__ */ jsx14("strong", { children: lauf.failure?.class }),
12401
12376
  " \u2014 ",
12402
12377
  lauf.failure?.message
12403
12378
  ] }),
12404
- lauf.failure?.diagnostics && lauf.failure.diagnostics.length > 0 && /* @__PURE__ */ jsxs18("div", { className: "szenen-diagnose", "data-testid": "lauf-diagnosen", children: [
12405
- /* @__PURE__ */ jsx18("h4", { children: "Befunde" }),
12406
- /* @__PURE__ */ jsx18(Diagnosen, { befunde: lauf.failure.diagnostics, testId: "lauf-befunde" })
12379
+ lauf.failure?.diagnostics && lauf.failure.diagnostics.length > 0 && /* @__PURE__ */ jsxs14("div", { className: "szenen-diagnose", "data-testid": "lauf-diagnosen", children: [
12380
+ /* @__PURE__ */ jsx14("h4", { children: "Befunde" }),
12381
+ /* @__PURE__ */ jsx14(Diagnosen, { befunde: lauf.failure.diagnostics, testId: "lauf-befunde" })
12382
+ ] }),
12383
+ /* @__PURE__ */ jsx14(Herkunft, { lauf }),
12384
+ /* @__PURE__ */ jsx14(Widerspruch, { lauf }),
12385
+ /* @__PURE__ */ jsx14(Belege, { lauf }),
12386
+ /* @__PURE__ */ jsx14(RecoveryPanel, { port, lauf }),
12387
+ folgeblock(lauf)
12388
+ ] }),
12389
+ lauf && lauf.status === "succeeded" && /* @__PURE__ */ jsxs14("section", { className: "szenen-run", "data-testid": "lauf-ergebnis", children: [
12390
+ /* @__PURE__ */ jsx14("h3", { children: "Vorschlag" }),
12391
+ /* @__PURE__ */ jsx14(Herkunft, { lauf }),
12392
+ /* @__PURE__ */ jsx14(Widerspruch, { lauf }),
12393
+ /* @__PURE__ */ jsx14("p", { className: "szenen-run__feedback", children: lauf.feedback }),
12394
+ lauf.conflicts.length > 0 && /* @__PURE__ */ jsxs14("div", { className: "szenen-diagnose szenen-diagnose--konflikt", "data-testid": "konflikte", children: [
12395
+ /* @__PURE__ */ jsx14("h4", { children: "Widerspr\xFCche zwischen Bild und Prompt" }),
12396
+ /* @__PURE__ */ jsx14("ul", { children: lauf.conflicts.map((k, i) => /* @__PURE__ */ jsxs14("li", { children: [
12397
+ /* @__PURE__ */ jsx14("code", { children: k.field }),
12398
+ ": Bild sagt \u201E",
12399
+ k.from_image,
12400
+ '", Prompt sagt \u201E',
12401
+ k.from_prompt,
12402
+ '". Nichts davon wurde \xFCbernommen.'
12403
+ ] }, i)) })
12404
+ ] }),
12405
+ lauf.not_derivable.length > 0 && /* @__PURE__ */ jsxs14("div", { className: "szenen-diagnose", "data-testid": "nicht-ableitbar", children: [
12406
+ /* @__PURE__ */ jsx14("h4", { children: "Nicht ableitbar" }),
12407
+ /* @__PURE__ */ jsx14("ul", { children: lauf.not_derivable.map((n, i) => /* @__PURE__ */ jsxs14("li", { children: [
12408
+ /* @__PURE__ */ jsx14("code", { children: n.field }),
12409
+ ": ",
12410
+ n.reason
12411
+ ] }, i)) })
12412
+ ] }),
12413
+ lauf.assumptions.length > 0 && /* @__PURE__ */ jsxs14("div", { className: "szenen-diagnose", "data-testid": "annahmen", children: [
12414
+ /* @__PURE__ */ jsx14("h4", { children: "Erschlossen, nicht belegt" }),
12415
+ /* @__PURE__ */ jsx14("ul", { children: lauf.assumptions.map((a, i) => /* @__PURE__ */ jsx14("li", { children: a }, i)) })
12416
+ ] }),
12417
+ lauf.proposals.map((vorschlag) => {
12418
+ const bezug = REFERENCE_FIELD[vorschlag.type];
12419
+ const fertig = uebernommen[vorschlag.type];
12420
+ return /* @__PURE__ */ jsxs14(
12421
+ "article",
12422
+ {
12423
+ className: "szenen-proposal",
12424
+ "data-testid": `vorschlag-${vorschlag.type}`,
12425
+ children: [
12426
+ /* @__PURE__ */ jsx14("h4", { children: vorschlag.type }),
12427
+ !fertig && /* @__PURE__ */ jsxs14("label", { className: "szenen-field", children: [
12428
+ /* @__PURE__ */ jsx14("span", { children: "Titel" }),
12429
+ /* @__PURE__ */ jsx14(
12430
+ "input",
12431
+ {
12432
+ type: "text",
12433
+ value: titelFuer(vorschlag.type),
12434
+ onChange: (e) => setTitel((v) => ({
12435
+ ...v,
12436
+ [vorschlag.type]: e.target.value
12437
+ })),
12438
+ placeholder: fallbackProposalTitle(vorschlag.type),
12439
+ "data-testid": `titel-${vorschlag.type}`
12440
+ }
12441
+ )
12442
+ ] }),
12443
+ /* @__PURE__ */ jsx14("pre", { className: "szenen-proposal__payload", children: JSON.stringify(vorschlag.payload, null, 2) }),
12444
+ bezug && !fertig && /* @__PURE__ */ jsxs14(Fragment8, { children: [
12445
+ /* @__PURE__ */ jsx14(
12446
+ ReferencePicker,
12447
+ {
12448
+ port,
12449
+ contextId,
12450
+ type: bezug.refersTo,
12451
+ label: `Ver\xF6ffentlichte ${bezug.refersTo}-Version, auf die dieser Entwurf zeigen soll`,
12452
+ testId: `referenz-${vorschlag.type}`,
12453
+ onPick: (ref) => setReferenzen((v) => ({
12454
+ ...v,
12455
+ [vorschlag.type]: ref.version_id
12456
+ }))
12457
+ }
12458
+ ),
12459
+ referenzen[vorschlag.type] ? /* @__PURE__ */ jsxs14("p", { "data-testid": `referenz-gewaehlt-${vorschlag.type}`, children: [
12460
+ "Zeigt auf Version ",
12461
+ /* @__PURE__ */ jsx14("code", { children: referenzen[vorschlag.type] }),
12462
+ "."
12463
+ ] }) : (
12464
+ /* Der Grund steht **vor** der Handlung. Den Nutzer erst
12465
+ auf einen Knopf drücken zu lassen, um ihm dann eine
12466
+ Ablehnung zu zeigen, ist keine Auskunft. */
12467
+ /* @__PURE__ */ jsxs14("p", { "data-testid": `referenz-fehlt-${vorschlag.type}`, children: [
12468
+ "Diese ",
12469
+ /* @__PURE__ */ jsx14("strong", { children: "Einzel\xFCbernahme" }),
12470
+ " braucht eine ver\xF6ffentlichte ",
12471
+ bezug.refersTo,
12472
+ "-Version, auf die der Entwurf zeigt (D-03) \u2014 sie ist der Weg in einen bestehenden, l\xE4ngst ver\xF6ffentlichten Zusammenhang. Wollen Sie aus diesem Lauf erst einmal einen Prompt ausprobieren, nehmen Sie unten die ",
12473
+ /* @__PURE__ */ jsx14("strong", { children: "Draft-Kette" }),
12474
+ ": Dort entstehen Szene, Aufbau und Shot zusammenh\xE4ngend, und es muss nichts ver\xF6ffentlicht werden."
12475
+ ] })
12476
+ )
12477
+ ] }),
12478
+ fertig ? /* @__PURE__ */ jsxs14("p", { className: "szenen-proposal__done", children: [
12479
+ "Als Entwurf \xFCbernommen: ",
12480
+ /* @__PURE__ */ jsx14("code", { children: fertig }),
12481
+ ". Er ist noch nicht ver\xF6ffentlicht."
12482
+ ] }) : /* @__PURE__ */ jsx14(
12483
+ "button",
12484
+ {
12485
+ type: "button",
12486
+ onClick: () => void uebernehmen(vorschlag.type),
12487
+ disabled: Boolean(bezug) && !referenzen[vorschlag.type],
12488
+ "data-testid": `uebernehmen-${vorschlag.type}`,
12489
+ children: "Als Entwurf \xFCbernehmen"
12490
+ }
12491
+ )
12492
+ ]
12493
+ },
12494
+ vorschlag.type
12495
+ );
12496
+ }),
12497
+ /* @__PURE__ */ jsx14(ChainActions, { port, runId: lauf.run_id }),
12498
+ /* @__PURE__ */ jsx14(Belege, { lauf }),
12499
+ folgeblock(lauf)
12500
+ ] })
12501
+ ] });
12502
+ };
12503
+
12504
+ // src/features/szenen/areas/SceneArea.tsx
12505
+ import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
12506
+ var SceneArea = ({ port, contextId }) => {
12507
+ const kannAbleiten = capabilitiesOf(port).derivation;
12508
+ const [ableiten, setAbleiten] = useState17(false);
12509
+ const zeigeDerive = kannAbleiten && ableiten;
12510
+ return /* @__PURE__ */ jsxs15("div", { className: "szenen-scene", "data-testid": "bereich-szene", children: [
12511
+ /* @__PURE__ */ jsxs15("div", { className: "szenen-elements__toolbar", children: [
12512
+ /* @__PURE__ */ jsx15("p", { className: "szenen-area__lead", children: "Szenen dieses Kontexts. Auswahl \xF6ffnet die Bearbeitung der Nodes und Beziehungen und startet Prompt-L\xE4ufe." }),
12513
+ kannAbleiten && /* @__PURE__ */ jsx15(
12514
+ "button",
12515
+ {
12516
+ type: "button",
12517
+ className: "szenen-elements__new",
12518
+ "data-testid": "neu-aus-bild-text",
12519
+ "aria-expanded": ableiten,
12520
+ onClick: () => setAbleiten((offen) => !offen),
12521
+ children: ableiten ? "Zur\xFCck zu den Szenen" : "+ Neu aus Bild/Text"
12522
+ }
12523
+ )
12524
+ ] }),
12525
+ !kannAbleiten && /* @__PURE__ */ jsx15("p", { className: "szenen-view__capability-note", "data-testid": "hinweis-keine-rekonstruktion", children: "Aus Bild oder Text l\xE4sst sich in diesem Host keine Szene ableiten." }),
12526
+ zeigeDerive ? /* @__PURE__ */ jsx15(DeriveArea, { port, contextId }) : /* @__PURE__ */ jsx15(ElementsArea, { port, contextId, restrictToTypes: ["scene"] })
12527
+ ] });
12528
+ };
12529
+
12530
+ // src/features/szenen/areas/AdvancedArea.tsx
12531
+ import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
12532
+ var AdvancedArea = ({ port, contextId }) => /* @__PURE__ */ jsxs16("div", { className: "szenen-erweitert", "data-testid": "bereich-erweitert", children: [
12533
+ /* @__PURE__ */ jsx16("p", { className: "szenen-area__lead", children: "Optionale Pr\xE4zisierung: Bildaufbau und Shot, Kameras und Stile der Aufnahme, Zielmodelle, Rekonstruktionsregeln und Sequenzen. F\xFCr den normalen Weg von der Szene zum Bild wird hier nichts gebraucht." }),
12534
+ /* @__PURE__ */ jsx16(
12535
+ ElementsArea,
12536
+ {
12537
+ port,
12538
+ contextId,
12539
+ restrictToTypes: ERWEITERT_TYPES,
12540
+ allTypesLabel: "alle erweiterten Typen",
12541
+ listTitle: "Erweitert"
12542
+ }
12543
+ )
12544
+ ] });
12545
+
12546
+ // src/features/szenen/areas/PromptsArea.tsx
12547
+ import { useMemo as useMemo4, useState as useState18 } from "react";
12548
+ import { Fragment as Fragment9, jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
12549
+ var HERKUNFT_TEXT2 = {
12550
+ published: "aus ver\xF6ffentlichtem Shot",
12551
+ draft_chain: "aus Draft-Kette",
12552
+ scene_direct: "direkt aus Szene",
12553
+ unresolved: "Herkunft unvollst\xE4ndig"
12554
+ };
12555
+ var PromptsArea = ({ port, contextId }) => {
12556
+ const faehig = capabilitiesOf(port);
12557
+ const [nachladen, setNachladen] = useState18(0);
12558
+ const [offen, setOffen] = useState18(null);
12559
+ const [alleKontexte, setAlleKontexte] = useState18(false);
12560
+ const [mitFehllaeufen, setMitFehllaeufen] = useState18(false);
12561
+ const [herkunft, setHerkunft] = useState18("alle");
12562
+ const [phase] = usePortQuery(
12563
+ () => port.runs.listAllRuns ? port.runs.listAllRuns({ status: "all" }) : Promise.resolve({
12564
+ kind: "ok",
12565
+ value: { runs: [], hiddenByStatus: 0, hiddenByContext: 0, withoutContext: 0 }
12566
+ }),
12567
+ [port, nachladen]
12568
+ );
12569
+ const alle = phase.status === "ready" ? phase.value.runs : [];
12570
+ const sicht = useMemo4(() => selectPromptRuns(alle, {
12571
+ status: mitFehllaeufen ? "all" : "succeeded",
12572
+ ...alleKontexte ? {} : { contextId }
12573
+ }), [alle, mitFehllaeufen, alleKontexte, contextId]);
12574
+ const titel = useLaufTitel(port, alle);
12575
+ const gezeigt = useMemo4(
12576
+ () => herkunft === "alle" ? sicht.runs : sicht.runs.filter((lauf) => groupOf(lauf).kind === herkunft),
12577
+ [sicht.runs, herkunft]
12578
+ );
12579
+ if (!faehig.promptOverview) {
12580
+ return /* @__PURE__ */ jsx17("div", { className: "szenen-prompts", "data-testid": "prompts-bereich", children: /* @__PURE__ */ jsx17("p", { "data-testid": "hinweis-keine-promptsicht", children: "Dieser Host bietet keine herkunfts\xFCbergreifende Prompt-Liste an. Prompt-L\xE4ufe bleiben im Detail ihrer Szene bzw. ihres Shots erreichbar \u2014 es ist kein Fehler und kein vor\xFCbergehender Zustand." }) });
12581
+ }
12582
+ return /* @__PURE__ */ jsxs17("div", { className: "szenen-prompts", "data-testid": "prompts-bereich", children: [
12583
+ /* @__PURE__ */ jsxs17("div", { className: "szenen-prompts__toolbar", children: [
12584
+ /* @__PURE__ */ jsx17("h3", { className: "szenen-prompts__heading", children: "Prompts" }),
12585
+ /* @__PURE__ */ jsxs17("label", { className: "szenen-prompts__filter", children: [
12586
+ "Herkunft",
12587
+ /* @__PURE__ */ jsxs17(
12588
+ "select",
12589
+ {
12590
+ "data-testid": "prompts-herkunft",
12591
+ value: herkunft,
12592
+ onChange: (e) => setHerkunft(e.target.value),
12593
+ children: [
12594
+ /* @__PURE__ */ jsx17("option", { value: "alle", children: "alle" }),
12595
+ /* @__PURE__ */ jsx17("option", { value: "published", children: HERKUNFT_TEXT2.published }),
12596
+ /* @__PURE__ */ jsx17("option", { value: "draft_chain", children: HERKUNFT_TEXT2.draft_chain }),
12597
+ /* @__PURE__ */ jsx17("option", { value: "scene_direct", children: HERKUNFT_TEXT2.scene_direct }),
12598
+ /* @__PURE__ */ jsx17("option", { value: "unresolved", children: HERKUNFT_TEXT2.unresolved })
12599
+ ]
12600
+ }
12601
+ )
12602
+ ] }),
12603
+ /* @__PURE__ */ jsxs17("label", { className: "szenen-prompts__filter", children: [
12604
+ /* @__PURE__ */ jsx17(
12605
+ "input",
12606
+ {
12607
+ type: "checkbox",
12608
+ "data-testid": "prompts-alle-kontexte",
12609
+ checked: alleKontexte,
12610
+ onChange: (e) => setAlleKontexte(e.target.checked)
12611
+ }
12612
+ ),
12613
+ "Alle Kontexte"
12614
+ ] }),
12615
+ /* @__PURE__ */ jsxs17("label", { className: "szenen-prompts__filter", children: [
12616
+ /* @__PURE__ */ jsx17(
12617
+ "input",
12618
+ {
12619
+ type: "checkbox",
12620
+ "data-testid": "prompts-mit-fehllaeufen",
12621
+ checked: mitFehllaeufen,
12622
+ onChange: (e) => setMitFehllaeufen(e.target.checked)
12623
+ }
12624
+ ),
12625
+ "Fehll\xE4ufe zeigen"
12626
+ ] })
12627
+ ] }),
12628
+ phase.status === "loading" && /* @__PURE__ */ jsx17("p", { "data-testid": "prompts-laden", children: "Prompts werden geladen \u2026" }),
12629
+ phase.status === "error" && /* @__PURE__ */ jsxs17("p", { "data-testid": "prompts-fehler", role: "alert", children: [
12630
+ "Prompts konnten nicht geladen werden: ",
12631
+ phase.message
12632
+ ] }),
12633
+ phase.status === "ready" && /* @__PURE__ */ jsxs17(Fragment9, { children: [
12634
+ gezeigt.length === 0 && /* @__PURE__ */ jsx17("p", { "data-testid": "keine-prompts", children: alle.length === 0 ? "Es gibt noch keinen Prompt-Lauf." : `Kein Prompt passt zu dieser Auswahl \u2014 von ${alle.length} vorhandenen L\xE4ufen bleibt keiner \xFCbrig.` }),
12635
+ /* @__PURE__ */ jsx17("ol", { "data-testid": "prompts-liste", children: gezeigt.map((lauf) => /* @__PURE__ */ jsx17(
12636
+ PromptEintrag,
12637
+ {
12638
+ port,
12639
+ lauf,
12640
+ alle,
12641
+ titel: titel.get(lauf.run_id) ?? null,
12642
+ offen: lauf.run_id === offen,
12643
+ onUmschalten: () => setOffen(
12644
+ lauf.run_id === offen ? null : lauf.run_id
12645
+ ),
12646
+ itemMoeglich: faehig.saveRunAsItem,
12647
+ onItemGespeichert: () => setNachladen((n) => n + 1)
12648
+ },
12649
+ lauf.run_id
12650
+ )) }),
12651
+ (sicht.hiddenByContext > 0 || sicht.withoutContext > 0 || sicht.hiddenByStatus > 0) && /* @__PURE__ */ jsxs17("p", { className: "szenen-prompts__ausgeblendet", "data-testid": "prompts-ausgeblendet", children: [
12652
+ sicht.hiddenByStatus > 0 && `${sicht.hiddenByStatus} Fehllauf/-l\xE4ufe ausgeblendet. `,
12653
+ sicht.hiddenByContext > 0 && `${sicht.hiddenByContext} Lauf/L\xE4ufe geh\xF6ren zu einem anderen Kontext. `,
12654
+ sicht.withoutContext > 0 && `${sicht.withoutContext} Lauf/L\xE4ufe nennen keinen Kontext und werden keinem zugeordnet \u2014 \u201EAlle Kontexte" zeigt sie. `
12655
+ ] })
12656
+ ] })
12657
+ ] });
12658
+ };
12659
+ var PromptEintrag = ({ port, lauf, alle, titel, offen, onUmschalten, itemMoeglich, onItemGespeichert }) => {
12660
+ const gruppe = groupOf(lauf);
12661
+ const runde = roundOfRun(lauf, siblingsOf(lauf, alle));
12662
+ return /* @__PURE__ */ jsxs17("li", { className: "szenen-prompts__eintrag", "data-testid": `prompt-${lauf.run_id}`, children: [
12663
+ /* @__PURE__ */ jsxs17("p", { className: "szenen-prompts__herkunft", "data-testid": `herkunft-${lauf.run_id}`, children: [
12664
+ /* @__PURE__ */ jsx17("span", { "data-herkunft": gruppe.kind, children: HERKUNFT_TEXT2[gruppe.kind] }),
12665
+ gruppe.kind === "unresolved" && // D-75: Was nicht belegbar ist, wird benannt und nicht
12666
+ // durch eine plausible Kennung ersetzt.
12667
+ /* @__PURE__ */ jsxs17("span", { className: "szenen-prompts__hinweis", children: [
12668
+ " \u2014 ",
12669
+ gruppe.reason
12670
+ ] })
12671
+ ] }),
12672
+ /* @__PURE__ */ jsx17("ol", { className: "szenen-prompts__lauf", children: /* @__PURE__ */ jsx17(
12673
+ RundenEintrag,
12674
+ {
12675
+ port,
12676
+ lauf,
12677
+ runde,
12678
+ titel,
12679
+ offen,
12680
+ onUmschalten,
12681
+ itemMoeglich,
12682
+ onItemGespeichert
12683
+ }
12684
+ ) })
12685
+ ] });
12686
+ };
12687
+
12688
+ // src/features/szenen/areas/MediaArea.tsx
12689
+ import { useState as useState19 } from "react";
12690
+ import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
12691
+ var leer = async () => ({ kind: "ok", value: [] });
12692
+ var MediaArea = ({ port }) => {
12693
+ const media = port.media;
12694
+ const [versionInput, setVersionInput] = useState19("");
12695
+ const [versionId, setVersionId] = useState19("");
12696
+ const [itemInput, setItemInput] = useState19("");
12697
+ const [itemId, setItemId] = useState19("");
12698
+ const [assetId, setAssetId] = useState19("");
12699
+ const [role, setRole] = useState19("reference");
12700
+ const [position, setPosition] = useState19("0");
12701
+ const [notiz, setNotiz] = useState19(null);
12702
+ const [busy, setBusy] = useState19(false);
12703
+ const [refresh, setRefresh] = useState19(0);
12704
+ const [versionPhase] = usePortQuery(
12705
+ () => versionId ? media.listVersionMedia(versionId) : leer(),
12706
+ [media, versionId, refresh]
12707
+ );
12708
+ const [itemPhase] = usePortQuery(
12709
+ () => itemId ? media.listItemMedia(itemId) : Promise.resolve({ kind: "ok", value: [] }),
12710
+ [media, itemId, refresh]
12711
+ );
12712
+ const zuordnen = async () => {
12713
+ if (!versionInput.trim() || !assetId.trim()) {
12714
+ setNotiz({ tone: "error", text: "Version-ID und Asset-ID sind erforderlich." });
12715
+ return;
12716
+ }
12717
+ const parsedPosition = Number(position);
12718
+ if (!Number.isInteger(parsedPosition) || parsedPosition < 0) {
12719
+ setNotiz({ tone: "error", text: `Position muss eine nicht-negative Ganzzahl sein, war ${JSON.stringify(position)}.` });
12720
+ return;
12721
+ }
12722
+ setBusy(true);
12723
+ const result = await media.attachVersionMedium({
12724
+ versionId: versionInput.trim(),
12725
+ assetId: assetId.trim(),
12726
+ role,
12727
+ position: parsedPosition
12728
+ });
12729
+ setNotiz(noticeFor(result, "Referenzmedium zuordnen"));
12730
+ if (result.kind === "ok") {
12731
+ setVersionId(versionInput.trim());
12732
+ setRefresh((value) => value + 1);
12733
+ }
12734
+ setBusy(false);
12735
+ };
12736
+ const entfernen = async (medium) => {
12737
+ setBusy(true);
12738
+ const result = await media.detachVersionMedium({
12739
+ versionId,
12740
+ assetId: medium.assetId,
12741
+ role: medium.role
12742
+ });
12743
+ setNotiz(noticeFor(result, "Referenzmedium entfernen"));
12744
+ if (result.kind === "ok") setRefresh((value) => value + 1);
12745
+ setBusy(false);
12746
+ };
12747
+ const versionMedien = versionPhase.status === "ready" ? versionPhase.value : [];
12748
+ const itemMedien = itemPhase.status === "ready" ? itemPhase.value : [];
12749
+ return /* @__PURE__ */ jsxs18("div", { className: "szenen-media", "data-testid": "bereich-medien", children: [
12750
+ /* @__PURE__ */ jsx18("p", { className: "szenen-area__lead", children: "Bereits vorhandene Medien-Assets einer Elementversion zuordnen. Hochgeladen wird hier nichts \u2014 Medien entstehen \xFCber den bestehenden Speicherweg aus Stufe 5." }),
12751
+ /* @__PURE__ */ jsxs18("section", { children: [
12752
+ /* @__PURE__ */ jsx18("h3", { children: "Version" }),
12753
+ /* @__PURE__ */ jsxs18("div", { className: "szenen-media__lookup", children: [
12754
+ /* @__PURE__ */ jsxs18("label", { children: [
12755
+ "Version-ID",
12756
+ /* @__PURE__ */ jsx18("input", { value: versionInput, onChange: (event) => setVersionInput(event.target.value) })
12757
+ ] }),
12758
+ /* @__PURE__ */ jsx18("button", { type: "button", onClick: () => setVersionId(versionInput.trim()), children: "Medien laden" })
12759
+ ] }),
12760
+ /* @__PURE__ */ jsxs18("div", { className: "szenen-media__attach", children: [
12761
+ /* @__PURE__ */ jsxs18("label", { children: [
12762
+ "Asset-ID",
12763
+ /* @__PURE__ */ jsx18("input", { value: assetId, onChange: (event) => setAssetId(event.target.value) })
12764
+ ] }),
12765
+ /* @__PURE__ */ jsxs18("label", { children: [
12766
+ "Rolle",
12767
+ /* @__PURE__ */ jsxs18("select", { value: role, onChange: (event) => setRole(event.target.value), children: [
12768
+ /* @__PURE__ */ jsx18("option", { value: "reference", children: "reference" }),
12769
+ /* @__PURE__ */ jsx18("option", { value: "mask", children: "mask" }),
12770
+ /* @__PURE__ */ jsx18("option", { value: "palette", children: "palette" }),
12771
+ /* @__PURE__ */ jsx18("option", { value: "example", children: "example" })
12772
+ ] })
12773
+ ] }),
12774
+ /* @__PURE__ */ jsxs18("label", { children: [
12775
+ "Position",
12776
+ /* @__PURE__ */ jsx18("input", { type: "number", min: "0", value: position, onChange: (event) => setPosition(event.target.value) })
12777
+ ] }),
12778
+ /* @__PURE__ */ jsx18("button", { type: "button", disabled: busy, onClick: zuordnen, children: "zuordnen" })
12407
12779
  ] }),
12408
- /* @__PURE__ */ jsx18(Herkunft, { lauf }),
12409
- /* @__PURE__ */ jsx18(Widerspruch, { lauf }),
12410
- /* @__PURE__ */ jsx18(Belege, { lauf }),
12411
- /* @__PURE__ */ jsx18(RecoveryPanel, { port, lauf }),
12412
- folgeblock(lauf)
12413
- ] }),
12414
- lauf && lauf.status === "succeeded" && /* @__PURE__ */ jsxs18("section", { className: "szenen-run", "data-testid": "lauf-ergebnis", children: [
12415
- /* @__PURE__ */ jsx18("h3", { children: "Vorschlag" }),
12416
- /* @__PURE__ */ jsx18(Herkunft, { lauf }),
12417
- /* @__PURE__ */ jsx18(Widerspruch, { lauf }),
12418
- /* @__PURE__ */ jsx18("p", { className: "szenen-run__feedback", children: lauf.feedback }),
12419
- lauf.conflicts.length > 0 && /* @__PURE__ */ jsxs18("div", { className: "szenen-diagnose szenen-diagnose--konflikt", "data-testid": "konflikte", children: [
12420
- /* @__PURE__ */ jsx18("h4", { children: "Widerspr\xFCche zwischen Bild und Prompt" }),
12421
- /* @__PURE__ */ jsx18("ul", { children: lauf.conflicts.map((k, i) => /* @__PURE__ */ jsxs18("li", { children: [
12422
- /* @__PURE__ */ jsx18("code", { children: k.field }),
12423
- ": Bild sagt \u201E",
12424
- k.from_image,
12425
- '", Prompt sagt \u201E',
12426
- k.from_prompt,
12427
- '". Nichts davon wurde \xFCbernommen.'
12428
- ] }, i)) })
12780
+ versionPhase.status === "loading" && versionId && /* @__PURE__ */ jsx18("p", { children: "Versionsmedien werden geladen \u2026" }),
12781
+ versionPhase.status === "error" && /* @__PURE__ */ jsxs18("p", { role: "alert", children: [
12782
+ "Versionsmedien konnten nicht geladen werden: ",
12783
+ versionPhase.message
12429
12784
  ] }),
12430
- lauf.not_derivable.length > 0 && /* @__PURE__ */ jsxs18("div", { className: "szenen-diagnose", "data-testid": "nicht-ableitbar", children: [
12431
- /* @__PURE__ */ jsx18("h4", { children: "Nicht ableitbar" }),
12432
- /* @__PURE__ */ jsx18("ul", { children: lauf.not_derivable.map((n, i) => /* @__PURE__ */ jsxs18("li", { children: [
12433
- /* @__PURE__ */ jsx18("code", { children: n.field }),
12434
- ": ",
12435
- n.reason
12436
- ] }, i)) })
12785
+ versionPhase.status === "ready" && versionId && versionMedien.length === 0 && /* @__PURE__ */ jsxs18("p", { children: [
12786
+ "Version ",
12787
+ versionId,
12788
+ " hat keine Medien."
12437
12789
  ] }),
12438
- lauf.assumptions.length > 0 && /* @__PURE__ */ jsxs18("div", { className: "szenen-diagnose", "data-testid": "annahmen", children: [
12439
- /* @__PURE__ */ jsx18("h4", { children: "Erschlossen, nicht belegt" }),
12440
- /* @__PURE__ */ jsx18("ul", { children: lauf.assumptions.map((a, i) => /* @__PURE__ */ jsx18("li", { children: a }, i)) })
12790
+ /* @__PURE__ */ jsx18("ul", { className: "szenen-media__list", children: versionMedien.map((medium) => /* @__PURE__ */ jsxs18("li", { children: [
12791
+ /* @__PURE__ */ jsx18("code", { children: medium.assetId }),
12792
+ /* @__PURE__ */ jsxs18("span", { children: [
12793
+ medium.role,
12794
+ " \xB7 Position ",
12795
+ medium.position
12796
+ ] }),
12797
+ medium.url && /* @__PURE__ */ jsx18("a", { href: medium.url, target: "_blank", rel: "noreferrer", children: "\xF6ffnen" }),
12798
+ /* @__PURE__ */ jsx18("button", { type: "button", disabled: busy, onClick: () => entfernen(medium), children: "entfernen" })
12799
+ ] }, `${medium.assetId}:${medium.role}`)) })
12800
+ ] }),
12801
+ /* @__PURE__ */ jsxs18("section", { children: [
12802
+ /* @__PURE__ */ jsx18("h3", { children: "Item-Medien" }),
12803
+ /* @__PURE__ */ jsxs18("div", { className: "szenen-media__lookup", children: [
12804
+ /* @__PURE__ */ jsxs18("label", { children: [
12805
+ "Item-ID",
12806
+ /* @__PURE__ */ jsx18("input", { value: itemInput, onChange: (event) => setItemInput(event.target.value) })
12807
+ ] }),
12808
+ /* @__PURE__ */ jsx18("button", { type: "button", onClick: () => setItemId(itemInput.trim()), children: "Item-Medien laden" })
12441
12809
  ] }),
12442
- lauf.proposals.map((vorschlag) => {
12443
- const bezug = REFERENCE_FIELD[vorschlag.type];
12444
- const fertig = uebernommen[vorschlag.type];
12445
- return /* @__PURE__ */ jsxs18(
12446
- "article",
12447
- {
12448
- className: "szenen-proposal",
12449
- "data-testid": `vorschlag-${vorschlag.type}`,
12450
- children: [
12451
- /* @__PURE__ */ jsx18("h4", { children: vorschlag.type }),
12452
- !fertig && /* @__PURE__ */ jsxs18("label", { className: "szenen-field", children: [
12453
- /* @__PURE__ */ jsx18("span", { children: "Titel" }),
12454
- /* @__PURE__ */ jsx18(
12455
- "input",
12456
- {
12457
- type: "text",
12458
- value: titelFuer(vorschlag.type),
12459
- onChange: (e) => setTitel((v) => ({
12460
- ...v,
12461
- [vorschlag.type]: e.target.value
12462
- })),
12463
- placeholder: fallbackProposalTitle(vorschlag.type),
12464
- "data-testid": `titel-${vorschlag.type}`
12465
- }
12466
- )
12467
- ] }),
12468
- /* @__PURE__ */ jsx18("pre", { className: "szenen-proposal__payload", children: JSON.stringify(vorschlag.payload, null, 2) }),
12469
- bezug && !fertig && /* @__PURE__ */ jsxs18(Fragment8, { children: [
12470
- /* @__PURE__ */ jsx18(
12471
- ReferencePicker,
12472
- {
12473
- port,
12474
- contextId,
12475
- type: bezug.refersTo,
12476
- label: `Ver\xF6ffentlichte ${bezug.refersTo}-Version, auf die dieser Entwurf zeigen soll`,
12477
- testId: `referenz-${vorschlag.type}`,
12478
- onPick: (ref) => setReferenzen((v) => ({
12479
- ...v,
12480
- [vorschlag.type]: ref.version_id
12481
- }))
12482
- }
12483
- ),
12484
- referenzen[vorschlag.type] ? /* @__PURE__ */ jsxs18("p", { "data-testid": `referenz-gewaehlt-${vorschlag.type}`, children: [
12485
- "Zeigt auf Version ",
12486
- /* @__PURE__ */ jsx18("code", { children: referenzen[vorschlag.type] }),
12487
- "."
12488
- ] }) : (
12489
- /* Der Grund steht **vor** der Handlung. Den Nutzer erst
12490
- auf einen Knopf drücken zu lassen, um ihm dann eine
12491
- Ablehnung zu zeigen, ist keine Auskunft. */
12492
- /* @__PURE__ */ jsxs18("p", { "data-testid": `referenz-fehlt-${vorschlag.type}`, children: [
12493
- "Diese ",
12494
- /* @__PURE__ */ jsx18("strong", { children: "Einzel\xFCbernahme" }),
12495
- " braucht eine ver\xF6ffentlichte ",
12496
- bezug.refersTo,
12497
- "-Version, auf die der Entwurf zeigt (D-03) \u2014 sie ist der Weg in einen bestehenden, l\xE4ngst ver\xF6ffentlichten Zusammenhang. Wollen Sie aus diesem Lauf erst einmal einen Prompt ausprobieren, nehmen Sie unten die ",
12498
- /* @__PURE__ */ jsx18("strong", { children: "Draft-Kette" }),
12499
- ": Dort entstehen Szene, Aufbau und Shot zusammenh\xE4ngend, und es muss nichts ver\xF6ffentlicht werden."
12500
- ] })
12501
- )
12502
- ] }),
12503
- fertig ? /* @__PURE__ */ jsxs18("p", { className: "szenen-proposal__done", children: [
12504
- "Als Entwurf \xFCbernommen: ",
12505
- /* @__PURE__ */ jsx18("code", { children: fertig }),
12506
- ". Er ist noch nicht ver\xF6ffentlicht."
12507
- ] }) : /* @__PURE__ */ jsx18(
12508
- "button",
12509
- {
12510
- type: "button",
12511
- onClick: () => void uebernehmen(vorschlag.type),
12512
- disabled: Boolean(bezug) && !referenzen[vorschlag.type],
12513
- "data-testid": `uebernehmen-${vorschlag.type}`,
12514
- children: "Als Entwurf \xFCbernehmen"
12515
- }
12516
- )
12517
- ]
12518
- },
12519
- vorschlag.type
12520
- );
12521
- }),
12522
- /* @__PURE__ */ jsx18(ChainActions, { port, runId: lauf.run_id }),
12523
- /* @__PURE__ */ jsx18(Belege, { lauf }),
12524
- folgeblock(lauf)
12525
- ] })
12810
+ itemPhase.status === "error" && /* @__PURE__ */ jsxs18("p", { role: "alert", children: [
12811
+ "Item-Medien konnten nicht geladen werden: ",
12812
+ itemPhase.message
12813
+ ] }),
12814
+ /* @__PURE__ */ jsx18("ul", { className: "szenen-media__list", children: itemMedien.map((medium) => /* @__PURE__ */ jsxs18("li", { children: [
12815
+ /* @__PURE__ */ jsx18("code", { children: medium.assetId }),
12816
+ /* @__PURE__ */ jsxs18("span", { children: [
12817
+ medium.role,
12818
+ " \xB7 Position ",
12819
+ medium.position
12820
+ ] }),
12821
+ medium.url && /* @__PURE__ */ jsx18("a", { href: medium.url, target: "_blank", rel: "noreferrer", children: "\xF6ffnen" })
12822
+ ] }, `${medium.assetId}:${medium.role}:${medium.position}`)) })
12823
+ ] }),
12824
+ notiz && /* @__PURE__ */ jsx18("p", { role: notiz.tone === "error" ? "alert" : "status", "data-tone": notiz.tone, children: notiz.text })
12526
12825
  ] });
12527
12826
  };
12528
12827
 
@@ -12534,9 +12833,9 @@ var SzenenView = ({
12534
12833
  initialArea,
12535
12834
  onAreaChange
12536
12835
  }) => {
12537
- const bereiche = useMemo4(() => areasFor(port), [port]);
12538
- const faehig = useMemo4(() => capabilitiesOf(port), [port]);
12539
- const [aktiv, setAktiv] = useState17(() => resolveArea(port, initialArea));
12836
+ const bereiche = useMemo5(() => areasFor(port), [port]);
12837
+ const faehig = useMemo5(() => capabilitiesOf(port), [port]);
12838
+ const [aktiv, setAktiv] = useState20(() => resolveArea(port, initialArea));
12540
12839
  const wechsle = (id) => {
12541
12840
  setAktiv(id);
12542
12841
  onAreaChange?.(id);
@@ -12547,7 +12846,7 @@ var SzenenView = ({
12547
12846
  /* @__PURE__ */ jsxs19("div", { children: [
12548
12847
  /* @__PURE__ */ jsx19("p", { className: "szenen-view__eyebrow", children: "Vom Motiv zum Bild" }),
12549
12848
  /* @__PURE__ */ jsx19("h2", { children: "Bildprompt aus einer Szene" }),
12550
- /* @__PURE__ */ jsx19("p", { children: "Bausteine w\xE4hlen, Szene und Bildaufbau festlegen und daraus einen wiederholbaren Prompt erzeugen." })
12849
+ /* @__PURE__ */ jsx19("p", { children: 'Eine Szene anlegen oder aus Bild bzw. Text ableiten und daraus einen Prompt starten. Alle so entstandenen Prompts stehen mit ihren Bildern unter \u201EPrompts". Bausteine und Erweitertes pr\xE4zisieren den Weg, wenn er pr\xE4ziser werden soll.' })
12551
12850
  ] }),
12552
12851
  /* @__PURE__ */ jsx19("span", { className: "szenen-view__step", children: aktuellerBereich.title })
12553
12852
  ] }),
@@ -12566,7 +12865,8 @@ var SzenenView = ({
12566
12865
  bereich.id
12567
12866
  )) }),
12568
12867
  /* @__PURE__ */ jsxs19("section", { className: "szenen-view__area", "aria-label": aktuellerBereich.title, children: [
12569
- aktiv === "derive" && port.derivation && /* @__PURE__ */ jsx19(DeriveArea, { port, contextId }),
12868
+ aktiv === "scene" && /* @__PURE__ */ jsx19(SceneArea, { port, contextId }),
12869
+ aktiv === "prompts" && /* @__PURE__ */ jsx19(PromptsArea, { port, contextId }),
12570
12870
  aktiv === "elements" && /* @__PURE__ */ jsx19(
12571
12871
  ElementsArea,
12572
12872
  {
@@ -12577,9 +12877,7 @@ var SzenenView = ({
12577
12877
  listTitle: "Bausteine"
12578
12878
  }
12579
12879
  ),
12580
- aktiv === "scene" && /* @__PURE__ */ jsx19(SceneArea, { port, contextId }),
12581
- aktiv === "setup" && /* @__PURE__ */ jsx19(SetupArea, { port, contextId }),
12582
- aktiv === "shot" && /* @__PURE__ */ jsx19(ShotArea, { port, contextId }),
12880
+ aktiv === "advanced" && /* @__PURE__ */ jsx19(AdvancedArea, { port, contextId }),
12583
12881
  aktiv === "media" && port.media && /* @__PURE__ */ jsx19(MediaArea, { port, contextId })
12584
12882
  ] }),
12585
12883
  (!faehig.saveRunAsItem || !faehig.media) && /* @__PURE__ */ jsxs19("details", { className: "szenen-view__host-notes", children: [
@@ -13650,6 +13948,15 @@ function createHfElementStore(options) {
13650
13948
  return {
13651
13949
  getElement(elementId) {
13652
13950
  return { kind: "ok", value: state.elements.get(elementId) ?? null };
13951
+ },
13952
+ // Aus **derselben** gefalteten Sicht wie `getElement` und ohne
13953
+ // weiteren Netzzugriff: Nur so faellt die Policy-Auswahl des
13954
+ // Szene-Direktlaufs in dieselbe Konsistenzgrenze wie das Einfrieren
13955
+ // der Szene (Schritt 03 §3). Stillgelegte Elemente sind nicht dabei —
13956
+ // Stilllegen ist Ausblenden (D-04), wie bei `listElements`.
13957
+ listElements(filter) {
13958
+ const gefunden = [...state.elements.values()].map((snapshot) => snapshot.element).filter((element) => !element.retired && element.type === filter.type && (element.context_id ?? null) === (filter.contextId ?? null));
13959
+ return { kind: "ok", value: gefunden };
13653
13960
  }
13654
13961
  };
13655
13962
  } catch (error) {
@@ -13657,6 +13964,9 @@ function createHfElementStore(options) {
13657
13964
  return {
13658
13965
  getElement() {
13659
13966
  return { kind: "error", message };
13967
+ },
13968
+ listElements() {
13969
+ return { kind: "error", message };
13660
13970
  }
13661
13971
  };
13662
13972
  }
@@ -14354,7 +14664,8 @@ async function resolveScenePayload(input) {
14354
14664
  sceneVersionId = "",
14355
14665
  resolver,
14356
14666
  contextChain,
14357
- userInstruction
14667
+ userInstruction,
14668
+ autoPolicies
14358
14669
  } = input;
14359
14670
  if (!isObject11(scenePayload)) {
14360
14671
  return {
@@ -14389,6 +14700,7 @@ async function resolveScenePayload(input) {
14389
14700
  resolver,
14390
14701
  contextChain,
14391
14702
  userInstruction,
14703
+ autoPolicies,
14392
14704
  assumptions,
14393
14705
  diagnostics
14394
14706
  });
@@ -14404,6 +14716,7 @@ async function komponiere(z) {
14404
14716
  resolver,
14405
14717
  contextChain,
14406
14718
  userInstruction,
14719
+ autoPolicies,
14407
14720
  assumptions,
14408
14721
  diagnostics
14409
14722
  } = z;
@@ -14566,6 +14879,11 @@ async function komponiere(z) {
14566
14879
  }
14567
14880
  const payload = resolved.version.payload;
14568
14881
  policies.push({
14882
+ // Die Herkunft steht in der aufgeloesten Version, nicht in der Referenz:
14883
+ // `element_id` gehoert zur Version und wird hier nicht aus dem `ref`
14884
+ // uebernommen, der nur eine `version_id` fuehrt.
14885
+ element_id: resolved.version.element_id,
14886
+ version_id: resolved.version.version_id,
14569
14887
  subtype: str(payload.subtype) ?? "general",
14570
14888
  rank: num(payload.rank) ?? 0,
14571
14889
  text: str(payload.text) ?? "",
@@ -14573,6 +14891,16 @@ async function komponiere(z) {
14573
14891
  });
14574
14892
  }
14575
14893
  policies.sort((a, b) => a.rank - b.rank);
14894
+ for (const auto of autoPolicies ?? []) {
14895
+ policies.push({
14896
+ element_id: auto.element_id,
14897
+ version_id: auto.version_id,
14898
+ subtype: auto.subtype,
14899
+ rank: auto.rank,
14900
+ text: auto.text,
14901
+ locale: auto.locale
14902
+ });
14903
+ }
14576
14904
  const fragments = [];
14577
14905
  for (const [i, ref] of asArray3(settings.fragment_refs).entries()) {
14578
14906
  const resolved = await refOf(
@@ -14776,6 +15104,10 @@ async function komponiere(z) {
14776
15104
  assumptions,
14777
15105
  diagnostics,
14778
15106
  capabilities: eingefroreneFaehigkeiten,
15107
+ // Die eine kanonische Stelle: die Anweisung des Aufrufers, sonst die im
15108
+ // Shot hinterlegte. Beim Szene-Direktlauf gibt es nur die erste — und
15109
+ // genau sie fehlte dem Renderer bisher (Schritt 03 §7).
15110
+ user_instruction: userInstruction ?? shotInstruction,
14779
15111
  context_chain: [...contextChain],
14780
15112
  target_model_resolution: targetModelResolution
14781
15113
  }
@@ -14815,6 +15147,110 @@ function describeReason(reason) {
14815
15147
  }
14816
15148
  }
14817
15149
 
15150
+ // src/lib/szenen/scenePolicies.ts
15151
+ var GENERAL_POLICY_SUBTYPE = "general";
15152
+ var isObject12 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
15153
+ var str2 = (v) => typeof v === "string" && v.trim().length > 0 ? v : null;
15154
+ var num2 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
15155
+ function sortScenePolicies(policies) {
15156
+ return [...policies].sort((a, b) => a.rank - b.rank || a.chain_index - b.chain_index || (a.element_id < b.element_id ? -1 : a.element_id > b.element_id ? 1 : 0));
15157
+ }
15158
+ function scenePolicyFingerprint(policies) {
15159
+ return policies.map((p) => `${p.element_id}@${p.version_id}`).join(",");
15160
+ }
15161
+ function resolveGeneralScenePolicies(snapshot, contextChain) {
15162
+ if (typeof snapshot.listElements !== "function") {
15163
+ return {
15164
+ kind: "error",
15165
+ message: "Die Momentaufnahme liefert keine Elementliste. Allgemeine Kontext-Policies eines Szene-Direktlaufs lassen sich damit nicht bestimmen; eine leere Policy-Liste waere eine Behauptung ueber den Bestand, die niemand geprueft hat.",
15166
+ retryable: false
15167
+ };
15168
+ }
15169
+ const kette = contextChain.length > 0 ? contextChain : [null];
15170
+ const gesehen = /* @__PURE__ */ new Set();
15171
+ const gefunden = [];
15172
+ for (const [chainIndex, link] of kette.entries()) {
15173
+ const liste = snapshot.listElements({ contextId: link, type: "prompt_policy" });
15174
+ if (liste.kind !== "ok" || !liste.value) {
15175
+ return {
15176
+ kind: "error",
15177
+ message: liste.message ?? `Die prompt_policy-Elemente des Kontexts ${link ?? "global"} konnten nicht gelesen werden.`,
15178
+ retryable: true
15179
+ };
15180
+ }
15181
+ for (const element of liste.value) {
15182
+ if (gesehen.has(element.element_id)) continue;
15183
+ gesehen.add(element.element_id);
15184
+ const gelesen = snapshot.getElement(element.element_id);
15185
+ if (gelesen.kind !== "ok") {
15186
+ return {
15187
+ kind: "error",
15188
+ message: gelesen.message ?? `Element ${element.element_id} konnte nicht gelesen werden.`,
15189
+ retryable: true
15190
+ };
15191
+ }
15192
+ const stand = gelesen.value;
15193
+ if (!stand) {
15194
+ return {
15195
+ kind: "error",
15196
+ message: `Element ${element.element_id} steht in der Elementliste des Kontexts ${link ?? "global"}, aber nicht in derselben Momentaufnahme.`,
15197
+ retryable: false
15198
+ };
15199
+ }
15200
+ const versionen = stand.versions ?? [];
15201
+ const payloadVon = (versionId2) => {
15202
+ const payload2 = versionen.find((v) => v.version_id === versionId2)?.payload;
15203
+ return isObject12(payload2) ? payload2 : null;
15204
+ };
15205
+ const istGeneral = (versionId2) => str2(payloadVon(versionId2)?.subtype) === GENERAL_POLICY_SUBTYPE;
15206
+ const kopf = effectivePreferredHeadSafe(
15207
+ { element: stand.element, versions: versionen, preferredHeads: stand.preferredHeads },
15208
+ kette
15209
+ );
15210
+ if (kopf.kind === "dag_fehler") {
15211
+ return {
15212
+ kind: "error",
15213
+ message: `Der Versionsgraph der Policy ${element.element_id} ist nicht aufbaubar: ${kopf.message}`,
15214
+ retryable: false
15215
+ };
15216
+ }
15217
+ if (kopf.kind === "keine_version") continue;
15218
+ const resolution = kopf.outcome.resolution;
15219
+ if (resolution.kind === "fork") {
15220
+ const relevant = resolution.heads.filter(istGeneral);
15221
+ if (relevant.length === 0) continue;
15222
+ return {
15223
+ kind: "rejected",
15224
+ message: `Die Policy ${element.element_id} hat ${resolution.heads.length} veroeffentlichte Koepfe und in diesem Kontext keine greifende Auswahl. Mindestens einer davon ist eine allgemeine Regel (${relevant.join(", ")}). Welche gilt, entscheidet keine Reihenfolge (D-36) \u2014 bitte einen bevorzugten Kopf setzen. Es wurde kein Modell gerufen.`,
15225
+ element_id: element.element_id,
15226
+ heads: resolution.heads
15227
+ };
15228
+ }
15229
+ const versionId = usableHeadVersionId(resolutionOf(kopf));
15230
+ if (!versionId) continue;
15231
+ const payload = payloadVon(versionId);
15232
+ if (!payload) {
15233
+ return {
15234
+ kind: "error",
15235
+ message: `Die wirksame Version ${versionId} der Policy ${element.element_id} steht nicht mit lesbarer Payload in der Momentaufnahme.`,
15236
+ retryable: false
15237
+ };
15238
+ }
15239
+ if (str2(payload.subtype) !== GENERAL_POLICY_SUBTYPE) continue;
15240
+ gefunden.push({
15241
+ element_id: element.element_id,
15242
+ version_id: versionId,
15243
+ subtype: GENERAL_POLICY_SUBTYPE,
15244
+ rank: num2(payload.rank) ?? 0,
15245
+ text: str2(payload.text) ?? "",
15246
+ locale: str2(payload.locale),
15247
+ chain_index: chainIndex
15248
+ });
15249
+ }
15250
+ }
15251
+ return { kind: "ok", policies: sortScenePolicies(gefunden) };
15252
+ }
15253
+
14818
15254
  // src/lib/szenen/freezeDraftChain.ts
14819
15255
  function ladeKnoten(sicht, elementId, erwarteterTyp) {
14820
15256
  const gelesen = sicht.getElement(elementId);
@@ -15016,9 +15452,19 @@ async function freezeSceneWorkingState(input) {
15016
15452
  const a = await store.readSnapshot({ fresh: false });
15017
15453
  const szene = ladeSzene(a, sceneElementId, contextChain);
15018
15454
  if ("fehler" in szene) return ausfallErgebnis(szene);
15455
+ const policiesA = resolveGeneralScenePolicies(a, contextChain);
15456
+ if (policiesA.kind === "error") {
15457
+ return { kind: "error", message: policiesA.message, retryable: policiesA.retryable };
15458
+ }
15459
+ if (policiesA.kind !== "ok") return { kind: "rejected", message: policiesA.message };
15019
15460
  const b = await store.readSnapshot({ fresh: true });
15020
15461
  const erneut = ladeSzene(b, sceneElementId, contextChain);
15021
15462
  if ("fehler" in erneut) return ausfallErgebnis(erneut);
15463
+ const policiesB = resolveGeneralScenePolicies(b, contextChain);
15464
+ if (policiesB.kind === "error") {
15465
+ return { kind: "error", message: policiesB.message, retryable: policiesB.retryable };
15466
+ }
15467
+ if (policiesB.kind !== "ok") return { kind: "rejected", message: policiesB.message };
15022
15468
  if (erneut.draft_id !== szene.draft_id || erneut.revision !== szene.revision || erneut.version_id !== szene.version_id) {
15023
15469
  return {
15024
15470
  kind: "conflict",
@@ -15028,6 +15474,17 @@ async function freezeSceneWorkingState(input) {
15028
15474
  actualRevision: erneut.revision ?? 0
15029
15475
  };
15030
15476
  }
15477
+ const vorher = scenePolicyFingerprint(policiesA.policies);
15478
+ const nachher = scenePolicyFingerprint(policiesB.policies);
15479
+ if (vorher !== nachher) {
15480
+ return {
15481
+ kind: "conflict",
15482
+ message: `Die wirksamen allgemeinen Policies der Szene ${sceneElementId} haben sich waehrend des Einfrierens geaendert (erwartet [${vorher || "\u2014"}], vorhanden [${nachher || "\u2014"}]). Es wurde kein Modell gerufen.`,
15483
+ node: { type: "scene", element_id: sceneElementId, draft_id: szene.draft_id ?? "" },
15484
+ expectedRevision: szene.revision ?? 0,
15485
+ actualRevision: erneut.revision ?? 0
15486
+ };
15487
+ }
15031
15488
  const aufgeloest = await resolveScenePayload({
15032
15489
  scenePayload: szene.payload,
15033
15490
  sceneElementId: szene.element_id,
@@ -15036,7 +15493,10 @@ async function freezeSceneWorkingState(input) {
15036
15493
  sceneVersionId: szene.version_id ?? "",
15037
15494
  resolver,
15038
15495
  contextChain,
15039
- userInstruction
15496
+ userInstruction,
15497
+ // Der aus A gebildete und gegen B bestaetigte Satz — kein dritter
15498
+ // Leseweg nach dem Freeze.
15499
+ autoPolicies: policiesA.policies
15040
15500
  });
15041
15501
  if (aufgeloest.kind !== "resolved") {
15042
15502
  return {
@@ -15053,7 +15513,8 @@ async function freezeSceneWorkingState(input) {
15053
15513
  revision: szene.revision,
15054
15514
  version_id: szene.version_id
15055
15515
  },
15056
- input: aufgeloest.input
15516
+ input: aufgeloest.input,
15517
+ policies: policiesA.policies
15057
15518
  };
15058
15519
  }
15059
15520
 
@@ -15113,6 +15574,24 @@ function buildSystemInstruction2(input) {
15113
15574
  'Widersprechen sie einander, nenne den Widerspruch mit beiden Quellen in "notes" \u2014',
15114
15575
  "waehle nicht still eine Seite."
15115
15576
  );
15577
+ if (input.policies.length > 0) {
15578
+ zeilen.push(
15579
+ "",
15580
+ 'In "policies" stehen verbindliche Transformationsregeln fuer die Formulierung.',
15581
+ "Setze sie um, ohne ihren Wortlaut in den Prompt zu uebernehmen; sie sind",
15582
+ "Anweisung an dich, nicht Prompttext. Bei gleichem Rang gilt die Reihenfolge",
15583
+ "der Liste."
15584
+ );
15585
+ }
15586
+ if (input.user_instruction !== null && input.user_instruction !== void 0) {
15587
+ zeilen.push(
15588
+ "",
15589
+ '"user_instruction" ist eine ZUSAETZLICHE Arbeitsanweisung fuer genau diesen Lauf.',
15590
+ "Sie tritt zu den Policies hinzu und hebt keine davon auf. Widerspricht sie einer",
15591
+ 'Policy erkennbar, nenne den Widerspruch mit beiden Quellen in "feedback" bzw.',
15592
+ '"notes" \u2014 waehle nicht still eine Seite.'
15593
+ );
15594
+ }
15116
15595
  if (input.camera === null) {
15117
15596
  zeilen.push(
15118
15597
  "",
@@ -15134,7 +15613,7 @@ function buildSystemInstruction2(input) {
15134
15613
  function buildUserPrompt2(input) {
15135
15614
  return JSON.stringify(input, null, 2);
15136
15615
  }
15137
- var isObject12 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
15616
+ var isObject13 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
15138
15617
  function parseRunResponse(raw) {
15139
15618
  const text = raw.trim().replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/, "").trim();
15140
15619
  if (text.length === 0) return { ok: false, message: "Die Antwort war leer." };
@@ -15148,7 +15627,7 @@ function parseRunResponse(raw) {
15148
15627
  }
15149
15628
  }
15150
15629
  function checkRunResponse(value, input) {
15151
- if (!isObject12(value)) {
15630
+ if (!isObject13(value)) {
15152
15631
  return { ok: false, message: `Die Antwort ist kein Objekt, sondern ${Array.isArray(value) ? "array" : typeof value}.` };
15153
15632
  }
15154
15633
  if (typeof value.positive !== "string" || value.positive.trim().length === 0) {
@@ -15170,7 +15649,7 @@ function checkRunResponse(value, input) {
15170
15649
  };
15171
15650
  }
15172
15651
  const visibility = value.visibility;
15173
- if (!isObject12(visibility)) {
15652
+ if (!isObject13(visibility)) {
15174
15653
  return { ok: false, message: '"visibility" fehlt \u2014 die Pflichtdiagnosen aus D-21.' };
15175
15654
  }
15176
15655
  if (typeof visibility.basis !== "string") {
@@ -15182,7 +15661,7 @@ function checkRunResponse(value, input) {
15182
15661
  const genannt = /* @__PURE__ */ new Set();
15183
15662
  const nodes = [];
15184
15663
  for (const eintrag of visibility.nodes) {
15185
- if (!isObject12(eintrag) || typeof eintrag.node_id !== "string" || typeof eintrag.state !== "string") {
15664
+ if (!isObject13(eintrag) || typeof eintrag.node_id !== "string" || typeof eintrag.state !== "string") {
15186
15665
  return { ok: false, message: 'Ein Eintrag in "visibility.nodes" hat keine node_id oder keinen state.' };
15187
15666
  }
15188
15667
  genannt.add(eintrag.node_id);
@@ -15295,8 +15774,13 @@ function createEventLogRunPersistence(channel) {
15295
15774
  // Nur veroeffentlichte Laeufe. Ein Draft-Lauf hat eine **leere**
15296
15775
  // shot_version_id (D-98) und wuerde bei der Suche nach '' sonst
15297
15776
  // faelschlich mitkommen — eine stille Vermischung zweier Herkuenfte.
15777
+ //
15778
+ // Seit P1-B faellt die Entscheidung nicht mehr hier, sondern in
15779
+ // `groupKeyOf()`: dieselbe Regel, aus der auch die Geschwister und
15780
+ // damit die Rundennummer entstehen. Vorher stand sie hier **und**
15781
+ // — anders — in `domainService.getPromptRunWithSiblings()`.
15298
15782
  value: collectPromptRuns(events).filter(
15299
- (run) => sourceOf(run).kind === "published" && run.shot_version_id === shotVersionId
15783
+ (run) => groupKeyOf(run) === `published:${shotVersionId}`
15300
15784
  )
15301
15785
  };
15302
15786
  } catch (error) {
@@ -15318,10 +15802,9 @@ function createEventLogRunPersistence(channel) {
15318
15802
  const events = await channel.readEvents();
15319
15803
  return {
15320
15804
  kind: "ok",
15321
- value: collectPromptRuns(events).filter((run) => {
15322
- const quelle = sourceOf(run);
15323
- return quelle.kind === "draft_chain" && quelle.chain_id === chainId;
15324
- })
15805
+ value: collectPromptRuns(events).filter(
15806
+ (run) => groupKeyOf(run) === `chain:${chainId}`
15807
+ )
15325
15808
  };
15326
15809
  } catch (error) {
15327
15810
  return queryError(error, `Laeufe der Kette ${chainId} konnten nicht gelesen werden`);
@@ -15332,10 +15815,9 @@ function createEventLogRunPersistence(channel) {
15332
15815
  const events = await channel.readEvents();
15333
15816
  return {
15334
15817
  kind: "ok",
15335
- value: collectPromptRuns(events).filter((run) => {
15336
- const quelle = sourceOf(run);
15337
- return quelle.kind === "scene_direct" && quelle.scene.element_id === sceneElementId;
15338
- })
15818
+ value: collectPromptRuns(events).filter(
15819
+ (run) => groupKeyOf(run) === `scene:${sceneElementId}`
15820
+ )
15339
15821
  };
15340
15822
  } catch (error) {
15341
15823
  return queryError(
@@ -15344,6 +15826,16 @@ function createEventLogRunPersistence(channel) {
15344
15826
  );
15345
15827
  }
15346
15828
  },
15829
+ // P1-A: dieselbe Faltung, nur ohne Herkunftsfilter. Sie las schon bisher
15830
+ // in jedem der drei Fälle den **vollen** Log — hier fällt lediglich das
15831
+ // Aussieben weg.
15832
+ async listAll() {
15833
+ try {
15834
+ return { kind: "ok", value: collectPromptRuns(await channel.readEvents()) };
15835
+ } catch (error) {
15836
+ return queryError(error, "Die Prompt-Laeufe konnten nicht gelesen werden");
15837
+ }
15838
+ },
15347
15839
  async record(record) {
15348
15840
  try {
15349
15841
  await channel.appendEvent(SZENEN_EVENT_TYPES.promptRunRecorded, record);
@@ -15640,7 +16132,25 @@ function createClientRunPort(options) {
15640
16132
  `Laeufe der Szene ${sceneElementId} konnten nicht gelesen werden`
15641
16133
  );
15642
16134
  }
15643
- }
16135
+ },
16136
+ // ── Die gemeinsame Prompt-Sicht (P1-A) ────────────────────────────────
16137
+ //
16138
+ // Sie wird nur angeboten, wenn die **Persistenz** aufzählen kann. Ein
16139
+ // Host, dessen Speicher das nicht hergibt, bekommt hier keine Operation —
16140
+ // und die Ansicht nennt den Grund, statt eine leere Liste zu zeigen (§8).
16141
+ // Der Filter läuft über `selectPromptRuns()`, dieselbe Funktion, die auch
16142
+ // der Server benutzt; zwei Bezugsrahmen wären zwei Wahrheiten.
16143
+ ...typeof runs.listAll === "function" ? {
16144
+ async listAllRuns(filter) {
16145
+ try {
16146
+ const alle = await runs.listAll();
16147
+ if (alle.kind !== "ok") return alle;
16148
+ return { kind: "ok", value: selectPromptRuns(alle.value, filter) };
16149
+ } catch (error) {
16150
+ return queryError(error, "Die Prompt-Laeufe konnten nicht gelesen werden");
16151
+ }
16152
+ }
16153
+ } : {}
15644
16154
  };
15645
16155
  }
15646
16156
 
@@ -17021,22 +17531,29 @@ export {
17021
17531
  resolverFromQueries,
17022
17532
  isProjectionCurrent,
17023
17533
  isOk,
17024
- SZENEN_ITEM_PREFIX,
17025
- itemIdForRun,
17026
- isSzenenItemId,
17027
- checkSzenenBatchOrigin,
17028
- mergeSzenenBatchOrigin,
17029
- roundOfRun,
17030
- deriveLineage,
17031
- deriveItemFromRun,
17032
17534
  SZENEN_EVENT_PREFIX,
17033
17535
  SZENEN_EVENT_TYPES,
17034
17536
  reduceElementEvents,
17035
17537
  draftRevisionOf,
17036
17538
  logRevisionOf,
17037
17539
  preferredHeadRevisionOf,
17540
+ sourceOf,
17038
17541
  collectPromptRuns,
17039
17542
  findPromptRun,
17543
+ groupOf,
17544
+ groupKeyOf,
17545
+ siblingsOf,
17546
+ namingElementOf,
17547
+ contextOfRun,
17548
+ selectPromptRuns,
17549
+ SZENEN_ITEM_PREFIX,
17550
+ itemIdForRun,
17551
+ isSzenenItemId,
17552
+ checkSzenenBatchOrigin,
17553
+ mergeSzenenBatchOrigin,
17554
+ roundOfRun,
17555
+ deriveLineage,
17556
+ deriveItemFromRun,
17040
17557
  DEFAULT_SEED_VORLAGE,
17041
17558
  parseSeedListe,
17042
17559
  formatSeedListe,
@@ -17108,6 +17625,10 @@ export {
17108
17625
  resolveShotPayload,
17109
17626
  resolveScenePayload,
17110
17627
  capabilityGate,
17628
+ GENERAL_POLICY_SUBTYPE,
17629
+ sortScenePolicies,
17630
+ scenePolicyFingerprint,
17631
+ resolveGeneralScenePolicies,
17111
17632
  freezeDraftChain,
17112
17633
  freezeSceneWorkingState,
17113
17634
  buildSystemInstruction2,