Dritte Etappe. Die Ansicht lag bisher im URL-Hash (`#models`), gespeist aus einem
useState in App.tsx. Das war fuer Reload und Lesezeichen brauchbar — aber nur auf
View-Ebene; fuer den Zustand DARUNTER war kein Platz.
## Was jetzt in der Adresse steht (Befund B-05)
/modelle?reiter=routing der Reiter war lokaler State, nicht teilbar
/ideen?offen=<id> die aufgeklappte Karte; wer waehrend eines
laufenden Workers neu lud, verlor seinen Platz
/wissen?datei=<pfad> jede Vault-Notiz verlinkbar
<ueberall>?system=wartung|logs die System-Schublade inkl. Reiter
Alle Suchparameter werden validiert (app/router.tsx) — ein Link mit Unsinn darin
faellt auf den Normalfall zurueck, statt die Ansicht in einen halben Zustand zu
bringen.
## Alte Lesezeichen brechen nicht
lib/hashUmleitung.ts biegt `#models` per replaceState auf `/modelle`, EINMAL vor
dem Router-Mount. Fuenf Tests decken das ab (jeder NAV-Eintrag, die Schreibweise
`#/models`, erhaltene Suchparameter, unbekannter Hash, kein Hash) — die Bruecke
sieht sonst wie toter Code aus und waere ein naheliegender Kandidat zum Wegraeumen.
Das Backend brauchte KEINE Zeile: der SPA-Catch-all in app.py:148-168 beantwortet
jede unbekannte Route schon immer mit index.html. Vorher geprueft, nicht gehofft.
## Fehlergrenze pro Route (Befund B-13)
Vorher hing eine einzige Grenze in main.tsx um alles — ein Renderfehler im
Modell-Manager nahm Cockpit, Konsole und Chronik mit. Jetzt faengt jede Route fuer
sich (components/RouteFehler.tsx: was passiert ist, was man tun kann, technische
Einzelheiten aufklappbar). AppErrorBoundary bleibt als letztes Netz fuer Fehler
ausserhalb jeder Route. Dazu eine 404-Seite, die Schiene und Kopfzeile stehen
laesst — im Browser geprueft.
## Budget: der Router kostete 29 kB, sie sind wieder drin
TanStack Router hob den Start-Chunk von 111 auf 141 kB gzip und riss damit das in
P0 gesetzte Ampel-Budget (125 kB). Statt das Budget hochzusetzen — was es als
Signal entwertet haette — den Platz zurueckgeholt: SystemDrawer und CommandPalette
sind beim Start UNSICHTBAR und liegen jetzt hinter lazy(). Die Palette laedt beim
ersten Strg+K und bleibt dann gemountet.
Start-Chunk gzip 111 411 -> 114 978 B (Budget 125 000, weiter scharf)
dist gesamt 1 565 521 B (Budget 3 145 728)
## Nebenbei
· Befund B-09 erledigt: Der "Suchen"-Knopf baute ein GEFAELSCHTES KeyboardEvent
(`new KeyboardEvent("keydown", { metaKey: true })`) und feuerte es aufs
Dokument. Jetzt ein eigener Kanal; in P3 loest der Store auch den ab.
· Der Schliessen-Knopf der System-Schublade hatte kein aria-label — ein reiner
Icon-Knopf ohne Namen. Nachgeholt (beim Pruefen aufgefallen).
· nav.ts fuehrt jetzt den Pfad je Eintrag + navFuerPfad() mit Laengen-Sortierung,
damit /ideen/<id> die Sidebar bei "Ideen" markiert. Mit Tests.
## Verifiziert im Browser (lokales Backend, echtes Produktions-Buendel)
/ -> /cockpit, Sidebar markiert
/#models -> /modelle, Sidebar markiert
/modelle?reiter=routing -> Reiter "Routing & Warm-Set" aktiv
/cockpit?system=logs -> Schublade offen, Reiter "System-Logs" aktiv;
Schliessen entfernt den Parameter wieder
/gibtsnicht -> 404-Seite, Schiene + Kopfzeile intakt
Zurueck-Taste -> voriger Pfad
26/26 Tests gruen · ESLint 0 Fehler · tsc sauber.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Mission Control 2.0
Steuerzentrale des lokalen KI-Stacks auf dem Bosgame M5 (AMD Ryzen AI MAX+ 395 „Strix Halo", 122 GB Unified Memory, keine dedizierte GPU — llama.cpp über Vulkan/RADV). Läuft live als sudo-freier systemd-User-Dienst und ist auf Autonomie ausgelegt: Die Box wartet sich selbst, prüft sich selbst und meldet sich, wenn etwas nicht stimmt.
100 % lokal. Kein Cloud-Modell, kein externer Dienst im Datenpfad.
Die drei Bahnen
| Bahn | Was sie tut | Wo |
|---|---|---|
| Steuerzentrale | Modelle, Routing, Wartung, Gedächtnis, Ideen-Queue, Auftragsbuch | MC2 :9001 |
| Coding | Agentic IDE (z.B. OpenCode Desktop) auf Dev-PC via lokaler API + MCP | 100% lokal |
| Lucy | Sprach-Companion mit 3D-Avatar, Augen und Ohren | eigenes Repo Hitonabi/lucy |
Lucy holt ihr Hirn direkt über das MC2-Gateway (:9010/v1) mit nativer Bildweiche und Voice-Streaming.
Ports & Dienste
| Port | Dienst | Erreichbar |
|---|---|---|
9001 |
MC2 (FastAPI + React) — Cockpit, API, Konsole | LAN |
8080 |
llama-swap — Modell-Router | LAN |
9010 |
mc2-gateway — /v1-Datenpfad (model: auto, Bild-Weiche) |
loopback |
8642 · 9119 |
Hermes-Gateway · Hermes-Web-UI | loopback |
8765 · 8650 |
Mem0-Sidecar · Voice-Sidecar (STT/TTS) | loopback |
7682 |
ttyd — Box-Konsole, same-origin unter /console/ |
loopback |
Units in deploy/: mission-control-2 · mc2-gateway · mc2-steward ·
mem0-service · voice-service · box-console · hermes-builtin-ui + Timer für Backup,
Auto-Update, Self-Smoke und Bagatell-Annahme. llama-swap läuft als System-Unit.
Die Bau-Pipeline
Idee in MC2 → Gitea-Repo (mit CI-Ampel + VERIFY) → in Agentic IDE bauen → Ampel → main
└── autonomes Vibe Coding via OpenCode Desktop + MCP
Jedes neue Repo wird von deploy/gitea-repo-create.sh mit beiden
Wächtern geboren:
.gitea/workflows/ci.yml— die Außen-Prüfung nach dem Push (Gitea Actions)VERIFY— die Innen-Prüfung: eine Zeile, wie man das Projekt testet. Die Agentic IDE führt sie im Mix-Ansatz vor jedem Push aus, um Code-Fehler ("Quality Gap") abzufangen. KeineVERIFY-Datei = Prüf-Tor aus.
Modelle & Rollen
Gemessen auf der Box (Stand: 27.08.2026, Vulkan b10653):
| Rolle | Modell | Tempo | Aufgabe |
|---|---|---|---|
coder |
Qwen3.8-27B (dicht, 27B) | 12,7 t/s | Plant und baut — der Haupt-Coder. 131k Kontext (ganzer Slot), multimodal |
hermes / fast |
Qwen3.6-35B-A3B | 69,6–90 t/s | Lucys Hirn und Sucher-Subagent. Immer warm, 65k/Slot |
debugger |
Muse-Glimmer-30B | 40–50 t/s (DFlash) | Runtime-Debugger & Fehler-Diagnostiker (multimodal) |
vision |
Qwen3-VL-30B-A3B | auf Abruf | Lucys Augen (On-Demand) |
heavy |
gpt-oss-120b | nur nachts | Chef-Gutachter (4:30 Uhr). Nie tagsüber — verdrängt das warme Set |
embed · reranker |
Qwen3 0.6B | immer warm | Vektorsuche + Feinsortierung |
Sieben Rollen, mehr nicht. Frühere Fassungen listeten hier auch
kritiker,scoutunddense-planer— die Modell-Konsolidierung vom 19.08. hat sie entfernt (ein Coder, ein Agent-Hirn). Der dichte 27B ist seither nicht mehr „Planer" neben dem Coder, sondern ist der Coder. Details:docs/wissen/STACK.md.
‼️ Dichte Modelle sind auf dieser Box bandbreitengebunden. Der Prefill bricht mit wachsendem
Kontext ein — beim früheren Kritiker (Devstral, dicht) waren bei 32k gemessene 63 t/s ≈ 9 Minuten
nur zum Lesen, weshalb er hart auf 16k gedeckelt war. Das gilt weiter für jedes dichte Modell:
coder (Qwen3.8-27B) liefert ~12,7 t/s gegen ~90 t/s des MoE-Hirns — kein Konfigfehler, sondern
das 215-GB/s-Limit der Plattform. Der Kritiker selbst ist seit dem 19.08. nicht mehr im Stack.
‼️ Speicher-Regel: Warm-Set + größtes On-Demand-Modell ≤ ~115 GB. Die ko-residente Gruppe
(groups.brains) steht auf persistent: true (Verdrängungsschutz; live gegengeprüft
27.08.2026). Wichtig ist nicht der Schalter, sondern: alles, was gleichzeitig warm sein muss,
gehört in DIESELBE Gruppe — zwei Gruppen verdrängen sich gegenseitig, und persistent schützt
nicht davor (gemessen 25.07.). Details und
Messwerte: docs/wissen/VERDIKTE.md.
Qualitäts-Tore
- Prüf-Tor —
VERIFYnach jeder Etappe; rot → der Agent (OpenCode Desktop) repariert lokal nach. - CI-Ampel — Lint (ruff) · Import/Syntax (compileall) · Frontend-Build. Läuft in Gitea.
Gemeinsame Lehre dahinter: Wissen lebt in Datei + git, nicht im schrumpfenden Chat-Kontext. Kontext-Komprimierung löscht still die Regeln mit.
Selbsterhaltung
- Health-Wächter (
sentry) + Warm-Set-Wächter (warmer, per Env abschaltbar) - Updates mit Fangnetz — Backup → Update → Postcheck → bei Fehler Auto-Rollback + Pin
- Melde-Briefkasten (
/api/voice/announce) — alles, was die Box von sich aus sagen will; Lucy pollt ihn und spricht es. Absenderloop= Coding-Ereignisse - Gedächtnis — Mem0-Sidecar, auto-lernend, semantisch, mit Auto-Dedupe
- Tägliche Self-Smokes, Zeitmaschine (Snapshot + Ein-Klick-Restore), Chronik der autonomen Taten
API (Auswahl)
health · models/* · discover · fit · groups · routing/* · system/* · maintenance/* · connect · memory/* · agent/* · ideen/* · auftragsbuch/* · chronik · eigenleben · wissen · zeitmaschine/* · reminders/* · voice/* · events (SSE)
OpenAI-kompatibel: /v1/chat/completions, /v1/completions. MCP-Server: mcp/.
Entwickeln
# Backend
cd backend
python -m venv .venv && .venv/Scripts/python -m pip install -r requirements.txt # Windows
.venv/Scripts/python -m uvicorn app:app --port 9000
# Frontend (Dev, proxyt /api → :9000)
cd frontend && npm install && npm run dev # http://localhost:5173
# Frontend (Build → wird vom Backend ausgeliefert)
cd frontend && npm run build # → frontend/dist
frontend/dist wird mitcommittet — die Box hat kein Node; Deploy ist ein git pull plus
Dienst-Neustart. Vor jedem Commit lohnt der Ampel-Vorlauf: ruff check . und npm run build.
Env-Vars (Auswahl)
| Variable | Default | Zweck |
|---|---|---|
MC_PORT |
9000 |
MC-Backend-Port (die Unit auf der Box setzt 9001) |
MC_LLAMA_SWAP_URL |
http://127.0.0.1:8080 |
Engine/Router |
MC_CONFIG_PATH |
/etc/llama-swap/config.yaml |
llama-swap-Config |
MC_V1_UPSTREAM |
– | gesetzt → /v1 geht an mc2-gateway (:9010) statt in-process |
| MC_ENGINE_PATH | /opt/llamacpp-vulkan | aktive Engine (Vulkan-Build) |
| MC_REWARM_ENABLED | 1 | Warm-Set-Wächter (auf der Box bewusst 0) |
| MC_DRAFTS_DIR · MC_SPEC_TYPE | $MODELS/drafts · draft-simple | Spekulatives Dekodieren |
Weiterlesen
| Dokument | Inhalt |
|---|---|
docs/BEDIENUNG.md |
Wie man MC2 benutzt |
docs/RUNBOOK.md · docs/DISASTER_RECOVERY.md |
Betrieb, Störungen, Wiederherstellung |
docs/HERMES_SETUP.md |
Hermes-Agent, Profile, Crons |
docs/AUFTRAGSBUCH.md |
Vorschlags-Inbox und das Ein-Klick-Gate |
docs/wissen/VERDIKTE.md |
Finale Technik-Entscheide — nicht neu aufrollen |
docs/wissen/FALLEN.md · docs/wissen/OFFENE-FAEDEN.md |
Stolpersteine · offene Punkte |
| AGENTS.md | Arbeitsregeln für Agenten in diesem Repo |