Darstellung: Inline-Code-Chips fuer Dark Mode, 58 Seiten auf .mdx (Komponenten rendern jetzt)
Befund 1 (Nutzer): Inline-Code war im Dark Mode kaum lesbar.
- src/styles/custom.css: eigene Chip-Farben (--tibi-inline-*), Rahmen, nowrap in der ersten Tabellenspalte
- gemessen: Text/Chip 10,2:1 dunkel, 12,4:1 hell
Befund 2 (beim Nachmessen gefunden): 58 Seiten waren .md - Starlight-Komponenten wurden NICHT gerendert
(rohe <Aside>/<Steps>-Tags, import-Zeile als sichtbarer Text auf 57 Seiten).
- alle 58 Seiten auf .mdx umgestellt und MDX-konform gemacht (Imports, Block-Tags in eigenen Zeilen,
HTML-Kommentare -> {/* */}, geschweifte Klammern escaped)
- nachher: 428 Asides, 87 Steps, 158 Tab-Gruppen gerendert, 0 geleakte Imports
- fehlender Import in reference/hooks-daten ergaenzt
Regressionsschutz: audit-docs.mjs prueft jetzt Komponente-ohne-Import, .md-mit-Komponente,
geleakte Imports und rohe Tags im gebauten dist/. AGENTS.md 3 dokumentiert die .mdx-Regel.
Nebenfund: de.json mit ASCII-Umschreibungen -> Issue tibi-admin-nova #6
Build: 71 Seiten gruen, Audit 7 legitime Platzhalter-Marker
This commit is contained in:
1 parent
06c5f0d8ea
commit
dcdb6ee637
64 files changed
+246
-104
No files matched your search
@@ -38,6 +38,12 @@ Jede Seite nennt ihre Quelle-der-Wahrheit (Code zuerst), hat einen Stempel am En
|
|||||||
## 3. Neue Seite anlegen
|
## 3. Neue Seite anlegen
|
||||||
|
|
||||||
- Datei `src/content/docs/<bereich>/<slug>.md` mit Frontmatter `title` + `description`.
|
- Datei `src/content/docs/<bereich>/<slug>.md` mit Frontmatter `title` + `description`.
|
||||||
|
- **Sobald die Seite eine Starlight-Komponente nutzt (`<Aside>`, `<Steps>`, `<Tabs>`, `<Card>`, `<LinkCard>`, `<Badge>`, `<FileTree>`), muss die Datei `.mdx` heißen.** In reinem Markdown (`.md`) werden Komponenten-Tags **nicht** gerendert: sie landen als unbekannte HTML-Tags im Ergebnis, und die `import`-Zeile erscheint als sichtbarer Text auf der Seite (`scripts/audit-docs.mjs` prüft das gegen `dist/`).
|
||||||
|
- MDX-Regeln, die die Konvertierung erfüllen muss:
|
||||||
|
- `import …` steht als erste Zeile **vor** dem Inhalt (nach dem Frontmatter).
|
||||||
|
- Block-Komponenten: öffnendes Tag in eigener Zeile, Inhalt, schließendes Tag in eigener Zeile (nicht `Text</Aside>` in einer Zeile).
|
||||||
|
- Kommentar-Hinweise als `{/* … */}` schreiben, **nicht** als `<!-- … -->`.
|
||||||
|
- Geschweifte Klammern im Fließtext escapen (`\{count\}`) — in Code-Spans und Codeblöcken nicht nötig.
|
||||||
- Sidebar: jede Gruppe explizit in `astro.config.mjs` eintragen (beim Neuaufbau pro Bereich ergänzen; `autogenerate` erst nutzen, sobald der Ordner gepflegt befüllt ist).
|
- Sidebar: jede Gruppe explizit in `astro.config.mjs` eintragen (beim Neuaufbau pro Bereich ergänzen; `autogenerate` erst nutzen, sobald der Ordner gepflegt befüllt ist).
|
||||||
- Bilder nach `src/assets/`, max. 200 KB, deutsche Alt-Texte.
|
- Bilder nach `src/assets/`, max. 200 KB, deutsche Alt-Texte.
|
||||||
- Screenshots: nur Mock-Projekt `corporate` (nie `t1`), Ablauf unter `plans/t-shots-arbeitsauftrag.md`.
|
- Screenshots: nur Mock-Projekt `corporate` (nie `t1`), Ablauf unter `plans/t-shots-arbeitsauftrag.md`.
|
||||||
@@ -57,6 +63,9 @@ npm run build # muss grün durchlaufen (prüft interne Links NIC
|
|||||||
- `scripts/audit-docs.mjs` meldet tote Links/Anker, kaputte Tabellen, fehlende Alt-Texte und offene
|
- `scripts/audit-docs.mjs` meldet tote Links/Anker, kaputte Tabellen, fehlende Alt-Texte und offene
|
||||||
Platzhalter-Marker. Ergebnis **muss** „0 tote Links, 0 kaputte Tabellen" sein; verbleibende Marker
|
Platzhalter-Marker. Ergebnis **muss** „0 tote Links, 0 kaputte Tabellen" sein; verbleibende Marker
|
||||||
sind zu begründen.
|
sind zu begründen.
|
||||||
|
- Zusätzlich prüft das Skript das **gebaute** `dist/`: geleakte `import`-Zeilen, rohe `<Aside>`/`<Steps>`-Tags
|
||||||
|
und fehlende Komponenten-Klassen. Erst `npm run build`, dann `node scripts/audit-docs.mjs` — so fällt auf,
|
||||||
|
wenn eine Seite als `.md` statt `.mdx` angelegt wurde.
|
||||||
- `scripts/gen-schema-matrix.mjs` und `reference/schema-properties.md` sind ein Paar: Seite nie von Hand
|
- `scripts/gen-schema-matrix.mjs` und `reference/schema-properties.md` sind ein Paar: Seite nie von Hand
|
||||||
editieren, Schemas nie in der Doku nachpflegen — nur `npm run gen:schemas` laufen lassen.
|
editieren, Schemas nie in der Doku nachpflegen — nur `npm run gen:schemas` laufen lassen.
|
||||||
- `scripts/sync-server-docs.mjs` ist **stillgelegt** (der Server-Sync erzeugte verwaiste Seiten ohne
|
- `scripts/sync-server-docs.mjs` ist **stillgelegt** (der Server-Sync erzeugte verwaiste Seiten ohne
|
||||||
|
|||||||
+50
-50
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"generatedAt": "2026-10-17T13:19:19.983Z",
|
"generatedAt": "2026-10-17T13:54:38.079Z",
|
||||||
"stats": {
|
"stats": {
|
||||||
"files": 70,
|
"files": 70,
|
||||||
"byDir": {
|
"byDir": {
|
||||||
@@ -27,60 +27,60 @@
|
|||||||
"emptyFenceLang": 0,
|
"emptyFenceLang": 0,
|
||||||
"proseWalls": [],
|
"proseWalls": [],
|
||||||
"asciiUmlauts": [
|
"asciiUmlauts": [
|
||||||
"src/content/docs/admin/aktionen.md",
|
"src/content/docs/admin/aktionen.mdx",
|
||||||
"src/content/docs/anwender/aktionen.md",
|
"src/content/docs/anwender/aktionen.mdx",
|
||||||
"src/content/docs/projekt/felder-widgets.md",
|
"src/content/docs/projekt/felder-widgets.mdx",
|
||||||
"src/content/docs/projekt/mcp-nutzen.md",
|
"src/content/docs/projekt/mcp-nutzen.mdx",
|
||||||
"src/content/docs/projekt/navigation-i18n.md",
|
"src/content/docs/projekt/navigation-i18n.mdx",
|
||||||
"src/content/docs/projekt/ssr-website.md",
|
"src/content/docs/projekt/ssr-website.mdx",
|
||||||
"src/content/docs/reference/schema-properties.md"
|
"src/content/docs/reference/schema-properties.md"
|
||||||
],
|
],
|
||||||
"hollowMarkers": [
|
"hollowMarkers": [
|
||||||
"src/content/docs/admin/exporte.md:37 Platzhalter",
|
"src/content/docs/admin/exporte.mdx:37 Platzhalter",
|
||||||
"src/content/docs/anwender/seiten-bauen.md:45 Platzhalter",
|
"src/content/docs/anwender/seiten-bauen.mdx:45 Platzhalter",
|
||||||
"src/content/docs/einstieg/neues-projekt.md:26 Platzhalter",
|
"src/content/docs/einstieg/neues-projekt.mdx:26 Platzhalter",
|
||||||
"src/content/docs/einstieg/schnellstart.md:48 noch nicht",
|
"src/content/docs/einstieg/schnellstart.mdx:48 noch nicht",
|
||||||
"src/content/docs/einstieg/schnellstart.md:21 Platzhalter",
|
"src/content/docs/einstieg/schnellstart.mdx:21 Platzhalter",
|
||||||
"src/content/docs/einstieg/was-ist-tibi.md:11 Platzhalter",
|
"src/content/docs/einstieg/was-ist-tibi.mdx:11 Platzhalter",
|
||||||
"src/content/docs/projekt/deploy.md:26 Platzhalter"
|
"src/content/docs/projekt/deploy.mdx:26 Platzhalter"
|
||||||
],
|
],
|
||||||
"t1Refs": [
|
"t1Refs": [
|
||||||
"src/content/docs/adr/0003-selbstlaeufer.md"
|
"src/content/docs/adr/0003-selbstlaeufer.md"
|
||||||
],
|
],
|
||||||
"tibiAdminRefs": [
|
"tibiAdminRefs": [
|
||||||
"src/content/docs/admin/aktionen.md (2×)",
|
"src/content/docs/admin/aktionen.mdx (2×)",
|
||||||
"src/content/docs/admin/ansichten-listen.md (2×)",
|
"src/content/docs/admin/ansichten-listen.mdx (2×)",
|
||||||
"src/content/docs/admin/benutzer-rechte.md (7×)",
|
"src/content/docs/admin/benutzer-rechte.mdx (7×)",
|
||||||
"src/content/docs/admin/customizing.md (2×)",
|
"src/content/docs/admin/customizing.mdx (2×)",
|
||||||
"src/content/docs/admin/eintrags-editor.md (2×)",
|
"src/content/docs/admin/eintrags-editor.mdx (2×)",
|
||||||
"src/content/docs/admin/exporte.md (2×)",
|
"src/content/docs/admin/exporte.mdx (2×)",
|
||||||
"src/content/docs/admin/ki-funktionen.md (3×)",
|
"src/content/docs/admin/ki-funktionen.mdx (3×)",
|
||||||
"src/content/docs/admin/konzept.md (4×)",
|
"src/content/docs/admin/konzept.mdx (4×)",
|
||||||
"src/content/docs/admin/medien.md (2×)",
|
"src/content/docs/admin/medien.mdx (2×)",
|
||||||
"src/content/docs/admin/setup.md (5×)",
|
"src/content/docs/admin/setup.mdx (5×)",
|
||||||
"src/content/docs/adr/0001-starlight.md (1×)",
|
"src/content/docs/adr/0001-starlight.md (1×)",
|
||||||
"src/content/docs/adr/0002-code-schlaegt-doku.md (2×)",
|
"src/content/docs/adr/0002-code-schlaegt-doku.md (2×)",
|
||||||
"src/content/docs/adr/0003-selbstlaeufer.md (1×)",
|
"src/content/docs/adr/0003-selbstlaeufer.md (1×)",
|
||||||
"src/content/docs/anwender/anmelden.md (5×)",
|
"src/content/docs/anwender/anmelden.mdx (5×)",
|
||||||
"src/content/docs/anwender/benutzer-teams.md (1×)",
|
"src/content/docs/anwender/benutzer-teams.mdx (1×)",
|
||||||
"src/content/docs/anwender/exportieren.md (3×)",
|
"src/content/docs/anwender/exportieren.mdx (3×)",
|
||||||
"src/content/docs/anwender/ki-nutzen.md (1×)",
|
"src/content/docs/anwender/ki-nutzen.mdx (1×)",
|
||||||
"src/content/docs/anwender/lesen-suchen-filtern.md (1×)",
|
"src/content/docs/anwender/lesen-suchen-filtern.mdx (1×)",
|
||||||
"src/content/docs/anwender/medien.md (1×)",
|
"src/content/docs/anwender/medien.mdx (1×)",
|
||||||
"src/content/docs/anwender/orientierung.md (2×)",
|
"src/content/docs/anwender/orientierung.mdx (2×)",
|
||||||
"src/content/docs/anwender/seiten-bauen.md (1×)",
|
"src/content/docs/anwender/seiten-bauen.mdx (1×)",
|
||||||
"src/content/docs/anwender/sichern.md (1×)",
|
"src/content/docs/anwender/sichern.mdx (1×)",
|
||||||
"src/content/docs/einstieg/begriffe.md (4×)",
|
"src/content/docs/einstieg/begriffe.md (4×)",
|
||||||
"src/content/docs/einstieg/neues-projekt.md (1×)",
|
"src/content/docs/einstieg/neues-projekt.mdx (1×)",
|
||||||
"src/content/docs/einstieg/schnellstart.md (1×)",
|
"src/content/docs/einstieg/schnellstart.mdx (1×)",
|
||||||
"src/content/docs/einstieg/was-ist-tibi.md (3×)",
|
"src/content/docs/einstieg/was-ist-tibi.mdx (3×)",
|
||||||
"src/content/docs/projekt/audit-backup.md (2×)",
|
"src/content/docs/projekt/audit-backup.mdx (2×)",
|
||||||
"src/content/docs/projekt/jobs-actions.md (1×)",
|
"src/content/docs/projekt/jobs-actions.mdx (1×)",
|
||||||
"src/content/docs/projekt/navigation-i18n.md (1×)",
|
"src/content/docs/projekt/navigation-i18n.mdx (1×)",
|
||||||
"src/content/docs/projekt/pagebuilder-dev.md (1×)",
|
"src/content/docs/projekt/pagebuilder-dev.mdx (1×)",
|
||||||
"src/content/docs/projekt/sammlungen-anlegen.md (1×)",
|
"src/content/docs/projekt/sammlungen-anlegen.mdx (1×)",
|
||||||
"src/content/docs/projekt/suche.md (2×)",
|
"src/content/docs/projekt/suche.mdx (2×)",
|
||||||
"src/content/docs/reference/tastatur-kurzbefehle.md (2×)"
|
"src/content/docs/reference/tastatur-kurzbefehle.mdx (2×)"
|
||||||
],
|
],
|
||||||
"fm_hero": 1,
|
"fm_hero": 1,
|
||||||
"fm_template": 1
|
"fm_template": 1
|
||||||
@@ -92,43 +92,43 @@
|
|||||||
},
|
},
|
||||||
"findings": [
|
"findings": [
|
||||||
{
|
{
|
||||||
"file": "src/content/docs/admin/exporte.md",
|
"file": "src/content/docs/admin/exporte.mdx",
|
||||||
"kind": "hollow",
|
"kind": "hollow",
|
||||||
"msg": "Marker \"Platzhalter\": Stehen im Export-Dialog eigene Reiter **vor** dem Standard-Tab, hat das Projekt fertige Berichte in `collectio",
|
"msg": "Marker \"Platzhalter\": Stehen im Export-Dialog eigene Reiter **vor** dem Standard-Tab, hat das Projekt fertige Berichte in `collectio",
|
||||||
"line": 37
|
"line": 37
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"file": "src/content/docs/anwender/seiten-bauen.md",
|
"file": "src/content/docs/anwender/seiten-bauen.mdx",
|
||||||
"kind": "hollow",
|
"kind": "hollow",
|
||||||
"msg": "Marker \"Platzhalter\": Die kleine Vorschau benötigt nach der Bildauswahl einen Moment. Ein Platzhalterbild ist in dieser Phase normal",
|
"msg": "Marker \"Platzhalter\": Die kleine Vorschau benötigt nach der Bildauswahl einen Moment. Ein Platzhalterbild ist in dieser Phase normal",
|
||||||
"line": 45
|
"line": 45
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"file": "src/content/docs/einstieg/neues-projekt.md",
|
"file": "src/content/docs/einstieg/neues-projekt.mdx",
|
||||||
"kind": "hollow",
|
"kind": "hollow",
|
||||||
"msg": "Marker \"Platzhalter\": ## 2. Platzhalter und Starter-Reste",
|
"msg": "Marker \"Platzhalter\": ## 2. Platzhalter und Starter-Reste",
|
||||||
"line": 26
|
"line": 26
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"file": "src/content/docs/einstieg/schnellstart.md",
|
"file": "src/content/docs/einstieg/schnellstart.mdx",
|
||||||
"kind": "hollow",
|
"kind": "hollow",
|
||||||
"msg": "Marker \"noch nicht\": - `project not found` → Projektdateien liegen da, aber das Projekt ist im laufenden tibi-server noch nicht reg",
|
"msg": "Marker \"noch nicht\": - `project not found` → Projektdateien liegen da, aber das Projekt ist im laufenden tibi-server noch nicht reg",
|
||||||
"line": 48
|
"line": 48
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"file": "src/content/docs/einstieg/schnellstart.md",
|
"file": "src/content/docs/einstieg/schnellstart.mdx",
|
||||||
"kind": "hollow",
|
"kind": "hollow",
|
||||||
"msg": "Marker \"Platzhalter\": ## 2. Platzhalter ersetzen",
|
"msg": "Marker \"Platzhalter\": ## 2. Platzhalter ersetzen",
|
||||||
"line": 21
|
"line": 21
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"file": "src/content/docs/einstieg/was-ist-tibi.md",
|
"file": "src/content/docs/einstieg/was-ist-tibi.mdx",
|
||||||
"kind": "hollow",
|
"kind": "hollow",
|
||||||
"msg": "Marker \"Platzhalter\": - **Projekt-Website (aus `tibi-svelte-starter` geklont):** eigenständige Website auf Tibi-Basis — normale klei",
|
"msg": "Marker \"Platzhalter\": - **Projekt-Website (aus `tibi-svelte-starter` geklont):** eigenständige Website auf Tibi-Basis — normale klei",
|
||||||
"line": 11
|
"line": 11
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"file": "src/content/docs/projekt/deploy.md",
|
"file": "src/content/docs/projekt/deploy.mdx",
|
||||||
"kind": "hollow",
|
"kind": "hollow",
|
||||||
"msg": "Marker \"Platzhalter\": Im Starter stehen Platzhalter (`__PROJECT_NAME__`, `_CUSTOMER_ID_`, `LIVE_URL=https://www`).",
|
"msg": "Marker \"Platzhalter\": Im Starter stehen Platzhalter (`__PROJECT_NAME__`, `_CUSTOMER_ID_`, `LIVE_URL=https://www`).",
|
||||||
"line": 26
|
"line": 26
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ Jede Fähigkeit von tibi-server / tibi-admin braucht genau eine Dokustelle. Der
|
|||||||
| jobs (Cron) + actions | projekt/jobs-actions | ✅ |
|
| jobs (Cron) + actions | projekt/jobs-actions | ✅ |
|
||||||
| snapshots + backup/restore | projekt/audit-backup | ✅ |
|
| snapshots + backup/restore | projekt/audit-backup | ✅ |
|
||||||
| search (Textindex, RRF-Hybrid, Regenerate) | projekt/suche (+ projekt/sammlungen-anlegen für Index-YAML) | ✅ |
|
| search (Textindex, RRF-Hybrid, Regenerate) | projekt/suche (+ projekt/sammlungen-anlegen für Index-YAML) | ✅ |
|
||||||
| embedding + vectorindex | projekt/suche (Kurzüberblick) | ✅ |
|
| embedding + vectorindex (inkl. Failover-Gruppen, Startprüfung/Quarantäne/Rückkehr, `goldenPath`, Status-Endpunkte) | server/konfiguration (Gruppen im Detail), server/betrieb (Status/Störungen), projekt/suche (Kurzüberblick) | ✅ |
|
||||||
| rankfusion (RRF-Formel) | projekt/suche | ✅ |
|
| rankfusion (RRF-Formel) | projekt/suche | ✅ |
|
||||||
| permissions (public/user/token, Orgs/Teams-Matrix) | projekt/rechte-tokens | ✅ |
|
| permissions (public/user/token, Orgs/Teams-Matrix) | projekt/rechte-tokens | ✅ |
|
||||||
| filecleanup (automatisch, keine Config-Fläche) | kein eigener Artikel — Einzeiler in server/betrieb prüfen (T-FINISH) | ⏳ |
|
| filecleanup (automatisch, keine Config-Fläche) | kein eigener Artikel — Einzeiler in server/betrieb prüfen (T-FINISH) | ⏳ |
|
||||||
@@ -182,6 +182,7 @@ Vollständige Prüfung von Code und Doku, dann Abarbeitung in Wellen. Übersicht
|
|||||||
| F | P8 Meta (AGENTS.md, Werkzeuge, Issues) | ✅ |
|
| F | P8 Meta (AGENTS.md, Werkzeuge, Issues) | ✅ |
|
||||||
| — | P9 Repo-Hygiene: 5 Alt-Kopien gelöscht (~6,1 GB), 6 mit unpushed Commits behalten | ✅ |
|
| — | P9 Repo-Hygiene: 5 Alt-Kopien gelöscht (~6,1 GB), 6 mit unpushed Commits behalten | ✅ |
|
||||||
| H | Ton: Fehlerabschnitte auf Handbuch-Sprache (Regel in AGENTS.md §1, 12 Anwender-Seiten + 5 Stellen) | ✅ |
|
| H | Ton: Fehlerabschnitte auf Handbuch-Sprache (Regel in AGENTS.md §1, 12 Anwender-Seiten + 5 Stellen) | ✅ |
|
||||||
|
| I | Darstellung: Inline-Code-Chips für Dark Mode, 58 Seiten auf `.mdx` (Komponenten rendern jetzt), Render-Prüfung im Audit-Skript | ✅ |
|
||||||
| — | Issues in den Nachbar-Repos (13) | ✅ tibi-server #42–#48, tibi-admin-nova #2–#5, tibi-types #3/#4 |
|
| — | Issues in den Nachbar-Repos (13) | ✅ tibi-server #42–#48, tibi-admin-nova #2–#5, tibi-types #3/#4 |
|
||||||
|
|
||||||
**Neue Werkzeuge:** `scripts/audit-docs.mjs` (Struktur-/Link-/Bildprüfung, `plans/audit-report.json`),
|
**Neue Werkzeuge:** `scripts/audit-docs.mjs` (Struktur-/Link-/Bildprüfung, `plans/audit-report.json`),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Offene Punkte in den Nachbar-Repos (bereit zum Anlegen als Issue)
|
# Offene Punkte in den Nachbar-Repos (bereit zum Anlegen als Issue)
|
||||||
|
|
||||||
Stand: 2026-10-17 · **alle 13 Issues sind angelegt** (Gitea, Repos `cms/tibi-server`, `cms/tibi-admin-nova`, `cms/tibi-types`); Nummer je Zeile in der ersten Spalte.
|
Stand: 2026-10-17 · **alle 14 Issues sind angelegt** (Gitea, Repos `cms/tibi-server`, `cms/tibi-admin-nova`, `cms/tibi-types`); Nummer je Zeile in der ersten Spalte.
|
||||||
|
|
||||||
Stand: 2026-10-17 (erste Fassung). Alle Punkte sind am Code belegt und aus dem Doku-Audit entstanden
|
Stand: 2026-10-17 (erste Fassung). Alle Punkte sind am Code belegt und aus dem Doku-Audit entstanden
|
||||||
(`plans/doku-audit.md`). Je Eintrag: Titel für das Issue, Repo, Beleg, Auswirkung, Vorschlag.
|
(`plans/doku-audit.md`). Je Eintrag: Titel für das Issue, Repo, Beleg, Auswirkung, Vorschlag.
|
||||||
@@ -26,6 +26,8 @@ Stand: 2026-10-17 (erste Fassung). Alle Punkte sind am Code belegt und aus dem D
|
|||||||
| A3 **#4** | Wiederherstellen-Dialog nur bei Änderungen sichtbar | `AuditRestoreDialog.svelte` — Feldauswahl erscheint nur bei ungespeicherten Änderungen, sonst „Keine Änderungen" | Doku muss den Sonderfall erklären; im Audit erwähnt | Hinweistext im UI prüfen |
|
| A3 **#4** | Wiederherstellen-Dialog nur bei Änderungen sichtbar | `AuditRestoreDialog.svelte` — Feldauswahl erscheint nur bei ungespeicherten Änderungen, sonst „Keine Änderungen" | Doku muss den Sonderfall erklären; im Audit erwähnt | Hinweistext im UI prüfen |
|
||||||
| A4 **#3** | Actions fehlen im Mock-Projekt `corporate` | `frontend/assets/mock/_config/corporate/config.yml` hatte keinen `actions`-Block (nur `t1`) | Screenshots/Reviews ohne aussagekräftiges Demo-Projekt (erledigt in der Doku-Arbeit, s. u.) | übernommen: `actions/reindex-search.yml` + `meta.exports` in `corporate` ergänzt |
|
| A4 **#3** | Actions fehlen im Mock-Projekt `corporate` | `frontend/assets/mock/_config/corporate/config.yml` hatte keinen `actions`-Block (nur `t1`) | Screenshots/Reviews ohne aussagekräftiges Demo-Projekt (erledigt in der Doku-Arbeit, s. u.) | übernommen: `actions/reindex-search.yml` + `meta.exports` in `corporate` ergänzt |
|
||||||
|
|
||||||
|
| A5 **#6** | ASCII-Umschreibungen in UI-Texten | `frontend/src/lib/i18n/locales/de.json:178` („ausfuehrbare Methode fuer diese Aktion"), `:194` („vor dem Ausfuehren") | Rechtschreibfehler im deutschen UI; Doku zitiert die Texte wörtlich | Umlaute korrigieren (`ausführbare`, `für`, `Ausführen`) |
|
||||||
|
|
||||||
## tibi-types
|
## tibi-types
|
||||||
|
|
||||||
| # | Titel | Beleg | Auswirkung | Vorschlag |
|
| # | Titel | Beleg | Auswirkung | Vorschlag |
|
||||||
|
|||||||
+35
-3
@@ -179,6 +179,18 @@ for (const f of files) {
|
|||||||
if (!im[1].trim()) add(f, 'image', 'Bild ohne Alt-Text', line);
|
if (!im[1].trim()) add(f, 'image', 'Bild ohne Alt-Text', line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Komponente genutzt, aber nicht importiert (rendert dann als rohes HTML)
|
||||||
|
const usedComponents = new Set(
|
||||||
|
[...text.matchAll(/<(Aside|Steps|Tabs|TabItem|Card|CardGrid|LinkCard|Badge|FileTree)\b/g)].map((m) => m[1]),
|
||||||
|
);
|
||||||
|
const imported = new Set(
|
||||||
|
([...text.matchAll(/^import\s*\{([^}]*)\}/gm)].flatMap((m) => m[1].split(',').map((s) => s.trim()))),
|
||||||
|
);
|
||||||
|
for (const c of usedComponents) {
|
||||||
|
if (!imported.has(c) && f.endsWith('.mdx')) add(f, 'import', `Komponente <${c}> genutzt, aber nicht importiert`);
|
||||||
|
if (!f.endsWith('.mdx')) add(f, 'import', `Komponente <${c}> in einer .md-Datei — Datei muss .mdx sein`);
|
||||||
|
}
|
||||||
|
|
||||||
// Starlight-Komponenten
|
// Starlight-Komponenten
|
||||||
for (const c of new Set(STARLIGHT_COMPONENTS)) {
|
for (const c of new Set(STARLIGHT_COMPONENTS)) {
|
||||||
const n = (text.match(new RegExp(`<${c}[\\s/>]`, 'g')) ?? []).length;
|
const n = (text.match(new RegExp(`<${c}[\\s/>]`, 'g')) ?? []).length;
|
||||||
@@ -248,6 +260,26 @@ for (const f of files) {
|
|||||||
if (badAdmin) stats.tibiAdminRefs.push(`${rel(f)} (${badAdmin.length}×)`);
|
if (badAdmin) stats.tibiAdminRefs.push(`${rel(f)} (${badAdmin.length}×)`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Render-Prüfung gegen dist/ (Komponenten müssen echt gerendert sein) ----
|
||||||
|
const DIST = path.join(ROOT, 'dist');
|
||||||
|
const renderFindings = [];
|
||||||
|
if (fs.existsSync(DIST)) {
|
||||||
|
const htmlFiles = walk(DIST).filter((f) => f.endsWith('.html'));
|
||||||
|
const RAW_TAG = /<(Aside|Steps|Tabs|TabItem|Card|CardGrid|LinkCard|Badge|FileTree)[\s/>]/;
|
||||||
|
for (const f of htmlFiles) {
|
||||||
|
const html = fs.readFileSync(f, 'utf8');
|
||||||
|
if (html.includes('astrojs/starlight/components')) {
|
||||||
|
renderFindings.push({ file: rel(f), kind: 'render', msg: 'import-Zeile steht sichtbar im HTML (Seite ist .md statt .mdx)', line: null });
|
||||||
|
}
|
||||||
|
const m = RAW_TAG.exec(html);
|
||||||
|
if (m) {
|
||||||
|
renderFindings.push({ file: rel(f), kind: 'render', msg: `Komponenten-Tag <${m[1]}> ungerendert im HTML (Seite ist .md statt .mdx)`, line: null });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
renderFindings.push({ file: 'dist/', kind: 'render', msg: 'dist/ fehlt — zuerst `npm run build` laufen lassen', line: null });
|
||||||
|
}
|
||||||
|
|
||||||
// --- Sidebar-Abgleich -----------------------------------------------------
|
// --- Sidebar-Abgleich -----------------------------------------------------
|
||||||
const cfg = fs.readFileSync(path.join(ROOT, 'astro.config.mjs'), 'utf8');
|
const cfg = fs.readFileSync(path.join(ROOT, 'astro.config.mjs'), 'utf8');
|
||||||
const sidebarSlugs = [...cfg.matchAll(/slug:\s*'([^']+)'/g)].map((m) => m[1]);
|
const sidebarSlugs = [...cfg.matchAll(/slug:\s*'([^']+)'/g)].map((m) => m[1]);
|
||||||
@@ -259,10 +291,10 @@ const report = {
|
|||||||
generatedAt: new Date().toISOString(),
|
generatedAt: new Date().toISOString(),
|
||||||
stats,
|
stats,
|
||||||
sidebar: { count: sidebarSlugs.length, notInSidebar, sidebarMissing },
|
sidebar: { count: sidebarSlugs.length, notInSidebar, sidebarMissing },
|
||||||
findings,
|
findings: [...findings, ...renderFindings],
|
||||||
summary: {
|
summary: {
|
||||||
total: findings.length,
|
total: findings.length + renderFindings.length,
|
||||||
byKind: findings.reduce((a, f) => ({ ...a, [f.kind]: (a[f.kind] ?? 0) + 1 }), {}),
|
byKind: [...findings, ...renderFindings].reduce((a, f) => ({ ...a, [f.kind]: (a[f.kind] ?? 0) + 1 }), {}),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,10 @@ meta:
|
|||||||
| `execution.cancellable` | Schema-seitig vorgesehen, im Frontend **ohne Verwendung** (kein Abbruch-Knopf; `grep` über `frontend/src` findet keine Auswertung) — lang laufende Actions brechen nur über SSE-Ende oder Netzwerkfehler ab |
|
| `execution.cancellable` | Schema-seitig vorgesehen, im Frontend **ohne Verwendung** (kein Abbruch-Knopf; `grep` über `frontend/src` findet keine Auswertung) — lang laufende Actions brechen nur über SSE-Ende oder Netzwerkfehler ab |
|
||||||
| Upload-Fortschritt | Enthält `data` Datei-Bytes (`hasInlineUploadPayload`), erzeugt `runAction` einen Byte-Toast (`createByteProgressToast`, `ActionView.svelte:350-357`) und füttert ihn per `onUploadProgress` (`ActionView.svelte:377`) — Erfolgs-Toast erst nach Server-Antwort |
|
| Upload-Fortschritt | Enthält `data` Datei-Bytes (`hasInlineUploadPayload`), erzeugt `runAction` einen Byte-Toast (`createByteProgressToast`, `ActionView.svelte:350-357`) und füttert ihn per `onUploadProgress` (`ActionView.svelte:377`) — Erfolgs-Toast erst nach Server-Antwort |
|
||||||
|
|
||||||
<Aside type="note">Fortschritt während der Ausführung kommt ausschließlich aus SSE-Events plus `output.mapping.progress` (siehe Reiter oben) — `execution` steuert daran nichts.</Aside>
|
<Aside type="note">
|
||||||
|
Fortschritt während der Ausführung kommt ausschließlich aus SSE-Events plus `output.mapping.progress` (siehe Reiter oben) — `execution` steuert daran nichts.
|
||||||
|
|
||||||
|
</Aside>
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -85,7 +88,10 @@ Liefert die Action Live-Events (`Content-Type: text/event-stream`), zeigt `Actio
|
|||||||
- Status- und Meldungstext aus `progress.statusField` / `progress.messageField`.
|
- Status- und Meldungstext aus `progress.statusField` / `progress.messageField`.
|
||||||
- Optionale Zusatzfelder (`progress.fields`) aus jedem Event.
|
- Optionale Zusatzfelder (`progress.fields`) aus jedem Event.
|
||||||
|
|
||||||
<Aside type="note">Ohne `output.mapping.progress` in der Action-Meta gibt es bewusst **keinen** Balken — ein 0-%-Balken bei jeder alten Action wäre irreführend. Dann bleibt JSON das Ergebnis.</Aside>
|
<Aside type="note">
|
||||||
|
Ohne `output.mapping.progress` in der Action-Meta gibt es bewusst **keinen** Balken — ein 0-%-Balken bei jeder alten Action wäre irreführend. Dann bleibt JSON das Ergebnis.
|
||||||
|
|
||||||
|
</Aside>
|
||||||
|
|
||||||
</TabItem>
|
</TabItem>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
@@ -105,7 +111,10 @@ Formular (query + data) → Ausführen → [SSE-Events → Balken] → Ergebnis
|
|||||||
| `permission` / `not found` | Falscher Kopf oder Action gelöscht | [Token-Köpfe](/reference/token-koepfe/) und Action-Namen prüfen |
|
| `permission` / `not found` | Falscher Kopf oder Action gelöscht | [Token-Köpfe](/reference/token-koepfe/) und Action-Namen prüfen |
|
||||||
| Netzwerkfehler | Server nicht erreichbar | [Admin einrichten](/admin/setup/) prüfen, erneut versuchen |
|
| Netzwerkfehler | Server nicht erreichbar | [Admin einrichten](/admin/setup/) prüfen, erneut versuchen |
|
||||||
|
|
||||||
<Aside type="caution">Actions können Daten ändern. Starte eine unbekannte Action erst in einer Testumgebung — der Verlauf (`_actions/<name>` im Audit) zeigt nur, was bereits lief.</Aside>
|
<Aside type="caution">
|
||||||
|
Actions können Daten ändern. Starte eine unbekannte Action erst in einer Testumgebung — der Verlauf (`_actions/<name>` im Audit) zeigt nur, was bereits lief.
|
||||||
|
|
||||||
|
</Aside>
|
||||||
|
|
||||||
Klick-Abläufe dazu stehen im Test-Plan `docs/test-plans/40-actions.md` (Methoden-Tabs, ausführbar vs. gesperrt, Ergebnis und Fortschritt).
|
Klick-Abläufe dazu stehen im Test-Plan `docs/test-plans/40-actions.md` (Methoden-Tabs, ausführbar vs. gesperrt, Ergebnis und Fortschritt).
|
||||||
|
|
||||||
File renamed without changes.
+8
-2
@@ -121,7 +121,10 @@ admin:
|
|||||||
allowSnapshots: true
|
allowSnapshots: true
|
||||||
```
|
```
|
||||||
|
|
||||||
<Aside type="caution">Fehlt ein Flag, scheitert die Operation serverseitig — der Admin zeigt dann einen Rechte-Fehler. Vergib nur, was das Projekt wirklich braucht.</Aside>
|
<Aside type="caution">
|
||||||
|
Fehlt ein Flag, scheitert die Operation serverseitig — der Admin zeigt dann einen Rechte-Fehler. Vergib nur, was das Projekt wirklich braucht.
|
||||||
|
|
||||||
|
</Aside>
|
||||||
|
|
||||||
## Stellvertretung (Impersonation)
|
## Stellvertretung (Impersonation)
|
||||||
|
|
||||||
@@ -133,7 +136,10 @@ Admins können sich als ein Benutzerkonto anmelden, um dessen Sicht zu prüfen:
|
|||||||
| Erkennen | Banner/Status zeigt die Stellvertretung (`AdminLayout`, `AdminHub`, `UserDetailDrawer`) |
|
| Erkennen | Banner/Status zeigt die Stellvertretung (`AdminLayout`, `AdminHub`, `UserDetailDrawer`) |
|
||||||
| Beenden | `POST /login/impersonate?logout=1` → Server löscht den Stellvertretungs-Cookie und stellt die Admin-Sitzung wieder her |
|
| Beenden | `POST /login/impersonate?logout=1` → Server löscht den Stellvertretungs-Cookie und stellt die Admin-Sitzung wieder her |
|
||||||
|
|
||||||
<Aside type="caution">Stellvertretung nur mit Freigabe nutzen — du handelst mit den Rechten der vertretenen Person, und der Vorgang wird protokolliert (Audit). Währenddessen keine Token erstellen.</Aside>
|
<Aside type="caution">
|
||||||
|
Stellvertretung nur mit Freigabe nutzen — du handelst mit den Rechten der vertretenen Person, und der Vorgang wird protokolliert (Audit). Währenddessen keine Token erstellen.
|
||||||
|
|
||||||
|
</Aside>
|
||||||
|
|
||||||
## Fehler
|
## Fehler
|
||||||
|
|
||||||
@@ -71,7 +71,10 @@ Volle Kontext-Tabelle in der Repo-Doku `custom-export-script.md`; Bedienung unte
|
|||||||
</TabItem>
|
</TabItem>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
<Aside type="caution">Anpassungen an Sammlungs-Config und Skripten erst im lokalen Stack ([einrichten](/admin/setup/)) testen — falsche `meta`-Einträge blenden Ansichten oder Export-Reiter ersatzlos aus.</Aside>
|
<Aside type="caution">
|
||||||
|
Anpassungen an Sammlungs-Config und Skripten erst im lokalen Stack ([einrichten](/admin/setup/)) testen — falsche `meta`-Einträge blenden Ansichten oder Export-Reiter ersatzlos aus.
|
||||||
|
|
||||||
|
</Aside>
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
File renamed without changes.
File renamed without changes.
@@ -42,7 +42,7 @@ Was die KI dabei sieht (`aiController.ts`, `AiChat.svelte`): Neben dem UI-Snapsh
|
|||||||
|
|
||||||
Das **„Kontextfenster“** liest der Chat aus dem Modellkatalog (Endpunkt `/api/ai/models`, `configured.chat.contextWindow`); antwortet der Katalog nicht, gelten 96 000 Token (`MODEL_CONTEXT_WINDOW`). Aktuell meldet der Proxy 262 144 (siehe `config/ai-proxy.config.json`, `chat.contextWindow`).
|
Das **„Kontextfenster“** liest der Chat aus dem Modellkatalog (Endpunkt `/api/ai/models`, `configured.chat.contextWindow`); antwortet der Katalog nicht, gelten 96 000 Token (`MODEL_CONTEXT_WINDOW`). Aktuell meldet der Proxy 262 144 (siehe `config/ai-proxy.config.json`, `chat.contextWindow`).
|
||||||
|
|
||||||
Tempo der Cursor-Animation: **„Nova-Speed“** mit **„Hyperspeed“** (0, alles sofort), **„Schnell“** (1, Standard), **„Mittel“** (2), **„Langsam“** (3) — als Befehle (**„Nova-Speed: …“**) und Kennung `ai-animation-speed` in `localStorage`. Bei zu vielen Schritten stoppt Nova von selbst: „Automatisch gestoppt – zu viele aufeinanderfolgende Aktionen. Nova wurde nach {count} Schritten angehalten …“ — dann Anfrage neu formulieren oder Felder manuell prüfen.
|
Tempo der Cursor-Animation: **„Nova-Speed“** mit **„Hyperspeed“** (0, alles sofort), **„Schnell“** (1, Standard), **„Mittel“** (2), **„Langsam“** (3) — als Befehle (**„Nova-Speed: …“**) und Kennung `ai-animation-speed` in `localStorage`. Bei zu vielen Schritten stoppt Nova von selbst: „Automatisch gestoppt – zu viele aufeinanderfolgende Aktionen. Nova wurde nach \{count\} Schritten angehalten …“ — dann Anfrage neu formulieren oder Felder manuell prüfen.
|
||||||
|
|
||||||
## Zusammenfassen
|
## Zusammenfassen
|
||||||
|
|
||||||
@@ -57,8 +57,8 @@ Wächst ein Gespräch Richtung Kontextgrenze, komprimiert `lib/aiSummarizer.ts`
|
|||||||
- Reserviert sind 10 000 Token für System-Prompt, Werkzeug-Definitionen und Antwort (`RESERVED_TOKENS`).
|
- Reserviert sind 10 000 Token für System-Prompt, Werkzeug-Definitionen und Antwort (`RESERVED_TOKENS`).
|
||||||
- Zusammenfassungs-Modell: `proxy-managed` — auch hier entscheidet der Proxy, nicht das Frontend. Der Aufruf geht an den Zusammenfassungs-Endpunkt mit Profil `summarizer` und liest einen SSE-Strom (inkl. Zähler); Antwort leer oder Netzfehler → Rückfall auf hartes Kürzen.
|
- Zusammenfassungs-Modell: `proxy-managed` — auch hier entscheidet der Proxy, nicht das Frontend. Der Aufruf geht an den Zusammenfassungs-Endpunkt mit Profil `summarizer` und liest einen SSE-Strom (inkl. Zähler); Antwort leer oder Netzfehler → Rückfall auf hartes Kürzen.
|
||||||
- Hartes Kürzen hält Werkzeug-Paare zusammen: Verwaiste `tool`-Antworten und `assistant`-Nachrichten ohne vollständige Ergebnisse fliegen raus (`hardTruncate`, `sanitizeWireMessages`) — sonst würde die API den Turn ablehnen.
|
- Hartes Kürzen hält Werkzeug-Paare zusammen: Verwaiste `tool`-Antworten und `assistant`-Nachrichten ohne vollständige Ergebnisse fliegen raus (`hardTruncate`, `sanitizeWireMessages`) — sonst würde die API den Turn ablehnen.
|
||||||
- UI: Währenddessen steht **„Kontext wird zusammengefasst…“**, danach **„Kontext zusammengefasst“** bzw. **„Zusammenfassung aktiv“** mit **„{count} Nachrichten komprimiert · ~{tokens} Tokens gespart“**.
|
- UI: Währenddessen steht **„Kontext wird zusammengefasst…“**, danach **„Kontext zusammengefasst“** bzw. **„Zusammenfassung aktiv“** mit **„\{count\} Nachrichten komprimiert · ~\{tokens\} Tokens gespart“**.
|
||||||
- Themenwechsel: Schlägt Nova einen neuen Chat vor (**„Neuen Chat starten?“** — **„Neuen Chat starten“** oder **„Nein, weiter“**), fasst `summarizeForTransfer` den ganzen Verlauf zusammen und stellt deine letzte Nachricht wörtlich unter „LATEST REQUEST“. Im neuen Chat erscheint das als **„Kontext aus vorherigem Chat“** (**„{count} Nachrichten aus vorherigem Chat · ~{tokens} Tokens übertragen“**).
|
- Themenwechsel: Schlägt Nova einen neuen Chat vor (**„Neuen Chat starten?“** — **„Neuen Chat starten“** oder **„Nein, weiter“**), fasst `summarizeForTransfer` den ganzen Verlauf zusammen und stellt deine letzte Nachricht wörtlich unter „LATEST REQUEST“. Im neuen Chat erscheint das als **„Kontext aus vorherigem Chat“** (**„\{count\} Nachrichten aus vorherigem Chat · ~\{tokens\} Tokens übertragen“**).
|
||||||
|
|
||||||
## Stimme
|
## Stimme
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ Antworten anhören statt lesen (`lib/aiTTS.ts`, Endpunkt `/api/ai/tts`) — Knop
|
|||||||
| Tempo | **„Geschwindigkeit“** 0,5–2,0, Schritt 0,1, Standard **1,3** (**„Zurücksetzen“** stellt den Standard wieder her) |
|
| Tempo | **„Geschwindigkeit“** 0,5–2,0, Schritt 0,1, Standard **1,3** (**„Zurücksetzen“** stellt den Standard wieder her) |
|
||||||
| Format | MP3 (`responseFormat: mp3`) — Opus im WebM, wenn dein Browser es kann (`preferredTTSFormat`) |
|
| Format | MP3 (`responseFormat: mp3`) — Opus im WebM, wenn dein Browser es kann (`preferredTTSFormat`) |
|
||||||
|
|
||||||
Verhalten: Quelle zuerst Browser-**„Systemstimme auf diesem Gerät“** (passend zu deiner Dokumentsprache, Standard `de-DE`), sonst **„KI-Stimme“** (Proxy-Modell `qwen3-tts-0.6b-base`) — Anzeige **„Stimme: {voice}“**. Beim Streamen spricht Nova satzweise mit: erster Block ab ~60 Zeichen, danach ~120-Zeichen-Bündel, bis zu 2 parallele Anfragen, lückenlos aneinandergereiht. Schalter **„Sprachausgabe“** / **„Sprachausgabe aus“**; Zeichen und Kosten meldet der Server per Kopf (`X-AI-Characters`, `X-AI-Cost-Usd`) und landen unter **„Sprachausgabe“** in **„Konversation gesamt“**.
|
Verhalten: Quelle zuerst Browser-**„Systemstimme auf diesem Gerät“** (passend zu deiner Dokumentsprache, Standard `de-DE`), sonst **„KI-Stimme“** (Proxy-Modell `qwen3-tts-0.6b-base`) — Anzeige **„Stimme: \{voice\}“**. Beim Streamen spricht Nova satzweise mit: erster Block ab ~60 Zeichen, danach ~120-Zeichen-Bündel, bis zu 2 parallele Anfragen, lückenlos aneinandergereiht. Schalter **„Sprachausgabe“** / **„Sprachausgabe aus“**; Zeichen und Kosten meldet der Server per Kopf (`X-AI-Characters`, `X-AI-Cost-Usd`) und landen unter **„Sprachausgabe“** in **„Konversation gesamt“**.
|
||||||
|
|
||||||
</TabItem>
|
</TabItem>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
@@ -93,7 +93,7 @@ Zusatz: **Vision** (`/api/ai/vision`) beschreibt Bilder für CMS-Felder („erfi
|
|||||||
|
|
||||||
## Werkzeuge
|
## Werkzeuge
|
||||||
|
|
||||||
Die KI ruft UI-Werkzeuge statt zu raten (`aiTools.ts` → `aiController.ts`). Labels wörtlich aus `de.json` (`admin.ai.tools.*`); Status dazu: **„Arbeitet…“** währenddessen, danach **„1 Aktion ausgeführt“** bzw. **„{count} Aktionen ausgeführt“**, **„Details“** öffnet den **„Tool-Inspector“** (**„Tool-Aufruf“** / **„Tool-Rückgabe“**, **„Formatiert“** / **„Roh“**, **„Alle Schritte kopieren“**):
|
Die KI ruft UI-Werkzeuge statt zu raten (`aiTools.ts` → `aiController.ts`). Labels wörtlich aus `de.json` (`admin.ai.tools.*`); Status dazu: **„Arbeitet…“** währenddessen, danach **„1 Aktion ausgeführt“** bzw. **„\{count\} Aktionen ausgeführt“**, **„Details“** öffnet den **„Tool-Inspector“** (**„Tool-Aufruf“** / **„Tool-Rückgabe“**, **„Formatiert“** / **„Roh“**, **„Alle Schritte kopieren“**):
|
||||||
|
|
||||||
| Gruppe | Werkzeuge (UI-Name) |
|
| Gruppe | Werkzeuge (UI-Name) |
|
||||||
|---|---|
|
|---|---|
|
||||||
@@ -113,7 +113,10 @@ Die KI ruft UI-Werkzeuge statt zu raten (`aiTools.ts` → `aiController.ts`). La
|
|||||||
|
|
||||||
Stapel-Limits (`aiTools.ts`): `run_tool_batch` fasst bis zu 40 ändernde Schritte (100 bei rein lesenden wie **„Kontext abrufen“**, **„Projekte auflisten“**, **„Benutzer auflisten“**) — darüber verweigert der Batch. `get_context` (**„Kontext abrufen“**) und `get_entry_context` lesen gezielt nach: Standardablauf ist erst Eintrag öffnen, dann `get_entry_context`, dann die Feld-Updates möglichst als ein Batch.
|
Stapel-Limits (`aiTools.ts`): `run_tool_batch` fasst bis zu 40 ändernde Schritte (100 bei rein lesenden wie **„Kontext abrufen“**, **„Projekte auflisten“**, **„Benutzer auflisten“**) — darüber verweigert der Batch. `get_context` (**„Kontext abrufen“**) und `get_entry_context` lesen gezielt nach: Standardablauf ist erst Eintrag öffnen, dann `get_entry_context`, dann die Feld-Updates möglichst als ein Batch.
|
||||||
|
|
||||||
<Aside type="note">Alle Aktionen sind nicht destruktiv angelegt; `prepare_bulk_delete` bereitet nur vor und `restore_from_audit` (**„Aus Audit übernehmen"**) fragt vorher bei dir nach. Zwei Debug-Ansichten: `AiDebugContext.svelte` (Befehlspalette: **„Debug: KI-Kontext anzeigen"**) zeigt, welchen Kontext die KI gerade sieht; `AiVisionOverlay.svelte` (Befehlspalette: **„Debug: KI-Vision"**, Schalter **„Debug: KI-Vision (steuerbare Elemente anzeigen)"**) legt ein Röntgen-Overlay über alle steuerbaren Elemente mit ihren Kennungen.</Aside>
|
<Aside type="note">
|
||||||
|
Alle Aktionen sind nicht destruktiv angelegt; `prepare_bulk_delete` bereitet nur vor und `restore_from_audit` (**„Aus Audit übernehmen"**) fragt vorher bei dir nach. Zwei Debug-Ansichten: `AiDebugContext.svelte` (Befehlspalette: **„Debug: KI-Kontext anzeigen"**) zeigt, welchen Kontext die KI gerade sieht; `AiVisionOverlay.svelte` (Befehlspalette: **„Debug: KI-Vision"**, Schalter **„Debug: KI-Vision (steuerbare Elemente anzeigen)"**) legt ein Röntgen-Overlay über alle steuerbaren Elemente mit ihren Kennungen.
|
||||||
|
|
||||||
|
</Aside>
|
||||||
|
|
||||||
## Grenzen und Kosten
|
## Grenzen und Kosten
|
||||||
|
|
||||||
@@ -137,7 +140,7 @@ Wichtig zur Einordnung: Der Admin-Chat läuft über den Proxy (`/api/ai/chat`, `
|
|||||||
| **„Rate-Limit erreicht. Bitte warte einen Moment und versuche es erneut.“** | 429 am Proxy | Kurz warten, erneut versuchen |
|
| **„Rate-Limit erreicht. Bitte warte einen Moment und versuche es erneut.“** | 429 am Proxy | Kurz warten, erneut versuchen |
|
||||||
| **„Der KI-Dienst ist vorübergehend nicht erreichbar. Bitte versuche es später erneut.“** | 5xx am Proxy | Später erneut versuchen |
|
| **„Der KI-Dienst ist vorübergehend nicht erreichbar. Bitte versuche es später erneut.“** | 5xx am Proxy | Später erneut versuchen |
|
||||||
| **„Mikrofon-Zugriff verweigert. …“** | Browser-Recht fehlt | Mikrofon in den Browser-Einstellungen freigeben |
|
| **„Mikrofon-Zugriff verweigert. …“** | Browser-Recht fehlt | Mikrofon in den Browser-Einstellungen freigeben |
|
||||||
| **„Transkription fehlgeschlagen: {error}“** | Rate-Limit, Netz oder Proxy-Fehler | Kürzeren Abschnitt sprechen, erneut versuchen |
|
| **„Transkription fehlgeschlagen: \{error\}“** | Rate-Limit, Netz oder Proxy-Fehler | Kürzeren Abschnitt sprechen, erneut versuchen |
|
||||||
| Stimme klingt falsch | Andere Stimme aktiv | Stimme in den KI-Einstellungen zurück auf `eva-de` setzen |
|
| Stimme klingt falsch | Andere Stimme aktiv | Stimme in den KI-Einstellungen zurück auf `eva-de` setzen |
|
||||||
|
|
||||||

|

|
||||||
File renamed without changes.
File renamed without changes.
@@ -102,7 +102,10 @@ yarn build # esbuild-Bundle, muss fehlerfrei durchlaufen
|
|||||||
yarn test:e2e # Playwright E2E
|
yarn test:e2e # Playwright E2E
|
||||||
```
|
```
|
||||||
|
|
||||||
<Aside type="tip">Läuft `yarn build` grün und zeigt der Admin nach Login die Projektliste, ist das Setup fertig. Weiter geht es mit [Admin anpassen](/admin/customizing/).</Aside>
|
<Aside type="tip">
|
||||||
|
Läuft `yarn build` grün und zeigt der Admin nach Login die Projektliste, ist das Setup fertig. Weiter geht es mit [Admin anpassen](/admin/customizing/).
|
||||||
|
|
||||||
|
</Aside>
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ import { Aside, Steps } from '@astrojs/starlight/components';
|
|||||||
1. Öffne das Projekt und wähle die Aktion aus der Liste.
|
1. Öffne das Projekt und wähle die Aktion aus der Liste.
|
||||||
2. Lies oben, was die Aktion tut (Abschnitt **Methoden**).
|
2. Lies oben, was die Aktion tut (Abschnitt **Methoden**).
|
||||||
3. Fülle unter **Eingaben** alle benötigten Felder aus.
|
3. Fülle unter **Eingaben** alle benötigten Felder aus.
|
||||||
4. Korrigiere markierte Felder, solange die Meldung **Bitte korrigiere {count} Feldfehler vor dem Ausfuehren.** steht.
|
4. Korrigiere markierte Felder, solange die Meldung **Bitte korrigiere \{count\} Feldfehler vor dem Ausfuehren.** steht.
|
||||||
5. Klicke auf **Ausführen**.
|
5. Klicke auf **Ausführen**.
|
||||||
6. Warte, bis statt **Läuft…** wieder **Ausführen** dasteht.
|
6. Warte, bis statt **Läuft…** wieder **Ausführen** dasteht.
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ Steht statt **Ausführen** der Knopf **Gesperrt**, fehlt dem Konto die Berechtig
|
|||||||
|
|
||||||
## Fortschritt und Ergebnis lesen
|
## Fortschritt und Ergebnis lesen
|
||||||
|
|
||||||
Während der **Ausführung** zeigt der Bereich **Fortschritt** einen Balken mit **{percent}% abgeschlossen** oder einer Zählung wie **{index} von {count}**. Danach steht das Ergebnis unter **Letztes Ergebnis** mit **Zusammenfassung** und **Details**.
|
Während der **Ausführung** zeigt der Bereich **Fortschritt** einen Balken mit **\{percent\}% abgeschlossen** oder einer Zählung wie **\{index\} von \{count\}**. Danach steht das Ergebnis unter **Letztes Ergebnis** mit **Zusammenfassung** und **Details**.
|
||||||
|
|
||||||
<Steps>
|
<Steps>
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ Die Anmeldeadresse erhältst du von der Administration; speichere sie anschließ
|
|||||||
|
|
||||||
Kurz vor dem automatischen Abmelden erscheint der Hinweis **Sitzung läuft ab** mit der Meldung „Du wirst wegen Inaktivität gleich automatisch abgemeldet.". Wähle **Angemeldet bleiben**, um weiterzuarbeiten, oder **Jetzt abmelden**, um die Sitzung sofort zu beenden. Reagierst du nicht, meldet dich tibi-admin automatisch ab und es erscheint der Hinweis **Sitzung abgelaufen – bitte neu anmelden**.
|
Kurz vor dem automatischen Abmelden erscheint der Hinweis **Sitzung läuft ab** mit der Meldung „Du wirst wegen Inaktivität gleich automatisch abgemeldet.". Wähle **Angemeldet bleiben**, um weiterzuarbeiten, oder **Jetzt abmelden**, um die Sitzung sofort zu beenden. Reagierst du nicht, meldet dich tibi-admin automatisch ab und es erscheint der Hinweis **Sitzung abgelaufen – bitte neu anmelden**.
|
||||||
|
|
||||||
<!-- Screenshot (T-SHOTS): Hinweisdialog Sitzung läuft ab mit Angemeldet bleiben und Jetzt abmelden, Mock-Projekt corporate, Alt-Text deutsch -->
|
{/* Screenshot (T-SHOTS): Hinweisdialog Sitzung läuft ab mit Angemeldet bleiben und Jetzt abmelden, Mock-Projekt corporate, Alt-Text deutsch */}
|
||||||
|
|
||||||
<Steps>
|
<Steps>
|
||||||
|
|
||||||
+5
-5
@@ -26,7 +26,7 @@ Ohne Administrator-Recht sperrt die Ansicht mit **Keine Administrator-Berechtigu
|
|||||||
|
|
||||||
## Analyse lesen
|
## Analyse lesen
|
||||||
|
|
||||||
Das **Analyse-Ergebnis** nennt zuerst die Zahl der gefundenen Sammlungen (**{count} Collections gefunden**) sowie Quell-Projekt und Erstelldatum der Datei. Die Tabelle darunter listet pro **Collection** die Spalten **Dokumente**, **Medien** und **Hinweise**.
|
Das **Analyse-Ergebnis** nennt zuerst die Zahl der gefundenen Sammlungen (**\{count\} Collections gefunden**) sowie Quell-Projekt und Erstelldatum der Datei. Die Tabelle darunter listet pro **Collection** die Spalten **Dokumente**, **Medien** und **Hinweise**.
|
||||||
|
|
||||||
<Steps>
|
<Steps>
|
||||||
|
|
||||||
@@ -48,10 +48,10 @@ Lies die Analyse vollständig, bevor du fortfährst. Bei ausgeschalteter Zusamme
|
|||||||
|
|
||||||
<Steps>
|
<Steps>
|
||||||
|
|
||||||
1. Klicke auf **Wiederherstellung starten** (mit Auswahl: **Wiederherstellung starten ({n} Collections)**).
|
1. Klicke auf **Wiederherstellung starten** (mit Auswahl: **Wiederherstellung starten (\{n\} Collections)**).
|
||||||
2. Verfolge den Fortschritt (**Stelle {name} wieder her…**) und warte auf **Wiederherstellung abgeschlossen**.
|
2. Verfolge den Fortschritt (**Stelle \{name\} wieder her…**) und warte auf **Wiederherstellung abgeschlossen**.
|
||||||
3. Lies die Zusammenfassung: **{docs} Dokumente in {n} Collections wiederhergestellt**, dazu ggf. **{n} Mediendateien kopiert**.
|
3. Lies die Zusammenfassung: **\{docs\} Dokumente in \{n\} Collections wiederhergestellt**, dazu ggf. **\{n\} Mediendateien kopiert**.
|
||||||
4. Beachte übersprungene Sammlungen (**{n} Collections übersprungen (existieren nicht im Ziel)**).
|
4. Beachte übersprungene Sammlungen (**\{n\} Collections übersprungen (existieren nicht im Ziel)**).
|
||||||
5. Öffne danach die betroffenen Sammlungen und prüfe Stichproben.
|
5. Öffne danach die betroffenen Sammlungen und prüfe Stichproben.
|
||||||
|
|
||||||
</Steps>
|
</Steps>
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-1
@@ -57,7 +57,7 @@ Liefert die Suche keine Treffer, gehe wie folgt vor:
|
|||||||
|
|
||||||
Arbeitet deine Sammlung mit Hintergrundsuche, baut tibi-admin den **Suchindex** im Hintergrund auf. Solange Einträge offen sind, zeigt ein Hinweisbanner über der Liste „wird im Hintergrund aktualisiert" mit der Zahl der offenen Einträge. Du kannst normal weiterarbeiten; sobald der Zähler auf null steht, verschwindet das Banner von selbst. Über **Details ein-/ausblenden** siehst du den Stand je Sammlung, bei Problemen stößt **Neu aufbauen** den Aufbau erneut an.
|
Arbeitet deine Sammlung mit Hintergrundsuche, baut tibi-admin den **Suchindex** im Hintergrund auf. Solange Einträge offen sind, zeigt ein Hinweisbanner über der Liste „wird im Hintergrund aktualisiert" mit der Zahl der offenen Einträge. Du kannst normal weiterarbeiten; sobald der Zähler auf null steht, verschwindet das Banner von selbst. Über **Details ein-/ausblenden** siehst du den Stand je Sammlung, bei Problemen stößt **Neu aufbauen** den Aufbau erneut an.
|
||||||
|
|
||||||
<!-- Screenshot (T-SHOTS): Suchindex-Hinweisbanner im Projekt-/Sammlungs-Header, Mock-Projekt corporate, Alt-Text deutsch -->
|
{/* Screenshot (T-SHOTS): Suchindex-Hinweisbanner im Projekt-/Sammlungs-Header, Mock-Projekt corporate, Alt-Text deutsch */}
|
||||||
|
|
||||||
## Filtern und sortieren
|
## Filtern und sortieren
|
||||||
|
|
||||||
+5
-5
@@ -16,7 +16,7 @@ Die **Massenbearbeitung** ändert viele Einträge in einem Durchgang — zum Bei
|
|||||||
1. Öffne die Sammlung mit den Einträgen.
|
1. Öffne die Sammlung mit den Einträgen.
|
||||||
2. Markiere die Einträge einzeln, oder nutze **Alle auswählen** für die ganze Seite.
|
2. Markiere die Einträge einzeln, oder nutze **Alle auswählen** für die ganze Seite.
|
||||||
3. Klicke auf **Bearbeiten** (Taste `e` geht auch).
|
3. Klicke auf **Bearbeiten** (Taste `e` geht auch).
|
||||||
4. Der Dialog zeigt oben **Massenoperationen** und wie viele Einträge betroffen sind (**{count} ausgewählt**).
|
4. Der Dialog zeigt oben **Massenoperationen** und wie viele Einträge betroffen sind (**\{count\} ausgewählt**).
|
||||||
|
|
||||||
</Steps>
|
</Steps>
|
||||||
|
|
||||||
@@ -33,11 +33,11 @@ Ohne Auswahl betrifft die Aktion alle Einträge der Sammlung. Brich in dem Fall
|
|||||||
3. Lege unter **Operationen** fest, was passieren soll (**Operation hinzufügen**, Feld wählen und Aktion wie **Setzen auf** oder **Suchen & Ersetzen** bestimmen).
|
3. Lege unter **Operationen** fest, was passieren soll (**Operation hinzufügen**, Feld wählen und Aktion wie **Setzen auf** oder **Suchen & Ersetzen** bestimmen).
|
||||||
4. Öffne die **Vorschau** und lies, wie viele der ausgewählten Einträge betroffen sind.
|
4. Öffne die **Vorschau** und lies, wie viele der ausgewählten Einträge betroffen sind.
|
||||||
5. Klicke auf **Änderungen anwenden** und bestätige die Nachfrage.
|
5. Klicke auf **Änderungen anwenden** und bestätige die Nachfrage.
|
||||||
6. Warte die Meldung ab: **{count} Einträge aktualisiert** bedeutet Erfolg.
|
6. Warte die Meldung ab: **\{count\} Einträge aktualisiert** bedeutet Erfolg.
|
||||||
|
|
||||||
</Steps>
|
</Steps>
|
||||||
|
|
||||||
Die Nachfrage warnt ehrlich: **{count} Einträge werden aktualisiert. Diese Aktion kann nicht rückgängig gemacht werden.** Lies sie, bevor du bestätigst.
|
Die Nachfrage warnt ehrlich: **\{count\} Einträge werden aktualisiert. Diese Aktion kann nicht rückgängig gemacht werden.** Lies sie, bevor du bestätigst.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -62,9 +62,9 @@ Die Massenbearbeitung lässt sich nicht rückgängig machen. Prüfe die **Vorsch
|
|||||||
|
|
||||||
| Meldung | Bedeutung (Ursache) | Vorgehen |
|
| Meldung | Bedeutung (Ursache) | Vorgehen |
|
||||||
| ------- | ------------------- | -------- |
|
| ------- | ------------------- | -------- |
|
||||||
| „{done} von {total} aktualisiert, {failed} fehlgeschlagen" | Einzelne Einträge sind gescheitert (z. B. Pflichtfeld leer, fehlende Berechtigung). | Prüfe die gescheiterten Einträge einzeln. |
|
| „\{done\} von \{total\} aktualisiert, \{failed\} fehlgeschlagen" | Einzelne Einträge sind gescheitert (z. B. Pflichtfeld leer, fehlende Berechtigung). | Prüfe die gescheiterten Einträge einzeln. |
|
||||||
| **Füge mindestens eine Operation hinzu.** | Es ist noch keine **Operation** angelegt. | Lege unter **Operationen** mindestens eine Operation an. |
|
| **Füge mindestens eine Operation hinzu.** | Es ist noch keine **Operation** angelegt. | Lege unter **Operationen** mindestens eine Operation an. |
|
||||||
|
|
||||||
Zum Löschen vieler Einträge wechsele oben auf **Löschen** — dort heißt der Knopf **Löschen** statt **Änderungen anwenden**, und die Nachfrage lautet **Möchtest du {count} Einträge wirklich unwiderruflich löschen?**.
|
Zum Löschen vieler Einträge wechsele oben auf **Löschen** — dort heißt der Knopf **Löschen** statt **Änderungen anwenden**, und die Nachfrage lautet **Möchtest du \{count\} Einträge wirklich unwiderruflich löschen?**.
|
||||||
|
|
||||||
Verifiziert am 2b091d8 2026-10-17 (tibi-admin-nova)
|
Verifiziert am 2b091d8 2026-10-17 (tibi-admin-nova)
|
||||||
@@ -80,7 +80,7 @@ Ohne **OK** geht die Anpassung verloren. Klicke zuerst auf **OK** und speichere
|
|||||||
|
|
||||||
## Direkt bearbeiten und KI-Beschreibung
|
## Direkt bearbeiten und KI-Beschreibung
|
||||||
|
|
||||||
In der Upload-Warteschlange („{done} von {total} hochgeladen") bearbeitest du Einträge vor dem Hochladen: **Bearbeiten & hochladen** öffnet den Eintrag im Dialog (**Medieneintrag bearbeiten**), **Schnell-Upload** lädt ohne Bearbeitung. Große Bilder verkleinert tibi-admin automatisch („Bild auf {width}×{height} verkleinert").
|
In der Upload-Warteschlange („\{done\} von \{total\} hochgeladen") bearbeitest du Einträge vor dem Hochladen: **Bearbeiten & hochladen** öffnet den Eintrag im Dialog (**Medieneintrag bearbeiten**), **Schnell-Upload** lädt ohne Bearbeitung. Große Bilder verkleinert tibi-admin automatisch („Bild auf \{width\}×\{height\} verkleinert").
|
||||||
|
|
||||||
Fehlt die Bildbeschreibung, erstellt die KI sie selbst („KI beschreibt das Bild…" → „KI-Beschreibung bereit"). Bereits ausgefüllte Beschreibungen bleiben stehen. Bei Bedarf brichst du ab (**KI-Beschreibung abbrechen**) oder stößt sie über **Erneut versuchen** erneut an.
|
Fehlt die Bildbeschreibung, erstellt die KI sie selbst („KI beschreibt das Bild…" → „KI-Beschreibung bereit"). Bereits ausgefüllte Beschreibungen bleiben stehen. Bei Bedarf brichst du ab (**KI-Beschreibung abbrechen**) oder stößt sie über **Erneut versuchen** erneut an.
|
||||||
|
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+12
-3
@@ -10,9 +10,18 @@ Drei Ebenen: Das Audit-Log protokolliert Änderungen, Snapshots frieren Datenst
|
|||||||
Suchbegriffe: Änderungshistorie, Verlauf, Wiederherstellen, Snapshot, Datensicherung.
|
Suchbegriffe: Änderungshistorie, Verlauf, Wiederherstellen, Snapshot, Datensicherung.
|
||||||
|
|
||||||
<CardGrid>
|
<CardGrid>
|
||||||
<Card title="Audit-Log">Protokolliert Änderungen — wer, wann, vorher/nachher.</Card>
|
<Card title="Audit-Log">
|
||||||
<Card title="Snapshots">Frieren Datenstände im Ordner `snapshotPath` ein.</Card>
|
Protokolliert Änderungen — wer, wann, vorher/nachher.
|
||||||
<Card title="Backups">Voll-Export als ZIP für Umzug und Ernstfall.</Card>
|
|
||||||
|
</Card>
|
||||||
|
<Card title="Snapshots">
|
||||||
|
Frieren Datenstände im Ordner `snapshotPath` ein.
|
||||||
|
|
||||||
|
</Card>
|
||||||
|
<Card title="Backups">
|
||||||
|
Voll-Export als ZIP für Umzug und Ernstfall.
|
||||||
|
|
||||||
|
</Card>
|
||||||
</CardGrid>
|
</CardGrid>
|
||||||
|
|
||||||
## Audit einschalten und lesen
|
## Audit einschalten und lesen
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+8
-2
@@ -10,8 +10,14 @@ Beides sind JavaScript-Programme in der goja-Laufzeit des **tibi-server** — wi
|
|||||||
Suchbegriffe: Cron-Job, geplante Aufgabe, Action-Endpunkt, Kontaktformular-Backend.
|
Suchbegriffe: Cron-Job, geplante Aufgabe, Action-Endpunkt, Kontaktformular-Backend.
|
||||||
|
|
||||||
<CardGrid>
|
<CardGrid>
|
||||||
<Card title="Jobs">Laufen nach Zeitplan (Cron) — zum Beispiel Aufräumen alle 5 Minuten.</Card>
|
<Card title="Jobs">
|
||||||
<Card title="Aktionen">Laufen auf Abruf per HTTP — zum Beispiel Kontaktformular oder Webhook.</Card>
|
Laufen nach Zeitplan (Cron) — zum Beispiel Aufräumen alle 5 Minuten.
|
||||||
|
|
||||||
|
</Card>
|
||||||
|
<Card title="Aktionen">
|
||||||
|
Laufen auf Abruf per HTTP — zum Beispiel Kontaktformular oder Webhook.
|
||||||
|
|
||||||
|
</Card>
|
||||||
</CardGrid>
|
</CardGrid>
|
||||||
|
|
||||||
<Aside type="note">
|
<Aside type="note">
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-1
@@ -201,7 +201,7 @@ Design-Regeln aus dem Starter (`api/config.yml`, `meta.agent.designGuide`): Svel
|
|||||||
| `closeTitle` | Schließen-Knopf mit ESC-Hinweis („Schließen (ESC)") | `PagebuilderOverlay.svelte:348`, `PagebuilderOverviewOverlay.svelte:725`, `de.json:596` |
|
| `closeTitle` | Schließen-Knopf mit ESC-Hinweis („Schließen (ESC)") | `PagebuilderOverlay.svelte:348`, `PagebuilderOverviewOverlay.svelte:725`, `de.json:596` |
|
||||||
| `viewportDesktop` / `viewportTablet` / `viewportPhone` | Breiten-Presets 1280 / 768 / 375 in der Viewport-Steuerung | `PagebuilderViewportControl.svelte:23-25`, `de.json:605-607` |
|
| `viewportDesktop` / `viewportTablet` / `viewportPhone` | Breiten-Presets 1280 / 768 / 375 in der Viewport-Steuerung | `PagebuilderViewportControl.svelte:23-25`, `de.json:605-607` |
|
||||||
| Drill-Down-Modi `overlay` / `inline` | `overlay` (Standard): Fullscreen-Overlay mit Layer-Stack; `inline`: direkte Blockliste im Formular bei `meta.drillDown: false` | `PagebuilderOverviewOverlay.svelte:4-8,34,61,83`, `PagebuilderWidget.svelte:205,238` |
|
| Drill-Down-Modi `overlay` / `inline` | `overlay` (Standard): Fullscreen-Overlay mit Layer-Stack; `inline`: direkte Blockliste im Formular bei `meta.drillDown: false` | `PagebuilderOverviewOverlay.svelte:4-8,34,61,83`, `PagebuilderWidget.svelte:205,238` |
|
||||||
| `blueprintMoreFields` | „+{count} weitere" — eingeklappte Restfelder auf der Blueprint-Karte | `BlueprintCard.svelte:125`, `de.json:611` |
|
| `blueprintMoreFields` | „+\{count\} weitere" — eingeklappte Restfelder auf der Blueprint-Karte | `BlueprintCard.svelte:125`, `de.json:611` |
|
||||||
| `blueprintChildren` | Kind-Zähler („1 Kind" / „n Kinder") | `BlueprintCard.svelte:101`, `de.json:610` |
|
| `blueprintChildren` | Kind-Zähler („1 Kind" / „n Kinder") | `BlueprintCard.svelte:101`, `de.json:610` |
|
||||||
| `blueprintNoData` | Leertext „Keine Daten" bei fehlenden Block-Daten | `BlueprintCard.svelte:132`, `de.json:612` |
|
| `blueprintNoData` | Leertext „Keine Daten" bei fehlenden Block-Daten | `BlueprintCard.svelte:132`, `de.json:612` |
|
||||||
| ESC / Blur / Drilldown | `Escape` schließt nur den obersten Layer (`isTopLayer`), vorher `activeElement.blur()`; Drilldown-Navigation übernimmt Blur selbst | `PagebuilderOverlay.svelte:190-198,244`, `PagebuilderOverviewOverlay.svelte:378-382` |
|
| ESC / Blur / Drilldown | `Escape` schließt nur den obersten Layer (`isTopLayer`), vorher `activeElement.blur()`; Drilldown-Navigation übernimmt Blur selbst | `PagebuilderOverlay.svelte:190-198,244`, `PagebuilderOverviewOverlay.svelte:378-382` |
|
||||||
File renamed without changes.
File renamed without changes.
@@ -133,12 +133,12 @@ Quelldatei der Vorlage ist `frontend/spa.html`. `ci-modify-config.sh` ersetzt `_
|
|||||||
|
|
||||||
| Marker | Inhalt |
|
| Marker | Inhalt |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `<!--HEAD-->` | Head aus dem SSR-Render |
|
| `{/*HEAD*/}` | Head aus dem SSR-Render |
|
||||||
| `<!--HTML-->` | Gerendertes App-HTML |
|
| `{/*HTML*/}` | Gerendertes App-HTML |
|
||||||
| `<!--PRELOAD-->` | Preload-Hinweise (`scripts/preload-meta.sh`) |
|
| `{/*PRELOAD*/}` | Preload-Hinweise (`scripts/preload-meta.sh`) |
|
||||||
| `__TIMESTAMP__` | Build-Stempel für `/dist`-Assets (Cache-Buster, schon beim Kopieren ersetzt) |
|
| `__TIMESTAMP__` | Build-Stempel für `/dist`-Assets (Cache-Buster, schon beim Kopieren ersetzt) |
|
||||||
| `<!--SSR.ERROR-->` | Render-Fehler als Kommentar (leer im Normalfall) |
|
| `{/*SSR.ERROR*/}` | Render-Fehler als Kommentar (leer im Normalfall) |
|
||||||
| `<!--SSR.COMMENT-->` | Diagnose (`url`, `deps`) als Kommentar |
|
| `{/*SSR.COMMENT*/}` | Diagnose (`url`, `deps`) als Kommentar |
|
||||||
| `<html lang>` | Sprache aus dem URL-Präfix (`de`/`en`, sonst `de`) |
|
| `<html lang>` | Sprache aus dem URL-Präfix (`de`/`en`, sonst `de`) |
|
||||||
|
|
||||||
Die Sammlung `ssr` (`api/collections/ssr.yml`) hält einen Eintrag je URL:
|
Die Sammlung `ssr` (`api/collections/ssr.yml`) hält einen Eintrag je URL:
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -3,6 +3,8 @@ title: 'Hook-Referenz: Daten'
|
|||||||
description: 'db, cache, request, response und fs im Hook-JS: Signaturen aus internal/hook, je ein Beispiel und je ein belegter Fehlerfall.'
|
description: 'db, cache, request, response und fs im Hook-JS: Signaturen aus internal/hook, je ein Beispiel und je ein belegter Fehlerfall.'
|
||||||
---
|
---
|
||||||
|
|
||||||
|
import { Aside } from '@astrojs/starlight/components';
|
||||||
|
|
||||||
In Hooks sprichst du diese fünf Pakete über `context` an, z. B. `context.db.find(...)` oder `context.request()`. Die Signaturen stammen aus den `// args:`- bzw. `// JS signature:`-Kommentaren in `internal/hook/context_*.go` im tibi-server; wo so ein Kommentar fehlt, ist die Signatur aus Funktionsrumpf und `_test`-Datei abgeleitet und entsprechend markiert. Jede Funktion zeigt genau einen Fehlerfall mit dem originalen Error-Text aus Code oder Tests (Status-Code aus den Hook-Tests, meist `500`).
|
In Hooks sprichst du diese fünf Pakete über `context` an, z. B. `context.db.find(...)` oder `context.request()`. Die Signaturen stammen aus den `// args:`- bzw. `// JS signature:`-Kommentaren in `internal/hook/context_*.go` im tibi-server; wo so ein Kommentar fehlt, ist die Signatur aus Funktionsrumpf und `_test`-Datei abgeleitet und entsprechend markiert. Jede Funktion zeigt genau einen Fehlerfall mit dem originalen Error-Text aus Code oder Tests (Status-Code aus den Hook-Tests, meist `500`).
|
||||||
|
|
||||||
## db – Collections lesen und schreiben
|
## db – Collections lesen und schreiben
|
||||||
+5
-5
@@ -12,12 +12,12 @@ Jedes dieser fünf Modelle hat dieselben fünf Routen; dazu kommen Meta- und Sco
|
|||||||
|
|
||||||
| Methode + Pfad | Zweck | Rechte |
|
| Methode + Pfad | Zweck | Rechte |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `GET /api/v1/user`, `POST /api/v1/user`, `GET /api/v1/user/:id`, `PUT /api/v1/user/:id`, `DELETE /api/v1/user/:id` | Nutzer anlegen, lesen, ändern, löschen (Passwort nie in Antworten) | Nutzer-Scope (`user.read` …) bzw. Admin-Token; Org-/Team-Zugehörigkeit schränkt ein |
|
| `GET /api/v1/user`, `POST /api/v1/user`, `GET /api/v1/user/:id`, `PUT /api/v1/user/:id`, `DELETE /api/v1/user/:id` | Nutzer anlegen, lesen, ändern, löschen (Passwort nie in Antworten) | Nutzer-Scope (z. B. `user.read`) bzw. Admin-Token; Org-/Team-Zugehörigkeit schränkt ein |
|
||||||
| `GET /api/v1/project`, `POST /api/v1/project`, `GET /api/v1/project/:id`, `PUT /api/v1/project/:id`, `DELETE /api/v1/project/:id` | Projekte registrieren und konfigurieren | Projekt-Scope (`project.read` …); Fremd-Orgs sind unsichtbar |
|
| `GET /api/v1/project`, `POST /api/v1/project`, `GET /api/v1/project/:id`, `PUT /api/v1/project/:id`, `DELETE /api/v1/project/:id` | Projekte registrieren und konfigurieren | Projekt-Scope (z. B. `project.read`); Fremd-Orgs sind unsichtbar |
|
||||||
| `GET /api/v1/org`, `POST /api/v1/org`, `GET /api/v1/org/:id`, `PUT /api/v1/org/:id`, `DELETE /api/v1/org/:id` | Mandanten (Orgs) verwalten | Org-Scope (`org.read` …); nur eigene Org |
|
| `GET /api/v1/org`, `POST /api/v1/org`, `GET /api/v1/org/:id`, `PUT /api/v1/org/:id`, `DELETE /api/v1/org/:id` | Mandanten (Orgs) verwalten | Org-Scope (z. B. `org.read`); nur eigene Org |
|
||||||
| `GET /api/v1/team`, `POST /api/v1/team`, `GET /api/v1/team/:id`, `PUT /api/v1/team/:id`, `DELETE /api/v1/team/:id` | Gruppen in einer Org verwalten | Team-Scope (`team.read` …) |
|
| `GET /api/v1/team`, `POST /api/v1/team`, `GET /api/v1/team/:id`, `PUT /api/v1/team/:id`, `DELETE /api/v1/team/:id` | Gruppen in einer Org verwalten | Team-Scope (z. B. `team.read`) |
|
||||||
| `GET /api/v1/token`, `POST /api/v1/token`, `GET /api/v1/token/:id`, `PUT /api/v1/token/:id`, `DELETE /api/v1/token/:id` | Eigene Personal-Access-Tokens (PAT) verwalten | Login-Sitzung nötig — ein PAT darf **nicht** seine eigene Verwaltung aufrufen |
|
| `GET /api/v1/token`, `POST /api/v1/token`, `GET /api/v1/token/:id`, `PUT /api/v1/token/:id`, `DELETE /api/v1/token/:id` | Eigene Personal-Access-Tokens (PAT) verwalten | Login-Sitzung nötig — ein PAT darf **nicht** seine eigene Verwaltung aufrufen |
|
||||||
| `GET /api/v1/token/_scopes` | Katalog aller Scopes, die du aktuell vergeben darfst (gleiche Quelle wie die Anlage-Prüfung) | Nur Nutzer-Login (`X-Auth-Token`/Session); PAT → `403` |
|
| `GET /api/v1/token/_scopes` | Katalog aller Scopes, die du aktuell vergeben darfst (gleiche Quelle wie die Anlage-Prüfung) | Nur Nutzer-Login (`X-Auth-Token` bzw. Session-Cookie); PAT → `403` |
|
||||||
| `GET /api/v1/_meta` | Feld-Metadaten **aller** System-Modelle als `{models: {user: […], …}}` | Wie die Modell-Routen (System-Ebene) |
|
| `GET /api/v1/_meta` | Feld-Metadaten **aller** System-Modelle als `{models: {user: […], …}}` | Wie die Modell-Routen (System-Ebene) |
|
||||||
| `GET /api/v1/_meta/<modell>` | Feld-Metadaten eines Modells (`user`, `project`, `org`, `team`, `token`) | Wie oben |
|
| `GET /api/v1/_meta/<modell>` | Feld-Metadaten eines Modells (`user`, `project`, `org`, `team`, `token`) | Wie oben |
|
||||||
|
|
||||||
File renamed without changes.
File renamed without changes.
+3
-1
@@ -43,7 +43,9 @@ curl -s -X POST "$SERVER_URL/api/v1/project" \
|
|||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
<Aside type="note" title="Zwei Login-Pfade, ein Login">
|
<Aside type="note" title="Zwei Login-Pfade, ein Login">
|
||||||
Direkt am Server heißt die Route `/api/v1/login` (`setup.go`: Gruppe `/api/v1` + `/login`). Im Starter-Stack proxyt der Admin-Host `/api/...` auf den Server — deshalb steht im Beispiel `$ADMIN_URL/api/login`. Beide meinen denselben Login, nur auf verschiedenen Wegen.</Aside>
|
Direkt am Server heißt die Route `/api/v1/login` (`setup.go`: Gruppe `/api/v1` + `/login`). Im Starter-Stack proxyt der Admin-Host `/api/...` auf den Server — deshalb steht im Beispiel `$ADMIN_URL/api/login`. Beide meinen denselben Login, nur auf verschiedenen Wegen.
|
||||||
|
|
||||||
|
</Aside>
|
||||||
|
|
||||||
## Verwechslungs-Fallen
|
## Verwechslungs-Fallen
|
||||||
|
|
||||||
@@ -54,7 +54,19 @@ Die Volltextsuche läuft pro Projekt in einem Worker. Nach Config-Änderungen mu
|
|||||||
| `POST /api/v1/_/:project/_/admin/reload` | Lädt Projekt-Config neu (Recht `project.reload`) |
|
| `POST /api/v1/_/:project/_/admin/reload` | Lädt Projekt-Config neu (Recht `project.reload`) |
|
||||||
| `POST /api/v1/_/:project/_/admin/regenerate-search` | Baut Suchindex neu auf (`project.regenerate-search`) |
|
| `POST /api/v1/_/:project/_/admin/regenerate-search` | Baut Suchindex neu auf (`project.regenerate-search`) |
|
||||||
| `GET /api/v1/_/:project/_/admin/search-worker/status` | Status des Such-Workers |
|
| `GET /api/v1/_/:project/_/admin/search-worker/status` | Status des Such-Workers |
|
||||||
| `GET /api/v1/_/:project/_/admin/embedding/status` | Status der Embedding-Provider |
|
| `GET /api/v1/_/:project/_/admin/embedding/status` | Status der Embedding-Provider/Gruppen (`project.regenerate-search`; Fehlertexte der Mitglieder sind redigiert) |
|
||||||
|
| `GET /api/v1/admin/embedding/status` | Derselbe Status serverweit (`server.shutdown`, mit vollen Fehlertexten) |
|
||||||
|
|
||||||
|
Der Embedding-Status nennt je Gruppe die Referenz und je Mitglied `state` und `breaker`:
|
||||||
|
|
||||||
|
| `state` | Bedeutung | Vorgehen |
|
||||||
|
|---|---|---|
|
||||||
|
| `live` | Mitglied antwortet | — |
|
||||||
|
| `degraded` | Sicherung offen, letzte Aufrufe scheiterten | Log-Zeile des Mitglieds prüfen; `COOLDOWN_AFTER_UNHEALTHY` und `CHECK_INTERVAL` steuern die Rückkehr |
|
||||||
|
| `quarantined` | Startprüfung fehlgeschlagen (Vektoren weichen ab, Sparse-Form anders, nicht deterministisch) | Modell/Version/Gewichte der Gegenstelle prüfen; mit `CHECK_INTERVAL > 0` kommt sie automatisch zurück, sonst Neustart |
|
||||||
|
| `offline` | Gruppe hat kein verifiziertes Mitglied (oder Config-Fehler) | Warnzeile `embedding group … offline` im Log; Ursache in `MEMBERS`/`PREFERRED_ORDER`/Provider-Config beheben |
|
||||||
|
|
||||||
|
Ist die Gruppe weg, bleiben neue Dokumente ohne Vektoren liegen (sie werden beim nächsten Schreibvorgang oder per `regenerate-search` nachgezogen) — Suchanfragen auf solche Sammlungen brechen mit einer Meldung ab, die die Gruppe nennt.
|
||||||
|
|
||||||
```bash title="Nach Config-Änderung: Reload plus Suchindex neu aufbauen"
|
```bash title="Nach Config-Änderung: Reload plus Suchindex neu aufbauen"
|
||||||
curl -X POST http://localhost:8080/api/v1/_/meinprojekt/_/admin/reload \
|
curl -X POST http://localhost:8080/api/v1/_/meinprojekt/_/admin/reload \
|
||||||
@@ -104,4 +116,4 @@ Waisen findest du per Dateisuche im Upload-Pfad (`media/` bzw. `uploadPath` der
|
|||||||
|
|
||||||
Begriffe wie Collection, Hook oder Namespace klärt [Begriffe](/einstieg/begriffe/). Zum Einrichten siehe [Schnellstart](/einstieg/schnellstart/).
|
Begriffe wie Collection, Hook oder Namespace klärt [Begriffe](/einstieg/begriffe/). Zum Einrichten siehe [Schnellstart](/einstieg/schnellstart/).
|
||||||
|
|
||||||
Verifiziert am 68b4278 2026-10-15 (tibi-server); Compose-Profile am e3f92eb 2026-10-14 (tibi-svelte-starter). Datei-Cleanup aus `internal/filecleanup/cleanup.go` und Aufrufern (`collection_delete.go`, `collection_bulk_delete.go`, `collection_put.go`, `hook/context_db.go`)
|
Verifiziert am d272041 2026-10-17 (tibi-server); Compose-Profile am e3f92eb 2026-10-14 (tibi-svelte-starter). Datei-Cleanup aus `internal/filecleanup/cleanup.go` und Aufrufern (`collection_delete.go`, `collection_bulk_delete.go`, `collection_put.go`, `hook/context_db.go`). Embedding-Status aus `internal/controller/admin_embedding_status.go` und `internal/embedding/registry.go` (Snapshot/Health-Loop).
|
||||||
+15
-1
@@ -149,10 +149,24 @@ EMBEDDING_GROUP_MAIN_POLICY=prefer-in-order
|
|||||||
EMBEDDING_GROUP_MAIN_TIMEOUT_TOTAL=30s
|
EMBEDDING_GROUP_MAIN_TIMEOUT_TOTAL=30s
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Was eine Gruppe beim Start und im Betrieb tut
|
||||||
|
|
||||||
|
Die vollständige Fassung steht in `tibi-server/docs/02-configuration.md`; hier die Betreiber-Kurzfassung:
|
||||||
|
|
||||||
|
- **Prüfung beim Start.** Referenz ist das erste Mitglied aus `PREFERRED_ORDER`, das antwortet (zwei Versuche). Jedes weitere Mitglied muss dieselben Vektoren liefern: Kosinus ≥ 0.999, zweimal identisch (deterministische Inferenz), gleiche Sparse-Form (beide mit oder beide ohne Sparse-Vektoren) und — wenn eine Gold-Datei verankert ist — auch dagegen passen. Abweichende Mitglieder sind `quarantined`; ohne ein einziges verifiziertes Mitglied ist die Gruppe `offline`. Der Server startet trotzdem.
|
||||||
|
- **Rückkehr.** Mit `CHECK_INTERVAL > 0` prüft der Health-Loop Quarantänisierte neu gegen die aktuelle Referenz und nimmt sie zurück, sobald sie wieder passen — auch eine `offline` Gruppe kommt so zurück. Ohne `CHECK_INTERVAL` half bisher nur ein Neustart. Nach `COOLDOWN_AFTER_UNHEALTHY` öffnet außerdem die nächste Anfrage das Mitglied wieder halb (nur ein Versuch gleichzeitig).
|
||||||
|
- **Fehlkonfiguration** (unbekanntes Mitglied, Tippfehler in `PREFERRED_ORDER`, doppelter Gruppen- oder Mitgliedsname, Namensgleichheit mit einem Provider, abweichende Modell-Identität) macht die Gruppe `offline` plus Warnzeile im Log — nie den ganzen Server.
|
||||||
|
- **Timeouts.** Der bevorzugte Member läuft in das Gruppen-`TIMEOUT_PER_ATTEMPT`; ein Ausweich-Member bekommt `max(Provider-Timeout, Gruppen-Timeout)`, damit ein kurzes Gruppen-Timeout einen kalten lokalen Fallback nicht abschneidet — beim Bulk-Schreiben genauso. Bei `POLICY=fastest-wins` oder `HEDGE_AFTER_SLOW` immer `TIMEOUT_TOTAL` setzen. Sind alle Sicherungen offen, antwortet die Gruppe sofort mit Fehler, statt die Gegenstellen zu bombardieren.
|
||||||
|
- **Dense-only-Endpoints bleiben kompatibel:** fehlen Sparse-Vektoren, obwohl `SPARSE` aktiv ist, liefert der Provider weiter dense-only Treffer (Hybrid-Suche fällt auf dense zurück) und schreibt einmalig eine Warnung; `SPARSE=false` schaltet sie stumm. Innerhalb einer **Gruppe** lehnt die Prüfung ein Mitglied mit abweichender Sparse-Form ab, damit ein Failover nie still Sparse-Vektoren verliert.
|
||||||
|
- **Während die Gruppe weg ist**, bleiben Dokumente liegen: Der Batch-Weg meldet sie dem Aufrufer als offen, einzelne Schreibvorgänge lassen den Such-Eintrag stehen. Nachziehen per nächstem Schreibvorgang, `regenerate-search` oder `autoRegenerate`; Suchanfragen brechen mit einer Meldung ab, die die Gruppe beim Namen nennt.
|
||||||
|
|
||||||
Provider-Env zum Vergleich (Provider `<NAME>` → `EMBEDDING_<NAME>_…`, ebenfalls Bindestrich zu Unterstrich):
|
Provider-Env zum Vergleich (Provider `<NAME>` → `EMBEDDING_<NAME>_…`, ebenfalls Bindestrich zu Unterstrich):
|
||||||
`APIKEY`, `TYPE`, `MODEL`, `MODELPATH`, `DIMENSIONS`, `BASEURL`, `DOCUMENTPREFIX`, `QUERYPREFIX`, `REVISION`, `TIMEOUTPERATTEMPT`, `SLOWTHRESHOLD`, `SPARSE` —
|
`APIKEY`, `TYPE`, `MODEL`, `MODELPATH`, `DIMENSIONS`, `BASEURL`, `DOCUMENTPREFIX`, `QUERYPREFIX`, `REVISION`, `TIMEOUTPERATTEMPT`, `SLOWTHRESHOLD`, `SPARSE` —
|
||||||
z. B. `EMBEDDING_BGE_M3_MODELPATH`, `EMBEDDING_BGE_M3_DIMENSIONS`.
|
z. B. `EMBEDDING_BGE_M3_MODELPATH`, `EMBEDDING_BGE_M3_DIMENSIONS`.
|
||||||
Unbekannte `POLICY`/`DISTRIBUTION` oder ungültige Durations lassen die Gruppe mit Fehler im Log scheitern; unpassende `WEIGHTS`/`RACE_*`-Kombis geben nur eine Warnung und werden ignoriert.
|
Unbekannte `POLICY`/`DISTRIBUTION` oder ungültige Durations lassen die Gruppe mit Fehler im Log scheitern; unpassende `WEIGHTS`/`RACE_*`-Kombis geben nur eine Warnung und werden ignoriert.
|
||||||
|
Provider- und Gruppen-Env gelten auch mit Bindestrich im Namen (`EMBEDDING_BGE-M3_TYPE`): der Server übernimmt solche Alt-Schlüssel beim Start auf die Unterstrich-Form und schreibt eine Hinweiszeile ins Log.
|
||||||
|
|
||||||
|
Wo die **Gold-Dateien** für die Mitglieds-Prüfung liegen, setzt du global: `embedding.goldenPath` bzw. `EMBEDDING_GOLDEN_PATH` (Vorgabe `testdata/embedding-golden` relativ zum Arbeitsverzeichnis); erzeugen mit `go run ./cmd/embed-probe-golden`. Ohne verankerte Gold-Datei protokolliert die Gruppe das beim Start und prüft nur gegen die Referenz.
|
||||||
|
|
||||||
## Admin-Tokens
|
## Admin-Tokens
|
||||||
|
|
||||||
@@ -185,4 +199,4 @@ api:
|
|||||||
|
|
||||||
Weiter: [Betrieb und Beobachtung](/server/betrieb/) zeigt Profile und Metriken. [Sicherheit](/server/sicherheit/) erklärt Token-Arten und Ratelimit.
|
Weiter: [Betrieb und Beobachtung](/server/betrieb/) zeigt Profile und Metriken. [Sicherheit](/server/sicherheit/) erklärt Token-Arten und Ratelimit.
|
||||||
|
|
||||||
Verifiziert am 68b4278 2026-10-15 (tibi-server); Starter-Compose am e3f92eb 2026-10-14 (tibi-svelte-starter); Go-Version aus `go.mod`. Upload-Kaskade aus `internal/controller/collection.go` (resolveAllowedMimeTypes), Gruppen-Env aus `internal/config/server.go` und `internal/config/embedding_group.go`.
|
Verifiziert am d272041 2026-10-17 (tibi-server); Starter-Compose am e3f92eb 2026-10-14 (tibi-svelte-starter); Go-Version aus `go.mod`. Upload-Kaskade aus `internal/controller/collection.go` (resolveAllowedMimeTypes), Provider-/Gruppen-Env und `goldenPath` aus `internal/config/server.go`, Gruppen-Regeln aus `internal/config/embedding_group.go`, Prüfung/Quarantäne/Rückkehr/Timeouts aus `internal/embedding/{registry,probe,group}.go`, Pending-Verhalten aus `internal/utils/search.go`.
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -18,6 +18,11 @@
|
|||||||
--tibi-sidebar: #f8f9fa;
|
--tibi-sidebar: #f8f9fa;
|
||||||
--tibi-topbar: #ffffff;
|
--tibi-topbar: #ffffff;
|
||||||
--tibi-card-border: #e5e7eb;
|
--tibi-card-border: #e5e7eb;
|
||||||
|
|
||||||
|
/* Inline-Code-Chips (hell): Grau mit Rahmen statt Flaeche ohne Kante */
|
||||||
|
--tibi-inline-bg: #e9ecf1;
|
||||||
|
--tibi-inline-border: #d3d7de;
|
||||||
|
--tibi-inline-text: #1f2937;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-theme='dark'] {
|
:root[data-theme='dark'] {
|
||||||
@@ -29,6 +34,11 @@
|
|||||||
--tibi-sidebar: #16181d;
|
--tibi-sidebar: #16181d;
|
||||||
--tibi-topbar: #16181d;
|
--tibi-topbar: #16181d;
|
||||||
--tibi-card-border: #333a44;
|
--tibi-card-border: #333a44;
|
||||||
|
|
||||||
|
/* Inline-Code-Chips (dunkel): deutlich abgesetzt vom Seitenhintergrund (#16181d) */
|
||||||
|
--tibi-inline-bg: #333945;
|
||||||
|
--tibi-inline-border: #525b6b;
|
||||||
|
--tibi-inline-text: #eef1f6;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- Flächen in Nova-Nähe ---------- */
|
/* ---------- Flächen in Nova-Nähe ---------- */
|
||||||
@@ -114,3 +124,22 @@
|
|||||||
.sl-link-card:hover {
|
.sl-link-card:hover {
|
||||||
border-color: var(--tibi-nova);
|
border-color: var(--tibi-nova);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---------- Inline-Code: eigenstaendige Chips, auch im Dark Mode lesbar ----------
|
||||||
|
Starlight faerbt Inline-Code nur mit --sl-color-bg-inline-code (gray-5/gray-6).
|
||||||
|
Im Dark Mode liegt das zu nah am Seitenhintergrund, deshalb fester Rahmen,
|
||||||
|
eigene Textfarbe und mehr Innenabstand. Betrifft nur Inline-Code — Codebloecke
|
||||||
|
(Expressive Code) bleiben unberuehrt, weil `pre > code` nicht adressiert wird. */
|
||||||
|
.sl-markdown-content :not(pre) > code:not(:where(.not-content *)) {
|
||||||
|
background-color: var(--tibi-inline-bg);
|
||||||
|
border: 1px solid var(--tibi-inline-border);
|
||||||
|
border-radius: 0.3rem;
|
||||||
|
color: var(--tibi-inline-text);
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 0.12em 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Methoden-/Status-Spalten (etwa `GET`, `POST`, `404`) umbrechen nicht mitten im Wort */
|
||||||
|
.sl-markdown-content td:first-child code:not(:where(.not-content *)) {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
Reference in new issue
Block a user