Update AI Prompt System and Documentation
All checks were successful
Deploy Development / deploy (push) Successful in 41s
Test Suite / pytest-backend (push) Successful in 42s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 12s
Test Suite / k6 /health Baseline (push) Successful in 33s
Test Suite / playwright-tests (push) Successful in 1m18s

- Added a new target architecture document for the AI Prompt System, detailing context types, composition, and planning phases.
- Refactored the backend to utilize a shared function for loading AI prompt rows, reducing SQL duplication in the `exercise_ai` module.
- Incremented the application version to 0.8.159 and updated the changelog to reflect these changes, including enhancements to the AI prompt management and documentation links.
This commit is contained in:
Lars 2026-05-22 11:05:35 +02:00
parent 2148d0aa7f
commit cdeddc7cec
8 changed files with 268 additions and 31 deletions

View File

@ -4,6 +4,8 @@
**Datum:** 2026-05-30
**Status:** Kern umgesetzt (`ai_prompts`, `prompt_resolver`, Superadmin-HTTP-API); Kaskaden geplant (Abschnitt 8)
**Zielbild (Roadmap):** `.claude/docs/technical/AI_PROMPT_TARGET_ARCHITECTURE.md` — Kontext-Arten, Composition, Planung/Rahmen, Phasenplan.
**Ist-Stand API (Superadmin):**
- `GET /api/admin/ai-prompts`, `GET /api/admin/ai-prompts/{id}`, `PUT …`, `POST …/preview`, `POST …/reset-template`, `GET /api/admin/ai-prompts/catalog/placeholders`

View File

@ -0,0 +1,164 @@
# KI-Prompt-System — Zielarchitektur (Shinkan Jinkendo)
**Version:** 1.0
**Datum:** 2026-05-30
**Status:** VERBINDLICHE ZIELRICHTUNG (Roadmap — nicht alles bereits umgesetzt)
**Ergänzt:** `AI_PROMPT_SYSTEM_SPEC.md` (aktueller Ist-Stand APIs/DB/UI), Mitai-Anleihen aus gleichnamigen Konzepten (Admin-Prompts, Platzhalter)
---
## 1. Zweck
Dieses Dokument beschreibt das **Zielbild**, damit spätere Arbeiten (**Trainingsplanung**, **mehrstufige Rahmenprogramme**, **Phasen/Streams**, weitere KI-Artefakte) **nicht** zu wiederholten Refaktoren von Übungs-KI oder OpenRouter-Anbindung zwingen.
**Leitkriterien:** wenige stabile Schnittflächen, Kontext pro Domäne, komponierbare Prompts, gültige Ausgaben, Betrieb ohne Code-Deploy für kleine Tweaks.
---
## 2. Leitprinzipien
### 2.1 Eine stabile Ausführungsschicht
Alle produktiven KI-Aufrufe sollten mittelfristig über eine **einheitliche Fassade** laufen:
- **Eingabe:** `slug` (+ optional Kontext-Arten-Enum), **serialisierter Domän-Kontext** (Pydantic pro Kind), Konfiguration (Modell, Temperatur, … aus Env/DB).
- **Ausgabe:** Text oder validiertes JSON, Metadaten (`model`, `slug`, ggf. `prompt_version`/Hash), strukturierte Fehler.
Router und Frontend rufen diese Schicht oder schmale Orchestratoren — **nicht** direkt `httpx`/OpenRouter an jeder Ecke verteilt.
**Frühere Konkretisierung (Umsetzung gestartet):** Modul `backend/ai_prompt_runtime.py` mit **Kontext-Arten** und **gemeinsamen DB-Ladeschritten** für `ai_prompts`; Übungs-KI konsumiert diese Schicht ohne Zirkelschluss zu Domänlogik (`exercise_ai`).
### 2.2 Trennung: Semantik vs. Transport
- **Semantik:** Was soll das Modell liefern? Das hängt an **Prompt-Definition**, **Ausgabeformat** (`text`/`json`) und nachvollziehbarer Validierung — nicht am HTTP-Client.
- **Transport:** OpenRouter, Modellwahl, Retry, Timeouts bleiben in einem oder wenigen Hilfsmodulen.
### 2.3 Kontext-Namespaces für Platzhalter
Platzhalter und erlaubte Keys sind **pro logischer Kontext-Art** definiert, z.B.:
- `exercise_form_ai` — heute: Übungsformular-Vorschläge.
- später: `training_unit`, `framework_program_slot`, `import_wiki`, …
Damit kann der Katalog wachsen, ohne dass alle Keys in einen globalen Soup-Namespace müssen (`exercise_*` vs. `framework_*` ohne Kollisionen). Optional später **präfixierte** Keys (`exercise.title`, `slot.index`).
### 2.4 Komposition / Kaskade explizit
**Ziel:** Mehrteilige Prompts („System“„Nutzer“Anhänge) und **Einbindung anderer Vorlagen** als **Daten** (Kompositionsmodell), nicht nur als unbearbeiteter Freitext mit `{{include}}`.
Skizzen (noch nicht vollständig umgesetzt):
- Tabelle oder JSON-Spalte `composition`/`ai_prompt_segments`: geordnete Segmente mit `role` (`system` \| `user` \| äquivalent zum jeweiligen API-Shape), Quelle (`inline`, `ref_slug`), optional `ref_slug`, Schema-Version.
- Einbindungen mit **Maximaltiefe** und **Zykluserkennung** — keine unbegrenzten Makro-Ketten.
Bis dahin bleiben zusammenhängende Anweisungen in **einem** DB-Template pro Slug tragbar (`exercise_skill_suggestions` + `{{skills_catalog}}` bleiben gültig).
---
## 3. Zieldatenmodell (Schichten)
### 3.1 Definition (`ai_prompts` — bereits vorhanden, evolviert)
| Konzept | Bedeutung |
|--------|-----------|
| `slug`, `category`, `output_format`, `active` | Adressierung & Schalter |
| `template` | aktueller Inhalt |
| `default_template` | Referenz zum Zurücksetzen (Migration **069**) |
| `output_schema` (JSONB) | optional: JSON-Outputs validieren |
**Ausbaustufen:**
1. Nur `template`-Text (**heute**, plus Mustache über `prompt_resolver`).
2. Zusätzlich **Versionierung**: Historie oder `template_version`/Audit (wer hat wann geändert).
3. **Segmentierte Composition** wie in Abschnitt 2.4.
### 3.2 Kontext-Builder pro Domäne
Pro **Kontext-Art** eine klar genannte Routine (Pattern: registrierbare Builder):
| Kontext-Art | Beispiel-Input aus der App | Beispiel-Platzhalter / Daten |
|-------------|----------------------------|------------------------------|
| `exercise_form_ai` | Titel, Ziel/Durchführung (HTML→Plain), Fokuskontext, Retrieval-Profil-Influenza | `exercise_*`, `skills_catalog` |
| `training_unit` (geplant) | Sektionen, Zeiten, Phasen/Streams, verknüpfte Übungs-IDs | `unit_*`, `sections_summary_*` |
| `framework_program` (geplant) | Ziele pro Woche/Schicht, Slots, bereits geplante Einheiten, Skill-Scores | `framework_*`, `slot_*`, aggregierte KPIs |
**Regel:** Planungs-UI baut keine Prompt-Strings; sie liefert **Domän-DTOs** → Builder erzeugen **Platzhalter-Map + ggf. Anhänge**.
### 3.3 Skill-Retrieval und Prompts
`ai_skill_retrieval_profiles` steuert **KatalogZusammenstellung** vor dem Platzhalter `{{skills_catalog}}` — das bleibt **orthogonal** zur Prompt-Verwaltung: Prompt ändert *Anweisung*, Profil ändert *welche Skills im Kontextfenster sind*.
---
## 4. Trainingsplanung & Rahmen — erwartete Komplexität
Risiken: sehr große Kontexte (viele Slots, Streams, Bibliotheken), wiederholte KI-Anfragen, Token-Limits.
**Vorbereitende Strategien:**
1. **Gestufte Kontexte:** Rohdaten → interne Kurzfassungen (optional zweiter Prompt oder heuristisch) → finale Generator-Prompt nur mit komprimierten Summaries.
2. **Slug-Pro-Use-Case:** z.B. `training_unit_trainer_notes`, `framework_slot_coach_hint` — jeweils schmaler Vertrag statt „ein Prompt für alles“.
3. **Output-Verträge:** JSON-Schema + Server-Validierung vor UI; Fehlermeldungen mit Referenz auf Slug/Version.
4. **Feature-Flags / Modell-Overrides** pro Slug (optional in DB oder Env) für Dev/Prod ohne große Codepfade.
---
## 5. Mitai (Jinkendo)
Konzeptionell **gleiche Bausteine** (admin-konfigurierbare Prompts, Platzhalter, Preview), **andere** Kontext-Builder und ggf. andere Mandanten/Overlays. Eine gemeinsame **Resolver-/Mustache-Ebene** ist wünschenswert; **Shinkan-spezifische** Planungs- und Rahmenkontexte bleiben in Shinkan gekapselt.
---
## 6. Betrieb, Sicherheit, Observability
- **Audit:** `updated_by` / Änderungshistorie für Templates (Backlog), heute: Timestamps.
- **Prompt-Injection:** System-/User-Segmente trennen; sensible Regeln in `system`/`developer`-äquivalenten Blöcken (wenn API das hergibt).
- **Logging:** weiter `SHINKAN_AI_DEBUG`; langfristig Hash/Länge des **aufgelösten** Prompts pro Request (ohne Secrets).
- **Kosten/Latenz:** Timeouts, max. Token-Hinweise pro Slug-Konfiguration.
---
## 7. Phasenplan (empfohlen, ohne Big-Bang)
```mermaid
flowchart LR
subgraph heute
A[ai_prompts DB]
B[prompt_resolver Mustache]
C[ai_prompt_runtime Loader + ContextKind]
D[exercise_ai]
end
A --> B
A --> C
C --> D
B --> D
```
| Phase | Inhalt |
|-------|--------|
| **P0 (gestartet)** | `AiPromptContextKind`, `load_ai_prompt_row` zentral; Übungs-KI nutzt Laufzeit; Platzhalter-Katalog pro Kontext erweiterbar. |
| **P1** | Einheitliche `run_ai_job`-Fassade (Slug + Kind + Pydantic-Payload + Validierung); Router nur noch dünne Adapter. |
| **P2** | Versionierung oder Audit-Spalten; optionale Modell-/Temperatur-Overrides pro Slug in DB oder Config-Tabelle. |
| **P3** | Composition/Segmente (JSON Schema Version 1) + UI nur für komplexe Slugs. |
| **P4** | Erste Planungs-/Rahmen-Slugs mit dedizierten Buildern und Token-Budget-Strategien. |
---
## 8. Was bewusst vermieden werden soll
- Vollständige „Workflow-Engine“ mit beliebigen Graphen, bevor 23 konkrete Planungs-Anwendungsfälle live sind.
- Pro-Verein-Prompt-Kopien vor klar definierter Produkt-Anforderung (sonst Daten- und Pflege-Spirale).
- Unbegrenzte `include`-rekursive Textmakros ohne Tiefenschutz.
---
## 9. Querverweise
- Ist-Implementierung Prompts/UI: `AI_PROMPT_SYSTEM_SPEC.md`
- Zugriffsrecht Admin-Prompts: `ACCESS_LAYER_ENDPOINT_AUDIT.md`
- Retrieval-Profile: `.claude/docs/working/AI_SKILL_RETRIEVAL_PROFILES_SPEC.md`
- Übungs-KI-Codepfad: `backend/exercise_ai.py`, `backend/prompt_resolver.py`, `backend/ai_prompt_runtime.py`
---
**Version:** 1.0 · **Datum:** 2026-05-30

View File

@ -17,6 +17,7 @@
> | Fachlicher Nutzerüberblick (Design/Product) | **`docs/FACHLICHE_NUTZERFUNKTIONEN.md`** |
> | Architektur-Zielbild, Refaktor-Roadmap, verbindliche Shinkan-Regeln | **`docs/architecture/README.md`** |
> | Performance-Baseline (Phase 0) | **`docs/architecture/BASELINE_SNAPSHOT.md`** |
> | KI-Prompt-System — Zielarchitektur | `.claude/docs/technical/AI_PROMPT_TARGET_ARCHITECTURE.md` |
## Projekt-Übersicht

View File

@ -0,0 +1,74 @@
"""
Gemeinsame KI-Prompt-Laufzeit (Shinkan): DB-Lesezugriff ai_prompts + Kontext-Arten.
Bleibt ohne Import von exercise_ai (kein Zirkel). Domänen wie exercise_ai nutzen
load_ai_prompt_row und die Enum; Platzhalter bauen sie selbst oder über geteilte Builder.
"""
from __future__ import annotations
from enum import Enum
from typing import Any, Dict, Optional
_EXERCISE_AI_SLUGS = frozenset(
{
"exercise_summary",
"exercise_skill_suggestions",
}
)
class AiPromptContextKind(str, Enum):
"""
Logischer Kontext fuer Platzhalter/Builder erweiterbar fuer Planung/Rahmen
ohne bestehende Slugs zu invalidieren.
"""
EXERCISE_FORM_AI = "exercise_form_ai"
def context_kind_for_slug(slug: str) -> Optional[AiPromptContextKind]:
"""Ordnet einen DB-Slug einer Kontext-Art zu, sofern registriert."""
s = (slug or "").strip().lower()
if s in _EXERCISE_AI_SLUGS:
return AiPromptContextKind.EXERCISE_FORM_AI
return None
def load_ai_prompt_row(cur, slug: str, *, active_only: bool = True) -> Optional[Dict[str, Any]]:
"""
Laedt eine Zeile ai_prompts fuer Laufzeit-Orchestrierung.
active_only=True: inaktive Prompts werden wie fehlend behandelt (503 im Aufrufer).
"""
if active_only:
cur.execute(
"""
SELECT slug, display_name, template, output_format, active
FROM ai_prompts
WHERE slug = %s AND active = true
""",
(slug,),
)
else:
cur.execute(
"""
SELECT slug, display_name, template, output_format, active
FROM ai_prompts
WHERE slug = %s
""",
(slug,),
)
row = cur.fetchone()
if not row:
return None
d = dict(row)
if active_only and not d.get("active", True):
return None
return d
__all__ = [
"AiPromptContextKind",
"context_kind_for_slug",
"load_ai_prompt_row",
]

View File

@ -17,6 +17,8 @@ from typing import Any, Dict, List, Mapping, MutableMapping, Optional, Sequence,
from fastapi import HTTPException
from openrouter_chat import OpenRouterError, normalize_openrouter_env, openrouter_chat_completion
from ai_prompt_runtime import load_ai_prompt_row
from prompt_resolver import render_mustache_template
_LOGGER = logging.getLogger("shinkan.exercise_ai")
@ -489,24 +491,6 @@ def build_contextual_skills_catalog_block(
return "\n".join(lines) if lines else "(keine aktiven Skills im Katalog)"
def _load_prompt_row(cur, slug: str) -> Optional[Dict[str, Any]]:
cur.execute(
"""
SELECT slug, display_name, template, output_format, active
FROM ai_prompts
WHERE slug = %s
""",
(slug,),
)
row = cur.fetchone()
if not row:
return None
d = dict(row)
if not d.get("active", True):
return None
return d
def build_exercise_placeholder_variables(
cur,
*,
@ -731,7 +715,7 @@ def run_exercise_ai_suggestion(
)
if want_summary:
prow = _load_prompt_row(cur, "exercise_summary")
prow = load_ai_prompt_row(cur, "exercise_summary")
if not prow:
raise HTTPException(status_code=503, detail="Prompt exercise_summary nicht aktiv oder fehlt in DB.")
try:
@ -771,7 +755,7 @@ def run_exercise_ai_suggestion(
result["summary"] = {"text": text, "ai_generated": True, "model": model}
if want_skills:
srow = _load_prompt_row(cur, "exercise_skill_suggestions")
srow = load_ai_prompt_row(cur, "exercise_skill_suggestions")
if not srow:
raise HTTPException(
status_code=503,

View File

@ -1,6 +1,6 @@
# Shinkan Jinkendo Version Information
APP_VERSION = "0.8.158"
APP_VERSION = "0.8.159"
BUILD_DATE = "2026-05-30"
DB_SCHEMA_VERSION = "20260530069"
@ -19,12 +19,13 @@ MODULE_VERSIONS = {
"media_legal_hold": "1.0.0", # P-11: Sofortsperre-Services (set_legal_hold, release_legal_hold)
"media_lifecycle": "1.1.0", # P-11: Retention-Job ueberspringt Legal-Hold-Assets
"admin_ai_skill_retrieval": "1.0.0", # Superadmin CRUD /api/admin/ai-skill-retrieval-profiles (Migration 068)
"admin_ai_prompts": "1.0.0", # Superadmin Prompt-Pflege /api/admin/ai-prompts* (067/069 ai_prompts)
"admin_ai_prompts": "1.0.1", # Prompt-Pflege + Zielarchitektur-Doku; gemeinsamer DB-Load uber ai_prompt_runtime
"ai_prompt_runtime": "0.1.0", # AiPromptContextKind, load_ai_prompt_row — Erweiterung Planung ohne Zirkel zu exercise_ai
"groups": "0.1.0",
"skills": "0.1.1", # DB 065 karate_relevance + relevance_level; CRUD unterstützt Felder
"skill_profiles": "1.0.0", # Phase 3: gewichtetes Fähigkeiten-Profil + skill-discovery/suggestions
"methods": "0.1.0",
"exercises": "2.31.0", # AI: build_exercise_placeholder_variables + prompt_resolver-Mustache (Leerstring bei fehlenden Keys)
"exercises": "2.31.1", # AI nutzt load_ai_prompt_row aus ai_prompt_runtime
"training_units": "0.4.0", # POST .../publish-to-framework: Ablauf aus geplanter Einheit → Rahmen-Slot-Blueprint
"training_programs": "0.1.0",
"planning": "0.15.0", # Vorlagen: Strukturvorschau, Bearbeiten inkl. Split-Sessions + Beschreibung
@ -39,6 +40,14 @@ MODULE_VERSIONS = {
}
CHANGELOG = [
{
"version": "0.8.159",
"date": "2026-05-30",
"changes": [
"Doku: AI_PROMPT_TARGET_ARCHITECTURE.md (Zielbild Kontext-Arten, Composition, Planung/Rahmen, Phasenplan); HANDOVER & docs/architecture/README verlinkt;",
"Backend ai_prompt_runtime: AiPromptContextKind, load_ai_prompt_row — exercise_ai ohne duplizierte Prompt-SQL;",
],
},
{
"version": "0.8.158",
"date": "2026-05-30",

View File

@ -1,7 +1,7 @@
# Shinkan Jinkendo Entwicklungsstand & Handover
**Stand:** 2026-05-29
**App-Version / DB-Schema:** App **`0.8.157`** (KI Übungen: UX-Flow + AI_DEBUG Logs), DB-Schema **`20260529068`** — maßgeblich **`backend/version.py`**: `APP_VERSION`, `DB_SCHEMA_VERSION`
**Stand:** 2026-05-30
**App-Version / DB-Schema:** App **`0.8.159`** u.a. **KI-Prompt-Zielarchitektur** + gemeinsames Modul **`ai_prompt_runtime`**; DB-Schema **`backend/version.py`** → `APP_VERSION`, `DB_SCHEMA_VERSION` (aktuell `20260530069`).
Diese Datei ist die **Einstiegs-Doku für neue Chat-Sessions**: Anforderungen im Detail stehen in `.claude/docs/` (siehe unten); hier der **implementierte Stand**, **Medien-Meilenstein** und **sinnvolle nächste Schritte**.
@ -29,6 +29,7 @@ Das Schema ist gegenüber dem Code zurück: Migration **`022_skills_schema_compl
| Media / Upload-Limits / Embed | `.claude/docs/technical/MEDIA_UPLOAD_SPEC.md` |
| MediaWiki-Import | `.claude/docs/technical/MEDIAWIKI_IMPORT_SPEC.md` |
| Zugriffsschicht, Mandant, Governance | `.claude/docs/technical/ACCESS_LAYER_AND_GOVERNANCE_PLAN.md` |
| KI-Prompt-System — Zielarchitektur (Roadmap) | `.claude/docs/technical/AI_PROMPT_TARGET_ARCHITECTURE.md` |
| Tenant-Endpoints (Audit) | `.claude/docs/working/ACCESS_LAYER_ENDPOINT_AUDIT.md` |
| Rahmenprogramm · Planung | `.claude/docs/technical/TRAINING_FRAMEWORK_SPEC.md` |
| **Trainingsmodule & Kombinationsübungen (Fachspez, Drift-Schutz)** | `.claude/docs/functional/Shinkan Trainingsmodule Kombinationsuebungen Spezifikation V2.md`10.2.1 Archetyp-IDs, §10.4 Coaching-Stufen, **Anhang A** Code-Abgleich) |
@ -88,14 +89,16 @@ Das Schema ist gegenüber dem Code zurück: Migration **`022_skills_schema_compl
- **Varianten:** Speichern in der **Aktionsleiste** persistiert zuerst geänderte Varianten (`persistPendingVariantChanges`), dann Übungs-Stammdaten; „Variante anlegen“ als `type="button"` ohne verschachteltes Formular (`createVariantFromDraft`)
- **Governance (Übungen):** Owner = `created_by`; Bearbeiten = Ersteller, Plattform-Admin oder `can_plan_in_club` bei `visibility=club`; Löschen `club` = nur `club_admin`; Details **`FEATURES_DELIVERED_2026-Q2.md`** §16, **`EXERCISES_API_SPEC.md`** Permissions
### 2.8 KI Assistenz Übungen & Skill-Katalog-Retrieval (Stand **0.8.157**)
### 2.8 KI Assistenz Übungen & Skill-Katalog-Retrieval (Stand **0.8.159**)
- **Doku:** Umsetzung `.claude/docs/working/AI_EXERCISE_IMPLEMENTATION_PLAN.md`; Profil-/JSON-Konzept `.claude/docs/working/AI_SKILL_RETRIEVAL_PROFILES_SPEC.md`; API-Felder **`KI_FEATURES_SPEC.md`** §5.2
- **DB:** Migration **`067`** **`ai_prompts`** (Slug **`exercise_summary`**, **`exercise_skill_suggestions`** — müssen **aktiv** sein); Migration **`068`** **`ai_skill_retrieval_profiles`** (Seed Standard + ggf. Gewaltschutz-Fokus)
- **Zielarchitektur (Pflicht fuer Erweiterungen):** `.claude/docs/technical/AI_PROMPT_TARGET_ARCHITECTURE.md` — Kontext-Arten, Composition, Einbindung Planung/Rahmen; Phasenplan P0P4.
- **Doku:** Umsetzung `.claude/docs/working/AI_EXERCISE_IMPLEMENTATION_PLAN.md`; Profil-/JSON-Konzept `.claude/docs/working/AI_SKILL_RETRIEVAL_PROFILES_SPEC.md`; Ist-Prompt/UI **`AI_PROMPT_SYSTEM_SPEC.md`**; API-Felder **`KI_FEATURES_SPEC.md`** §5.2
- **Runtime:** **`backend/ai_prompt_runtime.py`** — `AiPromptContextKind`, `load_ai_prompt_row` (gemeinsamer DB-Lesezugriff, kein Import von `exercise_ai`); **`exercise_ai`** nutzt `load_ai_prompt_row` fuer aktive Prompts
- **DB:** Migration **`067`** **`ai_prompts`** (Slug **`exercise_summary`**, **`exercise_skill_suggestions`** — müssen **aktiv** sein); Migration **`069`** setzt **`default_template`** wo leer; Migration **`068`** **`ai_skill_retrieval_profiles`** (Seed Standard + ggf. Gewaltschutz-Fokus)
- **`exercise_ai`:** Gewichtungen, KategorieAnteilCaps (~Token), Keyword-Patches aus Ziel/Durchführung (z.B. Rollenspiel vs. Befreiung/Haltegriff)
- **API:** `POST /api/exercises/ai/suggest` optional **`focus_areas_context`**; **`POST …/ai/regenerate`** nutzt gespeicherte `exercise_focus_areas`**Pflege:** Superadmin **`/api/admin/ai-skill-retrieval-profiles*`** (`routers/ai_skill_retrieval_admin.py`)
- **API:** `POST /api/exercises/ai/suggest` optional **`focus_areas_context`**; **`POST …/ai/regenerate`** nutzt gespeicherte `exercise_focus_areas`**Pflege:** Superadmin **`/api/admin/ai-skill-retrieval-profiles*`** (`routers/ai_skill_retrieval_admin.py`), **`/api/admin/ai-prompts*`** (`routers/ai_prompts_admin.py`), UI **`/admin/ai-prompts`**
- **Diagnose bei leerem Dialog / Fehlern:** Umgebungsvariable **`SHINKAN_AI_DEBUG=1`** auf der API; in den Logs dann **`AI_DEBUG`** (`shinkan.exercise_ai`) und **`[AI_DEBUG/openrouter]`** (`shinkan.openrouter`) mit Prompt-Längen, Token-Zahlen und ggf. JSON-Parse-Anfang
- **Frontend:** **`ExerciseFormPageRoot.jsx`**: „KI:“-Schaltflächen nur bei laufender Anfrage deaktiviert; vor einem neuen Lauf wird die Vorschau geschlossen (**keine dauergraue UI** nur wegen eines alten Modal-Zustands). **Pflege:** **`AdminAiSkillRetrievalPage.jsx`**, Route **`/admin/ai-skill-retrieval`**
- **Frontend:** **`ExerciseFormPageRoot.jsx`**: „KI:“-Schaltflächen nur bei laufender Anfrage deaktiviert; vor einem neuen Lauf wird die Vorschau geschlossen (**keine dauergraue UI** nur wegen eines alten Modal-Zustands). **Pflege:** **`AdminAiPromptsPage.jsx`** (`/admin/ai-prompts`), **`AdminAiSkillRetrievalPage.jsx`** (`/admin/ai-skill-retrieval`)
---

View File

@ -13,7 +13,7 @@ Dieses Bündel ist die **Leitlinie für die große Refaktorierung** nach dem MVP
| [`frontend/src/api/exercises.js`](../../frontend/src/api/exercises.js) | Phase 4: Übungen, Medien/Archiv, Progressionsgraphen, KI-Hilfen |
| [`frontend/src/api/planning.js`](../../frontend/src/api/planning.js) | Phase 4: Trainingsplanung (Einheiten, Vorlagen, Module, Rahmen, KPIs) |
| [BASELINE_SNAPSHOT.md](./BASELINE_SNAPSHOT.md) | Phase 0: Bundle-, API- und Last-Baseline (Messvorlagen, Vergleich nach Phase 2) |
| [VERBINDLICHE_REGELN_SHINKAN.md](./VERBINDLICHE_REGELN_SHINKAN.md) | **Verbindliche** Shinkan-spezifische Regeln (Ergänzung zu den globalen Rules) |
| [KI-Prompt-Zielarchitektur](../../.claude/docs/technical/AI_PROMPT_TARGET_ARCHITECTURE.md) | Roadmap: Kontext-Arten, Composition, Planung/Rahmen, Phasenplan (verbindliche Zielrichtung) |
## Tests (E2E / Refaktor-Budget)