@rslsp1/fa-app-tools 8.0.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.
@@ -13948,6 +13948,15 @@ function createHfElementStore(options) {
13948
13948
  return {
13949
13949
  getElement(elementId) {
13950
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 };
13951
13960
  }
13952
13961
  };
13953
13962
  } catch (error) {
@@ -13955,6 +13964,9 @@ function createHfElementStore(options) {
13955
13964
  return {
13956
13965
  getElement() {
13957
13966
  return { kind: "error", message };
13967
+ },
13968
+ listElements() {
13969
+ return { kind: "error", message };
13958
13970
  }
13959
13971
  };
13960
13972
  }
@@ -14652,7 +14664,8 @@ async function resolveScenePayload(input) {
14652
14664
  sceneVersionId = "",
14653
14665
  resolver,
14654
14666
  contextChain,
14655
- userInstruction
14667
+ userInstruction,
14668
+ autoPolicies
14656
14669
  } = input;
14657
14670
  if (!isObject11(scenePayload)) {
14658
14671
  return {
@@ -14687,6 +14700,7 @@ async function resolveScenePayload(input) {
14687
14700
  resolver,
14688
14701
  contextChain,
14689
14702
  userInstruction,
14703
+ autoPolicies,
14690
14704
  assumptions,
14691
14705
  diagnostics
14692
14706
  });
@@ -14702,6 +14716,7 @@ async function komponiere(z) {
14702
14716
  resolver,
14703
14717
  contextChain,
14704
14718
  userInstruction,
14719
+ autoPolicies,
14705
14720
  assumptions,
14706
14721
  diagnostics
14707
14722
  } = z;
@@ -14864,6 +14879,11 @@ async function komponiere(z) {
14864
14879
  }
14865
14880
  const payload = resolved.version.payload;
14866
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,
14867
14887
  subtype: str(payload.subtype) ?? "general",
14868
14888
  rank: num(payload.rank) ?? 0,
14869
14889
  text: str(payload.text) ?? "",
@@ -14871,6 +14891,16 @@ async function komponiere(z) {
14871
14891
  });
14872
14892
  }
14873
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
+ }
14874
14904
  const fragments = [];
14875
14905
  for (const [i, ref] of asArray3(settings.fragment_refs).entries()) {
14876
14906
  const resolved = await refOf(
@@ -15074,6 +15104,10 @@ async function komponiere(z) {
15074
15104
  assumptions,
15075
15105
  diagnostics,
15076
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,
15077
15111
  context_chain: [...contextChain],
15078
15112
  target_model_resolution: targetModelResolution
15079
15113
  }
@@ -15113,6 +15147,110 @@ function describeReason(reason) {
15113
15147
  }
15114
15148
  }
15115
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
+
15116
15254
  // src/lib/szenen/freezeDraftChain.ts
15117
15255
  function ladeKnoten(sicht, elementId, erwarteterTyp) {
15118
15256
  const gelesen = sicht.getElement(elementId);
@@ -15314,9 +15452,19 @@ async function freezeSceneWorkingState(input) {
15314
15452
  const a = await store.readSnapshot({ fresh: false });
15315
15453
  const szene = ladeSzene(a, sceneElementId, contextChain);
15316
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 };
15317
15460
  const b = await store.readSnapshot({ fresh: true });
15318
15461
  const erneut = ladeSzene(b, sceneElementId, contextChain);
15319
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 };
15320
15468
  if (erneut.draft_id !== szene.draft_id || erneut.revision !== szene.revision || erneut.version_id !== szene.version_id) {
15321
15469
  return {
15322
15470
  kind: "conflict",
@@ -15326,6 +15474,17 @@ async function freezeSceneWorkingState(input) {
15326
15474
  actualRevision: erneut.revision ?? 0
15327
15475
  };
15328
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
+ }
15329
15488
  const aufgeloest = await resolveScenePayload({
15330
15489
  scenePayload: szene.payload,
15331
15490
  sceneElementId: szene.element_id,
@@ -15334,7 +15493,10 @@ async function freezeSceneWorkingState(input) {
15334
15493
  sceneVersionId: szene.version_id ?? "",
15335
15494
  resolver,
15336
15495
  contextChain,
15337
- userInstruction
15496
+ userInstruction,
15497
+ // Der aus A gebildete und gegen B bestaetigte Satz — kein dritter
15498
+ // Leseweg nach dem Freeze.
15499
+ autoPolicies: policiesA.policies
15338
15500
  });
15339
15501
  if (aufgeloest.kind !== "resolved") {
15340
15502
  return {
@@ -15351,7 +15513,8 @@ async function freezeSceneWorkingState(input) {
15351
15513
  revision: szene.revision,
15352
15514
  version_id: szene.version_id
15353
15515
  },
15354
- input: aufgeloest.input
15516
+ input: aufgeloest.input,
15517
+ policies: policiesA.policies
15355
15518
  };
15356
15519
  }
15357
15520
 
@@ -15411,6 +15574,24 @@ function buildSystemInstruction2(input) {
15411
15574
  'Widersprechen sie einander, nenne den Widerspruch mit beiden Quellen in "notes" \u2014',
15412
15575
  "waehle nicht still eine Seite."
15413
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
+ }
15414
15595
  if (input.camera === null) {
15415
15596
  zeilen.push(
15416
15597
  "",
@@ -15432,7 +15613,7 @@ function buildSystemInstruction2(input) {
15432
15613
  function buildUserPrompt2(input) {
15433
15614
  return JSON.stringify(input, null, 2);
15434
15615
  }
15435
- var isObject12 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
15616
+ var isObject13 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
15436
15617
  function parseRunResponse(raw) {
15437
15618
  const text = raw.trim().replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/, "").trim();
15438
15619
  if (text.length === 0) return { ok: false, message: "Die Antwort war leer." };
@@ -15446,7 +15627,7 @@ function parseRunResponse(raw) {
15446
15627
  }
15447
15628
  }
15448
15629
  function checkRunResponse(value, input) {
15449
- if (!isObject12(value)) {
15630
+ if (!isObject13(value)) {
15450
15631
  return { ok: false, message: `Die Antwort ist kein Objekt, sondern ${Array.isArray(value) ? "array" : typeof value}.` };
15451
15632
  }
15452
15633
  if (typeof value.positive !== "string" || value.positive.trim().length === 0) {
@@ -15468,7 +15649,7 @@ function checkRunResponse(value, input) {
15468
15649
  };
15469
15650
  }
15470
15651
  const visibility = value.visibility;
15471
- if (!isObject12(visibility)) {
15652
+ if (!isObject13(visibility)) {
15472
15653
  return { ok: false, message: '"visibility" fehlt \u2014 die Pflichtdiagnosen aus D-21.' };
15473
15654
  }
15474
15655
  if (typeof visibility.basis !== "string") {
@@ -15480,7 +15661,7 @@ function checkRunResponse(value, input) {
15480
15661
  const genannt = /* @__PURE__ */ new Set();
15481
15662
  const nodes = [];
15482
15663
  for (const eintrag of visibility.nodes) {
15483
- 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") {
15484
15665
  return { ok: false, message: 'Ein Eintrag in "visibility.nodes" hat keine node_id oder keinen state.' };
15485
15666
  }
15486
15667
  genannt.add(eintrag.node_id);
@@ -17444,6 +17625,10 @@ export {
17444
17625
  resolveShotPayload,
17445
17626
  resolveScenePayload,
17446
17627
  capabilityGate,
17628
+ GENERAL_POLICY_SUBTYPE,
17629
+ sortScenePolicies,
17630
+ scenePolicyFingerprint,
17631
+ resolveGeneralScenePolicies,
17447
17632
  freezeDraftChain,
17448
17633
  freezeSceneWorkingState,
17449
17634
  buildSystemInstruction2,
package/dist/index.d.mts CHANGED
@@ -6,7 +6,7 @@ import { Node, Edge } from '@xyflow/react';
6
6
  import * as zustand_vanilla from 'zustand/vanilla';
7
7
  import { F as FeatureSliceId, b as SliceContract, a as PersistenceDescriptor, W as WorkspacePersistence, P as PersistedSlice, L as LoadResult, f as WriteResult, e as WorkspaceTabId, C as CommandResult, R as RequestContext, Q as QueryResult } from './contracts-DdYOMBl9.mjs';
8
8
 
9
- var version = "8.0.0";
9
+ var version = "9.0.0";
10
10
 
11
11
  declare function useOnClickOutside(ref: RefObject<HTMLElement | null>, handler: (e: MouseEvent | TouchEvent) => void): void;
12
12
 
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@ import { Node, Edge } from '@xyflow/react';
6
6
  import * as zustand_vanilla from 'zustand/vanilla';
7
7
  import { F as FeatureSliceId, b as SliceContract, a as PersistenceDescriptor, W as WorkspacePersistence, P as PersistedSlice, L as LoadResult, f as WriteResult, e as WorkspaceTabId, C as CommandResult, R as RequestContext, Q as QueryResult } from './contracts-DdYOMBl9.js';
8
8
 
9
- var version = "8.0.0";
9
+ var version = "9.0.0";
10
10
 
11
11
  declare function useOnClickOutside(ref: RefObject<HTMLElement | null>, handler: (e: MouseEvent | TouchEvent) => void): void;
12
12
 
package/dist/index.js CHANGED
@@ -132,7 +132,7 @@ __export(index_exports, {
132
132
  module.exports = __toCommonJS(index_exports);
133
133
 
134
134
  // package.json
135
- var version = "8.0.0";
135
+ var version = "9.0.0";
136
136
 
137
137
  // src/hooks/useOnClickOutside.ts
138
138
  var import_react = require("react");
@@ -253,7 +253,7 @@ function indexOfBytes(buffer, search, start = 0) {
253
253
  return -1;
254
254
  }
255
255
  function createXMPPacket(prompt, seed, model, id, tags = [], hierarchy) {
256
- const sanitize = (str2) => (str2 || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
256
+ const sanitize = (str3) => (str3 || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
257
257
  const escPrompt = sanitize(prompt);
258
258
  const escModel = sanitize(model || "AI Model");
259
259
  const escHierarchy = sanitize(hierarchy || "");
@@ -19402,6 +19402,15 @@ function createHfElementStore(options) {
19402
19402
  return {
19403
19403
  getElement(elementId) {
19404
19404
  return { kind: "ok", value: state.elements.get(elementId) ?? null };
19405
+ },
19406
+ // Aus **derselben** gefalteten Sicht wie `getElement` und ohne
19407
+ // weiteren Netzzugriff: Nur so faellt die Policy-Auswahl des
19408
+ // Szene-Direktlaufs in dieselbe Konsistenzgrenze wie das Einfrieren
19409
+ // der Szene (Schritt 03 §3). Stillgelegte Elemente sind nicht dabei —
19410
+ // Stilllegen ist Ausblenden (D-04), wie bei `listElements`.
19411
+ listElements(filter) {
19412
+ const gefunden = [...state.elements.values()].map((snapshot) => snapshot.element).filter((element) => !element.retired && element.type === filter.type && (element.context_id ?? null) === (filter.contextId ?? null));
19413
+ return { kind: "ok", value: gefunden };
19405
19414
  }
19406
19415
  };
19407
19416
  } catch (error) {
@@ -19409,6 +19418,9 @@ function createHfElementStore(options) {
19409
19418
  return {
19410
19419
  getElement() {
19411
19420
  return { kind: "error", message };
19421
+ },
19422
+ listElements() {
19423
+ return { kind: "error", message };
19412
19424
  }
19413
19425
  };
19414
19426
  }
@@ -20106,7 +20118,8 @@ async function resolveScenePayload(input) {
20106
20118
  sceneVersionId = "",
20107
20119
  resolver,
20108
20120
  contextChain,
20109
- userInstruction
20121
+ userInstruction,
20122
+ autoPolicies
20110
20123
  } = input;
20111
20124
  if (!isObject11(scenePayload)) {
20112
20125
  return {
@@ -20141,6 +20154,7 @@ async function resolveScenePayload(input) {
20141
20154
  resolver,
20142
20155
  contextChain,
20143
20156
  userInstruction,
20157
+ autoPolicies,
20144
20158
  assumptions,
20145
20159
  diagnostics
20146
20160
  });
@@ -20156,6 +20170,7 @@ async function komponiere(z) {
20156
20170
  resolver,
20157
20171
  contextChain,
20158
20172
  userInstruction,
20173
+ autoPolicies,
20159
20174
  assumptions,
20160
20175
  diagnostics
20161
20176
  } = z;
@@ -20318,6 +20333,11 @@ async function komponiere(z) {
20318
20333
  }
20319
20334
  const payload = resolved.version.payload;
20320
20335
  policies.push({
20336
+ // Die Herkunft steht in der aufgeloesten Version, nicht in der Referenz:
20337
+ // `element_id` gehoert zur Version und wird hier nicht aus dem `ref`
20338
+ // uebernommen, der nur eine `version_id` fuehrt.
20339
+ element_id: resolved.version.element_id,
20340
+ version_id: resolved.version.version_id,
20321
20341
  subtype: str(payload.subtype) ?? "general",
20322
20342
  rank: num(payload.rank) ?? 0,
20323
20343
  text: str(payload.text) ?? "",
@@ -20325,6 +20345,16 @@ async function komponiere(z) {
20325
20345
  });
20326
20346
  }
20327
20347
  policies.sort((a, b) => a.rank - b.rank);
20348
+ for (const auto of autoPolicies ?? []) {
20349
+ policies.push({
20350
+ element_id: auto.element_id,
20351
+ version_id: auto.version_id,
20352
+ subtype: auto.subtype,
20353
+ rank: auto.rank,
20354
+ text: auto.text,
20355
+ locale: auto.locale
20356
+ });
20357
+ }
20328
20358
  const fragments = [];
20329
20359
  for (const [i, ref] of asArray3(settings.fragment_refs).entries()) {
20330
20360
  const resolved = await refOf(
@@ -20528,12 +20558,120 @@ async function komponiere(z) {
20528
20558
  assumptions,
20529
20559
  diagnostics,
20530
20560
  capabilities: eingefroreneFaehigkeiten,
20561
+ // Die eine kanonische Stelle: die Anweisung des Aufrufers, sonst die im
20562
+ // Shot hinterlegte. Beim Szene-Direktlauf gibt es nur die erste — und
20563
+ // genau sie fehlte dem Renderer bisher (Schritt 03 §7).
20564
+ user_instruction: userInstruction ?? shotInstruction,
20531
20565
  context_chain: [...contextChain],
20532
20566
  target_model_resolution: targetModelResolution
20533
20567
  }
20534
20568
  };
20535
20569
  }
20536
20570
 
20571
+ // src/lib/szenen/scenePolicies.ts
20572
+ var GENERAL_POLICY_SUBTYPE = "general";
20573
+ var isObject12 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
20574
+ var str2 = (v) => typeof v === "string" && v.trim().length > 0 ? v : null;
20575
+ var num2 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
20576
+ function sortScenePolicies(policies) {
20577
+ 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));
20578
+ }
20579
+ function scenePolicyFingerprint(policies) {
20580
+ return policies.map((p) => `${p.element_id}@${p.version_id}`).join(",");
20581
+ }
20582
+ function resolveGeneralScenePolicies(snapshot, contextChain) {
20583
+ if (typeof snapshot.listElements !== "function") {
20584
+ return {
20585
+ kind: "error",
20586
+ 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.",
20587
+ retryable: false
20588
+ };
20589
+ }
20590
+ const kette = contextChain.length > 0 ? contextChain : [null];
20591
+ const gesehen = /* @__PURE__ */ new Set();
20592
+ const gefunden = [];
20593
+ for (const [chainIndex, link] of kette.entries()) {
20594
+ const liste = snapshot.listElements({ contextId: link, type: "prompt_policy" });
20595
+ if (liste.kind !== "ok" || !liste.value) {
20596
+ return {
20597
+ kind: "error",
20598
+ message: liste.message ?? `Die prompt_policy-Elemente des Kontexts ${link ?? "global"} konnten nicht gelesen werden.`,
20599
+ retryable: true
20600
+ };
20601
+ }
20602
+ for (const element of liste.value) {
20603
+ if (gesehen.has(element.element_id)) continue;
20604
+ gesehen.add(element.element_id);
20605
+ const gelesen = snapshot.getElement(element.element_id);
20606
+ if (gelesen.kind !== "ok") {
20607
+ return {
20608
+ kind: "error",
20609
+ message: gelesen.message ?? `Element ${element.element_id} konnte nicht gelesen werden.`,
20610
+ retryable: true
20611
+ };
20612
+ }
20613
+ const stand = gelesen.value;
20614
+ if (!stand) {
20615
+ return {
20616
+ kind: "error",
20617
+ message: `Element ${element.element_id} steht in der Elementliste des Kontexts ${link ?? "global"}, aber nicht in derselben Momentaufnahme.`,
20618
+ retryable: false
20619
+ };
20620
+ }
20621
+ const versionen = stand.versions ?? [];
20622
+ const payloadVon = (versionId2) => {
20623
+ const payload2 = versionen.find((v) => v.version_id === versionId2)?.payload;
20624
+ return isObject12(payload2) ? payload2 : null;
20625
+ };
20626
+ const istGeneral = (versionId2) => str2(payloadVon(versionId2)?.subtype) === GENERAL_POLICY_SUBTYPE;
20627
+ const kopf = effectivePreferredHeadSafe(
20628
+ { element: stand.element, versions: versionen, preferredHeads: stand.preferredHeads },
20629
+ kette
20630
+ );
20631
+ if (kopf.kind === "dag_fehler") {
20632
+ return {
20633
+ kind: "error",
20634
+ message: `Der Versionsgraph der Policy ${element.element_id} ist nicht aufbaubar: ${kopf.message}`,
20635
+ retryable: false
20636
+ };
20637
+ }
20638
+ if (kopf.kind === "keine_version") continue;
20639
+ const resolution = kopf.outcome.resolution;
20640
+ if (resolution.kind === "fork") {
20641
+ const relevant = resolution.heads.filter(istGeneral);
20642
+ if (relevant.length === 0) continue;
20643
+ return {
20644
+ kind: "rejected",
20645
+ 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.`,
20646
+ element_id: element.element_id,
20647
+ heads: resolution.heads
20648
+ };
20649
+ }
20650
+ const versionId = usableHeadVersionId(resolutionOf(kopf));
20651
+ if (!versionId) continue;
20652
+ const payload = payloadVon(versionId);
20653
+ if (!payload) {
20654
+ return {
20655
+ kind: "error",
20656
+ message: `Die wirksame Version ${versionId} der Policy ${element.element_id} steht nicht mit lesbarer Payload in der Momentaufnahme.`,
20657
+ retryable: false
20658
+ };
20659
+ }
20660
+ if (str2(payload.subtype) !== GENERAL_POLICY_SUBTYPE) continue;
20661
+ gefunden.push({
20662
+ element_id: element.element_id,
20663
+ version_id: versionId,
20664
+ subtype: GENERAL_POLICY_SUBTYPE,
20665
+ rank: num2(payload.rank) ?? 0,
20666
+ text: str2(payload.text) ?? "",
20667
+ locale: str2(payload.locale),
20668
+ chain_index: chainIndex
20669
+ });
20670
+ }
20671
+ }
20672
+ return { kind: "ok", policies: sortScenePolicies(gefunden) };
20673
+ }
20674
+
20537
20675
  // src/lib/szenen/freezeDraftChain.ts
20538
20676
  function ladeKnoten(sicht, elementId, erwarteterTyp) {
20539
20677
  const gelesen = sicht.getElement(elementId);
@@ -20735,9 +20873,19 @@ async function freezeSceneWorkingState(input) {
20735
20873
  const a = await store.readSnapshot({ fresh: false });
20736
20874
  const szene = ladeSzene(a, sceneElementId, contextChain);
20737
20875
  if ("fehler" in szene) return ausfallErgebnis(szene);
20876
+ const policiesA = resolveGeneralScenePolicies(a, contextChain);
20877
+ if (policiesA.kind === "error") {
20878
+ return { kind: "error", message: policiesA.message, retryable: policiesA.retryable };
20879
+ }
20880
+ if (policiesA.kind !== "ok") return { kind: "rejected", message: policiesA.message };
20738
20881
  const b = await store.readSnapshot({ fresh: true });
20739
20882
  const erneut = ladeSzene(b, sceneElementId, contextChain);
20740
20883
  if ("fehler" in erneut) return ausfallErgebnis(erneut);
20884
+ const policiesB = resolveGeneralScenePolicies(b, contextChain);
20885
+ if (policiesB.kind === "error") {
20886
+ return { kind: "error", message: policiesB.message, retryable: policiesB.retryable };
20887
+ }
20888
+ if (policiesB.kind !== "ok") return { kind: "rejected", message: policiesB.message };
20741
20889
  if (erneut.draft_id !== szene.draft_id || erneut.revision !== szene.revision || erneut.version_id !== szene.version_id) {
20742
20890
  return {
20743
20891
  kind: "conflict",
@@ -20747,6 +20895,17 @@ async function freezeSceneWorkingState(input) {
20747
20895
  actualRevision: erneut.revision ?? 0
20748
20896
  };
20749
20897
  }
20898
+ const vorher = scenePolicyFingerprint(policiesA.policies);
20899
+ const nachher = scenePolicyFingerprint(policiesB.policies);
20900
+ if (vorher !== nachher) {
20901
+ return {
20902
+ kind: "conflict",
20903
+ 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.`,
20904
+ node: { type: "scene", element_id: sceneElementId, draft_id: szene.draft_id ?? "" },
20905
+ expectedRevision: szene.revision ?? 0,
20906
+ actualRevision: erneut.revision ?? 0
20907
+ };
20908
+ }
20750
20909
  const aufgeloest = await resolveScenePayload({
20751
20910
  scenePayload: szene.payload,
20752
20911
  sceneElementId: szene.element_id,
@@ -20755,7 +20914,10 @@ async function freezeSceneWorkingState(input) {
20755
20914
  sceneVersionId: szene.version_id ?? "",
20756
20915
  resolver,
20757
20916
  contextChain,
20758
- userInstruction
20917
+ userInstruction,
20918
+ // Der aus A gebildete und gegen B bestaetigte Satz — kein dritter
20919
+ // Leseweg nach dem Freeze.
20920
+ autoPolicies: policiesA.policies
20759
20921
  });
20760
20922
  if (aufgeloest.kind !== "resolved") {
20761
20923
  return {
@@ -20772,7 +20934,8 @@ async function freezeSceneWorkingState(input) {
20772
20934
  revision: szene.revision,
20773
20935
  version_id: szene.version_id
20774
20936
  },
20775
- input: aufgeloest.input
20937
+ input: aufgeloest.input,
20938
+ policies: policiesA.policies
20776
20939
  };
20777
20940
  }
20778
20941
 
@@ -20832,6 +20995,24 @@ function buildSystemInstruction2(input) {
20832
20995
  'Widersprechen sie einander, nenne den Widerspruch mit beiden Quellen in "notes" \u2014',
20833
20996
  "waehle nicht still eine Seite."
20834
20997
  );
20998
+ if (input.policies.length > 0) {
20999
+ zeilen.push(
21000
+ "",
21001
+ 'In "policies" stehen verbindliche Transformationsregeln fuer die Formulierung.',
21002
+ "Setze sie um, ohne ihren Wortlaut in den Prompt zu uebernehmen; sie sind",
21003
+ "Anweisung an dich, nicht Prompttext. Bei gleichem Rang gilt die Reihenfolge",
21004
+ "der Liste."
21005
+ );
21006
+ }
21007
+ if (input.user_instruction !== null && input.user_instruction !== void 0) {
21008
+ zeilen.push(
21009
+ "",
21010
+ '"user_instruction" ist eine ZUSAETZLICHE Arbeitsanweisung fuer genau diesen Lauf.',
21011
+ "Sie tritt zu den Policies hinzu und hebt keine davon auf. Widerspricht sie einer",
21012
+ 'Policy erkennbar, nenne den Widerspruch mit beiden Quellen in "feedback" bzw.',
21013
+ '"notes" \u2014 waehle nicht still eine Seite.'
21014
+ );
21015
+ }
20835
21016
  if (input.camera === null) {
20836
21017
  zeilen.push(
20837
21018
  "",
@@ -20853,7 +21034,7 @@ function buildSystemInstruction2(input) {
20853
21034
  function buildUserPrompt2(input) {
20854
21035
  return JSON.stringify(input, null, 2);
20855
21036
  }
20856
- var isObject12 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
21037
+ var isObject13 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
20857
21038
  function parseRunResponse(raw) {
20858
21039
  const text = raw.trim().replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/, "").trim();
20859
21040
  if (text.length === 0) return { ok: false, message: "Die Antwort war leer." };
@@ -20867,7 +21048,7 @@ function parseRunResponse(raw) {
20867
21048
  }
20868
21049
  }
20869
21050
  function checkRunResponse(value, input) {
20870
- if (!isObject12(value)) {
21051
+ if (!isObject13(value)) {
20871
21052
  return { ok: false, message: `Die Antwort ist kein Objekt, sondern ${Array.isArray(value) ? "array" : typeof value}.` };
20872
21053
  }
20873
21054
  if (typeof value.positive !== "string" || value.positive.trim().length === 0) {
@@ -20889,7 +21070,7 @@ function checkRunResponse(value, input) {
20889
21070
  };
20890
21071
  }
20891
21072
  const visibility = value.visibility;
20892
- if (!isObject12(visibility)) {
21073
+ if (!isObject13(visibility)) {
20893
21074
  return { ok: false, message: '"visibility" fehlt \u2014 die Pflichtdiagnosen aus D-21.' };
20894
21075
  }
20895
21076
  if (typeof visibility.basis !== "string") {
@@ -20901,7 +21082,7 @@ function checkRunResponse(value, input) {
20901
21082
  const genannt = /* @__PURE__ */ new Set();
20902
21083
  const nodes = [];
20903
21084
  for (const eintrag of visibility.nodes) {
20904
- if (!isObject12(eintrag) || typeof eintrag.node_id !== "string" || typeof eintrag.state !== "string") {
21085
+ if (!isObject13(eintrag) || typeof eintrag.node_id !== "string" || typeof eintrag.state !== "string") {
20905
21086
  return { ok: false, message: 'Ein Eintrag in "visibility.nodes" hat keine node_id oder keinen state.' };
20906
21087
  }
20907
21088
  genannt.add(eintrag.node_id);