fixes before document generation refactory styles

This commit is contained in:
ValueOn AG 2026-04-29 22:54:21 +02:00
parent 5955caff61
commit 00d99f50f1
4 changed files with 69 additions and 33 deletions

View file

@ -1,5 +1,6 @@
<!-- status: plan --> <!-- status: plan -->
<!-- started: 2026-04-29 --> <!-- started: 2026-04-29 -->
<!-- reviewed: 2026-04-29 (critical review passed, corrections applied) -->
<!-- component: gateway, frontend-nyla --> <!-- component: gateway, frontend-nyla -->
# AI Reports: Generisches Style-Management, AI-Call-Konfiguration, Inline-Bilder # AI Reports: Generisches Style-Management, AI-Call-Konfiguration, Inline-Bilder
@ -59,6 +60,10 @@ explizit und auditierbar.
- Inline-Bilder erfordern Schema-Aenderung beim `cell`/`paragraph`/ - Inline-Bilder erfordern Schema-Aenderung beim `cell`/`paragraph`/
`bullet_list_item`-Content: weg von `string`, hin zu `inline-Run- `bullet_list_item`-Content: weg von `string`, hin zu `inline-Run-
Liste` (`text` | `image` | `link` | `bold` | `italic`). Liste` (`text` | `image` | `link` | `bold` | `italic`).
- **KEIN Backwards-Compat:** Altes String-basiertes Format wird NICHT
weiter unterstuetzt. Renderer bekommen NUR das neue Inline-Run-
Modell. Alte Workflow-Runs mit altem JSON-Output brechen bei erneutem
Rendering -- akzeptabler Trade-off fuer saubere Codebasis.
- Per-Node AI-Konfiguration darf das **zentrale AI-Gate** nicht - Per-Node AI-Konfiguration darf das **zentrale AI-Gate** nicht
umgehen: das Gate bleibt einzige Stelle, die Neutralisierung wirklich umgehen: das Gate bleibt einzige Stelle, die Neutralisierung wirklich
durchsetzt. Node-Parameter werden in den `AiCallRequest` reingefuettert durchsetzt. Node-Parameter werden in den `AiCallRequest` reingefuettert
@ -86,14 +91,18 @@ explizit und auditierbar.
- NICHT: User-konfigurierbare Custom-Themes via Admin-UI. - NICHT: User-konfigurierbare Custom-Themes via Admin-UI.
- NICHT: Aenderung am bestehenden Neutralisierungs-Engine; nur Eingangs- - NICHT: Aenderung am bestehenden Neutralisierungs-Engine; nur Eingangs-
Pfad ergaenzen. Pfad ergaenzen.
- NICHT: Backwards-Compat fuer altes JSON-Format (Clean-Break).
## Betroffene Module ## Betroffene Module
- Gateway: - Gateway:
- `gateway/modules/serviceCenter/services/serviceAgent/coreTools/_mediaTools.py` - `gateway/modules/serviceCenter/services/serviceAgent/coreTools/_mediaTools.py`
-- `_markdownToDocumentJson` raus, auf gemeinsamen Helper -- `_markdownToDocumentJson` (nested in `_registerMediaTools`, Z. 27-163)
umstellen; `renderDocument`-Tool-Schema ergaenzt um optionalen entfernen, Aufruf auf `subDocumentUtility.markdownToDocumentJson`
`style`-Parameter. umleiten. Image-Resolution-Logik (Z. 241-277, loest fileId -> base64
aus KnowledgeStore/Chat) VERBLEIBT in `_mediaTools` als Post-
Processing-Schritt nach dem Parser-Aufruf.
`renderDocument`-Tool-Schema ergaenzt um optionalen `style`-Parameter.
- `gateway/modules/serviceCenter/services/serviceGeneration/subDocumentUtility.py` - `gateway/modules/serviceCenter/services/serviceGeneration/subDocumentUtility.py`
-- alleinige MD->JSON-Funktion mit Inline-Run-Modell. -- alleinige MD->JSON-Funktion mit Inline-Run-Modell.
- `gateway/modules/serviceCenter/services/serviceGeneration/mainServiceGeneration.py` - `gateway/modules/serviceCenter/services/serviceGeneration/mainServiceGeneration.py`
@ -101,15 +110,21 @@ explizit und auditierbar.
Agent-Overrides). Agent-Overrides).
- `gateway/modules/serviceCenter/services/serviceGeneration/renderers/*` - `gateway/modules/serviceCenter/services/serviceGeneration/renderers/*`
-- alle 5 Renderer auf Style-Lookup umstellen, Inline-Run-Renderer. -- alle 5 Renderer auf Style-Lookup umstellen, Inline-Run-Renderer.
NUR neues Format (InlineRun); altes String-Format wird nicht mehr
unterstuetzt.
- `gateway/modules/datamodels/datamodelJson.py` -- Schema-Erweiterung - `gateway/modules/datamodels/datamodelJson.py` -- Schema-Erweiterung
fuer Inline-Runs und `cellContent`. fuer Inline-Runs und `cellContent`.
- `gateway/modules/datamodels/datamodelAi.py` -- - `gateway/modules/datamodels/datamodelAi.py` --
`AiCallRequest.allowedModels: Optional[List[str]]` (Whitelist). `AiCallOptions.allowedModels: Optional[List[str]]` (Whitelist;
analog `allowedProviders` Z. 164).
- `gateway/modules/serviceCenter/services/serviceAi/mainServiceAi.py` - `gateway/modules/serviceCenter/services/serviceAi/mainServiceAi.py`
-- Whitelist-Check vor Modellwahl, Fail-fast wenn keiner uebrig. -- `_calculateEffectiveModels()` (Z. ~1196, analog zu
`_calculateEffectiveProviders`); Whitelist-Check vor Modellwahl,
Fail-fast wenn keiner uebrig. `_ServicesAdapter.__getattr__`
(Z. 88-90) um `"allowedModels"` ergaenzen.
- `gateway/modules/features/graphicalEditor/nodeDefinitions/ai.py` - `gateway/modules/features/graphicalEditor/nodeDefinitions/ai.py`
-- Standardparameter `requireNeutralization` + `allowedModels` zu -- Standardparameter `requireNeutralization` + `allowedModels` zu
allen `ai.*`-Nodes (gemeinsamer Helper). allen `ai.*`-Nodes (gemeinsamer Helper `_AI_COMMON_PARAMS`).
- `gateway/modules/workflows/methods/methodAi/actions/*.py` -- Node- - `gateway/modules/workflows/methods/methodAi/actions/*.py` -- Node-
Parameter durchreichen in den `AiCallRequest`. Parameter durchreichen in den `AiCallRequest`.
- `gateway/modules/serviceCenter/services/serviceAgent/conversationManager.py` - `gateway/modules/serviceCenter/services/serviceAgent/conversationManager.py`
@ -123,6 +138,8 @@ explizit und auditierbar.
- Workspace-Settings: bestehender Neutralisierungs-Toggle bleibt; - Workspace-Settings: bestehender Neutralisierungs-Toggle bleibt;
neuer Multi-Select fuer `allowedModels` (Default: alle verfuegbaren neuer Multi-Select fuer `allowedModels` (Default: alle verfuegbaren
Modelle des Mandate). Modelle des Mandate).
- HINWEIS: Request-Model heisst `WorkspaceInputRequest` (NICHT
`WorkspaceUserInput`; siehe `routeFeatureWorkspace.py` Z. 102-113).
- Style-Vorschau (klein): Optional Snippet im FlowEditor, das den - Style-Vorschau (klein): Optional Snippet im FlowEditor, das den
`style`-Parameter eines `file.create`/`renderDocument`-Nodes `style`-Parameter eines `file.create`/`renderDocument`-Nodes
visualisieren kann (deferred). visualisieren kann (deferred).
@ -214,11 +231,12 @@ Neu: `inlineRuns: List[InlineRun]` mit
} }
``` ```
Backwards-kompatibel: Wenn der MD-Parser nur Text findet, bleibt es Wenn der MD-Parser nur Text findet, entsteht ein einzelner Run mit
ein einzelner Run mit `type: text`. Renderer bekommen einen Helper `type: text`. Renderer bekommen einen Helper
`_renderInlineRuns(runs, style, container)`, der pro Run das richtige `_renderInlineRuns(runs, style, container)`, der pro Run das richtige
Element produziert (Text-Run mit Style, Inline-Image-Anchor, Element produziert (Text-Run mit Style, Inline-Image-Anchor,
Hyperlink-Run, etc.). Hyperlink-Run, etc.). **Kein** altes `text: str`-Feld -- Renderer
arbeiten ausschliesslich mit `inlineRuns`.
**Markdown-Erkennung:** `![alt](file:xyz)` und `![alt](file:xyz "100pt")` **Markdown-Erkennung:** `![alt](file:xyz)` und `![alt](file:xyz "100pt")`
mitten in einem Paragraph oder in einer Tabellenzelle wird vom Parser mitten in einem Paragraph oder in einer Tabellenzelle wird vom Parser
@ -247,10 +265,10 @@ zu einem `image`-Run. Listen-Items dasselbe.
- **`_calculateEffectiveProviders()`** macht RBAC ∩ Workflow.allowedProviders - **`_calculateEffectiveProviders()`** macht RBAC ∩ Workflow.allowedProviders
und schreibt das in `request.options.allowedProviders` (`mainServiceAi.py` und schreibt das in `request.options.allowedProviders` (`mainServiceAi.py`
Z. 175-178). Z. 175-178).
- **`WorkspaceUserInput.allowedProviders`** + **`requireNeutralization`** - **`WorkspaceInputRequest.allowedProviders`** + **`requireNeutralization`**
werden vom Frontend pro Request mitgegeben werden vom Frontend pro Request mitgegeben
(`routeFeatureWorkspace.py` Z. 111-113) und in den (`routeFeatureWorkspace.py` Z. 111-113) und in den
`ServiceCenterContext` gesetzt (Z. 716-719). `ServiceCenterContext` gesetzt (Z. 713-719).
- **`ServiceCenterContext.requireNeutralization`** existiert (`context.py` - **`ServiceCenterContext.requireNeutralization`** existiert (`context.py`
Z. 23). Z. 23).
- **`GET /api/system/ai-models`** liefert die verfuegbaren Modelle - **`GET /api/system/ai-models`** liefert die verfuegbaren Modelle
@ -360,29 +378,35 @@ flowchart LR
| 2026-04-29 | Whitelist-Check vor Modellwahl; leer -> Fail-fast | Compliance: Workflow soll **deterministisch** scheitern statt stillschweigend ein nicht-erlaubtes Modell zu nehmen | | 2026-04-29 | Whitelist-Check vor Modellwahl; leer -> Fail-fast | Compliance: Workflow soll **deterministisch** scheitern statt stillschweigend ein nicht-erlaubtes Modell zu nehmen |
| 2026-04-29 | MD->JSON-Konsolidierung in `subDocumentUtility.py` | Bereits zentralerer Pfad als `_mediaTools` | | 2026-04-29 | MD->JSON-Konsolidierung in `subDocumentUtility.py` | Bereits zentralerer Pfad als `_mediaTools` |
| 2026-04-29 | Native XLSX-Charts via openpyxl spaeter | Heute reicht PNG-Embed; Chart-API ist eigene Komplexitaet | | 2026-04-29 | Native XLSX-Charts via openpyxl spaeter | Heute reicht PNG-Embed; Chart-API ist eigene Komplexitaet |
| 2026-04-29 | KEIN Backwards-Compat fuer altes JSON-Format | Clean-Break: alte Runs brechen, akzeptabler Trade-off fuer saubere Codebasis ohne Dispatch-Overhead |
| 2026-04-29 | `WorkspaceUserSettings` in `poweron_app` (nicht `poweron_workspace`) | Dort leben User-spezifische Instanz-Daten (FeatureAccess etc.) |
| 2026-04-29 | Image-Resolution-Logik verbleibt in `_mediaTools` (Post-Processing) | Nur der MD-Parser wird konsolidiert; fileId->base64-Auflosung ist kontextabhaengig (Chat-History, KnowledgeStore) |
| 2026-04-29 | `documentTheme` (Plan B) wird Prompt-Hint, NICHT Renderer-Parameter | Renderer hat kein Theme-Konzept; Agent leitet Style aus Hint ab |
## Umsetzungs-Checkliste ## Umsetzungs-Checkliste
### Phase 1 -- MD->JSON konsolidieren + Inline-Runs ### Phase 1 -- MD->JSON konsolidieren + Inline-Runs
- [ ] `subDocumentUtility.markdownToDocumentJson` zur einzigen Quelle - [ ] `subDocumentUtility.markdownToDocumentJson` zur einzigen Quelle
machen. machen (module-level Funktion, Z. 12+).
- [ ] `_mediaTools._markdownToDocumentJson` durch Aufruf des Helpers - [ ] `_mediaTools._markdownToDocumentJson` (nested in
ersetzen, lokale Funktion entfernen. `_registerMediaTools`, Z. 27-163) ENTFERNEN. Stattdessen
`subDocumentUtility.markdownToDocumentJson` aufrufen. Die Image-
Resolution-Logik (Z. 241-277: fileId -> base64 aus
KnowledgeStore/Chat) VERBLEIBT als Post-Processing nach dem
Parser-Aufruf.
- [ ] Schema-Erweiterung in `datamodels/datamodelJson.py`: - [ ] Schema-Erweiterung in `datamodels/datamodelJson.py`:
- `paragraph.inlineRuns: List[InlineRun]` (alt `text: str` als - `paragraph.inlineRuns: List[InlineRun]` (KEIN Backwards-Compat-
Backwards-Compat-Feld weiter unterstuetzt). Feld `text: str` -- Clean-Break).
- `bullet_list.items: List[List[InlineRun]]`. - `bullet_list.items: List[List[InlineRun]]`.
- `table.cell` neu strukturiert: `cellContent: List[InlineRun]` - `table.cell` neu: `cellContent: List[InlineRun]`.
oder `cellBlocks: List[Section]` (fuer komplexere Zellen mit - Altes String-basiertes Format wird NICHT mehr unterstuetzt.
eigenem Paragraph/Image-Block).
- [ ] MD-Parser im konsolidierten Helper: - [ ] MD-Parser im konsolidierten Helper:
- Inline `![alt](file:xyz)` an beliebiger Position erkennen -> - Inline `![alt](file:xyz)` an beliebiger Position erkennen ->
`image`-Run. `image`-Run.
- Inline `[text](url)` -> `link`-Run. - Inline `[text](url)` -> `link`-Run.
- `**bold**` / `*italic*` / `` `code` `` -> entsprechende Runs. - `**bold**` / `*italic*` / `` `code` `` -> entsprechende Runs.
- Tabellen-Zellen: erkennen ob nur Text -> einzelner Text-Run; - Tabellen-Zellen: voll geparst (inkl. Bild, Links, Formatierung).
sonst voll geparst (inkl. Bild).
- [ ] Helper `_renderInlineRuns(runs, style, container)` als gemeinsame - [ ] Helper `_renderInlineRuns(runs, style, container)` als gemeinsame
Spec; pro Renderer eigene Implementierung. Spec; pro Renderer eigene Implementierung.
@ -455,7 +479,7 @@ flowchart LR
`Workflow.allowedProviders`). `Workflow.allowedProviders`).
- [ ] `gateway/modules/serviceCenter/services/serviceAi/mainServiceAi.py`: - [ ] `gateway/modules/serviceCenter/services/serviceAi/mainServiceAi.py`:
- Neue private Methode `_calculateEffectiveModels()` analog zu - Neue private Methode `_calculateEffectiveModels()` analog zu
`_calculateEffectiveProviders()` (Z. 175-178). RBAC-Modelle ∩ `_calculateEffectiveProviders()` (Z. ~1196). RBAC-Modelle ∩
`Workflow.allowedModels``request.options.allowedModels`. `Workflow.allowedModels``request.options.allowedModels`.
- In `_call`/`_callStream`/`callEmbedding` analog zur - In `_call`/`_callStream`/`callEmbedding` analog zur
Provider-Logik aufrufen und in `request.options.allowedModels` Provider-Logik aufrufen und in `request.options.allowedModels`
@ -465,15 +489,17 @@ flowchart LR
- Fail-fast `RuntimeError` wenn die Filterkette leer wird, mit - Fail-fast `RuntimeError` wenn die Filterkette leer wird, mit
Audit-Log-Zeile (modelle, provider, rbac-permitted, workflow, Audit-Log-Zeile (modelle, provider, rbac-permitted, workflow,
node). node).
- [ ] `__getattr__` in `mainServiceAi.py` (Z. 88-90) erweitern: - [ ] `_ServicesAdapter.__getattr__` in `mainServiceAi.py` (Z. 88-90)
Tuple-Liste um `"allowedModels"` ergaenzen (damit erweitern: Tuple-Liste um `"allowedModels"` ergaenzen (damit
`service.allowedModels` analog `service.allowedProviders` `service.allowedModels` analog `service.allowedProviders`
aus dem Workflow durchgereicht wird). aus dem Workflow durchgereicht wird).
### Phase 5a -- Workspace User-Settings (Persistenz fuer alle drei Felder) ### Phase 5a -- Workspace User-Settings (Persistenz fuer alle drei Felder)
- [ ] Neue persistente Settings pro User × Workspace-Instanz. - [ ] Neue persistente Settings pro User × Workspace-Instanz.
Tabelle `WorkspaceUserSettings` (additiv via Auto-Init): Tabelle `WorkspaceUserSettings` in **`poweron_app`** (dort wo
`FeatureAccess`, `FeatureInstance` etc. leben; User-spezifische
Instanz-Daten). Additiv via Auto-Init:
- `instanceId UUID NOT NULL` - `instanceId UUID NOT NULL`
- `userId UUID NOT NULL` - `userId UUID NOT NULL`
- `requireNeutralization BOOL DEFAULT false` - `requireNeutralization BOOL DEFAULT false`
@ -486,13 +512,15 @@ flowchart LR
leer). leer).
- `PUT /api/workspace/{instanceId}/user-settings` -- speichern - `PUT /api/workspace/{instanceId}/user-settings` -- speichern
(alle drei Felder im Body). (alle drei Felder im Body).
- [ ] `WorkspaceUserInput.allowedModels: List[str] = []` (additiv, - [ ] `WorkspaceInputRequest.allowedModels: List[str] = Field(default_factory=list)`
`routeFeatureWorkspace.py` Z. 109-114). `requireNeutralization` (additiv, `routeFeatureWorkspace.py` Z. 102-113).
und `allowedProviders` sind dort schon vorhanden (Z. 112-113). `requireNeutralization` und `allowedProviders` sind dort schon
vorhanden (Z. 111-112).
- [ ] In `_runWorkspaceAgent` (Z. 693+): `allowedModels` ebenso - [ ] In `_runWorkspaceAgent` (Z. 693+): `allowedModels` ebenso
durchreichen wie heute `allowedProviders` (Z. 716-717) -- in das durchreichen wie heute `allowedProviders` (Z. 713-717) -- in das
`request.options.allowedModels`-Feld schreiben (siehe Phase 5 `request.options.allowedModels`-Feld schreiben (siehe Phase 5
Datenmodell). Datenmodell). Pattern analog:
`aiService.services.allowedModels = allowedModels`.
- [ ] Frontend Workspace: - [ ] Frontend Workspace:
- Workspace-Settings-Tab/Panel mit allen drei Feldern: - Workspace-Settings-Tab/Panel mit allen drei Feldern:
- Toggle `requireNeutralization`. - Toggle `requireNeutralization`.
@ -535,14 +563,20 @@ flowchart LR
### Phase 6 -- Trustee-Templates anpassen (entkoppelt vom Bau-Plan B) ### Phase 6 -- Trustee-Templates anpassen (entkoppelt vom Bau-Plan B)
- [ ] In `mainTrustee.py`-Templates: `style`-Block in `aiPrompt`-Node - [ ] In `mainTrustee.py`-Templates: neuen Node-Parameter `style`-Block
Parametern setzen (Finanzreport-Defaults: dunkelblaue Headings, setzen (Finanzreport-Defaults: dunkelblaue Headings,
konservatives Calibri etc.) -- damit Trustee out-of-the-box gut konservatives Calibri etc.) -- damit Trustee out-of-the-box gut
aussieht. aussieht. Der in Plan B gesetzte `documentTheme: "finance"`
wird als Hint fuer den Agent im Prompt benutzt (NICHT als
Renderer-Parameter); der Agent soll daraus seinen `style`-Block
ableiten.
- [ ] `requireNeutralization: true` falls Trustee-Daten sensibel - [ ] `requireNeutralization: true` falls Trustee-Daten sensibel
(entscheidet Compliance-Doku, Default empfohlen). (entscheidet Compliance-Doku, Default empfohlen).
- [ ] `allowedModels` pro Trustee-Workflow optional pinned (z.B. nur - [ ] `allowedModels` pro Trustee-Workflow optional pinned (z.B. nur
private LLM fuer Finance-Daten). private LLM fuer Finance-Daten).
- [ ] `documentTheme`-Parameter im Budget-Template (aus Plan B) in den
Prompt als Kontext-Hint einfuegen, statt als separaten
Renderer-Parameter. Der Renderer kennt KEIN Theme-Konzept.
### Phase 7 -- Tests / Snapshots ### Phase 7 -- Tests / Snapshots

View file

@ -14,6 +14,8 @@ Skip: reine Refactors, Formatting, Lint, Dep-Bumps, Test-only, Wiki-Tippfehler.
## 2026-04-29 ## 2026-04-29
- 2026-04-29 | feat | gateway, frontend-nyla | **B: Trustee Budget-Vergleich auf Excel umgestellt.** `mainTrustee.py` Template: `resultType: "xlsx"` + `documentTheme: "finance"` hart gesetzt. Prompt komplett refaktoriert: 1 Tabelle alle Konten, 1 Uebersichts-Chart (kein pro-Konto-Chart), Management-Summary. Frontend: Hinweistext "Excel-Bericht" im Budget-Tab ergaenzt. XLSX-Renderer (PNG-unter-Tabelle) verifiziert. (c-work: `3-validate/2026-04-trustee-budget-comparison-refactor.md`)
- 2026-04-29 | feat | gateway, frontend-nyla | **A2 Workflow-Run-Workspace + targetFeatureInstanceId implementiert.** Phase 1: `AutoWorkflow.targetFeatureInstanceId` (Pydantic + DB), createWorkflow-Fallback, Save-Validation (400 fuer non-template ohne targetId), Execute-RBAC-Check, `executeGraph` Placeholder-Substitution (`{{featureInstanceId}}`), Scheduler-Durchreichung, `_copyTemplateWorkflows` explizites Setzen, idempotente Boot-Backfill-Migration. Phase 2: FlowEditor CanvasHeader "Ziel-Instanz" Dropdown mit FeatureStore-Integration, Save/Load mit `targetFeatureInstanceId`. Phase 3: Neuer Backend-Endpoint `GET /api/automations/runs` + `GET /api/automations/runs/{runId}/detail` (RBAC via FeatureAccess), neuer "Workspace" Tab in AutomationsDashboardPage mit Run-Liste + Detail-View (Steps, Files, Download). Phase 4: TrusteeAnalyseView inline-Results durch "Im Workspace ansehen"-Link ersetzt, TrusteeAbschlussView Workspace-Link nach Completion ergaenzt. (c-work: `1-plan/2026-04-trustee-workflow-audit-and-run-workspace.md`) - 2026-04-29 | feat | gateway, frontend-nyla | **A2 Workflow-Run-Workspace + targetFeatureInstanceId implementiert.** Phase 1: `AutoWorkflow.targetFeatureInstanceId` (Pydantic + DB), createWorkflow-Fallback, Save-Validation (400 fuer non-template ohne targetId), Execute-RBAC-Check, `executeGraph` Placeholder-Substitution (`{{featureInstanceId}}`), Scheduler-Durchreichung, `_copyTemplateWorkflows` explizites Setzen, idempotente Boot-Backfill-Migration. Phase 2: FlowEditor CanvasHeader "Ziel-Instanz" Dropdown mit FeatureStore-Integration, Save/Load mit `targetFeatureInstanceId`. Phase 3: Neuer Backend-Endpoint `GET /api/automations/runs` + `GET /api/automations/runs/{runId}/detail` (RBAC via FeatureAccess), neuer "Workspace" Tab in AutomationsDashboardPage mit Run-Liste + Detail-View (Steps, Files, Download). Phase 4: TrusteeAnalyseView inline-Results durch "Im Workspace ansehen"-Link ersetzt, TrusteeAbschlussView Workspace-Link nach Completion ergaenzt. (c-work: `1-plan/2026-04-trustee-workflow-audit-and-run-workspace.md`)
- 2026-04-29 | docs | wiki | **Plan A2 finalisiert: Trustee Workflow-Audit + Generischer Workflow-Run-Workspace.** Cross-Check gegen Codebase (12 Punkte verifiziert, 4 Korrekturen eingearbeitet): `executeGraph` hat keine Placeholder-Substitution (muss neu gebaut werden), `_copyTemplateWorkflows` setzt `featureInstanceId` nicht im Payload (implizit via GE-Interface), `TrusteeAbschlussView` hat kein `resultText`/`resultDocuments` (nur status/summary), 7 Trustee-Templates statt 5 im Audit. Risiko-Sektion ergaenzt. (c-work: `1-plan/2026-04-trustee-workflow-audit-and-run-workspace.md`) - 2026-04-29 | docs | wiki | **Plan A2 finalisiert: Trustee Workflow-Audit + Generischer Workflow-Run-Workspace.** Cross-Check gegen Codebase (12 Punkte verifiziert, 4 Korrekturen eingearbeitet): `executeGraph` hat keine Placeholder-Substitution (muss neu gebaut werden), `_copyTemplateWorkflows` setzt `featureInstanceId` nicht im Payload (implizit via GE-Interface), `TrusteeAbschlussView` hat kein `resultText`/`resultDocuments` (nur status/summary), 7 Trustee-Templates statt 5 im Audit. Risiko-Sektion ergaenzt. (c-work: `1-plan/2026-04-trustee-workflow-audit-and-run-workspace.md`)