Compare commits
4 Commits
42e45b4b50
...
cb3a5adaf9
| Author | SHA1 | Date | |
|---|---|---|---|
| cb3a5adaf9 | |||
| 87c479323c | |||
| b95530ee70 | |||
| 3a6e3c5432 |
+27
@@ -0,0 +1,27 @@
|
|||||||
|
# .aiexclude — was der KI-Assistent (Antigravity/Gemini) NICHT lesen/indexieren soll.
|
||||||
|
# Gitignore-Syntax. Ziel: der Review fokussiert auf QUELLCODE, nicht auf Abhängigkeiten,
|
||||||
|
# Build-Output oder Binärdateien.
|
||||||
|
|
||||||
|
# Abhängigkeiten & Build-Output (kein Review-Ziel)
|
||||||
|
backend/.venv/
|
||||||
|
frontend/node_modules/
|
||||||
|
frontend/dist/
|
||||||
|
**/__pycache__/
|
||||||
|
*.pyc
|
||||||
|
.git/
|
||||||
|
|
||||||
|
# Große / binäre / sensible Dateien
|
||||||
|
*.vrm
|
||||||
|
*.gguf
|
||||||
|
*.onnx
|
||||||
|
*.safetensors
|
||||||
|
*.wav
|
||||||
|
*.env
|
||||||
|
.env
|
||||||
|
credentials*
|
||||||
|
*.key
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# Lokale Scratch-/Recon-Skripte
|
||||||
|
box_recon*
|
||||||
|
gemma_swap*
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
# Savepoint — Mission Control 2.0 (MC2)
|
||||||
|
|
||||||
|
_Stand: 2026-07-05. Zustands-Snapshot für einen externen Code-Review (Antigravity). Zuerst
|
||||||
|
`AGENTS.md` lesen (Projekt-Regeln), dann diese Datei (wo wir stehen), dann `README.md`/`docs/`._
|
||||||
|
|
||||||
|
## Was das ist (in einem Satz)
|
||||||
|
MC2 ist die **Web-Admin-Konsole** einer 100 % lokalen KI-Appliance („die Box", Bosgame M5 / AMD
|
||||||
|
Strix Halo, 128 GB Unified RAM, llama.cpp-Vulkan). Sie verwaltet Engine, Modelle, Gedächtnis,
|
||||||
|
Agenten-Status, Updates & Wartung — und dient teils als Gedächtnis-Oberfläche für die Sprach-
|
||||||
|
Begleiterin „Lucy".
|
||||||
|
|
||||||
|
## Architektur (Kurzform — Details in AGENTS.md/docs/)
|
||||||
|
- **Backend** `backend/` — FastAPI, `:9001` als systemd-**User-Dienst** (reboot-fest, sudo-frei).
|
||||||
|
Router (`routers/`, dünn) → Logik (`services/`, Single Source of Truth).
|
||||||
|
- **Frontend** `frontend/` — React/Vite/Tailwind/shadcn. **`frontend/dist` ist ABSICHT im git**
|
||||||
|
(Box hat kein Node; Backend liefert die gebauten Assets aus).
|
||||||
|
- **Eingebautes Gateway** `:9001/v1` (OpenAI-kompatibel) → llama-swap `:8080` (Engine, Vulkan/RADV).
|
||||||
|
- **Sidecars:** `mem0_service/` (Mem0-Gedächtnis), `voice_service/` (STT/TTS für den „Sprechen"-Tab),
|
||||||
|
`mcp/` (MCP-Server), `hermes/` (Hermes-Agent-Plugin), `client/hermes-pc` (PC-Executor).
|
||||||
|
|
||||||
|
## Aktueller Zustand
|
||||||
|
- **Stabil, in Produktion, „MC2 Final".** Ein Neubau („MC3") wurde bewusst VERWORFEN — MC2 wird
|
||||||
|
sauber gehalten und eingefroren, nicht neu erfunden.
|
||||||
|
- **Autonomie-Ausbau abgeschlossen** (Observability-Latenztrace, Fremd-Modell-Kritiker/Härtung,
|
||||||
|
nächtliches „Dreaming" mit Wissens-Vault) — jeweils propose-only, Mensch = Gate.
|
||||||
|
- **Zuletzt (Commit `ff1b9a0`, 05.07.):** `coder-lite` (Qwen3-Coder-30B) entfernt; der Verbinden-Tab
|
||||||
|
(`services/connect.py`) empfiehlt IDEs jetzt die realen Direkt-Modelle `coder`/`heavy`/`vision`
|
||||||
|
statt der virtuellen „coding"-Lane. Davor u. a. Engine-Update-Fix, Hermes-Terminal same-origin.
|
||||||
|
- **Modelle live:** hermes=Qwen3.6-35B-A3B (Agent-Hirn, immer warm) · coder=Qwen3-Coder-Next ·
|
||||||
|
heavy=gpt-oss-120b · vision=Qwen3-VL-30B · scout=GLM-4.6V · embed. Warm-Set = hermes+vision+embed.
|
||||||
|
|
||||||
|
## Nordstern & Randbedingungen (WICHTIG für den Review)
|
||||||
|
- **Zieht ohne Wartung über JAHRE durch.** Robustheit + Einfachheit schlagen Features. Der Betreiber
|
||||||
|
ist **kein Entwickler** — alles muss reboot-/update-fest und selbsterklärend sein.
|
||||||
|
- **100 % lokal, kein Cloud-Zwang** (Privatsphäre ist der Sinn). Hardware-Decke: ~124 GB, ein Topf.
|
||||||
|
- **Lucy ist ein SEPARATES Repo** (`F:\Coding Stuff\lucy`) — **nicht Teil dieses Reviews.**
|
||||||
|
|
||||||
|
## Bekannte raue Kanten (Kandidaten — gern bestätigen/erweitern)
|
||||||
|
- Doku-Drift möglich: `AGENTS.md` nennt „Box läuft in UTC" — die Box wurde inzwischen auf
|
||||||
|
`Europe/Berlin` umgestellt.
|
||||||
|
- Alte, disabled v1-System-Unit `mission-control.service` liegt kosmetisch herum (sudo zum Entfernen).
|
||||||
|
- Ältere Review-Notiz nannte toten Code-Verdacht (`pricing.py`, `token_stats.py`) — bitte prüfen.
|
||||||
|
- Ein paar frühere Frontend-Monolithen wurden entflochten; Rest-Altlasten möglich.
|
||||||
|
|
||||||
|
## Was NICHT empfohlen werden soll (bereits entschieden)
|
||||||
|
Cloud-Migration · Voll-Rewrite · schwere neue Frameworks · Engine-/Modell-Wechsel, die nicht in
|
||||||
|
124 GB passen · `frontend/dist` aus git nehmen (Absicht) · Security-Config anfassen. Erwünscht sind
|
||||||
|
**Bugs, Fragilität, tote Pfade, Sicherheitslücken, Vereinfachung (KISS/DRY), Wartbarkeit.**
|
||||||
|
|
||||||
|
## Letzter Sicherungspunkt
|
||||||
|
- git `ff1b9a0` „coder-lite raus + Verbinden-Tab auf echte Direkt-Modelle" (auf `main`, deployt, live).
|
||||||
+50
-16
@@ -10,6 +10,7 @@ import asyncio
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
|
from typing import Any, AsyncGenerator, Awaitable, Callable
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
@@ -18,9 +19,24 @@ from fastapi.responses import FileResponse
|
|||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
from starlette.requests import Request
|
from starlette.requests import Request
|
||||||
|
|
||||||
from config import FRONTEND_DIST, VERSION
|
from backend.config import FRONTEND_DIST, VERSION
|
||||||
from routers import agent, connect, console, gateway_proxy, health, hermes_ui, maintenance, memory, models, reminders as reminders_router, routing, system, voice
|
from backend.routers import (
|
||||||
from services import memory as memory_svc, reminders, sentry, warmer
|
agent,
|
||||||
|
connect,
|
||||||
|
console,
|
||||||
|
gateway_proxy,
|
||||||
|
health,
|
||||||
|
hermes_ui,
|
||||||
|
maintenance,
|
||||||
|
memory,
|
||||||
|
models,
|
||||||
|
routing,
|
||||||
|
system,
|
||||||
|
voice,
|
||||||
|
)
|
||||||
|
from backend.routers import reminders as reminders_router
|
||||||
|
from backend.services import memory as memory_svc
|
||||||
|
from backend.services import reminders, sentry, warmer
|
||||||
|
|
||||||
# Zentrales Logging — Level via MC_LOG_LEVEL (INFO default). Eine Konfiguration
|
# Zentrales Logging — Level via MC_LOG_LEVEL (INFO default). Eine Konfiguration
|
||||||
# für alle Module (logging.getLogger(__name__)).
|
# für alle Module (logging.getLogger(__name__)).
|
||||||
@@ -30,21 +46,28 @@ logging.basicConfig(
|
|||||||
)
|
)
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(app: FastAPI):
|
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
|
||||||
"""Hintergrund-Tasks an den App-Lebenszyklus binden: Re-Warm-Wächter fürs Agent-Hirn
|
"""Hintergrund-Tasks an den App-Lebenszyklus binden: Re-Warm-Wächter fürs Agent-Hirn
|
||||||
+ Health-Wächter (meldet Ausfälle/Erholung in den Lucy-Briefkasten und auf Telegram)."""
|
+ Health-Wächter (meldet Ausfälle/Erholung in den Lucy-Briefkasten und auf Telegram)."""
|
||||||
tasks = []
|
tasks: list[asyncio.Task[Any]] = []
|
||||||
if warmer.ENABLED:
|
if warmer.ENABLED:
|
||||||
tasks.append(asyncio.create_task(warmer.rewarm_loop()))
|
tasks.append(asyncio.create_task(warmer.rewarm_loop()))
|
||||||
log.info("Hirn-Re-Warm-Wächter aktiv (Intervall %ss, Hirn dynamisch aus Hermes-Config)", warmer.INTERVAL)
|
log.info(
|
||||||
|
"Hirn-Re-Warm-Wächter aktiv (Intervall %ss, Hirn dynamisch aus Hermes-Config)",
|
||||||
|
warmer.INTERVAL,
|
||||||
|
)
|
||||||
if sentry.ENABLED:
|
if sentry.ENABLED:
|
||||||
tasks.append(asyncio.create_task(sentry.sentry_loop()))
|
tasks.append(asyncio.create_task(sentry.sentry_loop()))
|
||||||
tasks.append(asyncio.create_task(reminders.reminders_loop()))
|
tasks.append(asyncio.create_task(reminders.reminders_loop()))
|
||||||
if memory_svc.AUTO_DEDUPE_ENABLED:
|
if memory_svc.AUTO_DEDUPE_ENABLED:
|
||||||
tasks.append(asyncio.create_task(memory_svc.auto_dedupe_loop()))
|
tasks.append(asyncio.create_task(memory_svc.auto_dedupe_loop()))
|
||||||
log.info("Mem0-Auto-Dedupe aktiv (alle %ss, Schwelle %s)",
|
log.info(
|
||||||
memory_svc.AUTO_DEDUPE_INTERVAL, memory_svc.AUTO_DEDUPE_THRESHOLD)
|
"Mem0-Auto-Dedupe aktiv (alle %ss, Schwelle %s)",
|
||||||
|
memory_svc.AUTO_DEDUPE_INTERVAL,
|
||||||
|
memory_svc.AUTO_DEDUPE_THRESHOLD,
|
||||||
|
)
|
||||||
# Geteilter HTTP-Client zur lokalen Engine: Keep-Alive/Connection-Pooling statt neuer Client
|
# Geteilter HTTP-Client zur lokalen Engine: Keep-Alive/Connection-Pooling statt neuer Client
|
||||||
# pro /v1-Anfrage (spart Sockets/TIME_WAIT unter parallelen Agent-Strömen von Zed/Kilo).
|
# pro /v1-Anfrage (spart Sockets/TIME_WAIT unter parallelen Agent-Strömen von Zed/Kilo).
|
||||||
app.state.gw_client = httpx.AsyncClient(
|
app.state.gw_client = httpx.AsyncClient(
|
||||||
@@ -55,7 +78,7 @@ async def lifespan(app: FastAPI):
|
|||||||
yield
|
yield
|
||||||
finally:
|
finally:
|
||||||
for task in tasks:
|
for task in tasks:
|
||||||
task.cancel()
|
_ = task.cancel()
|
||||||
await app.state.gw_client.aclose()
|
await app.state.gw_client.aclose()
|
||||||
|
|
||||||
|
|
||||||
@@ -71,7 +94,9 @@ app.add_middleware(
|
|||||||
|
|
||||||
|
|
||||||
@app.middleware("http")
|
@app.middleware("http")
|
||||||
async def no_cache(request: Request, call_next):
|
async def no_cache(
|
||||||
|
request: Request, call_next: Callable[[Request], Awaitable[httpx.Response]]
|
||||||
|
) -> httpx.Response:
|
||||||
resp = await call_next(request)
|
resp = await call_next(request)
|
||||||
if request.url.path.startswith("/api"):
|
if request.url.path.startswith("/api"):
|
||||||
resp.headers["Cache-Control"] = "no-cache"
|
resp.headers["Cache-Control"] = "no-cache"
|
||||||
@@ -85,12 +110,20 @@ app.include_router(system.router)
|
|||||||
app.include_router(connect.router)
|
app.include_router(connect.router)
|
||||||
app.include_router(memory.router)
|
app.include_router(memory.router)
|
||||||
app.include_router(agent.router)
|
app.include_router(agent.router)
|
||||||
app.include_router(voice.router) # Sprache: STT/TTS-Proxy + Hermes-Agent-Chat (Voice-Tab)
|
app.include_router(
|
||||||
app.include_router(reminders_router.router) # Erinnerungen/Routinen (A3) — feuern in den Briefkasten
|
voice.router
|
||||||
|
) # Sprache: STT/TTS-Proxy + Hermes-Agent-Chat (Voice-Tab)
|
||||||
|
app.include_router(
|
||||||
|
reminders_router.router
|
||||||
|
) # Erinnerungen/Routinen (A3) — feuern in den Briefkasten
|
||||||
app.include_router(gateway_proxy.router) # OpenAI-kompatibler /v1-Gateway (model:auto)
|
app.include_router(gateway_proxy.router) # OpenAI-kompatibler /v1-Gateway (model:auto)
|
||||||
app.include_router(maintenance.router)
|
app.include_router(maintenance.router)
|
||||||
app.include_router(console.router) # Box-Konsole (ttyd) same-origin durchreichen — VOR dem SPA-Catch-all
|
app.include_router(
|
||||||
app.include_router(hermes_ui.router) # Eingebaute Hermes-Web-GUI (hermes serve) same-origin unter /hermes-ui/ — VOR dem SPA-Catch-all
|
console.router
|
||||||
|
) # Box-Konsole (ttyd) same-origin durchreichen — VOR dem SPA-Catch-all
|
||||||
|
app.include_router(
|
||||||
|
hermes_ui.router
|
||||||
|
) # Eingebaute Hermes-Web-GUI (hermes serve) same-origin unter /hermes-ui/ — VOR dem SPA-Catch-all
|
||||||
|
|
||||||
|
|
||||||
# Prod: gebautes Frontend ausliefern (falls vorhanden). SPA-Fallback auf index.html.
|
# Prod: gebautes Frontend ausliefern (falls vorhanden). SPA-Fallback auf index.html.
|
||||||
@@ -113,6 +146,7 @@ if FRONTEND_DIST.exists():
|
|||||||
index = FRONTEND_DIST / "index.html"
|
index = FRONTEND_DIST / "index.html"
|
||||||
if index.exists():
|
if index.exists():
|
||||||
# index.html nie cachen → Browser zieht nach jedem Deploy das aktuelle (gehashte) Bundle.
|
# index.html nie cachen → Browser zieht nach jedem Deploy das aktuelle (gehashte) Bundle.
|
||||||
return FileResponse(index, headers={"Cache-Control": "no-cache, must-revalidate"})
|
return FileResponse(
|
||||||
|
index, headers={"Cache-Control": "no-cache, must-revalidate"}
|
||||||
|
)
|
||||||
return {"detail": "frontend not built"}
|
return {"detail": "frontend not built"}
|
||||||
|
|
||||||
|
|||||||
@@ -97,6 +97,10 @@ _HUI_DIST="$HOME/.hermes/hermes-agent/hermes_cli/web_dist"
|
|||||||
if [ -d "$_HUI_WEB" ] && [ -x "$HOME/.hermes/node/bin/npx" ]; then
|
if [ -d "$_HUI_WEB" ] && [ -x "$HOME/.hermes/node/bin/npx" ]; then
|
||||||
if ( cd "$_HUI_WEB" && PATH="$HOME/.hermes/node/bin:$PATH" npx --no-install vite build \
|
if ( cd "$_HUI_WEB" && PATH="$HOME/.hermes/node/bin:$PATH" npx --no-install vite build \
|
||||||
--base=/hermes-ui/ --outDir /tmp/hermes-ui-build --emptyOutDir ) >/tmp/hermes-ui-build.log 2>&1; then
|
--base=/hermes-ui/ --outDir /tmp/hermes-ui-build --emptyOutDir ) >/tmp/hermes-ui-build.log 2>&1; then
|
||||||
|
# Dienst VOR dem Tausch stoppen — sonst crasht der laufende `hermes serve`, wenn er index.html
|
||||||
|
# im Lösch-Fenster (rm→cp) liest (FileNotFoundError → Start-Limit → tot). Der reguläre restart
|
||||||
|
# weiter unten bringt ihn sauber auf der neuen web_dist hoch.
|
||||||
|
systemctl --user stop hermes-builtin-ui 2>/dev/null || true
|
||||||
rm -rf "$_HUI_DIST" && cp -r /tmp/hermes-ui-build "$_HUI_DIST" && echo "Hermes-GUI (base=/hermes-ui/) gebaut."
|
rm -rf "$_HUI_DIST" && cp -r /tmp/hermes-ui-build "$_HUI_DIST" && echo "Hermes-GUI (base=/hermes-ui/) gebaut."
|
||||||
else
|
else
|
||||||
echo "WARN: Hermes-GUI-Build fehlgeschlagen (siehe /tmp/hermes-ui-build.log) — bestehende web_dist bleibt."
|
echo "WARN: Hermes-GUI-Build fehlgeschlagen (siehe /tmp/hermes-ui-build.log) — bestehende web_dist bleibt."
|
||||||
@@ -118,6 +122,8 @@ loginctl enable-linger "$USER" >/dev/null 2>&1 || true
|
|||||||
# Voice-Sidecar (re)starten (best-effort; Erststart lädt das STT-Modell vor).
|
# Voice-Sidecar (re)starten (best-effort; Erststart lädt das STT-Modell vor).
|
||||||
[ -x "$HOME/.voice/venv/bin/python" ] && systemctl --user restart voice-service 2>/dev/null || true
|
[ -x "$HOME/.voice/venv/bin/python" ] && systemctl --user restart voice-service 2>/dev/null || true
|
||||||
# Eingebaute Hermes-Web-GUI (Loopback :9119) (re)starten — MC2 bettet sie unter /hermes-ui/ ein.
|
# Eingebaute Hermes-Web-GUI (Loopback :9119) (re)starten — MC2 bettet sie unter /hermes-ui/ ein.
|
||||||
|
# reset-failed, damit ein zuvor am Start-Limit gestorbener Dienst wieder anläuft.
|
||||||
|
systemctl --user reset-failed hermes-builtin-ui 2>/dev/null || true
|
||||||
systemctl --user restart hermes-builtin-ui 2>/dev/null || true
|
systemctl --user restart hermes-builtin-ui 2>/dev/null || true
|
||||||
systemctl --user restart mission-control-2
|
systemctl --user restart mission-control-2
|
||||||
command -v ttyd >/dev/null 2>&1 && systemctl --user restart hermes-terminal 2>/dev/null || true
|
command -v ttyd >/dev/null 2>&1 && systemctl --user restart hermes-terminal 2>/dev/null || true
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
# Antigravity-Review-Prompt — Mission Control 2.0
|
||||||
|
|
||||||
|
Prompt zum Einfügen in Antigravity 2.0 (Modell: **Gemini 3.1 Pro, High-Modus**). Projektordner =
|
||||||
|
dieses Repo. `.aiexclude` hält `.venv`/`node_modules`/`dist` aus dem Kontext.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Du bist ein erfahrener Senior-Reviewer und führst ein **vollständiges, ehrliches Code- und
|
||||||
|
Architektur-Review** dieses Projekts (Mission Control 2.0, kurz MC2) durch.
|
||||||
|
|
||||||
|
**Zuerst lesen — das ist der Rahmen, weiche nicht davon ab:**
|
||||||
|
1. `AGENTS.md` — die verbindlichen Projekt-Regeln.
|
||||||
|
2. `SAVEPOINT.md` — wo das Projekt gerade steht, Nordstern und Randbedingungen.
|
||||||
|
3. `README.md` und `docs/` — Kontext.
|
||||||
|
|
||||||
|
**Was MC2 ist:** die Web-Admin-Konsole einer **100 % lokalen** KI-Appliance (AMD Strix Halo, 128 GB,
|
||||||
|
llama.cpp-Vulkan). Backend = FastAPI (`backend/`, Dienst auf :9001), Frontend = React/Vite/Tailwind
|
||||||
|
(`frontend/`). Sidecars: `mem0_service/`, `voice_service/`, `mcp/`, `hermes/`, `client/`.
|
||||||
|
|
||||||
|
**Nordstern:** Das System muss **über Jahre ohne Wartung** laufen, betrieben von einem
|
||||||
|
**Nicht-Entwickler**. Robustheit, Einfachheit und Selbstheilung schlagen Features.
|
||||||
|
|
||||||
|
## Dein Auftrag
|
||||||
|
Prüfe das gesamte Repo (außer dem, was `.aiexclude` ausschließt). Suche gezielt nach:
|
||||||
|
- **Korrektheits-Bugs & Race Conditions** — besonders in `backend/services/` und den Routern.
|
||||||
|
- **Betriebs-Fragilität:** Was bricht bei **Reboot**, **Update** oder **Teil-Ausfall**? Was ist nicht
|
||||||
|
reboot-/idempotenz-fest? (Der Betreiber kann es nicht selbst debuggen.)
|
||||||
|
- **Sicherheitslücken** — Auth/Token-Handling, Command-Allowlists, Prompt-Injection-Guards,
|
||||||
|
Pfad-/Eingabe-Validierung, `sudo -n`-Nutzung. (Nur MELDEN, nichts an der Security-Config ändern.)
|
||||||
|
- **Ressourcen-Lecks & Fehlerbehandlung** — offene Clients/Dateien, verschluckte Exceptions,
|
||||||
|
fehlende Timeouts.
|
||||||
|
- **Toter/redundanter Code, DRY-/KISS-Verstöße, Über-Komplexität** — Vereinfachungs-Chancen.
|
||||||
|
- **Doku-/Realitäts-Drift** — Widersprüche zwischen `AGENTS.md`/Kommentaren und dem Code
|
||||||
|
(z. B. Zeitzone UTC vs. Europe/Berlin).
|
||||||
|
- **Wartbarkeit** — würde ein Fremder das in einem Jahr noch verstehen und sicher anfassen können?
|
||||||
|
|
||||||
|
## Harte Leitplanken (nicht empfehlen)
|
||||||
|
- KEINE Cloud-Migration, KEIN Voll-Rewrite, KEINE schweren neuen Frameworks.
|
||||||
|
- KEINE Modell-/Engine-Wechsel, die nicht in ~124 GB passen; keine Cloud-LLMs.
|
||||||
|
- `frontend/dist` bleibt bewusst im git (Box hat kein Node) — nicht als Fehler werten.
|
||||||
|
- Security-Config nur MELDEN, nie „einfach ändern".
|
||||||
|
- Bevorzuge **Vereinfachung und Härtung** vor neuen Features.
|
||||||
|
|
||||||
|
## Ausgabeformat (auf DEUTSCH)
|
||||||
|
1. **Gesamturteil** (3–5 Sätze): Wie gesund ist das Projekt? Trägt es den Nordstern „Jahre ohne Wartung"?
|
||||||
|
2. **Befunde, nach Schwere sortiert** — je Befund:
|
||||||
|
- Schweregrad **P0** (bricht/Sicherheit) · **P1** (echter Bug/Fragilität) · **P2** (Wartbarkeit) · **P3** (nice-to-have)
|
||||||
|
- `datei:zeile` · was ist das Problem · **warum es zählt** (konkretes Fehlszenario) · **konkreter Fix**
|
||||||
|
3. **Positives** — was bewusst gut gelöst ist (damit es nicht „wegoptimiert" wird).
|
||||||
|
4. **Was ich bewusst NICHT ändern würde** — und warum (Respekt vor den getroffenen Entscheidungen).
|
||||||
|
|
||||||
|
Sei ehrlich und konkret. Erfinde keine Probleme, um die Liste zu füllen. Wenn etwas gut ist, sag das.
|
||||||
@@ -35,8 +35,5 @@
|
|||||||
"tailwindcss": "^4.0.0",
|
"tailwindcss": "^4.0.0",
|
||||||
"typescript": "^5.6.3",
|
"typescript": "^5.6.3",
|
||||||
"vite": "^6.0.3"
|
"vite": "^6.0.3"
|
||||||
},
|
|
||||||
"allowScripts": {
|
|
||||||
"esbuild@0.25.12": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user