Neue Intake-Weiche Box/IDE. IDE-Ideen gehen direkt an das neue Profil
'projektstart' (am Triage/Auto-Zerleger vorbei, kein Werkstatt-Bau): es
haertet via konzept-fliessband ein Konzept, legt ein leeres Gitea-Repo an
und fuellt es NUR mit Doku (Konzept/Roadmap/AGENTS.md/.aiexclude). Ergebnis
ist ein vorbereitetes Projekt, das der Commander in Zed selbst baut.
UI: Toggle 'Box baut / Ich bau in Zed', IDE-Badge auf Karten.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Karten lassen sich gezielt anhalten (generischer Block + Prozessbaum-Kill),
frisch starten (Retry beendet Worker samt Kindern - uvicorn-Falle) und per
Prio-Pfeilen umsortieren (Dispatcher zieht priority DESC nativ). Laufende
Karten ohne Heartbeat >10 min bekommen ein Warn-Badge; der Ketten-Digest
alarmiert nach 15 min per Telegram, inkl. Kontext-Verdichtungs-Hinweis.
Ausloeser: Scaffold-Worker hing 45 min an selbst gestartetem uvicorn.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Lucys Augen-Waermer (alle 10 min, max_tokens=1 an "vision"), warmup.sh und
models/load enden konstruktionsbedingt mit finish_reason=length — die Warnung
vom 15.07. hielt jeden Ping fuer einen abgerissenen Worker und spammte den
Briefkasten (~alle 20 min, Serie 16.07. abends). Wer freiwillig auf <=16
Tokens deckelt, will keine echte Antwort -> keine Warnung; echte Abrisse
melden weiter.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Live-Diagnose 16.07.: Die 'Hirn'-Zeit der Voice-Turns (Dashboard 6,4-21,5s) war fast
vollstaendig Qwen3.6-Reasoning VOR dem ersten sprechbaren Wort (reasoning_content
2500+ Zeichen bei ~100 t/s; /no_think-Softswitch wird ignoriert; Prefix-Cache war
NICHT das Problem - live gemessen: Zeitstempel-Aenderung kostet nur ~0,8s).
Fix: Lucy traegt Marker [[MC:NO_THINK]] im System-Prompt; das Gateway strippt ihn
aus allen Messages (konstanter Text -> Prefix-Cache stabil) und setzt
chat_template_kwargs enable_thinking:false. Direkt am Hirn gemessen: 9,9s -> 0,8s,
Persona-Qualitaet unveraendert. Requests ohne Marker (Crons/Telegram/Werkstatt)
denken unveraendert weiter. Abschaltbar via MC_NO_THINK_MARKER="".
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Paket 1 - Metrik-Historie mit Zeitachse (User: 'WANN war Last?'):
- services/metrics_history.py: 10s-Sampler (CPU/RAM/GPU/Disk + Token-Totale) in
24h-Ringpuffer (aelteres faellt automatisch raus, nichts waechst unbegrenzt),
persistiert alle 5 min -> uebersteht Deploys; GET /api/system/history?minutes
mit Downsampling auf ~300 Punkte; Lifespan-Task in app.py
- Cockpit-Karten System-Status + Token-Durchsatz: Bereichs-Schalter Live/1h/24h,
sichtbare Zeitachse (HH:MM:SS bei kurzen, HH:MM bei langen Fenstern), Tooltip
zeigt Uhrzeit; Token-Raten in 1h/24h aus Totale-Deltas
Paket 2 - Verbinden selbsterklaerend:
- Box-IP vorbefuellt aus window.location.hostname (Dev-Fallback bleibt)
- MCP-Scriptpfad-Feld aus der Kopfzeile in die 'Gedaechtnis anbinden'-Karte
verschoben, mit Erklaerung WANN man es braucht
Paket 3 - Modelltausch-Loecher gestopft (Review 16.07.):
- install: Registrierung OHNE Alias-Umzug; Rolle wird erst NACH erfolgreichem
Download uebernommen (on_done) - hermes dabei durch den warm-bewussten
set_agent_brain-Flow statt rohem Alias-Move (Lucy waere sonst bis Download-
Ende tot gewesen); Re-Install erhaelt bestehende Aliase
- set_role_alias: lebenswichtige Aliase (hermes/embed) des Ziel-Modells
ueberleben jeden Rollen-Klick (Qwen3.6 haelt live hermes+fast!)
- Rollen-Endpoint verweigert Rollen-Wechsel am Halter geschuetzter Aliase
mit klarer Anleitung; Werkbank sperrt die Rollen-Chips sichtbar
Verifiziert: py_compile + Sampler-Smoke (2 Punkte, Persist ok) + Alias-Logik-
Unittest (3 Faelle) + Browser (Zeitachse tickt, Schalter, Leerzustand, Verbinden).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Die angenommene Karte feature/sse-backend-v1 ersetzte die bereits E2E-
getestete Hand-Implementierung mit drei harten Fehlern: 'type:' statt
'event:' (ungueltiges SSE-Framing - EventSource-Listener feuern NIE),
globaler Snapshot ueber alle Clients (verschluckt Events), Ideen-Zaehler
gegen nicht existierenden Endpunkt :9010/v1/ideen. Dazu doppelter
Router-Mount in app.py (Merge-Folge).
Zurueck auf den bewiesenen Kern (3s-Fingerprints, Basislinie je
Verbindung, is_disconnected, korrektes Framing) + die GUTE Idee der
Karte uebernommen: Running-Set der Modelle als Quelle (Laden/Entladen
invalidiert die Modelle-Ansicht). System-/Token-Metriken bleiben bewusst
beim Polling (aendern sich jede Sekunde = invalidate-Laerm).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Befund :9010 (Journal): httpx.ReadTimeout nach Sekunden trotz timeout=240 -
der gepoolte Keep-Alive-Client reicht Sockets wieder aus, die llama-swap
beim Modell-Swap gekappt hat. Der Beschreibungs-Unteraufruf nutzt jetzt
einen eigenen Kurzzeit-Client und versucht es einmal erneut.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kategorie-Skills (z. B. autonomous-ai-agents/hermes-agent) haben einen
Schraegstrich in der ID. Die Route /api/eigenleben/skill/{skill_id} nahm nur
EIN Pfadsegment -> Request fiel in den SPA-Fallback (index.html, Status 200),
die UI zeigte "(Konnte den Skill-Text nicht laden.)". Live bewiesen:
skill/wartung = JSON, skill/autonomous-ai-agents%2Fhermes-agent = HTML.
Fix: :path-Konverter in der Route; dazu im Service "."/".."-Segmente
explizit abweisen (das Zeichen-Set der bestehenden Validierung liesse
".." als Segment durch, bisher irrelevant, mit :path sauber dicht).
Backend-only, kein dist-Rebuild noetig.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
User-Entscheid 15.07. abends: P3-Worker-Jobs abgebrochen (22 Anlaeufe,
0 Ergebnisse) - 'du bearbeitest sie ein letztes Mal manuell'.
P3a KOMPLETT: backend/routers/events.py streamt SSE; ein Sammler prueft
alle 3 s billige Fingerabdruecke (Briefkasten-Cursor, Queue-Status,
Auftragsbuch-/Reminder-mtimes) und schickt bei Aenderung 'invalidate'
mit den React-Query-Keys. frontend/src/lib/events.ts haelt EIN
EventSource, invalidiert gezielt und entspannt die vier gedeckten
Poller x5 (relax() in queries.ts); reisst der Strom, reconnectet
EventSource selbst und die UI pollt wie bisher. Live-Graphen bleiben
bewusst beim Polling (aendern sich jede Sekunde).
P3b (TanStack Router) BEWUSST NICHT umgesetzt: Hash-Navigation liefert
Deep-Links + Zuruecktaste bereits; Router-Migration = hohes Regressions-
risiko ueber alle Views bei minimalem Gewinn fuer 1-Nutzer-LAN (gleiche
Logik wie das React-bleibt-Verdikt in UMBAUPLAN 3b).
P3c (OpenAPI-Typen) VERTAGT: ohne Pydantic-response_models liefert der
Generator leere Typen - Voraussetzung ist erst das Backend-Typing
(eigene, klein geschnittene Karten-Serie).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
User-Wunsch 15.07. ('es sollte eine Warnung geben - Kontext ist nicht
unendlich'): 4 P3-Worker starben still an finish_reason=length.
- Gateway erkennt abgerissene Antworten (Stream-Chunk + Non-Stream) und
meldet je Modell max. alle 10 min in den Briefkasten (silent -> Chronik),
Zustellung per MC_ANNOUNCE_HTTP ans Steuerpult (Store bleibt Ein-Schreiber).
- Steckbrief-Hook: KONTEXT-BUDGET & ETAPPEN-REGEL - gezielt lesen, grosse
Aufgaben in Etappen schneiden (kanban_create/complete mit Plan) statt
am Limit zu sterben.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
User-Feedback 15.07.:
1) 'Von allein' heisst jetzt 'Skills' (id #eigenleben bleibt, Links halten).
2) Jeder Skill traegt aktiv/inaktiv - Quelle ist Hermes' EIGENE Wahrheit
(hermes_cli.banner.get_available_skills via Hermes-venv, dieselbe Logik
wie das eingebaute WebUI: Plattform/Voraussetzungen/Config). Bewusst NUR
die Datenquelle wiederverwendet, nicht deren UI - Skill-VERWALTUNG bleibt
im Hermes-GUI-Tab, alles andere waere Bloat/Doppelbau.
3) Auftragsbuch: fertige Queue-Karten sind aufklappbar und zeigen das
ERGEBNIS des Workers (kanban_complete-Summary, lazy via
GET /api/ideen/{id}/ergebnis) - 'Dinge werden getestet, ich sehe aber
das Ergebnis nicht' ist damit zu.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
User-Wunsch 15.07.: EIN Viewpoint, was die Box selbst geleistet hat -
Chronik ist zu kompliziert. Neue Operativ-Ansicht #eigenleben:
- Skills aus ~/.hermes/skills (= Lucys Satz) mit Klartext-Beschreibung,
Nutzungszaehler (.usage.json) und Herkunft (selbst erstellt / von uns
gebaut / mitgeliefert), aufklappbar mit vollem SKILL.md.
- Vorschlags-Bilanz: angenommen (Auftragsbuch-Chronik) + abgelehnt mit
Grund (Lern-Journal) als eine Timeline + Zaehler.
Backend: services/eigenleben.py + routers/eigenleben.py (read-only).
Mit an Bord (User-Ja, SCHLAFEND): config.V1_UPSTREAM + app.py-Weiche +
gateway_forward aus dem P1-Gateway-Auszug - ohne MC_V1_UPSTREAM in der
Unit exakt altes Verhalten. Der aktive Rest von P1 kommt separat ueber
Branch umbau/p1-gateway-auszug (dort liegt auch diese View schon).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Idee aus verwaistem (nie verdrahtetem) Patch in der Hermes-Quelle
api_server.py - regelkonform in den MC2-Gateway umgezogen, Original
als docs/archiv/hermes-api_server-vision-patch-verwaist.diff archiviert.
Request mit Bild an coder: Bilder werden vorab von VL-30B beschrieben
und als Text injiziert, die Code-Frage bleibt beim Spezialisten.
Fallback bei Analyse-Fehler: bisherige Vision-Umleitung.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bild-Request loeste HTTP 500: HTTP-Header muessen latin-1 sein, das '→'
(U+2192) im x-mc-route-reason war nicht kodierbar. Die Weiche selbst
routete korrekt (VL-30B lud). Pfeil auf '->' geaendert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entscheid Weg A (vision-harness-verdikt): das MTP-Hirn (fast/hermes) bleibt
schnell und bildunfaehig; Bild-Requests routet das MC2-Gateway automatisch ans
Vision-Modell - kein manueller Modellwechsel, Lucys Flow bleibt.
router_logic.py: has_image(body) erkennt OpenAI-multimodalen content
(image_url/input_image/image); _text_of zieht jetzt nur Text-Parts fuer das
Komplexitaets-Routing (str() einer content-Liste haette die Zeichen-Schwelle
verfaelscht). VISION_CAPABLE = {vision, scout}.
routing_policy.py: neues UI-editierbares vision-Alias (Default env MC_ROUTE_VISION
= "vision"; leer = Weiche aus), darf wie coder_lite leer sein.
gateway_proxy.py _proxy: nach der Alias-Wahl - wenn ein Bild dabei ist und das
Ziel nicht bildfaehig - Override auf das vision-Alias (auch bei explizitem
model=hermes; genau Lucys Fall). Header x-mc-route-reason.
Verifiziert (Unit): Bild+hermes->vision, Bild+auto->vision, Text->fast,
Bild+scout->scout (schon bildfaehig), has_image korrekt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sackgasse behoben: ein Worker blockte eine Aufgabe mit einer Frage
(kanban block --kind needs_input), aber die Zentrale zeigte nur den
roten Status "haengt - braucht dich" - ohne die Frage und ohne
Eingabefeld. Der Worker blieb so dauerhaft stehen.
Backend (services/ideen.py):
- _blocker_frage(): liest die Worker-Frage aus dem juengsten
blocked-Event (payload.reason/kind), Fallback: BLOCKED:-Kommentar.
- list_queue() reichert blockierte Karten mit frage + frage_kind an
(max 6 Extra-show-Aufrufe pro Poll).
- answer_task(): unblock --reason schreibt die Antwort als Kommentar
und stellt die Karte auf ready -> Dispatcher spawnt den Worker neu,
der die Antwort im Kontext vorfindet. Mit ID-/Laengen-Validierung.
Router: POST /api/ideen/antwort.
Frontend (AuftragsbuchView): blockierte Karten zeigen die Frage
(je nach Grund "Die Box hat eine Frage:" / "kam hier nicht weiter:")
plus Antwortfeld + "Antworten & weiter". Fallback-Text ohne Grund.
Vertraegt sich mit dem Live-Log-Blick (nur triage/running).
Verifiziert: E2E gegen die echte Box-Kanban-CLI (Frage auslesen,
answer_task entsperrt + protokolliert, Fehlerpfade), py_compile +
Frontend-Build gruen, Antwort-UI im Dev-Server gerendert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
User-Auftrag 12.07. ("bau das alles ein im Sinne der Autonomie. Auch muss
Lucy selbst bemerken wenn sich etwas aendert"):
- deploy/selbst-inventur.sh (Cron 03:35): SELBST-STECKBRIEF wird LIVE aus
der Realitaet GENERIERT (Versionen, Dienste, Timer, Modelle, Crons,
Queue, Karten -> ~/.hermes/state/selbst-steckbrief.md) statt von Hand
gepflegt. Diff gegen gestern => die Box BEMERKT SELBST Aenderungen an
sich (stille Chronik-Karte + kurze Telegram-Zeile; sonst still).
- deploy/karten-gutachter.sh (Cron 04:00): stempelt jede neue Karte mit
"Empfehlung: ANNEHMEN/ABLEHNEN/UNKLAR + ein ehrlicher Satz" (prueft
Redundanz gegen den Steckbrief, Risiko, Nutzen; Ein-Schuss-Richter
gpt-oss/GLM; Stempel = Meinung, kein Gate; neuer Commit entwertet den
alten Stempel). Backend mischt den Stempel in /api/auftragsbuch,
UI zeigt ihn farbig auf der Karte.
- Ablehnen mit Grund (Lern-Klick): UI-Inline-Feld beim Ablehnen ->
/srv/models/mc2-ablehnungen.jsonl -> Idle-Radar bekommt die Gruende
als "NIE wieder vorschlagen"-Material vorgelegt.
- idle-radar-feed.sh: Material + Raster erweitert um Selbst-Steckbrief,
Inventur-Diff und Ablehn-Gruende (Fehlerfall 12.07.: redundanter
Gateway-Restart-Vorschlag waere damit gestorben).
- werkstatt-SOUL Regel 7 + wartung-Skill: REALITAETS-CHECK - existiert es
schon? Dann kanban_block statt Branch (ein Branch fuer Ueberfluessiges
ist ein gescheiterter Lauf).
- hermes-release-radar-feed.sh: echter Treffer legt zusaetzlich EINE rohe
Idee in die Queue (idempotent je Release-Tag) - der Blick nach draussen
fuettert denselben Kreislauf.
- deploy.sh: kopiert beide neuen Skripte; Doku AUFTRAGSBUCH.md +
wissen/OFFENE-FAEDEN.md; frontend/dist frisch gebaut (tsc+vite gruen,
UI gegen Live-Box verifiziert).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Das Auftragsbuch-Gegenstueck fuer Lucy (Abloesungs-Paket S3, PC-Annahme-Weg):
- backend/services/auftragsbuch.py: Multi-Repo (mc2 + lucy via ~/lucy-Clone).
Karten tragen repo-Feld; Status-Schluessel fuer Lucy = 'lucy:<branch>';
fehlt ~/lucy, werden Lucy-Karten still weggelassen. Runner je Repo.
- deploy/lucy-annahme.sh: detached Annahme-Runner fuer Lucy-Karten.
Vorpruefung am PC VOR dem Merge (Executor erreichbar, Arbeitskopie main+clean,
laeuft Lucy?), dann Merge im isolierten Worktree von ~/lucy -> Push main ->
PC zieht ff-only und baut detached (deploy/lucy-annahme.ps1 im Lucy-Repo),
Box pollt .lucy-annahme.json und spiegelt Fortschritt auf die Karte.
Rot = Merge automatisch revertiert, laufende Lucy bleibt die alte.
Executor-Zugang (URL+Token) kommt aus ~/.hermes/config.yaml — kein zweiter
Ablageort. Neustart nur, wenn Lucy vorher lief (User-Entscheid).
- Router/UI: repo-Parameter (rueckwaertskompatibel, Default mc2), rosa
Lucy-Badge, eigener Annahme-Confirm-Text, Diff/Ablehnen je Repo.
- werkstatt-SOUL: Lucy-Auftraege ebenfalls propose-only, bauen macht der PC
bei der Annahme.
- Doku: docs/AUFTRAGSBUCH.md (Lucy-Annahme-Kapitel), docs/wissen/OFFENE-FAEDEN
(S2 erledigt, S3-Stand).
Geprueft: py_compile gruen, bash -n gruen, tsc+vite build gruen (dist dabei).
Die /v1/models-Liste zeigte Router-Lanes (coding/chat), Rollen-Aliase und rohe
llama-swap-IDs durcheinander (verwirrte coding-vs-coder im Hermes-Desktop-Waehler).
Jetzt nur noch die Klarnamen-Aliase: Router-Lanes nicht mehr gelistet (Routing
bleibt, /chat/completions nimmt coding/chat weiter an), rohe Doppel-IDs ausgeblendet
wenn ein Alias sie schon zeigt, tote Konstanten LANES/_LANE_LABELS entfernt.
fast/scout/heavy unangetastet (tragend). py_compile gruen.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Der "Hermes GUI"-Tab (iframe auf /hermes-ui/) und das Hermes-Terminal-ttyd
(:7681) entfallen — die Agent-Oberfläche ist jetzt die Hermes-Desktop-App,
die über den BESTEHENDEN MC2-Proxy /hermes-ui/ (WS inklusive) an die Box
andockt. hermes-builtin-ui (:9119) bleibt als Desktop-Gateway erhalten und
wird im Dienste-Drawer + /api/system/services erstklassig geführt (statt
hermes-terminal); Wartungs-Allowlist kann ihn jetzt neu starten.
- Frontend: Tab/View raus (nav.ts, App.tsx, TerminalView.tsx gelöscht),
AgentView + (Legacy-)AgentStatusCard zeigen Desktop-Gateway statt ttyd,
Dienste-Zeile hermes-terminal → hermes-builtin-ui, Versions-Zeile
"Hermes UI" (nesquena-Karteileiche ~/hermes-webui) entfernt.
- Backend: terminal_url/terminal_reachable + HERMES_TERMINAL_* raus,
console.py proxyt nur noch die Box-Konsole, /api/system/services führt
hermes-builtin-ui, USER_SERVICES getauscht, hermes-webui-GitInfo raus.
- deploy.sh: legt hermes-terminal + hermes-webui idempotent still
(disable --now + Unit-Löschung). deploy/hermes-terminal.service bleibt
EINEN Zyklus im Repo (das laufende alte deploy.sh kopiert es noch —
Selbst-Reset-Falle); Aufräum-Commit folgt nach dem nächsten Deploy.
- frontend/dist mit-committet (Box baut nicht selbst).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Der letzte Meter des propose-only-Kreislaufs: Vorschlags-Branches (Werkstatt/
Orchestrator) und Traum-Skill-Kandidaten werden als API sichtbar; Annehmen laeuft
als detached systemd-Unit (Merge im Worktree -> Push main -> Deploy -> Health ->
Auto-Revert bei Rot). Dazu: Chronik-Endpoint (Announce-Store als Timeline),
Wissens-Vault-Reader (read-only, Traversal-Guard), Zeitmaschine (Snapshots +
detached Restore) und Morgenlage-Spiegel im Chef-Gutachter-Feed (priority=silent).
python-multipart explizit in requirements (voice braucht es, war implizit).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Neuer POST /api/maintenance/update-all kettet die AUSSTEHENDEN Updates
sequenziell (Engine -> Router -> Hermes -> OS) in einem maintenance-Job.
Bewusst reine Wiederverwendung: jeder Teil ist exakt der Befehl des
Einzel-Updates inkl. dessen Backup/Postcheck/Selbst-Rollback; &&-Kette
stoppt beim ersten Fehler, Banner-Zeilen im Log zeigen den Schritt.
OS zuletzt (breitester Eingriff, braucht als einziges das Box-Passwort;
fehlt es, laufen die sudo-freien Teile trotzdem und OS wird uebersprungen).
Hermes-Befehlskette in _hermes_update_cmd() extrahiert (DRY).
UI (SystemDrawer/Updates): Button 'Alle aktualisieren (N)' neben der
Update-Suche, nur sichtbar wenn etwas aussteht, gesperrt waehrend ein
Wartungs-Job laeuft, mit Bestaetigungs-Dialog der die Kette benennt.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(1) /v1/models meldet jetzt den ECHTEN Kontext pro Slot: --parallel teilt
den Server-Kontext hart auf (131072 / 2 Slots = 65536). Vorher budgetierte
Hermes gegen 131k -> Kompaktierung feuerte nie, llama-server kappte bei
~52k-Sessions Prompt/Antwort -> abgerissene Tool-Calls, Retry-Schleifen,
gefuehlte Abstuerze (journalctl 07.07 17:11, 152 msgs / ~51.700 Tokens).
Dazu auf der Box: context.engine 'default' (existiert nicht, warnte jeden
Turn) -> 'compressor' (der echte eingebaute Name).
(2) Cockpit: neue Sektion 'Leistung' mit den drei bestehenden Live-Karten
(System-Status, Token-Durchsatz, Latenz je Turn) — waren nach UI v3 nur
noch in der alten Zentrale, User will sie auf der Startseite. Browser-
verifiziert gegen die Box (rendert live, keine Konsolen-Fehler).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Beim Entfernen des httpx-Imports uebersehen: der /models-Endpoint nutzte httpx
noch direkt -> NameError/500. Jetzt zieht auch /models den geteilten
app.state.gw_client (request-Param ergaenzt). Live verifiziert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Vier verifizierte Befunde aus dem externen Review (Gemini 3.1 Pro):
- app.py: SPA-Fallback gegen Path-Traversal gehaertet (resolve + is_relative_to,
liefert nur noch Dateien INNERHALB von frontend/dist aus).
- app.py/gateway_proxy.py: geteilter httpx.AsyncClient im lifespan statt neuer
Client pro /v1-Anfrage (Keep-Alive/Pooling, spart Sockets unter parallelen Agent-Stroemen).
- system.py: check_versions_cached() mit threading.Lock + Double-Check gegen Scan-Stampede.
- AGENTS.md: Zeitzonen-Drift korrigiert (Box laeuft Europe/Berlin, nicht UTC).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Terminals (wie die Box-Konsole):
- hermes-terminal bindet jetzt NUR Loopback (--interface lo --base-path /hermes-terminal)
und wird von MC2 same-origin durchgereicht (routers/console.py generalisiert auf beide
ttyd-Instanzen). Kein eigener Firewall-Port mehr noetig.
- Beide Terminals starten die Shell/CLI ueber `su - hitonabi` → fragen beim Oeffnen das
Box-Passwort ab (PAM gegen das echte Konto, nichts gespeichert). „Login mit sudo-PW".
- agent_status.terminal_url = /hermes-terminal/ (+ reachable via Loopback-Check).
Engine-Update (llama.cpp) — Fix „nicht moeglich":
- update-engine.sh/update-swap.sh sind per sudoers NOPASSWD freigegeben → das fruehere
`sudo true`-Passwort-Gate hat sie faelschlich blockiert (wenn kein/falsches Box-PW). Gate
entfernt → Engine-/Router-Update laufen jetzt passwortlos.
OS-Update (apt) — Fix „nicht moeglich":
- DEBIAN_FRONTEND wird jetzt INNERHALB `sudo bash -c '…'` gesetzt statt `sudo VAR=… cmd`
(sonst lehnt sudos env-Policy die Variable ab und das Upgrade bricht ab).
- Frontend verschluckt password_required/incorrect_password nicht mehr still, sondern zeigt
einen klaren Hinweis (Box-Passwort in „Box-Zugang" setzen/pruefen).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Problem: ttyd auf :7682 war von aussen per ufw geblockt (nur 7681/9001 offen), also
im Browser Timeout — und ufw oeffnen braucht sudo, das MC2 hier nicht passwortlos hat.
Fix: ttyd bindet jetzt NUR an Loopback (--interface lo, --base-path /console) und wird
von MC2 ueber den ohnehin offenen Port 9001 same-origin durchgereicht:
- routers/console.py: HTTP-Passthrough (index/token) + WebSocket-Bridge (tty-Subprotokoll
auf beiden Seiten) → /console/ + /console/ws.
- app.py: console.router VOR dem SPA-Catch-all eingehaengt.
- config: BOX_CONSOLE_UPSTREAM (127.0.0.1:7682) + BOX_CONSOLE_PATH (/console/);
agent_status liefert box_console_url=/console/ + reachable=Upstream-Check.
- deploy/box-console.service: --interface lo --base-path /console.
- vite: /console (ws:true) fuer die Dev-Vorschau geproxyt.
Kein Firewall-/sudo-Eingriff noetig; Konsole laeuft same-origin zum Dashboard.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
voice_metrics.py: neben den rollenden Stats jetzt ein echter Per-Turn-Trace
(TurnTrace + Ringpuffer der letzten 60 Turns). Balken-Stufen zeitlich disjunkt
(stt · vision · hirn · gen); hirn misst ab mark_brain_start() VOR dem Hermes-
Request, damit die Vision-Zeit nicht doppelt gezaehlt wird. STT (davor) und
Mem0-Retrieve (Rueckruf waehrend) werden per park()/_take_* best-effort dem Turn
zugeordnet (Ein-Nutzer-Geraet, kein Turn-ID noetig). Mem0 = Unter-Detail INNERHALB
hirn (nicht addieren) -> ehrlich, kein Doppelzaehlen.
voice.py: TurnTrace in voice_chat's gen() (commit garantiert 1x via finally, auch
bei Fehler/Abbruch). STT-Endpoint parkt seine Dauer. NEU: GET /api/voice/metrics
(schliesst die Luecke - selbstkritik-feed.sh curlte das, existierte nie -> 404) +
GET /api/voice/trace?limit=N.
memory.py: GET /api/memory?q=... (= Hermes' Mem0-Prefetch) misst + parkt die
Retrieve-Zeit.
Frontend: LatencyCard (gestapelte Balken je Turn, "Taeter" = groesste Stufe,
Fehler-Turns rot, Tooltip mit "davon Mem0 X s"), Query useVoiceTrace, in der
Zentrale unter "Stack & Telemetrie". Lokal gegen Seed-Server verifiziert: 30,3-s-
Haenger -> Hirn-Balken 94% + "davon Mem0 26,1 s".
Grenzen (ehrlich, als Fussnote in der Karte): Tool-Runden im Hermes-LLM-Loop haben
keinen Callback an MC2 -> stecken in "Antwort". Reine Telegram-Text-Turns laufen an
MC2 vorbei und erscheinen hier nicht.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
f) Lucy/Voice-Reste aus dem MC2-Web-UI entfernt (kein "Sprechen"-Tab mehr):
VoiceLatencyCard + Sprach-Latenz-Plumbing (queries/api-Typen) und der
Backend-Leseendpoint /voice/metrics raus. Der Proaktivität-/Alarm-Kanal
(/voice/announce, /alarm) und die STT/TTS/chat-Proxys bleiben unberührt.
C15) README auf den Final-/Autonomie-Stand aktualisiert (Mem0 statt SQLite-MCP,
live+eingefroren, Lucy als eigenes Repo, Fangnetz-Updates/Werkstatt).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der ServicesCard-"Anzeige- statt Unit-Name"-Bug ist behoben (Frontend nutzt
durchgehend x.unit). Der echte Rest-Fehler lag in der ZWEITEN Restart-Wahrheit:
/api/system/restart (system.py) + das MCP-Tool restart_service hatten eine
veraltete Allowlist ohne llama-swap (Engine) und hermes-terminal, dafuer mit
Geist-Eintrag hermes-webui. Ein Engine-Neustart per Sprache/MCP schlug daher mit
"nicht erlaubt" fehl.
Fix: /api/system/restart delegiert jetzt an services.maintenance.restart_service
(EINE Allowlist-Wahrheit, kennt System- via sudo -n UND User-Dienste, wird auch
von der UI genutzt). MCP-Tool-Docstring auf die echten Dienste korrigiert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- /api/alarm: Lucy-unabhaengiger Telegram-Weg (fuer den PC-Lucy-Watchdog, wenn die App haengt).
- self-smoke.sh + mc2-selfsmoke.timer (taeglich 07:15): Gateway/Tools/Voice aktiv durchspielen,
Meldung nur bei Rot. Ergaenzt den passiven Health-Waechter um echte Funktion.
- self-repair.sh + autoupdate.sh: bei rotem Hermes-Update zieht die Box Config-Brueche selbst
(nur eindeutige, nicht-sicherheitsrelevante Keys; Backup -> YAML-Check -> Gehirn-Check, sonst
zurueck). Greift es nicht, haengt eine LLM-Diagnose an die Rollback-Meldung.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- services/announce.py: persistenter Briefkasten (/srv/models/mc2-announce.json),
POST /api/voice/announce + GET /api/voice/announcements (Cursor-Polling)
- services/sentry.py: Health-Wächter (Engine/Hirn/Hermes/Mem0/Voice/Platte),
flankenerkannt (Alarm nach 3 Fehl-Ticks, Entwarnung, 6h-Erinnerung),
meldet in Briefkasten + Telegram; Hirn-Verdrängung durch IDE-Last = kein Alarm
- notify.sh spiegelt jede Telegram-Meldung in den Briefkasten (Updates/Radar
erreichen damit auch die Desktop-Lucy)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1) /v1-Gateway haengt an jede Chat-Anfrage (ausser hermes/Lucy — SOUL.md
regelt das selbst) eine System-Direktive an: Antworten auf Deutsch,
Code/Bezeichner unveraendert. Abschaltbar via MC_GATEWAY_LANG_DIRECTIVE="".
2) mcp_web.py: neues Tool web_search (ddgs/DuckDuckGo, kein Key), Ergebnis
injection-geschuetzt via wrap_untrusted. Damit koennen IDE-Agents (Zed
via context_servers) und Hermes im Web suchen; Debug-Log geht auf stderr,
stdout bleibt MCP-sauber (verifiziert).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Das Frontend schickte den Anzeigenamen (z.B. 'Engine (llama-swap)')
an die Restart-API, die aber systemd-Unit-Namen (z.B. 'llama-swap')
erwartet. Backend gibt jetzt ein 'unit'-Feld mit; Frontend nutzt es
für restart(), disabled und key.
Radar-Erstlauf-Lehre: Hermes-Subagents fanden keine Kontextlaenge (llama-swap listet
nur kanonische Namen, ohne Metadaten), nahmen 256k an und rissen mit ihren max_tokens
den Server-Kontext. Gateway blendet jetzt Rollen-Aliase als Eintraege ein und liefert
context_length aus der geparsten llama-swap-Config. Delegation per hermes config auf
Verdikt gesetzt (max_concurrent_children 2, max_spawn_depth 1). Radar-Prompt: Fallback
"sequenziell selbst recherchieren, Report muss IMMER kommen".
Erstlauf-Ergebnis: Report wurde an Telegram zugestellt (Last run ok).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>