phase1a: Box-Diaet - schlafende Dienste, Sonntags-Update als Timer, tote Skills raus, Warm-Set nur Hirn
Ampel / ampel (push) Successful in 26s
Ampel / ampel (push) Successful in 26s
- Waechter und Dienste-Liste kennen "schlaeft": abgeschaltete Units (disable --now) sind kein Befund mehr; die Oberflaeche zeigt sie grau mit Knopf "Wecken" (fuer die Android-App spaeter). - Updates am Sonntag laufen wieder ueber mc2-autoupdate.timer (jobs/sonntags-update.sh) statt als Hermes-Cron, der sich beim Hermes-Update selbst neu startete (20.09.: 180 s, Fehlschlag). Flugplan und Waechter kennen den Timer. - 10 abgeloeste Skills (Werkstatt, Kanban, Orchestrator, Trend-Radar ...) aus dem Repo; deploy.sh verschiebt sie in ~/.hermes/skills-archiv statt sie weiter zu Lucy zu kopieren. - Embedding und Reranker schlafen: raus aus brains und Warm-Set, ttl 300, warmup.sh waermt sie nicht mehr vor. deploy.sh spielt Timer und Warm-Set-Drop-in selbst aus. - Dienste-Namen: "Box-Wart (MC2)", "Hermes-Dashboard", "Spracherkennung (Desktop-Lucy)". - Frontend neu gebaut (npm ci, lokale Pakete waren vom 28.08.). Tests: 87 gruen (neu: schlafende Dienste), Frontend Lint/Tests/Build gruen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
648be33d21
commit
45b5bf275c
@@ -14,7 +14,7 @@ from config import GATEWAY_URL, HERMES_API_URL, LLAMA_SWAP_URL, V1_UPSTREAM, VOI
|
||||
from fastapi import APIRouter
|
||||
from pydantic import BaseModel
|
||||
from services import backup as backup_svc
|
||||
from services import maintenance
|
||||
from services import maintenance, waechter
|
||||
from services.agent import agent_status
|
||||
from services.gateway import gateway_reachable
|
||||
from services.llamaswap import engine_reachable, list_models
|
||||
@@ -80,7 +80,7 @@ def services() -> dict:
|
||||
"ok": gateway_reachable(), "scope": "user"})
|
||||
# MC2 selbst antwortet gerade auf diesen Request — ok=True ist hier ehrlich;
|
||||
# die Zeile existiert für Restart/Logs, nicht als Erreichbarkeits-Orakel.
|
||||
rows.append({"name": "Steuerpult (MC2)", "unit": "mission-control-2", "url": gw_url,
|
||||
rows.append({"name": "Box-Wart (MC2)", "unit": "mission-control-2", "url": gw_url,
|
||||
"ok": True, "scope": "user"})
|
||||
else:
|
||||
rows.append({"name": "Gateway (integriert)", "unit": "mission-control-2", "url": gw_url,
|
||||
@@ -90,15 +90,20 @@ def services() -> dict:
|
||||
"ok": _user_unit_active("mc2-steward"), "scope": "user"},
|
||||
{"name": "Hermes-Gateway (Agent & Gedächtnis)", "unit": "hermes-gateway", "url": HERMES_API_URL,
|
||||
"ok": a["gateway_reachable"], "scope": "user"},
|
||||
{"name": "Hermes-GUI (Desktop-Gateway)", "unit": "hermes-builtin-ui", "url": a["hermes_ui_url"],
|
||||
{"name": "Hermes-Dashboard", "unit": "hermes-builtin-ui", "url": a["hermes_ui_url"],
|
||||
"ok": a["hermes_ui_reachable"], "scope": "user"},
|
||||
{"name": "Voice (STT/TTS)", "unit": "voice-service", "url": VOICE_SERVICE_URL,
|
||||
{"name": "Spracherkennung (Desktop-Lucy)", "unit": "voice-service", "url": VOICE_SERVICE_URL,
|
||||
"ok": _voice_reachable(), "scope": "user"},
|
||||
# Lucys Stimme (pocket-tts) spricht Telegram und Lucy-Desktop — bis 09/2026 fehlte
|
||||
# sie hier; die Box-Konsole ist mit dem Box-Wart-Umbau aus MC2 raus.
|
||||
{"name": "Lucys Stimme", "unit": "lucy-stimme", "url": "",
|
||||
"ok": _user_unit_active("lucy-stimme"), "scope": "user"},
|
||||
]
|
||||
# Bewusst abgeschaltete Dienste (24.09.2026: Spracherkennung bis zur Android-App) sind kein
|
||||
# Fehler — die Oberfläche zeigt sie als „schläft“ mit Knopf zum Wecken statt rot.
|
||||
for row in rows:
|
||||
row["schlaeft"] = (not row["ok"] and row["scope"] == "user"
|
||||
and waechter.schlaeft(waechter.dienst_zustand(row["unit"])))
|
||||
return {
|
||||
"services": rows,
|
||||
"links": {
|
||||
|
||||
@@ -74,7 +74,7 @@ DIENSTE: dict[str, tuple[bool, bool, str]] = {
|
||||
"hermes-gateway": (False, True, "Hermes"),
|
||||
"mc2-gateway": (False, True, "Modell-Gateway"),
|
||||
"mission-control-2": (False, True, "MC2"),
|
||||
"voice-service": (False, False, "Hör-Dienst"),
|
||||
"voice-service": (False, False, "Spracherkennung"),
|
||||
"lucy-stimme": (False, False, "Lucys Stimme"),
|
||||
"hermes-builtin-ui": (False, False, "Hermes-Dashboard"),
|
||||
}
|
||||
@@ -86,6 +86,8 @@ TIMER_DIENSTE: dict[str, tuple[str, bool]] = {
|
||||
"mc2-radar": ("Modell-Radar", False),
|
||||
# Rot: scheitert sie, erfährst du nichts von dem, was nachts passiert ist.
|
||||
"mc2-morgenmeldung": ("Morgenmeldung", True),
|
||||
# Seit 24.09.2026 ein eigener Timer statt Hermes-Cron (Hermes startet sich beim Update selbst neu).
|
||||
"mc2-autoupdate": ("Updates am Sonntag", True),
|
||||
}
|
||||
|
||||
HERMES_JOBS_PATH = HERMES_HOME / "cron" / "jobs.json"
|
||||
@@ -119,7 +121,7 @@ def _systemctl_show(name: str, system: bool) -> dict[str, str]:
|
||||
"""Zustand einer Unit. Auf Windows (Dev) oder ohne systemd: leeres Dict (harmlos)."""
|
||||
cmd = ["systemctl"] if system else ["systemctl", "--user"]
|
||||
cmd += ["show", name, "-p",
|
||||
"LoadState,ActiveState,SubState,Result,ExecMainStatus,InactiveExitTimestamp"]
|
||||
"LoadState,ActiveState,SubState,Result,ExecMainStatus,InactiveExitTimestamp,UnitFileState"]
|
||||
try:
|
||||
out = subprocess.run(cmd, capture_output=True, text=True, timeout=10).stdout
|
||||
except Exception:
|
||||
@@ -178,6 +180,17 @@ def _update_laeuft() -> bool:
|
||||
|
||||
# --- Prüfungen ------------------------------------------------------------------
|
||||
|
||||
def dienst_zustand(name: str, system: bool = False) -> dict[str, str]:
|
||||
"""systemd-Zustand einer Unit für andere Module (Dienste-Liste der Oberfläche)."""
|
||||
return _systemctl_show(name, system)
|
||||
|
||||
|
||||
def schlaeft(zustand: dict[str, str]) -> bool:
|
||||
"""Abgeschaltet und nicht mehr für den Autostart eingetragen = bewusst schlafen gelegt
|
||||
(24.09.2026: Konsole, Spracherkennung). Das ist kein Fehler; geweckt wird per Knopf."""
|
||||
return zustand.get("ActiveState") == "inactive" and zustand.get("UnitFileState") == "disabled"
|
||||
|
||||
|
||||
def pruefe_dienste() -> list[Befund]:
|
||||
befunde: list[Befund] = []
|
||||
for name, (system, wichtig, anzeige) in DIENSTE.items():
|
||||
@@ -187,6 +200,8 @@ def pruefe_dienste() -> list[Befund]:
|
||||
zustand = z.get("ActiveState", "")
|
||||
if zustand in ("active", "activating", "reloading", "deactivating"):
|
||||
continue
|
||||
if schlaeft(z):
|
||||
continue # bewusst schlafen gelegt (disable --now), z. B. die Spracherkennung bis zur App
|
||||
stufe = "rot" if wichtig else "gelb"
|
||||
aktionen = [_aktion("neustart", "Neu starten", dienst=name), _aktion("protokoll", "Protokoll", dienst=name)]
|
||||
if zustand == "failed":
|
||||
|
||||
@@ -15,7 +15,7 @@ from zoneinfo import ZoneInfo
|
||||
from services import modell_nutzung, waechter
|
||||
|
||||
TIMER = {"mc2-backup.timer": "Sicherung", "mc2-radar.timer": "Modell-Radar",
|
||||
"mc2-morgenmeldung.timer": "Morgenmeldung"}
|
||||
"mc2-morgenmeldung.timer": "Morgenmeldung", "mc2-autoupdate.timer": "Updates am Sonntag"}
|
||||
LOCAL_TZ = ZoneInfo(os.environ.get("MC_LOCAL_TZ", "Europe/Berlin"))
|
||||
|
||||
|
||||
|
||||
@@ -104,3 +104,19 @@ def test_befunde_werden_erst_nach_fail_after_takten_zum_hinweis(monkeypatch, tmp
|
||||
|
||||
stand = waechter.lese_stand()
|
||||
assert stand["aktiv"] is True and stand["hinweise"] == []
|
||||
|
||||
|
||||
def test_schlafende_dienste_sind_kein_befund(monkeypatch):
|
||||
"""24.09.2026: Spracherkennung und Konsole sind bewusst abgeschaltet (disable --now) — kein Alarm.
|
||||
Ein gestoppter, aber noch eingetragener Dienst bleibt dagegen ein Hinweis."""
|
||||
zustaende = {
|
||||
"voice-service": {"LoadState": "loaded", "ActiveState": "inactive", "UnitFileState": "disabled"},
|
||||
"lucy-stimme": {"LoadState": "loaded", "ActiveState": "inactive", "UnitFileState": "enabled"},
|
||||
}
|
||||
monkeypatch.setattr(waechter, "_systemctl_show",
|
||||
lambda name, system: zustaende.get(name, {"LoadState": "loaded", "ActiveState": "active"}))
|
||||
ids = {b.id for b in waechter.pruefe_dienste()}
|
||||
assert "dienst:voice-service" not in ids
|
||||
assert "dienst:lucy-stimme" in ids
|
||||
assert waechter.schlaeft(zustaende["voice-service"]) is True
|
||||
assert waechter.schlaeft({"ActiveState": "failed", "UnitFileState": "disabled"}) is False
|
||||
|
||||
+17
-1
@@ -53,8 +53,12 @@ main() {
|
||||
install -m 644 deploy/mc2-radar.service deploy/mc2-radar.timer "$HOME/.config/systemd/user/"
|
||||
# Morgenmeldung (24.09.2026): schickt um 07:00, was notify.sh nachts gesammelt hat.
|
||||
install -m 644 deploy/mc2-morgenmeldung.service deploy/mc2-morgenmeldung.timer "$HOME/.config/systemd/user/"
|
||||
# Updates am Sonntag (24.09.2026): eigener Timer statt Hermes-Cron.
|
||||
install -m 644 deploy/mc2-autoupdate.service deploy/mc2-autoupdate.timer "$HOME/.config/systemd/user/"
|
||||
# Warm-Set des Wächters (24.09.2026: nur noch das Hirn).
|
||||
install -D -m 644 deploy/mc2-steward.service.d-warmset.conf "$HOME/.config/systemd/user/mc2-steward.service.d/warmset.conf"
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable --now mc2-radar.timer mc2-morgenmeldung.timer
|
||||
systemctl --user enable --now mc2-radar.timer mc2-morgenmeldung.timer mc2-autoupdate.timer
|
||||
|
||||
# 4.5 Hermes Skills synchronisieren
|
||||
echo "Synchronisiere Hermes Skills..."
|
||||
@@ -67,6 +71,18 @@ main() {
|
||||
cp -r "$skill_dir"/* ~/.hermes/skills/"$skill_name"/
|
||||
fi
|
||||
done
|
||||
# Abgelöste Skills (24.09.2026) aus Lucys Skill-Index nehmen: verschoben nach
|
||||
# ~/.hermes/skills-archiv, nicht gelöscht. Dazu die alten Bindestrich-Doppel der übrigen Skills
|
||||
# (deploy.sh schreibt seit jeher die Unterstrich-Fassung).
|
||||
for alt in autonomie konzept-fliessband llm-wiki morning-report orchestrator projekt-start \
|
||||
pruefstand review trend-radar wartung konzept_fliessband llm_wiki morning_report \
|
||||
projekt_start trend_radar betrieb-playbook pc-pfad-cache; do
|
||||
if [ -d ~/.hermes/skills/"$alt" ]; then
|
||||
mkdir -p ~/.hermes/skills-archiv
|
||||
rm -rf ~/.hermes/skills-archiv/"$alt"
|
||||
mv ~/.hermes/skills/"$alt" ~/.hermes/skills-archiv/
|
||||
fi
|
||||
done
|
||||
|
||||
# 4.6 Hermes-Plugins aus dem Repo (09/2026: mc2-web-lesen, Seiten lokal lesen für web_extract).
|
||||
# Nur kopieren: Aktiviert wird ein Plugin einmalig von Hand (hermes plugins enable …), und neuer
|
||||
|
||||
@@ -7,13 +7,11 @@
|
||||
# Selbst-Pinnung. Es meldet auch schon selbst ueber notify.sh, also Telegram
|
||||
# UND Lucys Stimme.
|
||||
#
|
||||
# Dieser Aufsatz existiert nur, damit der Job unter `hermes cron list` steht
|
||||
# statt in einem separaten systemd-Timer. Ein Ort fuer alle Automatik — genau
|
||||
# deshalb ist am 20.08. tagelang niemandem aufgefallen, dass ein Waechter fehlte.
|
||||
#
|
||||
# Aufruf ueber Hermes-Cron:
|
||||
# hermes cron create '30 4 * * 0' --name 'Updates am Sonntag' \
|
||||
# --no-agent --script sonntags-update.sh --deliver local
|
||||
# Aufruf seit 24.09.2026 ueber mc2-autoupdate.timer (So 04:30) statt Hermes-Cron:
|
||||
# Als Kind des Hermes-Gateways hing der Lauf beim Hermes-Update am eigenen
|
||||
# Gateway-Neustart (20.09.: 180 s, als Fehlschlag beendet). Den einen Ort fuer
|
||||
# alle Automatik gibt es trotzdem: Der Flugplan im Cockpit zeigt Timer und
|
||||
# Hermes-Jobs zusammen, und der Waechter meldet gescheiterte Timer-Laeufe.
|
||||
set -uo pipefail
|
||||
|
||||
AUTOUPDATE="${AUTOUPDATE:-$HOME/mission-control-v2/deploy/autoupdate.sh}"
|
||||
|
||||
@@ -100,7 +100,8 @@ models:
|
||||
Qwen3-Embedding-0.6B:
|
||||
cmd: |
|
||||
llama-server -m /srv/models/Qwen3-Embedding-0.6B-GGUF/Qwen3-Embedding-0.6B-Q8_0.gguf --host 127.0.0.1 --port ${PORT} --embedding --pooling last -ngl 999 -fa on --load-mode none -c 8192
|
||||
ttl: 0
|
||||
# 24.09.2026: schläft (nicht mehr im Warm-Set) — lädt bei Bedarf, geht nach 5 Minuten wieder raus.
|
||||
ttl: 300
|
||||
aliases:
|
||||
- embed
|
||||
gpt-oss-120b:
|
||||
@@ -128,10 +129,11 @@ models:
|
||||
Qwen3-Reranker-0.6B:
|
||||
# Gedächtnis-Zweitstufe (07.07., Rollen-Audit): ordnet Gedächtnis-Suchtreffer nach echter
|
||||
# Relevanz (/v1/rerank, Mungert-GGUF — Community-Konvertierungen liefern oft Nullscores!).
|
||||
# Winzig (~0,7 GB) → in brains (verdrängungssicher); lädt in ~1-2 s, erste Anfrage wärmt.
|
||||
# Winzig (~0,7 GB), lädt in ~1-2 s. 24.09.2026: schläft (nicht mehr im Warm-Set, ohne Verbraucher
|
||||
# seit dem Mem0-Ausbau) — lädt bei Bedarf, geht nach 5 Minuten wieder raus.
|
||||
cmd: |
|
||||
llama-server -m /srv/models/Qwen3-Reranker-0.6B-GGUF/Qwen3-Reranker-0.6B-q8_0.gguf --host 127.0.0.1 --port ${PORT} --reranking --pooling rank --embedding -ngl 999 -fa on --load-mode none -c 8192
|
||||
ttl: 0
|
||||
ttl: 300
|
||||
aliases:
|
||||
- reranker
|
||||
groups:
|
||||
@@ -145,9 +147,9 @@ groups:
|
||||
# Hirn entlud den Coder (und die Bild-Zwillinge). Für OpenChamber hieß das: Lucy fragt etwas, der Coder
|
||||
# fliegt raus, die nächste Coding-Anfrage lädt ihn neu und rechnet den ganzen Vorlauf nach. Live gemessen.
|
||||
exclusive: false
|
||||
# 24.09.2026: nur noch das Hirn. Embedding und Reranker schlafen (User-Entscheid, seit dem
|
||||
# Mem0-Ausbau ohne Verbraucher) — sie laden bei Bedarf und gehen nach 5 Minuten wieder raus.
|
||||
members:
|
||||
- Qwen3-Embedding-0.6B
|
||||
- Qwen3-Reranker-0.6B
|
||||
- Qwen3.6-35B-A3B
|
||||
bild:
|
||||
# 24.09.2026: die Bild-Zwillinge von Hirn und Coder. swap: true = höchstens einer von beiden geladen;
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
[Unit]
|
||||
Description=MC2 Auto-Update (Router/Engine/Hermes mit Rollback+Pin, Telegram-Meldung)
|
||||
Documentation=file:%h/mission-control-v2/docs/AUTONOMIE_PLAN.md
|
||||
After=mc2-backup.service
|
||||
Description=MC2 Updates am Sonntag (llama-swap, Engine, Hermes mit Rollback und Festhalten)
|
||||
Documentation=file:%h/mission-control-v2/deploy/jobs/README.md
|
||||
After=mc2-backup.service network-online.target
|
||||
|
||||
# Seit 24.09.2026 wieder ein eigener Timer statt Hermes-Cron: Als Kind des Hermes-Gateways hing der
|
||||
# Lauf beim Hermes-Update am eigenen Gateway-Neustart (20.09.: 180 s, als Fehlschlag beendet).
|
||||
# sonntags-update.sh meldet einen Abbruch selbst per Telegram.
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/bash %h/mission-control-v2/deploy/autoupdate.sh
|
||||
ExecStart=/bin/bash %h/mission-control-v2/deploy/jobs/sonntags-update.sh
|
||||
TimeoutStartSec=3h
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
# Drop-in für mc2-steward.service — Ablage auf der Box:
|
||||
# ~/.config/systemd/user/mc2-steward.service.d/warmset.conf
|
||||
#
|
||||
# 26.07.2026 — Ko-Residenz ist nicht Warm-Pflicht. Die Gruppe `brains` enthaelt seit dem
|
||||
# Umbau auch Modelle MIT TTL (Coder 90 min, Kritiker 30 min); ohne diese Liste hielte der
|
||||
# Waechter sie faelschlich fuer dauerhaft faellig und arbeitete gegen die TTLs.
|
||||
# ANFUEHRUNGSZEICHEN SIND PFLICHT: systemd trennt Environment= an Leerzeichen, ohne sie
|
||||
# kommt nur das erste Modell an (live erlebt) — das Warm-Ziel waere still zu klein.
|
||||
# 26.07.2026 — Ko-Residenz ist nicht Warm-Pflicht. Die Gruppe `brains` kann auch Modelle MIT TTL
|
||||
# enthalten; ohne diese Liste hielte der Waechter sie faelschlich fuer dauerhaft faellig.
|
||||
# 24.09.2026 — Embedding und Reranker schlafen (User-Entscheid, seit dem Mem0-Ausbau ohne
|
||||
# Verbraucher): warm gehalten wird nur noch das Hirn.
|
||||
# ANFUEHRUNGSZEICHEN SIND PFLICHT, sobald mehrere Modelle drinstehen: systemd trennt Environment=
|
||||
# an Leerzeichen, ohne sie kommt nur das erste Modell an (live erlebt).
|
||||
# Das Modell-Radar schreibt die Zeile beim Uebernehmen eines neuen Hirns selbst um.
|
||||
[Service]
|
||||
Environment="MC_WARMSET=Qwen3-Embedding-0.6B Qwen3-Reranker-0.6B Qwen3.6-35B-A3B"
|
||||
Environment=MC_WARMUP_RERANK=reranker
|
||||
Environment="MC_WARMSET=Qwen3.6-35B-A3B"
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
---
|
||||
name: autonomie
|
||||
description: "Gesundheitsprüfungen der Box: Überprüft Logs (Syslog, Journalctl), checkt ob alle Container/Dienste laufen und leitet bei Bedarf selbstständige Reparaturen ein. Meldet Status via Telegram."
|
||||
version: 1.0.0
|
||||
author: MC2
|
||||
platforms: [linux]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [wartung, autonomie, health, mc2]
|
||||
---
|
||||
|
||||
# Autonomie & Self-Repair
|
||||
|
||||
Dieser Skill ermöglicht es der AI-Box, sich selbst zu überprüfen und bei Problemen zu reparieren.
|
||||
|
||||
## Ablauf
|
||||
1. **Dienste prüfen**: Führt `systemctl --user status` für alle relevanten MC2-Dienste aus.
|
||||
2. **Logs analysieren**: Prüft die letzten Fehler im `journalctl` (User und System-Ebene, falls Berechtigung vorhanden).
|
||||
3. **Selbstreparatur (Self-Repair)**: Falls bekannte Fehler auftauchen (z.B. Deadlocks, Speicherprobleme, hängende Ports), wird ein definierter Wiederanlauf (z.B. Neustart des Dienstes via `systemctl --user restart`) getriggert.
|
||||
4. **Meldung**: Das finale Ergebnis wird kompakt an den Commander via Telegram (über `deploy/notify.sh`) gesendet.
|
||||
@@ -1,225 +0,0 @@
|
||||
---
|
||||
name: konzept-fliessband
|
||||
description: "Erarbeitet eine rohe Idee durch mehrere Fach-Rollen bis WASSERDICHT — BEVOR gebaut wird, KEIN Code. Der starke Denker (heavy/gpt-oss-120b) waehlt den passenden Rollen-Cast, die Rollen schaerfen ein gemeinsames Konzept in Runden, ein Advocatus Diaboli (fremdes Modell) sucht Loecher, bis keine Blocker mehr offen sind (max 3 Runden). Ergebnis: EIN fertiges Konzept-Dokument, das der Commander in Hermes Desktop dem Coder vorwirft. Nutzen bei: 'erarbeite/entwickle ein Konzept', 'arbeite die Idee aus', 'wasserdichtes Konzept fuer App/Spiel/Tool', 'denk dir X aus bevor wir bauen', 'lass mehrere Experten/Rollen drueberschauen', 'mach das Konzept rund'. NICHT fuer Code-Bau (das ist projekt-start/orchestrator)."
|
||||
version: 1.0.0
|
||||
author: MC2 (Konzept-Fliessband 14.07.2026 — heavy denkt, Skeptiker haertet, propose-only)
|
||||
platforms: [linux]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [konzept, denken, mehrrollen, heavy, wasserdicht, vor-code]
|
||||
---
|
||||
|
||||
# Konzept-Fliessband — haerten bis wasserdicht, BEVOR gebaut wird
|
||||
|
||||
Nutze diesen Skill, wenn der Commander eine **Idee** hat, die erst als **Konzept** rundgedacht
|
||||
werden soll — nicht sofort gebaut. Du bist der **Manager**: du holst die tagesaktuelle Recherche,
|
||||
laesst den starken Denker (**heavy**) den passenden **Rollen-Cast** waehlen, moderierst mehrere
|
||||
**Denk-Runden**, in denen die Rollen das Konzept schaerfen, laesst einen **Advocatus Diaboli**
|
||||
(fremdes Modell) nach Loechern suchen — und lieferst am Ende **EIN wasserdichtes
|
||||
Konzept-Dokument**. Der Commander nimmt das Dokument und startet damit in Hermes Desktop ein
|
||||
Projekt; DORT baut der Coder. Hier wird **kein Code geschrieben**.
|
||||
|
||||
## Abgrenzung — wann DIESER Skill, wann ein anderer
|
||||
- **konzept-fliessband (hier):** rohe Idee → wasserdichtes **Konzept** (Text). Vor dem Bauen. KEIN Code.
|
||||
- **projekt-start:** das fertige Konzept → in Hermes Desktop planen + **bauen** (Coder). Danach.
|
||||
- **orchestrator:** einen Code-Auftrag zerlegen + an Worker delegieren. Nicht fuers Konzept-Denken.
|
||||
|
||||
> **Uebergabe:** Das Konzept-Dokument von hier ist exakt der Input, den `projekt-start` in Phase 1
|
||||
> als Vorlage will. Sag das dem Commander in der Uebergabe.
|
||||
|
||||
## Warum seriell (Box-Physik, ehrlich ansagen)
|
||||
Nur EIN grosses Modell passt in den Speicher. Die Rollen reden **nicht wirklich gleichzeitig** —
|
||||
DU moderierst Runden und traegst jede Stimme ins gemeinsame **lebende Konzept-Dokument**. Ergebnis
|
||||
ist echtes Aufeinander-Aufbauen, nur seriell statt Schwarm. **Minimiere Modell-Wechsel:** alle
|
||||
heavy-Rollen einer Runde am Stueck (heavy bleibt warm), DANN der Skeptiker (ein Swap zu GLM).
|
||||
|
||||
## Leitplanken (nicht verhandelbar)
|
||||
- **Jede Rollen-Stimme MUSS aus einem `worker.sh`-Aufruf an heavy stammen.** Denkst du dir die
|
||||
Beitraege selbst aus (statt heavy zu rufen), ist der Lauf GESCHEITERT — sag das ehrlich, statt
|
||||
Eigenbau als Mehr-Rollen-Arbeit auszugeben. **NIE `delegate_task` benutzen:** das laeuft ueber
|
||||
`delegation.model: coder` (ein Code-Modell, schwacher Generalist) und kann heavy gar nicht
|
||||
waehlen — genau der Fehler, den dieser Skill behebt. Beleg jede Rolle mit ihrem `worker.sh`-Aufruf
|
||||
UND den ersten Zeilen ihrer Roh-Ausgabe.
|
||||
- **heavy = `gpt-oss-120b` ist der Denker.** Sein Kaltladen (~28 s) setzt Lucys Sprech-Latenz kurz
|
||||
aus — fuer diesen Hintergrund-Job gewollt. heavy hat nur **32k Kontext** → halte das Konzept-
|
||||
Dokument kompakt und schleppe KEINE alten Runden-Protokolle mit (siehe Kontext-Uebergabe).
|
||||
- **REASONING-MODELLE brauchen Token-Luft (verifiziert 14.07.).** heavy (gpt-oss) UND der Skeptiker
|
||||
(`fast`) „denken" erst ausfuehrlich (im `reasoning_content`), bevor die eigentliche Antwort
|
||||
in `content` landet — `worker.sh`/`fremdblick.sh` lesen NUR `content`. Zu knappes `max_tokens` =
|
||||
das Modell verbraucht alles beim Denken, `content` bleibt LEER, das Skript meldet „FEHLGESCHLAGEN"
|
||||
(obwohl das Modell lief). GLM verbrennt real ~2000 Tokens Denken fuer 2 Zeilen Antwort. Deshalb
|
||||
IMMER grosszuegig: heavy-Aufrufe mit `WORKER_MAXTOK=6000`, den Skeptiker mit `FREMDBLICK_MAXTOK=4000`.
|
||||
Bekommst du trotzdem leeren `content` → Budget erhoehen und erneut rufen, NICHT selbst schreiben.
|
||||
- **Erster heavy-Aufruf laedt 60 GB kalt.** Rechne beim allerersten `worker.sh`-Aufruf einer Runde
|
||||
mit ~30 s Stille (Laden), bevor Text kommt — das ist KEIN Fehlschlag. Meldet der ERSTE heavy-Aufruf
|
||||
`FEHLGESCHLAGEN (finish=keins)`, ist das meist eine transiente Kaltstart-Kollision mit dem Warm-Set
|
||||
→ **einmal wiederholen** (beim zweiten Mal ist heavy geladen und antwortet). Scheitert es auch dann,
|
||||
ehrlich melden statt selbst zu schreiben.
|
||||
- **Der Skeptiker ist ein FREMDES Modell** (`fremdblick.sh`, GLM). Wer seine eigene Idee benotet,
|
||||
findet keine Loecher — der Advocatus Diaboli MUSS ein anderes Modell sein als der Denker.
|
||||
- **Aufwand zur Projektgroesse skalieren — nicht mit Kanonen auf Spatzen (WICHTIG).** Jeder
|
||||
heavy-Aufruf kostet auf dieser lokalen HW ~1 Min. Ein Mini-/Ein-Feature-Projekt (kleines Tool,
|
||||
ein Spiel-Prototyp, eine klar umrissene App) braucht KEINE volle Kaskade. Richtwerte:
|
||||
- **Klein / klar umrissen:** 2 Rollen, **1 Denk-Runde** + 1 Haertetest. Ist der Skeptiker danach
|
||||
zufrieden (WASSERDICHT), ist Schluss — keine zweite Runde erzwingen.
|
||||
- **Mittel:** 3 Rollen, bis 2 Runden.
|
||||
- **Gross / ambitioniert / viele bewegliche Teile:** volle 3-5 Rollen, bis 3 Runden.
|
||||
Du schaetzt die Groesse aus Idee + Recherche selbst ein und sagst sie im Uebergabe-Text
|
||||
(„Umfang: klein → 1 Runde"). **Woran du „gross" erkennst:** mehrere Subsysteme, echte
|
||||
Architektur-Entscheidungen, ein Datenmodell, externe Integrationen, Mehrbenutzer/Rechte,
|
||||
Security-Flaeche. Bei offensichtlich Kleinem im Zweifel kleiner; **bei echter Ambition aber zur
|
||||
VOLLEN Tiefe** — ein zu flaches Konzept fuer ein grosses Projekt kostet den Commander spaeter
|
||||
teure Bau-Zeit (er baut auf einem wackligen Plan), das ist schlimmer als ein paar Minuten
|
||||
Box-Zeit zu viel.
|
||||
- **★ ZIEL-PLATTFORM + INFRASTRUKTUR aus dem Auftrag sind BINDEND.** Stehen im Auftrag Zeilen
|
||||
„ZIEL-PLATTFORM (vom Commander gewaehlt): LXC/DOCKER …" und/oder „INFRASTRUKTUR des Commanders:
|
||||
…", dann plane den Tech-Vorschlag (Abschnitt 6) GENAU dafuer — nicht nach Industrie-Default.
|
||||
Der Commander faehrt ein Heimlabor mit Proxmox/LXC, systemd-Diensten und self-hosted Gitea, alles
|
||||
lokal — „einfach mal Docker" ist bei ihm NICHT automatisch die einfachste Loesung. Die beiden
|
||||
Ziele sind sauber getrennt: **LXC** = Dienst im Proxmox-Container (systemd, PBS sichert mit);
|
||||
**DOCKER** = NATIVES Docker nach Standard-Praxis (Dockerfile, compose, portabel, ueber
|
||||
CI-Pipelines baubar) — dieses Projekt darf bewusst ausserhalb der LXC-Welt leben, also KEINE
|
||||
Misch-Konstrukte wie „Docker im LXC mit Nesting" vorschlagen. Traegt die gewaehlte Plattform fuer
|
||||
dieses Projekt nicht (noetige Komponente gibt es nur als Image o. ae.), sag das im Konzept
|
||||
AUSDRUECKLICH mit Begruendung — still ignorieren gilt nicht.
|
||||
- **★ Explizite Commander-Wahl UEBERSTIMMT deine Einschaetzung.** Steht im Auftrag eine Zeile
|
||||
„AUFWAND (vom Commander gewaehlt): SIMPEL …" bzw. „… GRUENDLICH …" (der Commander hat in der
|
||||
Ideen-Ansicht „IDE: simpel" oder „IDE: gruendlich" gewaehlt), dann HALTE DICH DARAN — SIMPEL =
|
||||
2 Rollen/1 Runde, GRUENDLICH = volle 3-5 Rollen/bis 3 Runden — auch wenn deine eigene
|
||||
Schaetzung anders ausfaellt. Nur wenn KEINE solche Zeile da ist, entscheidest du selbst.
|
||||
- **Max 3 Denk-Runden — keine Endlosschleife.** Nach der letzten Runde (je nach Groesse 1-3) kommt
|
||||
IMMER die Editor-Endfassung, auch wenn Rest-Punkte offen sind (die dann ehrlich als „offene
|
||||
Punkte" ins Dokument). **Frueher raus ist gut:** meldet der Skeptiker WASSERDICHT, sofort zur
|
||||
Endfassung — keine weitere Runde „zur Sicherheit".
|
||||
- **Kein Code, kein Repo, keine Dateien in einem Projekt.** Der EINZIGE Output ist ein
|
||||
Konzept-Dokument (Markdown) + eine Telegram-Uebergabe. NIE bauen, NIE `main`/Worktrees anfassen,
|
||||
NIE deployen.
|
||||
- **Ehrlich statt schoen.** Findet der Skeptiker echte Blocker, die in 3 Runden nicht loesbar sind,
|
||||
gehoeren sie als „ungeloest: …" ins Dokument — nicht wegreden.
|
||||
- **Security-Config ist TABU** (Tokens, approvals, ssh, sudoers) — hier ohnehin nichts zu suchen.
|
||||
|
||||
## Die Helfer EXISTIEREN
|
||||
`~/.hermes/scripts/worker.sh` und `~/.hermes/scripts/fremdblick.sh` sind installiert, aber NICHT auf
|
||||
dem PATH → immer mit vollem Pfad rufen. Glaubst du, sie fehlen, IRRST du dich: erst
|
||||
`ls -la ~/.hermes/scripts/worker.sh` ausfuehren, dann nutzen. „Skript fehlt" ist KEIN Grund, den
|
||||
Schritt selbst zu erledigen.
|
||||
|
||||
## Ablauf
|
||||
|
||||
### 0. Ablage + Recherche (DU, mit deinen eigenen Web-Tools)
|
||||
`worker.sh`/`fremdblick.sh` haben KEIN Web. Die **tagesaktuelle Recherche** machst DU selbst mit
|
||||
deinem web-fetch-Tool — das ist dein Job als Manager, nicht der der zustandslosen Worker.
|
||||
```bash
|
||||
slug=<kurzer-kebab-name-der-idee>
|
||||
mkdir -p /tmp/konzept-$slug
|
||||
```
|
||||
Recherchiere knapp: Was gibt es schon (Konkurrenz-Apps/-Produkte)? Was fehlt denen? Welche
|
||||
Technik/Trends sind 2026 relevant? Schreibe die Fakten (mit Quelle) nach
|
||||
`/tmp/konzept-$slug/recherche.md`. Kurz und belegt — kein Roman.
|
||||
|
||||
### 1. Rollen-Cast waehlen (heavy)
|
||||
heavy legt den passenden Cast fuer GENAU dieses Konzept fest (ein Spiel braucht andere Rollen als
|
||||
ein Produktivitaets-Tool). Der **Advocatus Diaboli ist immer dabei** — aber der ist der Skeptiker
|
||||
in Schritt 4 (fremdblick), NICHT eine der heavy-Rollen.
|
||||
```bash
|
||||
printf '%s' "IDEE:
|
||||
$idee
|
||||
|
||||
RECHERCHE:
|
||||
$(cat /tmp/konzept-$slug/recherche.md)
|
||||
|
||||
Nenne die passenden Fach-Rollen, die dieses Konzept am besten wasserdicht machen — 2 fuer ein kleines/klar umrissenes Projekt, 3 fuer ein mittleres, 4-5 nur fuer ein grosses/ambitioniertes. Lieber weniger, gute Rollen. Je Rolle: Name + ein Satz, worauf sie besonders achtet. Gib NUR die nummerierte Liste aus." \
|
||||
| WORKER_MODEL=gpt-oss-120b WORKER_ROLE=prose WORKER_MAXTOK=6000 ~/.hermes/scripts/worker.sh > /tmp/konzept-$slug/cast.txt
|
||||
cat /tmp/konzept-$slug/cast.txt
|
||||
```
|
||||
|
||||
### 2. Erstentwurf (heavy, Editor-Hut)
|
||||
heavy schreibt den ersten Konzept-Entwurf aus Idee + Recherche in der **Struktur aus Schritt 5**
|
||||
nach `/tmp/konzept-$slug/konzept.md` — das ist ab jetzt das **lebende Dokument** (die Wahrheit,
|
||||
nicht das Protokoll).
|
||||
|
||||
### 3. Denk-Runde (heavy, je Rolle EIN Aufruf, am Stueck)
|
||||
Fuer jede Rolle aus `cast.txt` ein heavy-Aufruf. Gib ihr das **aktuelle** `konzept.md`, ab Runde 2
|
||||
zusaetzlich die **offenen Blocker** aus dem letzten Haertetest, und die klare Anweisung, aus IHRER
|
||||
Sicht zu schaerfen UND zu kritisieren (nicht nur zu loben):
|
||||
```bash
|
||||
printf '%s' "Du bist die Rolle: <Rolle aus cast.txt>. Schaerfe und kritisiere das folgende Konzept AUS DEINER FACHSICHT: was ist schwach, unrealistisch, unklar, was fehlt? Nenne konkrete Verbesserungen, keine Hoeflichkeiten.
|
||||
|
||||
AKTUELLES KONZEPT:
|
||||
$(cat /tmp/konzept-$slug/konzept.md)
|
||||
|
||||
OFFENE BLOCKER (falls Runde >= 2):
|
||||
$(cat /tmp/konzept-$slug/haertetest-*.txt 2>/dev/null | tail -40)" \
|
||||
| WORKER_MODEL=gpt-oss-120b WORKER_ROLE=prose WORKER_MAXTOK=6000 ~/.hermes/scripts/worker.sh > /tmp/konzept-$slug/runde<n>-<rolle>.txt
|
||||
```
|
||||
Sammle die Beitraege und **webe sie ins `konzept.md` ein** — Widerspruecke aufloesen, verdichten,
|
||||
nicht bloss anhaengen. Halte das Dokument kompakt (heavy-32k-Limit).
|
||||
|
||||
### 4. Haertetest (Advocatus Diaboli = fremdblick, GLM)
|
||||
Ein FREMDES Modell sucht Loecher im aktuellen Konzept:
|
||||
```bash
|
||||
printf '%s' "$(cat /tmp/konzept-$slug/konzept.md)" \
|
||||
| FREMDBLICK_SYS='Du bist der Advocatus Diaboli und ausdruecklich ein ANDERES Modell als der Autor. Zerlege dieses Konzept schonungslos: ungeloeste Fragen, unrealistische Annahmen, Widersprueche, fehlende Bausteine, Dinge die in der Praxis scheitern. Liste je Punkt EINE Zeile, markiert mit BLOCKER: (muss geloest werden, sonst nicht baubar) oder HINWEIS: (verbessert es, kein Muss). Ist nichts Wesentliches mehr offen, antworte NUR mit dem Wort WASSERDICHT. Nicke nichts aus Hoeflichkeit durch, erfinde keine Fakten.' \
|
||||
FREMDBLICK_MAXTOK=4000 ~/.hermes/scripts/fremdblick.sh > /tmp/konzept-$slug/haertetest-<runde>.txt
|
||||
cat /tmp/konzept-$slug/haertetest-<runde>.txt
|
||||
```
|
||||
**Schleifen-Regel (hart, max 3 Runden):**
|
||||
- Antwort enthaelt `BLOCKER:` UND Runde < 3 → zurueck zu Schritt 3, die Blocker adressieren.
|
||||
- Antwort = `WASSERDICHT` (oder nur `HINWEIS:`) → weiter zu Schritt 5.
|
||||
- Runde 3 erreicht → weiter zu Schritt 5, egal was offen ist (offene Blocker kommen in Abschnitt 8).
|
||||
|
||||
### 5. Endfassung (heavy, Editor)
|
||||
heavy schreibt die finale, saubere Fassung nach dieser festen Struktur (ueberschreibt `konzept.md`):
|
||||
```
|
||||
# <Projektname> — Konzept
|
||||
1. Problem & Motivation (warum das ueberhaupt)
|
||||
2. Zielgruppe (fuer wen genau)
|
||||
3. Kern-Idee (ein Absatz, der es auf den Punkt bringt)
|
||||
4. Features (Muss / Kann / Spaeter)
|
||||
5. Mechaniken & Ablauf (wie es sich anfuehlt, der rote Faden)
|
||||
6. Tech-Vorschlag (Plattform, Stack — und ist das Box-/PC-tauglich?)
|
||||
7. UX-Flow (die 3-5 wichtigsten Screens/Schritte)
|
||||
8. Risiken & offene Punkte (ehrlich, inkl. ungeloester Blocker aus dem Haertetest)
|
||||
9. MVP-Schnitt (was ZUERST gebaut wird — der spaetere Coder-Auftrag)
|
||||
```
|
||||
Dann eine Kopie an den Abhol-Ort:
|
||||
```bash
|
||||
mkdir -p ~/konzepte && cp /tmp/konzept-$slug/konzept.md ~/konzepte/$slug-konzept.md
|
||||
```
|
||||
|
||||
> **Arbeitest du an einer Kanban-Karte, sind Schritt 5-Kopie und Schritt 6 NICHT dein Ende.**
|
||||
> Die Ablage- und Uebergabe-Wege deiner Rolle (Profil-SOUL) gelten — z. B. `projektstart`:
|
||||
> Konzept ins **Repo** als `KONZEPT.md`, dann `kanban_complete`. Die Kopie nach `~/konzepte/`
|
||||
> ist dann nur ein Zweitablage-Ort, kein Abschluss. Nur ohne Karte (direkter Zuruf) endet
|
||||
> das Fliessband hier mit Schritt 6.
|
||||
|
||||
### 6. Uebergabe (Telegram, in LUCYS Stimme)
|
||||
```bash
|
||||
bash ~/mission-control-v2/deploy/notify.sh -s "[Konzept]" "<text>"
|
||||
```
|
||||
Der Text: erst 1-2 Saetze, was erarbeitet wurde und dass es fertig zum Bauen ist; dann knapp:
|
||||
- der **Cast** (welche Rollen mitgedacht haben),
|
||||
- **Runden + Haertetest-Ergebnis** (wasserdicht nach n Runden / welche Blocker offen blieben),
|
||||
- der **Pfad**: `~/konzepte/$slug-konzept.md`,
|
||||
- der **naechste Schritt fuer den Commander:** „In Hermes Desktop ein neues Projekt starten und dieses
|
||||
Konzept als Vorlage geben (projekt-start) — dann baut der Coder."
|
||||
Passt das ganze Konzept unter ~3500 Zeichen, haeng es direkt an die Nachricht. Sonst nur die
|
||||
Zusammenfassung + Pfad.
|
||||
|
||||
### 7. Belege (Pflicht — gegen Selbst-Erfindung)
|
||||
In deiner Antwort/Uebergabe nachweisen, dass wirklich delegiert wurde: je Rolle der `worker.sh`-
|
||||
Aufruf + die erste Zeile ihrer Roh-Ausgabe, und je Runde das Haertetest-Urteil. **Kein Beleg =
|
||||
GESCHEITERT** (dann hast du selbst geschrieben statt heavy — das ehrlich sagen, nicht kaschieren).
|
||||
|
||||
### 8. Nichts loeschen
|
||||
`/tmp/konzept-$slug/` (Recherche, Cast, Runden, Haertetests, konzept.md) bleibt liegen, bis der
|
||||
Commander das Konzept angenommen oder verworfen hat.
|
||||
|
||||
## Kontext-Uebergabe — hier geht es am ehesten schief
|
||||
`worker.sh`/`fremdblick.sh` starten **frisch und zustandslos**: kein Gedaechtnis der Runden, kein
|
||||
Zugriff auf Dateien. Sie sehen NUR, was du ihnen auf stdin gibst. Deshalb:
|
||||
- Immer das **aktuelle `konzept.md`** komplett mitgeben — nie „wie eben besprochen".
|
||||
- heavy hat nur **32k Kontext** → das Dokument kompakt halten, alte Runden-`.txt` NICHT in den
|
||||
Prompt schleppen (nur die offenen Blocker aus dem letzten Haertetest zaehlen).
|
||||
- Zu wenig Kontext → die Rolle raet. Zu viel Altlast → sie verliert den Fokus. Ziel: das kleinste,
|
||||
das den aktuellen Stand eindeutig macht.
|
||||
@@ -1,21 +0,0 @@
|
||||
---
|
||||
name: llm_wiki
|
||||
description: "Analysiert autonom Änderungen am Codebase oder Stack und aktualisiert die Markdown-Dateien im wissens-vault, sodass die Dokumentation immer aktuell ist."
|
||||
version: 1.0.0
|
||||
author: MC2
|
||||
platforms: [linux, macos, windows]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [docs, wiki, knowledge, mc2]
|
||||
---
|
||||
|
||||
# LLM Wiki (Auto-Docs)
|
||||
|
||||
Dieser Skill stellt sicher, dass das `wissens-vault` (die "Träume" und Notizen der Box) synchron zur echten Code-Realität bleibt.
|
||||
|
||||
## Ablauf
|
||||
1. **Git-Log Analyse**: Liest die Commits seit dem letzten Lauf aus dem Repository.
|
||||
2. **Impact-Analyse**: Bestimmt, welche Architektur-Teile, Skripte oder Frontend-Komponenten modifiziert wurden.
|
||||
3. **Vault-Update**: Sucht im `~/wissens-vault/` nach den betroffenen Markdown-Dokumenten (wie z.B. `STACK.md` oder `FALLEN.md`).
|
||||
4. **Dokumentation schreiben**: Überschreibt oder ergänzt die Dateien mit den neuesten Fakten und löscht veraltete Passagen, um Halluzinationen in der Zukunft zu vermeiden.
|
||||
5. **Commit**: Committet die angepassten Docs direkt in den Branch und schließt damit die Wissenslücke.
|
||||
@@ -1,21 +0,0 @@
|
||||
---
|
||||
name: morning_report
|
||||
description: "Sammelt Metriken, Vorfälle der Nacht und Neuigkeiten (z.B. Hacker News) und schickt morgens eine kompakte Sysadmin-Morgenlage via Telegram."
|
||||
version: 1.0.0
|
||||
author: MC2
|
||||
platforms: [linux, macos, windows]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [report, admin, daily, mc2]
|
||||
---
|
||||
|
||||
# Sysadmin Morgenlage (Morning Report)
|
||||
|
||||
Dieser Skill fungiert als dein persönlicher, KI-gesteuerter Sysadmin, der dir jeden Morgen (oder manuell getriggert) einen Statusbericht liefert.
|
||||
|
||||
## Ablauf
|
||||
1. **System-Metriken abrufen**: Ruft den Health-Status und Load der Box ab.
|
||||
2. **Logs durchkämmen**: Sucht nach Auffälligkeiten, Fehlern oder Crashes in der Nacht.
|
||||
3. **News Fetching**: Liest die Top-Posts von Hacker News (oder anderen Tech-Feeds), filtert sie nach AI-Relevanz und fasst die 3 wichtigsten Entwicklungen zusammen.
|
||||
4. **Offene Branches**: Nennt ungemergte Vorschlags-Branches auf Gitea (wartung/*, feature/*, doku/*), falls welche warten.
|
||||
5. **Report Generierung**: Bündelt all diese Informationen in eine kompakte, handyfreundliche (sehr kurze) Nachricht und schickt sie via Telegram an den Commander.
|
||||
@@ -1,220 +0,0 @@
|
||||
---
|
||||
name: orchestrator
|
||||
description: "Orchestrieren wie ein Manager: einen groesseren Auftrag in Teil-Tasks zerlegen, jeden SERIELL an das passende Worker-Modell delegieren (worker.sh, Ein-Schuss via llama-swap), die Ergebnisse einsammeln + zusammensetzen, per Fremd-Kritiker gaten und als Telegram-Vorschlag zurueckgeben. NIE selbst mergen/deployen — der Commander ist das Gate."
|
||||
version: 1.0.0
|
||||
author: MC2 (Autonomie — Orchestrator)
|
||||
platforms: [linux]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [orchestrator, delegation, werkstatt, mc2, fliessband]
|
||||
---
|
||||
|
||||
# Orchestrator — du managst, du fuehrst nicht alles selbst aus
|
||||
|
||||
Nutze diesen Skill, wenn ein Auftrag zu gross fuer EINEN Rutsch ist, sich aber in wenige klar
|
||||
abgegrenzte Teil-Tasks zerlegen laesst (ueberwiegend Code-Bau). Du bist der **Manager**: du
|
||||
zerlegst, verteilst die Teile SERIELL an Worker-Modelle (die arbeiten), fuegst die Ergebnisse
|
||||
zusammen und lieferst am Ende einen **Vorschlag** — der Commander entscheidet.
|
||||
|
||||
Das ist die Verallgemeinerung der **Werkstatt** (`wartung`): dort delegierst du EINEN Schritt
|
||||
(Code-Review) an ein Fremdmodell. Hier delegierst du MEHRERE Bau-Schritte an Worker und behaeltst
|
||||
die Integration + das Gate.
|
||||
|
||||
## Warum seriell (und warum das ok ist)
|
||||
Mehrere grosse Modelle GLEICHZEITIG passen nicht in den Speicher. llama-swap ist **seriell** — ein
|
||||
Modell laden → arbeiten → tauschen → naechstes. Orchestrierung ist ein **Fliessband, kein Schwarm.**
|
||||
Langsamer (Swap-Latenz + einer nach dem anderen: Minuten), aber bei Hintergrund-/Telegram-Jobs egal.
|
||||
|
||||
## Scope-Check zuerst (klein anfangen)
|
||||
Passt: ein Auftrag, der in **2–4 abgegrenzte Teil-Tasks** zerfaellt, jeder ein 1–2-Datei-Bau-Schritt
|
||||
(neues kleines Modul + Test, kleine neue Funktion + Verdrahtung, zusammenhaengender Refactor in
|
||||
wenigen Dateien). Zu gross (viele Module, echte Architektur-Entscheidungen, breite API-Aenderung):
|
||||
**Etappen-Weg statt Ablehnung** (Grossbau-Entscheid 10.07.2026) — zerlege das Projekt in Etappen,
|
||||
von denen JEDE fuer sich lauffaehig, gate-gruen und einzeln annehmbar ist. Baue in DIESEM Lauf nur
|
||||
Etappe 1 (als normalen Orchestrator-Durchlauf mit Workern + Zwei-Kritiker-Gate); den Etappen-Plan
|
||||
in den Telegram-Vorschlag schreiben und die Folge-Etappen als neue Aufgaben in die Ideen-Queue
|
||||
legen (`hermes kanban create "<Projekt> — Etappe <n>: <was>" --triage`, im Body: Plan + Branch der
|
||||
Vor-Etappe). Eine Folge-Etappe wird erst gebaut, wenn der Branch der Vor-Etappe in main ist —
|
||||
NIE auf unangenommene Branches aufbauen. Rauere Qualitaet ist bei Grossbau ok, aber ehrlich im
|
||||
Vorschlag ausweisen, was fehlt oder wacklig ist.
|
||||
|
||||
## Leitplanken (nicht verhandelbar)
|
||||
- **Du delegierst, du baust NICHT selbst.** Jedes Bau-Artefakt MUSS aus einem `worker.sh`-Aufruf
|
||||
stammen. Schreibst du den Code selbst (auch wenn der Teil-Task „einfach genug" wirkt), statt ihn
|
||||
vom Worker zu holen, ist der Lauf GESCHEITERT — sag das ehrlich, statt Eigenbau als Orchestrierung
|
||||
auszugeben. Belege jeden Teil-Task im Vorschlag mit dem `worker.sh`-Aufruf UND den ersten Zeilen
|
||||
seiner Roh-Ausgabe. (Warum so streng: das Manager-Modell kann kleine Tasks selbst — genau dann
|
||||
faellt Delegation aus Bequemlichkeit weg; das ist der haeufigste Orchestrierungs-Fehler.)
|
||||
- **„Task zu klein" ist KEIN Freibrief (kein Ermessensspielraum).** Du darfst Planung, Delegation
|
||||
oder das Zwei-Kritiker-Gate NICHT eigenmaechtig ueberspringen — auch nicht transparent angesagt
|
||||
(„Overkill, ich mach das direkt" = GESCHEITERTER Lauf, Vorfall 09.07.2026). Wirkt der Auftrag
|
||||
wirklich zu klein fuers Fliessband, ist dein EINZIGER erlaubter Ausweg: **abbrechen ohne Code**
|
||||
und im Vorschlag melden „zu klein fuer den Orchestrator — bitte als Werkstatt-Auftrag (hermes -z)
|
||||
oder direkt im Desktop laufen lassen". Ein Lauf, der Code liefert, enthaelt IMMER worker.sh-Belege
|
||||
UND beide Kritiker-Verdikte — ohne Ausnahme.
|
||||
- **Die Helfer EXISTIEREN.** `~/.hermes/scripts/worker.sh` und `~/.hermes/scripts/fremdblick.sh`
|
||||
sind installiert, aber NICHT auf deinem PATH → immer mit vollem Pfad aufrufen (nie bloss `worker.sh`).
|
||||
Glaubst du, sie fehlen, IRRST du dich: erst `ls -la ~/.hermes/scripts/worker.sh` ausfuehren und den
|
||||
Pfad lesen, dann nutzen. „Skript fehlt" ist KEIN gueltiger Grund, den Schritt selbst zu machen.
|
||||
- **Propose-only.** Am Ende steht IMMER ein Telegram-Vorschlag; die Entscheidung trifft der Commander.
|
||||
NIEMALS auf `main` committen, NIEMALS mergen, NIEMALS deployen oder Dienste neu starten.
|
||||
- **Nur im Worktree arbeiten.** Die Live-Instanz `~/mission-control-v2` bleibt unberuehrt.
|
||||
- **Warm-Set-Schutz (Speicher vs Latenz).** Worker werden ueber **`worker.sh`** aufgerufen.
|
||||
Fuer die Umsetzung von Code nutzt du **`coder`** (laedt klein neben dem Warm-Set).
|
||||
Fuer die initiale **Planung** nutzt du explizit den Chef-Gutachter **`gpt-oss-120b`** (heavy),
|
||||
auch wenn dessen Laden (~15s) Lucys Sprech-Latenz temporaer aussetzt. Das ist fuer diesen
|
||||
Hintergrund-Prozess gewollt.
|
||||
- **Fremd-Kritiker ist Pflicht-Gate.** Der zusammengesetzte Diff MUSS von `fremdblick.sh` (anderes
|
||||
Modell) gegengelesen werden, bevor du vorschlaegst. Ein Manager, der Worker-Output blind
|
||||
zusammenklebt, produziert leisen Muell.
|
||||
- **Security-Config ist TABU:** keine Tokens, approvals, ufw, sudoers, ssh-Keys anfassen.
|
||||
- **Hermes-first (10.07.2026):** Bevor ein Teil-Task NEUE Infrastruktur baut (Skript, Dienst,
|
||||
Tool, Cron), pruefe ob hermes-agent das nativ kann — erst in die Eigenbau-Landkarte schauen
|
||||
(`~/wissens-vault/eigenbau-landkarte.md`), notfalls `bash -lc 'hermes --help'`. Den
|
||||
Pruef-Befund in den Vorschlag schreiben („nativ vorhanden: nein/ja, weil …").
|
||||
- Gate rot oder Kritiker dagegen → trotzdem ehrlich melden (Branch bleibt liegen), nichts beschoenigen.
|
||||
|
||||
## Ablauf
|
||||
|
||||
### 1. Beratung & Zerlegen (Manager plant mit dem Chef)
|
||||
Bevor du selbst Tasks aufteilst, befragst du zwingend **`gpt-oss-120b`** nach einem Architektur-Plan:
|
||||
1. Sende den initialen Auftrag per `worker.sh` an den Chef-Planer:
|
||||
```bash
|
||||
printf '%s' "Auftrag: $auftrag" | WORKER_MODEL=gpt-oss-120b WORKER_ROLE=plan ~/.hermes/scripts/worker.sh > /tmp/orch-plan.txt
|
||||
```
|
||||
2. Lies den Plan (`cat /tmp/orch-plan.txt`) und nutze ihn, um den Auftrag in eine **geordnete, nummerierte Liste von Teil-Tasks** zu zerlegen.
|
||||
3. Fuer jeden Teil-Task entscheide: (a) Artefakt, (b) Worker (`coder` + `build`/`refactor`), (c) Kontext.
|
||||
|
||||
### 2. Worktree anlegen (Slug = kurzer Kebab-Case-Name des Auftrags)
|
||||
Worktrees liegen unter `~/.hermes/worktrees/` (NICHT /tmp — ueberlebt keinen Reboot und
|
||||
hinterlaesst kaputte Worktree-Registrierungen, Review-Befund 15.07.):
|
||||
```
|
||||
mkdir -p ~/.hermes/worktrees && cd ~/mission-control-v2 && git fetch -q origin \
|
||||
&& git worktree add ~/.hermes/worktrees/orch-<slug> -b orchestrator/<slug> origin/main
|
||||
mkdir -p ~/.hermes/worktrees/orch-<slug>-work # Ablage fuer rohe Worker-Ausgaben
|
||||
```
|
||||
|
||||
### 3. Routen — je Teil-Task ein Worker-Ein-Schuss (seriell)
|
||||
Fuer jeden Bau-Teil-Task:
|
||||
1. Baue die Eingabe: **genau der noetige Kontext** + der praezise Auftrag (siehe unten). Bereits
|
||||
fertige Artefakte aus frueheren Schritten als Kontext mitgeben, wenn der Worker sie braucht.
|
||||
2. Ruf den Worker auf und fang die Ausgabe roh ab:
|
||||
```
|
||||
printf '%s' "$eingabe" | WORKER_ROLE=build ~/.hermes/scripts/worker.sh > ~/.hermes/worktrees/orch-<slug>-work/<n>.out
|
||||
```
|
||||
(Default-Modell ist `coder`. Fuer einen bewusst anderen Worker `WORKER_MODEL=<rolle-oder-id>`.)
|
||||
3. **Pruefe die Ausgabe, bevor du sie verwendest:** Beginnt sie mit `FEHLT:`, hast du zu wenig
|
||||
Kontext gegeben → nachliefern und erneut rufen. Hat der Worker versehentlich einen ```-Codezaun
|
||||
oder Prosa drumherum gesetzt, entferne ihn. Dann schreibe das saubere Artefakt mit deinen
|
||||
Datei-Tools an seinen Platz im Worktree (`~/.hermes/worktrees/orch-<slug>/...`). Der Worker hat KEINE
|
||||
Datei-Haende — das Schreiben machst DU.
|
||||
4. **Schreibziel-Pflicht (Vorfall 09.07.2026):** JEDES write_file/patch-Ziel MUSS mit
|
||||
`~/.hermes/worktrees/orch-<slug>/` beginnen — vor dem ersten Schreiben einmal laut pruefen. NIEMALS nach
|
||||
`~/mission-control-v2/...` schreiben (Live-Checkout!), NIEMALS Work-Dirs/Worktrees FREMDER
|
||||
Slugs wiederverwenden (beim Doku-Lauf landete ein Artefakt im Live-Checkout, weil das alte
|
||||
`/tmp/orch-hermes-desktop-work` recycelt wurde). Existiert dein `~/.hermes/worktrees/orch-<slug>` noch nicht,
|
||||
ist das der Beweis, dass Schritt 2 fehlt — erst Worktree anlegen.
|
||||
5. **Grosse Artefakte NIE im Klartext in deine Antwort** — sie gehoeren in Dateien im Worktree.
|
||||
Wer Dateiinhalte in die Antwort kippt, stirbt am Output-Limit mitten im Lauf (Doku-Lauf
|
||||
09.07.2026: abgewuergt VOR Kritiker-Gate und Vorschlag). In der Antwort: Pfade + 1-Zeilen-Zusammenfassung.
|
||||
|
||||
### 4. Integrieren + Self-Gate (nach jedem Schritt bzw. am Ende)
|
||||
Die Worker liefern Bausteine — DU sorgst dafuer, dass sie zusammenpassen (Imports, Verdrahtung,
|
||||
Namen). Dann das Selbst-Gate, was zutrifft:
|
||||
- Python geaendert → `python3 -m py_compile <dateien>` (und wenn ein Test dabei ist und ohne
|
||||
schwere Deps laeuft: den Test im Worktree ausfuehren).
|
||||
- Shell geaendert → `bash -n <dateien>`
|
||||
- Frontend (`frontend/src/...`) → **Node EXISTIERT auf der Box** (bewiesen 09.07.2026, Läufe
|
||||
role-metadata + desktop-gateway): im Worktree `cd frontend && npm install && npm run build`
|
||||
ausfuehren und das neue `frontend/dist` MIT-committen (AGENTS.md-Pflicht — sonst zeigt die Box
|
||||
nach Merge+Deploy den alten Stand). **Danach `git checkout -- frontend/package-lock.json`**,
|
||||
falls npm install es nur als Nebeneffekt angefasst hat (wiederkehrendes Muster: 3 Laeufe in
|
||||
Folge hatten lockfile-Dreck) — es gehoert NUR in den Commit, wenn Dependencies sich wirklich
|
||||
aendern sollten. Schlaegt der Build fehl, ehrlich ausweisen: „Gate eingeschraenkt: Build
|
||||
fehlgeschlagen, tsc laeuft beim Merge auf dem PC."
|
||||
- **Live-Checkout unberuehrt (PFLICHT, zwei Beweise):**
|
||||
- `git -C ~/mission-control-v2 status --porcelain -uno` **muss LEER sein** (Beweis, dass du
|
||||
wirklich nur im Worktree gearbeitet hast — ein gruener Health-curl allein reicht NICHT, weil
|
||||
der laufende Dienst den alten Code im RAM haelt und eine schmutzige Datei auf der Platte nicht
|
||||
bemerkt).
|
||||
- `curl -sf http://127.0.0.1:9001/api/health` muss gruen bleiben.
|
||||
- Ist `git status` NICHT leer: die fremden Aenderungen im Live-Checkout mit
|
||||
`git -C ~/mission-control-v2 checkout -- <datei>` zuruecknehmen (deine Arbeit liegt sicher im
|
||||
Worktree) und im Vorschlag ehrlich erwaehnen.
|
||||
|
||||
### 5. Zwei-Kritiker-Gate ueber den GESAMTEN Diff (Pflicht)
|
||||
Zwei Zweitgutachter mit je anderer Staerke lesen den zusammengesetzten Diff gegen — aus demselben
|
||||
Grund wie in der Werkstatt („wer seine eigenen Hausaufgaben benotet, stimmt sich selbst zu"). **NICHT
|
||||
`delegate_task`** (laeuft ueber `heavy` → 64K-Floor + Warm-Set-Kollision).
|
||||
|
||||
**Zuerst ALLES stagen** — sonst fehlen NEUE Dateien im Diff (haeufigste Falle: `git diff` ignoriert
|
||||
untracked Dateien, die Kritiker bekaemen einen LEEREN Diff und wuerden alles blind ablehnen):
|
||||
```
|
||||
git -C ~/.hermes/worktrees/orch-<slug> add -A
|
||||
```
|
||||
Dann die Eingabe EINMAL bauen (mit `--cached`, damit die neuen Dateien drin sind):
|
||||
```
|
||||
EINGABE="AUFTRAG (im Wortlaut):
|
||||
<der urspruengliche Auftrag>
|
||||
|
||||
ZERLEGUNG (deine Teil-Tasks, je 1 Zeile):
|
||||
<1..n>
|
||||
|
||||
GIT-DIFF des Worktrees:
|
||||
$(git -C ~/.hermes/worktrees/orch-<slug> diff --cached origin/main)"
|
||||
```
|
||||
Ist dieser Diff LEER, hast du nicht gestaged (oder nichts gebaut) → NICHT weiter, erst beheben.
|
||||
**Kritik A — Kompetenz** (`coder`, starker Coder, vom Bauen noch geladen → KEIN Swap):
|
||||
```
|
||||
printf '%s' "$EINGABE" | FREMDBLICK_MODE=code ~/.hermes/scripts/fremdblick.sh
|
||||
```
|
||||
**Kritik B — Fremd-Blick** (`debugger`, andere Modellfamilie, andere blinde Flecken):
|
||||
```
|
||||
printf '%s' "$EINGABE" | FREMDBLICK_MODE=code FREMDBLICK_MODEL=debugger FREMDBLICK_MAXTOK=3000 ~/.hermes/scripts/fremdblick.sh
|
||||
```
|
||||
Reihenfolge bewusst: erst A (Coder-Next ist noch warm), dann B (ein Swap zu GLM). Beide beginnen mit
|
||||
`URTEIL: <ABGELEHNT | FREIGABE-MIT-VORBEHALT | FREIGABE>`. **Warte auf beide.**
|
||||
|
||||
**Gate-Regel (streng):** Sagt AUCH NUR EINER `ABGELEHNT` → nachbessern (max. 2 Runden: den
|
||||
betroffenen Teil-Task neu an den Worker, integrieren, BEIDE Kritiker erneut). `FREIGABE-MIT-VORBEHALT`
|
||||
→ die Vorbehalte adressieren oder im Vorschlag ehrlich ausweisen (NICHT wegdiskutieren). Nur wenn
|
||||
BEIDE tragen → Vorschlag. Beide Urteile KONKRET in den Vorschlag (welcher Kritiker was sagte). Faellt
|
||||
ein Kritiker technisch aus (`FEHLGESCHLAGEN`/`ABGESCHNITTEN`) → einmal wiederholen, sonst „⚠ Kritik X
|
||||
fiel aus" vermerken (NICHT als Freigabe zaehlen).
|
||||
|
||||
> Der schwere **Chef-Gutachter (`gpt-oss`)** laeuft NICHT in diesem heissen Pfad — er muesste 60 GB
|
||||
> kalt laden und Lucys Warm-Set stoeren. Er prueft separat NACHTS im Leerlauf ueber die offenen
|
||||
> Orchestrator-Vorschlaege (eigener Cron), wo Ladezeit + Warm-Set-Umbau verkraftbar sind.
|
||||
- `ABGELEHNT` / berechtigte `FREIGABE-MIT-VORBEHALT` → nachbessern (max. 2 Runden: den betroffenen
|
||||
Teil-Task neu an den Worker geben, integrieren, erneut gaten). Bleibt es kritisch: Kritik in den
|
||||
Vorschlag schreiben, Branch bleibt liegen, Entscheidung dem Commander.
|
||||
- `FREMDBLICK FEHLGESCHLAGEN`/`ABGESCHNITTEN` → einmal wiederholen; sonst im Vorschlag ehrlich
|
||||
„⚠ Fremd-Review fiel aus — UNGEPRUEFT" vermerken (NICHT als Freigabe behandeln).
|
||||
|
||||
### 6. Telegram-Vorschlag (in LUCYS Stimme)
|
||||
`bash ~/mission-control-v2/deploy/notify.sh -s "[Orchestrator]" "<text>"` — an den Commander, nicht
|
||||
als anonymer Job: erst 1–2 Saetze, was gebaut wurde und was er jetzt entscheiden soll; dann knapp:
|
||||
- die **Zerlegung** (welcher Teil-Task an welches Worker-Modell ging),
|
||||
- geaenderte/neue Dateien · Kern des Diffs,
|
||||
- Self-Gate-Ergebnis · Kritiker-Urteil KONKRET ausgeschrieben (nicht nur „ok"),
|
||||
- Branch-Name · Frage „merge oder verwerfen?"
|
||||
|
||||
### 7. Nichts loeschen
|
||||
Worktree + Branch + rohe Worker-Ausgaben bleiben liegen, bis der Commander entschieden hat.
|
||||
|
||||
## Kontext-Uebergabe — hier geht Orchestrierung am ehesten schief
|
||||
Jeder Worker startet **frisch und zustandslos**: kein Gedaechtnis der bisherigen Schritte, kein
|
||||
Zugriff aufs Repo. Er sieht NUR, was du ihm auf stdin gibst. Deshalb:
|
||||
- Gib ihm den **relevanten Ausschnitt** mit — die betroffene Datei (oder den betroffenen Block),
|
||||
benachbarte Muster zum Nachahmen, die genaue Signatur/den Namen, den er treffen muss, und bei
|
||||
Folge-Schritten die bereits fertigen Artefakte, auf die er aufbaut.
|
||||
- Sei praezise beim Zielartefakt: „Gib den VOLLSTAENDIGEN Inhalt der neuen Datei `X` aus" bzw. „Gib
|
||||
einen unified Diff gegen den folgenden Stand von `Y` aus".
|
||||
- Zu wenig Kontext → der Worker raet oder meldet `FEHLT:`. Zu viel unnoetiger Kontext → er verliert
|
||||
den Fokus. Ziel: das kleinste, das den Teil-Task eindeutig macht.
|
||||
|
||||
## Nach dem Commander-Entscheid (kommt als neuer Auftrag)
|
||||
- „verwerfen" → `git worktree remove ~/.hermes/worktrees/orch-<slug> --force && git branch -D orchestrator/<slug>`
|
||||
(+ `rm -rf ~/.hermes/worktrees/orch-<slug>-work`; Remote-Branch loeschen, falls gepusht).
|
||||
- „merge" → das Mergen nach main + Deploy macht der PC/Claude (Frontend-Builds gibt es nur dort).
|
||||
Du pushst NIE nach main.
|
||||
@@ -1,371 +0,0 @@
|
||||
---
|
||||
name: projekt-start
|
||||
description: "Startet und begleitet ein Coding-Projekt RICHTIG: erst verstehen, dann planen (mit hartem Freigabe-Gate), dann Gerüst, dann Code, dann Beweis — mit Sicherungspunkten (Savepoints) und Wahl des passenden Box-Modells je Aufgabe. Pflegt die drei Projektdateien AGENTS.md, SAVEPOINT.md und .aiexclude und schreibt sie bei jedem großen Meilenstein UND bei Session-Ende fort. Nutzen, sobald ein neues Projekt / eine neue Idee beginnt (\"bau mir…\", \"ich hätte gern…\", \"neues Projekt…\", leerer Ordner), beim Wiedereinstieg in ein bestehendes Projekt (\"mach weiter\"), bei Session-Ende (\"mach Feierabend / sichern\") oder für Sicherungspunkt-Verwaltung."
|
||||
version: 1.0.0
|
||||
author: MC2 (Ablösung 13.07.2026 — portiert vom PC-Skill F:\Coding Stuff\projekt-start, Zed-Verweise durch Hermes Desktop ersetzt)
|
||||
platforms: [linux, windows]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [projekt, planen, savepoint, coding, greenfield]
|
||||
---
|
||||
|
||||
# Projekt-Start
|
||||
|
||||
Du hilfst einem **Nicht-Entwickler** (spricht Deutsch, denkt in Zielen, nicht in Code).
|
||||
Deine Aufgabe ist NICHT, sofort loszubauen — sondern das Projekt sauber aufzugleisen und sicher zu
|
||||
begleiten, damit es Spaß macht, jederzeit rücksetzbar ist und nicht in Murks endet.
|
||||
|
||||
## Eiserne Regeln (nicht verhandelbar)
|
||||
|
||||
1. **Keine Zeile Code und keine Datei, bevor der Plan freigegeben ist.** Der Freigabe-Riegel
|
||||
in Phase 1 ist hart. Kein "ich fang schon mal an".
|
||||
2. **Deutsch, in Alltagssprache.** Fazit zuerst, Technik nur wo nötig und dann erklärt.
|
||||
3. **Eine Sache zur Zeit.** Kleine Schritte, nach jedem Schritt kurz zeigen, wo ihr steht.
|
||||
4. **Beweisen statt behaupten.** "Sollte gehen" zählt nicht — am Ende live testen und zeigen.
|
||||
5. **Sicherungspunkte setzen + Projektdateien pflegen.** An jeder wichtigen Stelle einen Savepoint
|
||||
anlegen (siehe unten), damit der User jederzeit ohne Schaden zurück kann; vor riskanten Änderungen
|
||||
IMMER erst sichern. **Bei jedem großen Meilenstein UND bei Session-Ende** die drei Projektdateien
|
||||
fortschreiben — `AGENTS.md`, `SAVEPOINT.md`, `.aiexclude` (siehe „Meilenstein-/Session-Ende-Ritual").
|
||||
6. **Dynamisch bleiben.** Die Projekttypen und Fragen unten sind BEISPIELE, kein Käfig. Passt
|
||||
der Typ nicht, leite die richtigen Fragen selbst ab. Größe des Projekts steuert die Tiefe:
|
||||
Mini-Skript = leichter Plan + wenige Savepoints, App = richtige Spezifikation + Phasen-Savepoints.
|
||||
7. **Geheimnisse schützen.** Nie Schlüssel/Passwörter/Tokens fest in den Code — immer in `.env`
|
||||
(+ `.gitignore` + `.aiexclude`). Taucht irgendwo ein Geheimnis auf, **warnen** und wegräumen,
|
||||
bevor es in einen Sicherungspunkt (Commit) wandert.
|
||||
8. **Nicht festfahren.** Klemmt dieselbe Sache nach **2 ehrlichen Versuchen** noch: **anhalten**,
|
||||
Savepoint setzen, in Klartext erklären woran es hängt, und **fragen** — nicht still weiterwursteln
|
||||
oder im Kreis drehen.
|
||||
|
||||
---
|
||||
|
||||
## Bau-Prinzipien (still befolgen — NICHT den User abfragen)
|
||||
|
||||
Das ist **dein** Handwerk, nicht seine Entscheidung. Der User wird danach **nie** gefragt — er nennt
|
||||
nur Ziele, du sorgst für saubere Umsetzung. Beim Bauen automatisch beachten:
|
||||
|
||||
- **KISS** — die einfachste Lösung, die reicht. Kein Framework/Muster, das der Umfang nicht rechtfertigt.
|
||||
- **YAGNI** — nur bauen, was jetzt gebraucht wird. Keine „könnte man später mal"-Features auf Verdacht.
|
||||
- **Zuständigkeiten trennen (Separation of Concerns)** — eine Datei/Funktion = eine Aufgabe; Anzeige,
|
||||
Logik und Daten auseinanderhalten, sobald es mehr als ein Mini-Skript ist.
|
||||
- **Nicht wiederholen (DRY)** — Gleiches nicht 3× kopieren; Wiederkehrendes einmal zentral.
|
||||
- **Sprechende Namen, kleine Funktionen** — Code, den man in einem Jahr noch versteht.
|
||||
- **Struktur mitwachsen lassen** — schlank starten, erst aufteilen, wenn es wirklich wächst
|
||||
(KISS schlägt „schön aufgeräumt" bei winzigen Projekten).
|
||||
|
||||
**Faulheits-Leiter — vor jeder neuen Zeile / neuen Abhängigkeit IN DIESER Reihenfolge fragen:**
|
||||
1. **Muss das überhaupt existieren?** Lässt sich die Anforderung ganz ohne neuen Code erfüllen?
|
||||
2. **Gibt es das schon?** Vorhandene Funktion/Datei wiederverwenden statt neu bauen.
|
||||
3. **Reicht Bordmittel / Standard-Bibliothek?** Kein neues Paket, wenn Sprache/Framework es schon kann.
|
||||
4. **Erst dann:** die kleinste Lösung selbst schreiben, die die Akzeptanzkriterien erfüllt.
|
||||
|
||||
**Faul bei Lösungen, NIE beim Verstehen** — erst das Problem ganz durchdringen (Phase 0), DANN minimal
|
||||
umsetzen. Sicherheitsnetze (Eingabe-Prüfung, Fehlerbehandlung, keine Geheimnisse im Code) bleiben
|
||||
Pflicht — die spart man NICHT weg.
|
||||
|
||||
**Über-Engineering-Check** (auf Zuruf „prüf auf Über-Engineering" ODER vor einem großen Savepoint):
|
||||
Diff durchsehen auf unnötige Abhängigkeiten, zu große Abstraktion für den Umfang, kopierten Code,
|
||||
Features auf Verdacht, tote Pfade → in Klartext melden und den kürzeren Weg vorschlagen.
|
||||
|
||||
Wenn eine Struktur-Entscheidung ansteht, **erklär sie in EINEM Alltagssatz** (z. B. „ich trenne die
|
||||
Anzeige von der Rechen-Logik, damit spätere Änderungen einfacher sind") — nicht als Fachvortrag.
|
||||
|
||||
---
|
||||
|
||||
## Der Ablauf: 4 Phasen
|
||||
|
||||
```
|
||||
Wiedereinstieg → bestehendes Projekt? Erst SAVEPOINT.md + AGENTS.md lesen, kurz "hier stehen wir"
|
||||
Phase 0 Verstehen [Planer] → Projektart bestimmen + die RICHTIGEN Fragen stellen
|
||||
Phase 1 Planen [Planer] → Plan vorlegen ── RIEGEL: auf "los", DANN Wechsel auf Coder ──
|
||||
Phase 2 Gerüst [Coder] → git + 3 Dateien (typgerecht) + Savepoint "start"
|
||||
Phase 3 Bauen [Coder] → in kleinen Schritten umsetzen, je Meilenstein ein Savepoint
|
||||
Phase 4 Beweisen [Coder] → testen, live zeigen, Savepoint "läuft"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Wiedereinstieg — bestehendes Projekt fortsetzen
|
||||
|
||||
Startest du in einem Projekt, das es **schon gibt** (Ordner nicht leer, ein neuer Chat), dann NICHT
|
||||
neu planen, sondern zuerst:
|
||||
1. **`SAVEPOINT.md` lesen** (falls vorhanden) + **`AGENTS.md`** — das ist die Übergabe vom letzten Mal.
|
||||
2. Dem User in **2 Sätzen** sagen: „Hier stehen wir: … — der nächste Schritt wäre …".
|
||||
3. Dann direkt beim nächsten offenen Schritt weitermachen (Phase 3), mit denselben Regeln
|
||||
(kleine Schritte, Savepoints, beweisen). Gibt es keine `SAVEPOINT.md`, biete an, eine anzulegen.
|
||||
|
||||
So schließt sich der Kreis: **Start → Feierabend (SAVEPOINT.md) → Wiedereinstieg** — nichts geht verloren.
|
||||
|
||||
---
|
||||
|
||||
## Phase 0 — Verstehen (dynamisch)
|
||||
|
||||
**Zuerst:** In 1–2 Sätzen zurückspiegeln, was du glaubst verstanden zu haben. Dann heraus-
|
||||
finden, **welche Art Projekt** das ist — frag es, wenn unklar. Erst danach die typ-passenden
|
||||
Fragen stellen. Stell **3–6 Fragen**, nicht mehr; keine Doktorarbeit.
|
||||
|
||||
**Fragen-Banken je Projektart (Beispiele — passe sie an):**
|
||||
|
||||
- **Web-App / Webseite (mit Oberfläche):**
|
||||
Wer benutzt sie? · Was soll man damit tun können (die 1–3 Kernaktionen)? · Muss sie Daten
|
||||
speichern (dann wo)? · Nur du oder mehrere Leute gleichzeitig? · Soll's im Netz erreichbar
|
||||
sein oder nur lokal? · Gibt's optisch eine Richtung, die dir gefällt?
|
||||
|
||||
- **Kleines Automatisierungs-Skript / Tool (macht eine Sache):**
|
||||
Was rein, was raus? · Startest du es von Hand oder soll es automatisch/regelmäßig laufen? ·
|
||||
Auf welchem Rechner (dein PC / die Box)? · Was passiert im Fehlerfall?
|
||||
|
||||
- **Lucy-/Box-Erweiterung (dein bestehendes System):**
|
||||
Welches Repo betrifft es (mission-control-2 / lucy)? · Läuft es auf der Box oder am PC? ·
|
||||
Berührt es das Warm-Set, die Sprach-Latenz oder Sicherheits-Config? (Wenn ja: extra vorsichtig,
|
||||
Mensch-Gate.) · Nur Frontend oder auch Backend? · **Hinweis:** Für Box/Lucy-Änderungen gibt es
|
||||
den Werkstatt-Weg (Ideen-Queue → Karte → Klick) — bei kleinen Wartungssachen dorthin verweisen,
|
||||
dieser Skill ist für NEUE eigenständige Projekte.
|
||||
|
||||
- **Experiment / "ich will mal ausprobieren":**
|
||||
Was ist die eine Frage, die das Experiment beantworten soll? · Wann ist es "erfolgreich"? ·
|
||||
Wegwerf-Prototyp oder soll daraus was Bleibendes werden?
|
||||
|
||||
- **Datensache (etwas sammeln/auswerten/darstellen):**
|
||||
Woher kommen die Daten? · Was willst du am Ende sehen (Tabelle, Diagramm, Report)? ·
|
||||
Einmalig oder wiederkehrend?
|
||||
|
||||
**Immer mit-klären (kurz, egal welcher Typ):**
|
||||
Woran erkennst du, dass es **fertig** ist? (konkrete Akzeptanz) · Gibt es einen Termin/Umfang-
|
||||
Deckel? · Welche **Risiken/Stolpersteine** siehst du? · Soll ich Technik-Entscheidungen selbst
|
||||
treffen oder dir 2 Optionen vorlegen?
|
||||
|
||||
**Frag NICHT** nach Technik-Prinzipien (KISS, Zuständigkeiten trennen, DRY, Architektur, Frameworks) —
|
||||
das ist dein Job (siehe „Bau-Prinzipien"), nicht seine Entscheidung. Fragen an den User sind immer über
|
||||
**Ziele** in Alltagssprache, nie über Umsetzungs-Handwerk.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1 — Plan vorlegen + HARTER RIEGEL
|
||||
|
||||
Leg einen **kurzen, lesbaren Plan** vor (kein Code!). Umfang skaliert mit der Projektgröße:
|
||||
|
||||
- **Ziel in einem Satz** — was am Ende geht.
|
||||
- **Vorgehen** — die 3–7 Schritte, in Reihenfolge, in Alltagssprache.
|
||||
- **Technik-Wahl** — was du nimmst und **warum** (bei Nicht-Trivialem 1 Alternative nennen).
|
||||
Standard-Defaults nutzen, nicht die exotische Kanone.
|
||||
- **"Fertig" heißt** — die Akzeptanzkriterien aus Phase 0, als Checkliste.
|
||||
- **Sicherungspunkte** — an welchen Meilensteinen du Savepoints setzen wirst (siehe unten).
|
||||
- **Risiken/Annahmen** — was schiefgehen kann, was du annimmst.
|
||||
|
||||
Dann **STOPP**: *"Passt der Plan so? Sag **los**, dann baue ich das Gerüst."*
|
||||
Warte auf ein klares Ja. Bei Änderungswünschen: Plan anpassen, erneut fragen. **Nichts anlegen,
|
||||
nichts schreiben, bis das Ja da ist.**
|
||||
|
||||
**Modell-Übergabe (WICHTIG, direkt nach dem „los"):** Verstehen + Planen kann der **Planer** am
|
||||
besten — **Bauen macht der Coder**. Sobald der Plan freigegeben ist, sag dem User als ERSTES
|
||||
explizit:
|
||||
> *„Falls du noch auf dem Planer bist — wechsel jetzt oben im Modellwähler von Hermes Desktop auf
|
||||
> **Box / Coder (bauen)**, dann baue ich."*
|
||||
|
||||
Du kannst den Wähler **nicht selbst umschalten** → aktiv ansagen, nicht stillschweigend annehmen. Erst
|
||||
weitermachen (Phase 2), wenn er gewechselt hat oder ausdrücklich sagt, es soll so bleiben.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2 — Gerüst aufsetzen (dynamisch, erst NACH Freigabe)
|
||||
|
||||
Immer (die drei Projektdateien + Netz):
|
||||
1. **git init** (falls noch kein Repo) — das ist das Sicherheitsnetz für alle Savepoints; erklär dem
|
||||
User in einem Satz, dass er dadurch jederzeit zurück kann.
|
||||
2. **`AGENTS.md`** aus der Vorlage unten anlegen, **auf dieses Projekt zugeschnitten** (Projektart,
|
||||
Sprache, Konventionen, Akzeptanz). Das ist die "einmal beibringen, immer befolgt"-Datei.
|
||||
3. **`SAVEPOINT.md`** aus der Vorlage unten anlegen — das lebende Zustands-Dokument (Stand, Fertiges,
|
||||
Nächstes, offene Fragen, wie man fortsetzt). Wird bei jedem Meilenstein + Session-Ende fortgeschrieben.
|
||||
4. **`.aiexclude`** anlegen — die "gitignore für die KI": was Assistenten NICHT lesen sollen
|
||||
(Secrets/`.env`, große Daten, Build-Output). Vorlage unten. Damit sie auch für DICH gilt, steht
|
||||
in der AGENTS.md-Vorlage die Regel „lies keine Dateien aus `.aiexclude`" — halte dich daran.
|
||||
5. **`README.md`**-Stub — was das Projekt ist, wie man es startet.
|
||||
6. **`.gitignore`** passend zur Technik.
|
||||
7. **Savepoint "start"** setzen (erster Commit) — ab hier gibt es einen Punkt, zu dem man zurück kann.
|
||||
|
||||
Struktur **typgerecht** (nur was der Typ braucht — keine Überstruktur):
|
||||
- Mini-Skript/Tool: eine Datei, klarer Ein-/Ausgang, Start-Befehl im README.
|
||||
- Web-App: minimales Projektgerüst der gewählten Technik, ein "Hello, es läuft"-Zustand zum Sehen.
|
||||
- **Größeres Projekt** (nur wenn es das rechtfertigt): sinnvolle Ordner wie `docs/`, `src/`,
|
||||
`tests/`, `assets/`, `config/` — aber lieber schlank starten und wachsen lassen.
|
||||
- Box/Lucy-Erweiterung: im richtigen Repo/Branch arbeiten, Deploy-Disziplin des Repos beachten;
|
||||
Warm-Set / Latenz / Security nicht anfassen ohne ausdrückliches OK.
|
||||
|
||||
Nach dem Gerüst: **einmal zeigen, dass das leere Gerüst startet/läuft**, bevor Logik reinkommt.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3 — Bauen
|
||||
|
||||
- In **kleinen Schritten**, ein Feature nach dem anderen — nicht fünf auf einmal.
|
||||
- **Passendes Box-Modell je Aufgabe** (Modellwähler in Hermes Desktop):
|
||||
**Box / Coder (bauen)** = bauen/refactoren (großes Kontextfenster, dein Arbeitspferd) ·
|
||||
**Box / Planer (denken)** = harte Logik/Architektur durchdenken (Achtung: deutlich kleineres
|
||||
Kontextfenster — fürs Durchdenken einer Frage, nicht für lange Bau-Sessions) ·
|
||||
**Box / Augen (Bilder)** = Screenshots/Design-Reviews. Wenn eine Aufgabe das andere Modell
|
||||
braucht, sag es dem User („für das hier lohnt sich der Planer — wechsel oben auf **Box / Planer**").
|
||||
- **Gezielte Edits**, nie ganze Dateien für eine Zeile überschreiben.
|
||||
- **Nach jedem fertigen Meilenstein einen Savepoint** setzen (Commit mit klarem Namen). Vor jeder
|
||||
riskanten Änderung ebenfalls erst sichern.
|
||||
- Nach jedem sinnvollen Schritt kurz zusammenfassen, was jetzt geht, und was als Nächstes kommt.
|
||||
- Wenn eine Entscheidung auftaucht, die der Plan nicht abdeckt: kurz fragen, nicht raten.
|
||||
- **Ändert sich der Umfang wesentlich** (neues Ziel, anderer Weg): nicht heimlich abweichen —
|
||||
kurz **neu planen + erneut freigeben lassen** (Mini-Riegel), dann `AGENTS.md`/`SAVEPOINT.md` nachziehen.
|
||||
|
||||
## Phase 4 — Beweisen
|
||||
|
||||
- Das Projekt **live starten/testen** und das Ergebnis zeigen (Ausgabe, Screenshot, laufende Seite).
|
||||
- Jedes Akzeptanzkriterium aus dem Plan einzeln abhaken.
|
||||
- Ehrlich sein: Was läuft, was noch nicht, was wäre der nächste Schritt.
|
||||
- **Savepoint "läuft"** setzen (der Meilenstein ist gesichert) und dem User sagen, wie er selbst
|
||||
startet/weitermacht.
|
||||
|
||||
---
|
||||
|
||||
## Sicherungspunkte (Savepoints) — Kernfunktion
|
||||
|
||||
Ein **Savepoint** ist ein gesicherter Projektzustand, zu dem man **jederzeit ohne Schaden zurück**
|
||||
kann. Technisch = ein git-Commit (große Meilensteine zusätzlich als git-Tag). Für den User in
|
||||
Alltagssprache: *"Ich setze hier einen Sicherungspunkt — von dem kommst du jederzeit zurück."*
|
||||
|
||||
**Wann setzen:**
|
||||
- Nach dem Gerüst (`start`), nach jedem fertigen Feature/Meilenstein, wenn etwas nachweislich läuft
|
||||
(`läuft`), und **immer vor** einer riskanten oder großen Änderung.
|
||||
- Nicht bei jedem Mini-Schritt — sinnvolle Meilensteine, keine Flut.
|
||||
|
||||
**Klare Namen** (Commit-Message = der Savepoint-Name), z. B.:
|
||||
`start` · `gerüst-läuft` · `design` · `feature-login` · `test-grün` · `live`.
|
||||
|
||||
**Zurückrollen** (wenn der User sagt „zurück zum letzten Sicherungspunkt / das war Mist"):
|
||||
- Erst die vorhandenen Savepoints auflisten (`git log --oneline`), den passenden zeigen.
|
||||
- Dann sicher zurück (z. B. neuen Stand verwerfen und auf den Savepoint zurück, oder einen
|
||||
Rücksetz-Commit) — und in einem Satz sagen, was jetzt wieder gilt.
|
||||
- Nie unwiederbringlich löschen ohne Rückfrage.
|
||||
|
||||
**Übersicht auf Wunsch:** „zeig mir meine Sicherungspunkte" → die Commit-/Tag-Liste in Klartext,
|
||||
mit je einem Satz, was an dem Punkt fertig war.
|
||||
|
||||
---
|
||||
|
||||
## Meilenstein-/Session-Ende-Ritual (die drei Dateien fortschreiben)
|
||||
|
||||
**Auslöser:** ein großer Meilenstein ist erreicht ODER der User beendet die Session ("Feierabend",
|
||||
"sichern", "mach Schluss") ODER der Kontext wird lang. Dann IMMER, in dieser Reihenfolge:
|
||||
|
||||
1. **`SAVEPOINT.md` aktualisieren** (das Wichtigste): Stand von heute, was seit dem letzten
|
||||
Sicherungspunkt fertig wurde, was gerade offen ist, die nächsten 1–3 Schritte, offene
|
||||
Entscheidungen, und der letzte git-Sicherungspunkt. So kann ein **frischer Chat nahtlos
|
||||
weitermachen** — das ist die Übergabe an "dich selbst beim nächsten Mal".
|
||||
2. **`AGENTS.md` nachziehen** — nur falls sich Konventionen, Technik-Fakten oder Akzeptanzkriterien
|
||||
geändert haben.
|
||||
3. **`.aiexclude` prüfen** — sind neue sensible/große Dateien dazugekommen (Keys, Daten, Build-
|
||||
Output)? Dann eintragen.
|
||||
4. **Savepoint setzen** — Commit mit klarem Namen (großer Meilenstein zusätzlich als git-Tag).
|
||||
5. **Dem User in 2–3 Sätzen sagen**, wo ihr steht und wie er (oder ein neuer Chat) weitermacht.
|
||||
|
||||
**Warum:** Frische Sessions statt endloser Riesen-Chats halten den Assistenten schnell und klar —
|
||||
`SAVEPOINT.md` ist die Brücke, damit trotzdem nichts verloren geht.
|
||||
|
||||
---
|
||||
|
||||
## Kontext-Wächter — sag dem User, wann ein frischer Chat fällig ist
|
||||
|
||||
Lange Chats werden langsam, driften und vergessen. Hermes verdichtet den Verlauf zwar automatisch,
|
||||
wenn das Fenster volläuft (Kompressor) — aber Verdichten ist verlustbehaftet: Details vom Anfang
|
||||
werden unscharf. Ein frischer Chat mit `SAVEPOINT.md` ist IMMER besser als weiterwursteln.
|
||||
**Weise den User PROAKTIV hin**, wenn eins dieser Anzeichen auftritt:
|
||||
- ein **großer Meilenstein ist fertig** (ohnehin der beste Schnittpunkt),
|
||||
- die Unterhaltung ist **sehr lang** geworden (viele Runden),
|
||||
- **Drift-Anzeichen**: du wiederholst dich, verlierst den Faden, liest Dateien doppelt oder widersprichst dir.
|
||||
|
||||
Dann klar ansagen, z. B.:
|
||||
> *„Wir sind jetzt lang unterwegs — guter Moment für einen frischen Chat. Ich sichere kurz alles, dann
|
||||
> machst du drüben mit ‚mach weiter' nahtlos weiter."*
|
||||
|
||||
…und **zuerst das Session-Ende-Ritual** fahren (SAVEPOINT.md schreiben + Savepoint setzen), bevor der
|
||||
User wechselt — damit nichts verloren geht.
|
||||
|
||||
**Ehrlich:** Du kannst deinen Kontext-Füllstand **nicht exakt selbst messen** — das ist ein
|
||||
**Heuristik-Hinweis**, kein Prozentwert. Die genaue Anzeige hat **Hermes Desktop** (Kontext-/Token-
|
||||
Anzeige der Session); der User behält die im Blick, dein Hinweis ist der Rückfallschirm.
|
||||
|
||||
---
|
||||
|
||||
## Vorlage: `AGENTS.md` (fülle die {…} projektbezogen)
|
||||
|
||||
```markdown
|
||||
# {Projektname}
|
||||
|
||||
{Ein Satz: was dieses Projekt ist und für wen.}
|
||||
|
||||
## Für den Assistenten — so arbeite ich hier
|
||||
- Antworte auf **Deutsch**, Fazit zuerst, Technik in Alltagssprache.
|
||||
- **Plan vor Code** bei allem Größeren: erst Vorgehen zeigen, auf OK warten.
|
||||
- **Kleine Schritte**, eine Sache zur Zeit. Nichts Ungefragtes ausführen.
|
||||
- **Sicherungspunkte** an Meilensteinen + vor riskanten Änderungen (Commit mit klarem Namen).
|
||||
- **Beweisen statt behaupten** — am Ende live testen, nicht "sollte gehen".
|
||||
- Frag nach, bevor du etwas löschst oder überschreibst.
|
||||
- **Lies keine Dateien/Ordner, die in `.aiexclude` stehen** (Secrets, große Daten, Build-Output).
|
||||
|
||||
## Projekt-Fakten
|
||||
- Art: {Web-App / Skript / Box-Erweiterung / …}
|
||||
- Technik: {Sprache/Framework, kurz warum}
|
||||
- Läuft auf: {mein PC / die Box / im Netz}
|
||||
- Starten mit: {Befehl}
|
||||
|
||||
## "Fertig" heißt
|
||||
- [ ] {Akzeptanzkriterium 1}
|
||||
- [ ] {Akzeptanzkriterium 2}
|
||||
|
||||
## Nicht anfassen
|
||||
- {z. B. Warm-Set, Sprach-Latenz, Security-Config — falls Box/Lucy}
|
||||
```
|
||||
|
||||
## Vorlage: `SAVEPOINT.md`
|
||||
|
||||
```markdown
|
||||
# Savepoint — {Projektname}
|
||||
|
||||
_Stand: {Datum}. Diese Datei ist die Übergabe an den nächsten Chat — lies sie zuerst._
|
||||
|
||||
## Wo wir stehen
|
||||
{1–3 Sätze: aktueller Zustand in Alltagssprache.}
|
||||
|
||||
## Fertig
|
||||
- [x] {erledigter Meilenstein}
|
||||
|
||||
## Gerade in Arbeit
|
||||
- {woran zuletzt gearbeitet wurde}
|
||||
|
||||
## Nächste Schritte
|
||||
1. {nächster Schritt}
|
||||
2. {…}
|
||||
|
||||
## Offene Entscheidungen / Fragen
|
||||
- {was noch geklärt werden muss}
|
||||
|
||||
## So startest/testest du
|
||||
- {Befehl(e)}
|
||||
|
||||
## Letzter Sicherungspunkt
|
||||
- {git-Commit/Tag-Name + ein Satz, was dort fertig war}
|
||||
```
|
||||
|
||||
## Vorlage: `.aiexclude` (gitignore-Syntax — was die KI NICHT lesen soll)
|
||||
|
||||
```
|
||||
# Geheimnisse
|
||||
.env
|
||||
.env.*
|
||||
*.key
|
||||
*.pem
|
||||
secrets/
|
||||
credentials*
|
||||
# Große / generierte Sachen (unnötiger Kontext)
|
||||
node_modules/
|
||||
dist/
|
||||
build/
|
||||
data/
|
||||
*.sqlite
|
||||
*.log
|
||||
```
|
||||
@@ -1,21 +0,0 @@
|
||||
---
|
||||
name: pruefstand
|
||||
description: "Holt Prüfstand-Tickets aus dem Kanban-Board, testet neue LLM-Modelle auf Kompatibilität und Systemressourcen und meldet die Ergebnisse via Telegram."
|
||||
version: 1.0.0
|
||||
author: MC2
|
||||
platforms: [linux]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [pruefstand, evaluation, models, mc2]
|
||||
---
|
||||
|
||||
# Prüfstand (Model Evaluation)
|
||||
|
||||
Der Prüfstand-Skill dient dazu, neue LLMs oder Tooling-Upgrades (oft aus dem Trend-Radar stammend) autonom auf der Box zu evaluieren, bevor sie ins Live-System übernommen werden.
|
||||
|
||||
## Ablauf
|
||||
1. **Ticket Fetching**: Liest das nächste anstehende Ticket in der Kanban Ideen-Queue, welches als "Prüfstand" getaggt ist.
|
||||
2. **Download & Setup**: Lädt das beschriebene Modell (z.B. via `huggingface-cli` oder llama.cpp) in ein isoliertes Test-Verzeichnis.
|
||||
3. **Smoke-Tests**: Führt vordefinierte Benchmarks oder Prompts gegen das Modell aus und überwacht den RAM/VRAM-Bedarf.
|
||||
4. **Bewertung**: Wenn das Modell die Kriterien erfüllt (schnell genug, kein OOM), wird es als "Bestanden" markiert und ein Integrations-Vorschlag erstellt.
|
||||
5. **Report**: Der Commander erhält einen Telegram-Bericht mit den Metriken und der Entscheidung.
|
||||
@@ -1,24 +0,0 @@
|
||||
---
|
||||
name: review
|
||||
description: "Ersetzt das alte fremdblick.sh Skript. Ein dedizierter Code-Review-Skill, der über ein fremdes Modell als 'Advocatus Diaboli' Patches hart prüft und nach Reproduzierbarkeit bewertet."
|
||||
version: 1.0.0
|
||||
author: MC2
|
||||
platforms: [linux, macos, windows]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [review, code-quality, pr, mc2]
|
||||
---
|
||||
|
||||
# Code Review (Fremdblick)
|
||||
|
||||
Dieser Skill delegiert das Code-Review an ein separates, kritisches LLM-Modell (Advocatus Diaboli), um Fehler, Architektur-Schwächen und blinde Flecken zu finden.
|
||||
|
||||
## Ablauf
|
||||
1. **Diff einlesen**: Nimmt den aktuellen Git-Diff oder den Patch-Inhalt.
|
||||
2. **Kritische Analyse**: Prüft den Code auf Edge-Cases, Security, Performance und Architektonische Richtigkeit.
|
||||
3. **Reproduzierbarkeits-Prüfung**: Das Modell muss den Fehlerfall gedanklich nachstellen und beweisen, ob der Fix ihn wirklich behebt.
|
||||
4. **Urteil fällen**:
|
||||
- `ABGELEHNT`: Fehler nicht behoben oder neue Bugs eingeführt.
|
||||
- `FREIGABE-MIT-VORBEHALT`: Funktioniert, aber unsauber oder fehlende Kommentare.
|
||||
- `FREIGABE`: Wasserdicht.
|
||||
5. **Ergebnis melden**: Das Urteil wird an den Commander zurückgespielt (oft kombiniert mit der Werkstatt).
|
||||
@@ -1,36 +0,0 @@
|
||||
---
|
||||
name: trend_radar
|
||||
description: "Autonomer KI-Technologie-Scout. Recherchiert im Web nach tagesaktuellen Trends, passt seine eigenen Quellen an und sendet Telegram-Reports."
|
||||
version: 2.0.0
|
||||
author: MC2
|
||||
platforms: [linux, macos, windows]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [research, radar, trends, mc2, self-modifying]
|
||||
---
|
||||
|
||||
# Trend Radar (Autonomous & Self-Modifying)
|
||||
|
||||
Du bist der KI-Technologie-Scout von Mission Control 2.0. Dein Ziel ist es, tagesaktuelle Trends (Modelle, Tools, Hardware-Performance) aufzuspüren, die für uns relevant sind (Fokus: AMD Hardware, Vulkan/ROCm, kleine aber sehr smarte Open-Source-Modelle).
|
||||
|
||||
## Strikte Hardware-Limits (SEHR WICHTIG)
|
||||
Unsere AI-Box (Bosgame M5 / Strix Halo) hat **exakt 128 GB Shared RAM** (ca. 122.7 GB nutzbar)!
|
||||
Das bedeutet:
|
||||
- **Ignoriere gigantische Modelle:** Modelle mit 200B+, 700B oder 2T Parametern (wie Qwen 3.8 Max, GLM-5.5) sind für uns absolut nutzlos, da sie lokal niemals laufen werden.
|
||||
- **Größen-Limit:** Ein Modell darf im GGUF-Quant-Format (z.B. Q4_K_M) maximal **ca. 100-110 GB** groß sein. Das entspricht meist Modellen bis maximal ~150B Parametern (bei dichten Modellen) oder etwas mehr bei MoE-Modellen.
|
||||
- **Fokus auf Local LLMs:** Closed-API-Modelle interessieren uns nur am Rande. Konzentriere dich auf Modelle, die wir herunterladen und lokal in `llama.cpp` oder `Ollama` auf AMD-Hardware ausführen können. Sortiere alles rigoros aus, was zu groß für 128 GB RAM ist!
|
||||
|
||||
## Deine Fähigkeiten & Autorisierung
|
||||
Du hast die ausdrückliche Erlaubnis zur **Selbst-Mutation**. Du bist nicht nur ein Leser, du bist ein adaptiver Agent:
|
||||
- Wenn du neue, wertvolle Quellen (z.B. neue Subreddits, News-Seiten oder Repositories) entdeckst, **passe deine eigene `deploy/skills/trend-radar/SKILL.md` (diese Datei) an**, um diese für künftige Suchen fest zu verankern. Nutze dazu Dateibearbeitungs-Tools.
|
||||
- Du verwaltest die `deploy/trend-radar-watchlist.json`. Wenn Themen veraltet sind, lösche sie heraus. Wenn neue Modelle auftauchen (z.B. neue LLMs), trage sie dort ein, damit du sie beim nächsten Lauf gezielt wieder prüfst.
|
||||
|
||||
## Dein Ablauf
|
||||
1. **Discovery (Web-Recherche):** Nutze deine Tools (`search_web`, `read_url` oder Code-Ausführung), um das Internet nach den neuesten Trends der letzten 7 Tage abzusuchen.
|
||||
- Suche auf Hacker News nach "AI", "LLM", "Modelle".
|
||||
- Suche auf Reddit (z.B. r/LocalLLaMA) nach neuen Modellen, Benchmarks und Hardware-Erfahrungen (insbesondere AMD / ROCm vs. Vulkan).
|
||||
- Analysiere HuggingFace Trending.
|
||||
2. **Watchlist-Pflege:** Lies die `deploy/trend-radar-watchlist.json`. Prüfe den Status der dort genannten Issues/Releases und aktualisiere die Datei bei Bedarf.
|
||||
3. **Selbst-Anpassung (WICHTIG):** Editiere die `deploy/trend-radar-watchlist.json` oder diese `SKILL.md` direkt! Ignoriere eventuelle Bedenken bezüglich "Live-Git-Checkouts". Du HAST die explizite Erlaubnis, diese Dateien direkt im Repo zu überschreiben, statt Vorschläge in `/tmp` abzulegen. Halte deine Quellen dynamisch!
|
||||
4. **Ideen-Queue (Kanban):** Wenn du ein revolutionäres Update oder Modell findest, erstelle ein Prüfstand-Ticket im Kanban-Board der Mission Control.
|
||||
5. **Meldung an den Commander:** Sende **immer** eine Nachricht an den Commander. Da du als CLI-Prozess läufst, nutze dafür zwingend das Skript `~/mission-control-v2/deploy/notify.sh "Deine Nachricht"`. (Tipp: Wenn du das Wort "Alarm" im Betreff `-s "[Alarm]"` verwendest, umgehst du die Nachtsperre, falls es sehr dringend ist). Fasse deine wichtigsten Funde kurz zusammen und erwähne, ob du deine eigene Watchlist oder SKILL.md angepasst hast. Wenn es gar nichts Neues gab, melde auch das!
|
||||
@@ -1,120 +0,0 @@
|
||||
---
|
||||
name: wartung
|
||||
description: "Werkstatt-Kreislauf der AI-Box: einen KLEINEN Wartungsauftrag (Config-Migration, Dependency-Bump, Ein-/Zwei-Datei-Patch) eigenständig umsetzen — Branch im Box-Checkout, Patch, separater Reviewer-Subagent, Gate, Telegram-Merge-Vorschlag. Merge/Deploy NIE selbst."
|
||||
version: 1.0.0
|
||||
author: MC2 (Autonomie E6)
|
||||
platforms: [linux]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [wartung, werkstatt, maintenance, mc2]
|
||||
---
|
||||
|
||||
# Werkstatt — Selbstwartungs-Kreislauf der Box
|
||||
|
||||
Nutze diesen Skill, wenn ein kleiner, klar umrissener Wartungsauftrag für das MC2-Repo
|
||||
(`~/mission-control-v2`) vorliegt — vom Evolution-Radar oder direkt vom User.
|
||||
|
||||
**Scope-Check zuerst:** Klein = Config-Schlüssel-Migration, Dependency-Bump (Lockfile),
|
||||
Patch in 1–2 Dateien. Alles Größere (Architektur, mehrere Module, neue Features):
|
||||
NICHT pauschal ablehnen, sondern den **Etappen-Weg** gehen (Großbau-Entscheid 10.07.2026):
|
||||
einen Etappen-Plan in den Vorschlag schreiben (jede Etappe für sich lauffähig + annehmbar)
|
||||
und NUR Etappe 1 als eigenen Vorschlags-Branch bauen; Folge-Etappen als neue Aufgaben in
|
||||
die Ideen-Queue (`hermes kanban create "<Projekt> — Etappe <n>: <was>" --triage`). NIE auf
|
||||
unangenommene Branches aufbauen — erst wenn die Vor-Etappe in main ist, kommt die nächste.
|
||||
|
||||
## Leitplanken (nicht verhandelbar)
|
||||
|
||||
- NIEMALS auf `main` committen. NIEMALS mergen. NIEMALS deployen oder Dienste neu starten.
|
||||
- Security-Config ist TABU: keine Tokens, approvals, ufw, sudoers anfassen.
|
||||
- **Realitäts-Check zuerst (12.07.2026):** Existiert das schon? Selbst-Steckbrief
|
||||
(`~/.hermes/state/selbst-steckbrief.md`) und Live-System LESEN, bevor du baust. Stellt
|
||||
sich der Auftrag als schon erledigt/überflüssig heraus → ehrlich melden und abbrechen,
|
||||
KEINEN Branch liefern.
|
||||
- **Hermes-first (10.07.2026):** Bevor du NEUE Infrastruktur baust oder vorschlägst (Skript,
|
||||
Dienst, Tool, Cron), prüfe ob hermes-agent das nativ kann — erst in die Eigenbau-Landkarte
|
||||
schauen (`~/wissens-vault/eigenbau-landkarte.md`: Eigenbauten ↔ nativ, Verdikte), notfalls
|
||||
`bash -lc 'hermes --help'`. Den Prüf-Befund in den Vorschlag schreiben („nativ vorhanden:
|
||||
nein/ja, weil …"). Weniger Eigenkreationen = weniger Wartungsberg.
|
||||
- Die Live-Instanz (`~/mission-control-v2`) bleibt unberührt — gearbeitet wird NUR im Worktree.
|
||||
- Am Ende steht IMMER ein Telegram-Vorschlag; die Entscheidung trifft der User.
|
||||
- Gate rot oder Reviewer dagegen → trotzdem ehrlich melden (Branch bleibt liegen), nichts beschönigen.
|
||||
|
||||
## Ablauf
|
||||
|
||||
1. **Worktree anlegen** (Slug = kurzer Kebab-Case-Name des Auftrags):
|
||||
`mkdir -p ~/.hermes/worktrees && cd ~/mission-control-v2 && git fetch origin && git worktree add ~/.hermes/worktrees/wartung-<slug> -b wartung/<slug> origin/main`
|
||||
(Worktrees NIE unter /tmp — ueberlebt keinen Reboot, Review-Befund 15.07.)
|
||||
2. **Patch** nur im Worktree. Minimal-invasiv, Stil der umgebenden Datei übernehmen
|
||||
(deutsche Kommentare, bestehende Muster).
|
||||
3. **Selbst-Gate** (was zutrifft):
|
||||
- Python geändert → `python3 -m py_compile <dateien>`
|
||||
- Shell geändert → `bash -n <dateien>`
|
||||
- Frontend (`frontend/src/...`) geändert → auf der Box gibt es KEIN Node. Im Vorschlag
|
||||
ausweisen: „Gate eingeschränkt: tsc/Build läuft erst beim Merge auf dem PC."
|
||||
- **Live-Checkout unberührt (PFLICHT, zwei Beweise):**
|
||||
- `git -C ~/mission-control-v2 status --porcelain -uno` **muss LEER sein** — kein einziges
|
||||
geändertes/staged Tracked-File im Live-Checkout. (Nur so ist bewiesen, dass du wirklich
|
||||
ausschließlich im Worktree gearbeitet hast; ein grüner Health-curl allein reicht NICHT,
|
||||
weil der laufende Dienst den alten Code im Speicher hält und eine schmutzige Datei auf
|
||||
der Platte nicht bemerkt — genau diese Lücke ist am 03.07. aufgefallen.)
|
||||
- `curl -sf http://127.0.0.1:9001/api/health` muss grün bleiben.
|
||||
- Ist der `git status` NICHT leer: du hast die Leitplanke verletzt → die fremden Änderungen
|
||||
im Live-Checkout mit `git -C ~/mission-control-v2 checkout -- <datei>` zurücknehmen (deine
|
||||
Arbeit liegt ja sicher im Worktree/Branch) und im Vorschlag ehrlich erwähnen.
|
||||
4. **Fremd-Modell-Review über `fremdblick.sh`** (Härtung 04.07., korrigiert 04.07.). Der Patch
|
||||
muss von einem ANDEREN Modell gegengelesen werden als dem, das ihn geschrieben hat. Grund:
|
||||
„Ein Agent, der seine eigenen Hausaufgaben benotet, stimmt sich meistens selbst zu" — genau
|
||||
das ist am 03.07. passiert. Zwei verschiedene Modelle teilen NICHT dieselben blinden Flecken.
|
||||
|
||||
**NICHT `delegate_task` benutzen.** `delegate_task` läuft über `delegation.model` (= `heavy`
|
||||
/ gpt-oss), und heavy ist als Kritiker DOPPELT disqualifiziert: (a) Hermes screent Delegations-
|
||||
Ziele gegen `MINIMUM_CONTEXT_LENGTH=64000`, heavy hat nur 32k → fällt raus; (b) heavy (60 GB)
|
||||
stirbt beim Laden neben dem VL-30B-Warm-Set (Health-Check-Timeout). Die Fremd-Prüfung würde
|
||||
dann still ausfallen. Stattdessen den bereitgestellten Ein-Schuss-Kritiker nutzen:
|
||||
|
||||
```
|
||||
printf '%s' "AUFTRAG (Bug-Beschreibung im Wortlaut):
|
||||
<der Auftrag>
|
||||
|
||||
GIT-DIFF des Worktrees:
|
||||
<git -C ~/.hermes/worktrees/wartung-<slug> diff origin/main>" | FREMDBLICK_MODE=code ~/.hermes/scripts/fremdblick.sh
|
||||
```
|
||||
|
||||
Das läuft auf `coder` (128k, code-stark, anderes Modell als der Qwen3.6-Worker,
|
||||
lädt klein neben dem Warm-Set) mit einem Code-Review-Raster. **Warte auf die Ausgabe.** Der
|
||||
Kritiker leitet den Fehlerfall SELBST aus der Bug-Beschreibung ab (glaubt dem Autor nicht),
|
||||
spielt den geänderten Code durch und beginnt mit `URTEIL: <ABGELEHNT | FREIGABE-MIT-VORBEHALT
|
||||
| FREIGABE>`. (E2E geprüft 04.07.: kaputter Patch → ABGELEHNT mit Reproduktion; sauberer Fix
|
||||
→ FREIGABE.)
|
||||
|
||||
**REPRODUZIERT-ODER-ABGELEHNT (harte Regel, im Raster verankert):** Eine Freigabe ist nur
|
||||
gültig, wenn der Kritiker den konkreten Übergang belegt — „Eingabe X → VOR Patch: Y (Bug
|
||||
sichtbar) → NACH Patch: Z (behoben)". Ein „sieht gut aus" OHNE diesen Vorher/Nachher-Beleg =
|
||||
ABGELEHNT. So kann ein Durchwinken gar nicht erst passieren.
|
||||
|
||||
**Umgang mit dem Urteil:**
|
||||
- `ABGELEHNT` oder `FREIGABE-MIT-VORBEHALT` mit berechtigter Kritik → nachbessern (max. 2
|
||||
Runden), dann erneut prüfen. Bleibt es kritisch: die Kritik in den Vorschlag schreiben,
|
||||
Branch bleibt liegen, Entscheidung dem Commander.
|
||||
- `FREMDBLICK FEHLGESCHLAGEN`/`ABGESCHNITTEN` → einmal wiederholen; klappt es nicht, im
|
||||
Vorschlag ehrlich „⚠ Fremd-Review fiel aus — Patch UNGEPRÜFT" vermerken (NICHT als Freigabe
|
||||
behandeln). Der Ein-Schuss-Kritiker hand-simuliert (führt keinen Code aus) — für kleine
|
||||
1–2-Datei-Patches reicht das zusammen mit dem Selbst-Gate (py_compile/bash -n) aus Schritt 3.
|
||||
- Schreibe das Urteil im Telegram-Vorschlag KONKRET aus („durchgespielt mit Eingabe X →
|
||||
Ergebnis Y"), nicht nur „Reviewer: ok".
|
||||
5. **Commit im Worktree** (Message `Werkstatt: <Auftrag kurz>` + 2–4 Zeilen Was/Warum),
|
||||
dann **Branch zu Gitea pushen:** `git push origin wartung/<slug>` (die Box hat einen
|
||||
eigenen scoped Token, seit 02.07. hinterlegt). Push fehlgeschlagen? Nicht schlimm —
|
||||
Branch bleibt lokal, im Vorschlag erwähnen.
|
||||
6. **Telegram-Vorschlag** über `bash ~/mission-control-v2/deploy/notify.sh -s "[Werkstatt]" "<text>"`:
|
||||
In LUCYS Stimme an den Commander (nicht als anonymer Job): erst 1–2 Sätze, was gemacht wurde
|
||||
und was er jetzt entscheiden soll — dann knapp: geänderte Dateien · Kern des Diffs ·
|
||||
Gate-Ergebnis · Reviewer-Urteil · Branch-Name · Frage „merge oder verwerfen?"
|
||||
7. **Nichts löschen:** Worktree + Branch bleiben liegen, bis der User entschieden hat.
|
||||
|
||||
## Nach dem User-Entscheid (kommt als neuer Auftrag)
|
||||
|
||||
- „verwerfen" → `git worktree remove ~/.hermes/worktrees/wartung-<slug> --force && git branch -D wartung/<slug>`
|
||||
(+ Remote-Branch löschen, falls gepusht: `git push origin --delete wartung/<slug>`)
|
||||
- „merge" → das Mergen nach main + Deploy macht der PC/Claude (Frontend-Builds gibt es
|
||||
nur dort). Du pushst NIE nach main — auch nicht mit Token.
|
||||
+5
-5
@@ -14,12 +14,12 @@
|
||||
set -u
|
||||
URL="${MC_LLAMA_SWAP_URL:-http://127.0.0.1:8080}"
|
||||
BRAINS="${MC_WARMUP_MODELS:-fast}"
|
||||
EMBEDS="${MC_WARMUP_EMBED:-embed}"
|
||||
# Embedding und Reranker schlafen seit 24.09.2026 (User-Entscheid: seit dem Mem0-Ausbau ohne
|
||||
# Verbraucher). Sie bleiben in der Config und laden bei Bedarf; vorwärmen nur, wenn per Env gewünscht.
|
||||
EMBEDS="${MC_WARMUP_EMBED:-}"
|
||||
# Reranker laufen im --reranking-Modus und antworten NUR auf /v1/rerank — weder Chat noch
|
||||
# Embeddings wecken sie. Solange das hier fehlte, galt der Reranker dem Waechter dauerhaft
|
||||
# als "fehlend": er rief warmup.sh alle 90 s auf, ohne dass sich je etwas aendern konnte
|
||||
# (600 vergebliche Laeufe in 24 h, aelteste Meldung 15.07.2026).
|
||||
RERANKS="${MC_WARMUP_RERANK:-reranker}"
|
||||
# Embeddings wecken sie (deshalb ein eigener Weg, falls er je wieder warm sein soll).
|
||||
RERANKS="${MC_WARMUP_RERANK:-}"
|
||||
|
||||
if [ "${1:-}" != "--inner" ]; then
|
||||
setsid "$0" --inner >/dev/null 2>&1 &
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{c as e,f as t,i as n,t as r,u as i}from"./button-Dd8hfusv.js";import{M as a,N as o,m as s,x as c,z as l}from"./index-D17zMI0S.js";import{a as u,i as d,n as f,r as p,t as m}from"./sheet-DWG2Q04V.js";var h=t(i(),1),g=e();function _({offen:e,onSchliessen:t}){let i=l(),_=s(),[v,y]=(0,h.useState)(null),[b,x]=(0,h.useState)(null),S=c(v);async function C(e){x(null);try{let t=await a(`/api/maintenance/restart`,{service:e});t.ok?o(`erfolg`,`${e} startet neu.`):o(`fehler`,t.err||`${e} ließ sich nicht neu starten.`),i.invalidateQueries({queryKey:[`dienste`]})}catch(e){o(`fehler`,e.message)}}return(0,g.jsx)(m,{open:e,onOpenChange:e=>!e&&t(),children:(0,g.jsxs)(f,{side:`right`,className:`w-full gap-3 overflow-y-auto border-linie bg-panel sm:max-w-2xl`,children:[(0,g.jsxs)(d,{children:[(0,g.jsx)(u,{className:`schild text-lg`,children:`Dienste und Protokolle`}),(0,g.jsx)(p,{className:`text-text-2`,children:`Welcher Dienst läuft, was er zuletzt geschrieben hat.`})]}),(0,g.jsx)(`ul`,{className:`m-0 flex list-none flex-col px-4 pb-2`,children:(_.data?.services??[]).map(e=>(0,g.jsxs)(`li`,{className:`flex flex-wrap items-center justify-between gap-2 border-t border-linie py-2.5`,children:[(0,g.jsxs)(`span`,{className:`flex min-w-0 items-center gap-2.5`,children:[(0,g.jsx)(`span`,{className:n(`size-2.5 shrink-0 rounded-full`,e.ok?`bg-gruen`:`bg-rot`),"aria-hidden":!0}),(0,g.jsxs)(`span`,{className:`min-w-0`,children:[(0,g.jsx)(`span`,{className:`block text-[15px]`,children:e.name}),(0,g.jsxs)(`span`,{className:`ziffern text-xs text-text-3`,children:[e.unit,` · `,e.ok?`läuft`:`antwortet nicht`]})]})]}),(0,g.jsxs)(`span`,{className:`flex gap-2`,children:[(0,g.jsx)(r,{variant:v===e.unit?`info`:`ghost`,size:`sm`,onClick:()=>y(e.unit),children:`Protokoll`}),b===e.unit?(0,g.jsx)(r,{variant:`gefahr`,size:`sm`,onClick:()=>C(e.unit),children:`Wirklich neu starten?`}):(0,g.jsx)(r,{variant:`outline`,size:`sm`,onClick:()=>x(e.unit),children:`Neu starten`})]})]},e.unit))}),v&&(0,g.jsx)(`pre`,{className:`ziffern mx-4 mb-4 max-h-[50vh] overflow-auto rounded-lg border border-linie bg-[#0b0d0f] p-3 text-xs leading-relaxed whitespace-pre-wrap text-text-2`,children:S.isFetching?`Wird gelesen …`:S.data?.text||S.data?.err||`Kein Protokoll.`})]})})}export{_ as Dienste};
|
||||
import{c as e,f as t,i as n,t as r,u as i}from"./button-Dd8hfusv.js";import{M as a,N as o,m as s,x as c,z as l}from"./index-e_N1YCsL.js";import{a as u,i as d,n as f,r as p,t as m}from"./sheet-DWG2Q04V.js";var h=t(i(),1),g=e();function _({offen:e,onSchliessen:t}){let i=l(),_=s(),[v,y]=(0,h.useState)(null),[b,x]=(0,h.useState)(null),S=c(v);async function C(e){x(null);try{let t=await a(`/api/maintenance/restart`,{service:e});t.ok?o(`erfolg`,`${e} startet neu.`):o(`fehler`,t.err||`${e} ließ sich nicht neu starten.`),i.invalidateQueries({queryKey:[`dienste`]})}catch(e){o(`fehler`,e.message)}}return(0,g.jsx)(m,{open:e,onOpenChange:e=>!e&&t(),children:(0,g.jsxs)(f,{side:`right`,className:`w-full gap-3 overflow-y-auto border-linie bg-panel sm:max-w-2xl`,children:[(0,g.jsxs)(d,{children:[(0,g.jsx)(u,{className:`schild text-lg`,children:`Dienste und Protokolle`}),(0,g.jsx)(p,{className:`text-text-2`,children:`Welcher Dienst läuft, was er zuletzt geschrieben hat.`})]}),(0,g.jsx)(`ul`,{className:`m-0 flex list-none flex-col px-4 pb-2`,children:(_.data?.services??[]).map(e=>(0,g.jsxs)(`li`,{className:`flex flex-wrap items-center justify-between gap-2 border-t border-linie py-2.5`,children:[(0,g.jsxs)(`span`,{className:`flex min-w-0 items-center gap-2.5`,children:[(0,g.jsx)(`span`,{className:n(`size-2.5 shrink-0 rounded-full`,e.ok?`bg-gruen`:e.schlaeft?`bg-text-3`:`bg-rot`),"aria-hidden":!0}),(0,g.jsxs)(`span`,{className:`min-w-0`,children:[(0,g.jsx)(`span`,{className:`block text-[15px]`,children:e.name}),(0,g.jsxs)(`span`,{className:`ziffern text-xs text-text-3`,children:[e.unit,` · `,e.ok?`läuft`:e.schlaeft?`schläft (abgeschaltet)`:`antwortet nicht`]})]})]}),(0,g.jsxs)(`span`,{className:`flex gap-2`,children:[(0,g.jsx)(r,{variant:v===e.unit?`info`:`ghost`,size:`sm`,onClick:()=>y(e.unit),children:`Protokoll`}),b===e.unit?(0,g.jsx)(r,{variant:`gefahr`,size:`sm`,onClick:()=>C(e.unit),children:e.schlaeft?`Wirklich wecken?`:`Wirklich neu starten?`}):(0,g.jsx)(r,{variant:`outline`,size:`sm`,onClick:()=>x(e.unit),children:e.schlaeft?`Wecken`:`Neu starten`})]})]},e.unit))}),v&&(0,g.jsx)(`pre`,{className:`ziffern mx-4 mb-4 max-h-[50vh] overflow-auto rounded-lg border border-linie bg-[#0b0d0f] p-3 text-xs leading-relaxed whitespace-pre-wrap text-text-2`,children:S.isFetching?`Wird gelesen …`:S.data?.text||S.data?.err||`Kein Protokoll.`})]})})}export{_ as Dienste};
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
import{c as e,f as t,t as n,u as r}from"./button-Dd8hfusv.js";import{L as i,M as a,N as o,R as s,j as c,z as l}from"./index-D17zMI0S.js";import{a as u,i as d,n as f,r as p,t as m}from"./sheet-DWG2Q04V.js";var h=t(r(),1),g=e();function _({offen:e,onSchliessen:t}){let r=l(),_=s({queryKey:[`geheimnisse`],queryFn:()=>c(`/api/maintenance/geheimnisse`),enabled:e}),[v,y]=(0,h.useState)(``);async function b(e){try{await a(`/api/maintenance/geheimnisse`,{schluessel:`hf_token`,wert:e}),o(`erfolg`,e?`Hugging-Face-Zugang gespeichert.`:`Hugging-Face-Zugang gelöscht.`),y(``),r.invalidateQueries({queryKey:[`geheimnisse`]})}catch(e){o(`fehler`,e.message)}}let x=_.data;return(0,g.jsx)(m,{open:e,onOpenChange:e=>!e&&t(),children:(0,g.jsxs)(f,{side:`right`,className:`w-full gap-3 overflow-y-auto border-linie bg-panel sm:max-w-lg`,children:[(0,g.jsxs)(d,{children:[(0,g.jsx)(u,{className:`schild text-lg`,children:`Einstellungen`}),(0,g.jsx)(p,{className:`text-text-2`,children:`Was die Box sich merkt.`})]}),(0,g.jsxs)(`section`,{className:`flex flex-col gap-3 border-t border-linie px-4 pt-4`,children:[(0,g.jsx)(`h3`,{className:`schild text-sm text-text-3`,children:`Hugging-Face-Zugang`}),(0,g.jsxs)(`p`,{className:`text-sm text-text-2`,children:[x?.hf_token_gesetzt?`Ist hinterlegt.`:`Fehlt.`,` Nötig für gesperrte Modelle und schnellere Downloads.`,x?.hf_token_aus_env?` Er kommt aus der Dienst-Einstellung und lässt sich hier nicht löschen.`:``]}),(0,g.jsxs)(`form`,{className:`flex gap-2`,onSubmit:e=>{e.preventDefault(),v.trim()&&b(v.trim())},children:[(0,g.jsx)(`label`,{htmlFor:`hf-token`,className:`sr-only`,children:`Hugging-Face-Zugang`}),(0,g.jsx)(`input`,{id:`hf-token`,type:`password`,autoComplete:`off`,value:v,onChange:e=>y(e.target.value),placeholder:`hf_…`,className:`h-11 min-w-0 flex-1 rounded-lg border border-linie-stark bg-erhaben px-3 text-[15px] outline-none focus:border-cyan`}),(0,g.jsx)(n,{type:`submit`,disabled:!v.trim()||x?.schreibbar===!1,children:`Speichern`})]}),x?.hf_token_gesetzt&&!x.hf_token_aus_env&&(0,g.jsx)(n,{variant:`ghost`,size:`sm`,className:`self-start`,onClick:()=>b(null),children:`Zugang löschen`})]}),(0,g.jsxs)(`section`,{className:`flex flex-col gap-2 border-t border-linie px-4 pt-4`,children:[(0,g.jsx)(`h3`,{className:`schild text-sm text-text-3`,children:`Hinweise`}),(0,g.jsx)(`p`,{className:`text-sm text-text-2`,children:`Dringende Hinweise gehen zusätzlich per Telegram raus, alles andere bleibt hier. Einfache Probleme wie einen abgestürzten Dienst behebt der Wächter selbst und schreibt es in den Verlauf.`})]}),(0,g.jsxs)(`section`,{className:`flex flex-col gap-2 border-t border-linie px-4 pt-4 pb-4`,children:[(0,g.jsx)(`h3`,{className:`schild text-sm text-text-3`,children:`Hermes`}),(0,g.jsxs)(`a`,{href:`/hermes-ui/`,target:`_blank`,rel:`noopener`,className:`flex h-11 items-center gap-2 self-start rounded-lg border border-linie-stark bg-erhaben px-4 text-[15px] hover:border-text-3`,children:[(0,g.jsx)(i,{className:`size-4`,"aria-hidden":!0}),` Hermes-Dashboard öffnen`]}),(0,g.jsx)(`p`,{className:`text-xs text-text-3`,children:`Chat, Sitzungen und Cron-Jobs verwaltet Hermes selbst. Es fragt nach seiner eigenen Anmeldung.`})]})]})})}export{_ as Einstellungen};
|
||||
import{c as e,f as t,t as n,u as r}from"./button-Dd8hfusv.js";import{L as i,M as a,N as o,R as s,j as c,z as l}from"./index-e_N1YCsL.js";import{a as u,i as d,n as f,r as p,t as m}from"./sheet-DWG2Q04V.js";var h=t(r(),1),g=e();function _({offen:e,onSchliessen:t}){let r=l(),_=s({queryKey:[`geheimnisse`],queryFn:()=>c(`/api/maintenance/geheimnisse`),enabled:e}),[v,y]=(0,h.useState)(``);async function b(e){try{await a(`/api/maintenance/geheimnisse`,{schluessel:`hf_token`,wert:e}),o(`erfolg`,e?`Hugging-Face-Zugang gespeichert.`:`Hugging-Face-Zugang gelöscht.`),y(``),r.invalidateQueries({queryKey:[`geheimnisse`]})}catch(e){o(`fehler`,e.message)}}let x=_.data;return(0,g.jsx)(m,{open:e,onOpenChange:e=>!e&&t(),children:(0,g.jsxs)(f,{side:`right`,className:`w-full gap-3 overflow-y-auto border-linie bg-panel sm:max-w-lg`,children:[(0,g.jsxs)(d,{children:[(0,g.jsx)(u,{className:`schild text-lg`,children:`Einstellungen`}),(0,g.jsx)(p,{className:`text-text-2`,children:`Was die Box sich merkt.`})]}),(0,g.jsxs)(`section`,{className:`flex flex-col gap-3 border-t border-linie px-4 pt-4`,children:[(0,g.jsx)(`h3`,{className:`schild text-sm text-text-3`,children:`Hugging-Face-Zugang`}),(0,g.jsxs)(`p`,{className:`text-sm text-text-2`,children:[x?.hf_token_gesetzt?`Ist hinterlegt.`:`Fehlt.`,` Nötig für gesperrte Modelle und schnellere Downloads.`,x?.hf_token_aus_env?` Er kommt aus der Dienst-Einstellung und lässt sich hier nicht löschen.`:``]}),(0,g.jsxs)(`form`,{className:`flex gap-2`,onSubmit:e=>{e.preventDefault(),v.trim()&&b(v.trim())},children:[(0,g.jsx)(`label`,{htmlFor:`hf-token`,className:`sr-only`,children:`Hugging-Face-Zugang`}),(0,g.jsx)(`input`,{id:`hf-token`,type:`password`,autoComplete:`off`,value:v,onChange:e=>y(e.target.value),placeholder:`hf_…`,className:`h-11 min-w-0 flex-1 rounded-lg border border-linie-stark bg-erhaben px-3 text-[15px] outline-none focus:border-cyan`}),(0,g.jsx)(n,{type:`submit`,disabled:!v.trim()||x?.schreibbar===!1,children:`Speichern`})]}),x?.hf_token_gesetzt&&!x.hf_token_aus_env&&(0,g.jsx)(n,{variant:`ghost`,size:`sm`,className:`self-start`,onClick:()=>b(null),children:`Zugang löschen`})]}),(0,g.jsxs)(`section`,{className:`flex flex-col gap-2 border-t border-linie px-4 pt-4`,children:[(0,g.jsx)(`h3`,{className:`schild text-sm text-text-3`,children:`Hinweise`}),(0,g.jsx)(`p`,{className:`text-sm text-text-2`,children:`Dringende Hinweise gehen zusätzlich per Telegram raus, alles andere bleibt hier. Einfache Probleme wie einen abgestürzten Dienst behebt der Wächter selbst und schreibt es in den Verlauf.`})]}),(0,g.jsxs)(`section`,{className:`flex flex-col gap-2 border-t border-linie px-4 pt-4 pb-4`,children:[(0,g.jsx)(`h3`,{className:`schild text-sm text-text-3`,children:`Hermes`}),(0,g.jsxs)(`a`,{href:`/hermes-ui/`,target:`_blank`,rel:`noopener`,className:`flex h-11 items-center gap-2 self-start rounded-lg border border-linie-stark bg-erhaben px-4 text-[15px] hover:border-text-3`,children:[(0,g.jsx)(i,{className:`size-4`,"aria-hidden":!0}),` Hermes-Dashboard öffnen`]}),(0,g.jsx)(`p`,{className:`text-xs text-text-3`,children:`Chat, Sitzungen und Cron-Jobs verwaltet Hermes selbst. Es fragt nach seiner eigenen Anmeldung.`})]})]})})}export{_ as Einstellungen};
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{c as e,s as t}from"./button-Dd8hfusv.js";import{F as n,I as r,L as i}from"./index-D17zMI0S.js";import{a,i as o,n as s,r as c,t as l}from"./sheet-DWG2Q04V.js";var u=t(),d=e();function f(e){let t=(0,u.c)(17),{verbindung:f,onDienste:p,onEinstellungen:m,onSchliessen:h}=e,g;t[0]===h?g=t[1]:(g=e=>!e&&h(),t[0]=h,t[1]=g);let _;t[2]===Symbol.for(`react.memo_cache_sentinel`)?(_=(0,d.jsxs)(o,{children:[(0,d.jsx)(a,{className:`schild text-lg`,children:`Mehr`}),(0,d.jsx)(c,{className:`sr-only`,children:`Weitere Bereiche`})]}),t[2]=_):_=t[2];let v;t[3]===Symbol.for(`react.memo_cache_sentinel`)?(v=(0,d.jsxs)(`a`,{href:`/hermes-ui/`,target:`_blank`,rel:`noopener`,className:`flex h-12 items-center gap-3 rounded-lg border border-linie px-4 text-base`,children:[(0,d.jsx)(i,{className:`size-5`,"aria-hidden":!0}),` Hermes-Dashboard öffnen`]}),t[3]=v):v=t[3];let y;t[4]===Symbol.for(`react.memo_cache_sentinel`)?(y=(0,d.jsx)(r,{className:`size-5`,"aria-hidden":!0}),t[4]=y):y=t[4];let b;t[5]===p?b=t[6]:(b=(0,d.jsxs)(`button`,{type:`button`,onClick:p,className:`flex h-12 items-center gap-3 rounded-lg border border-linie px-4 text-left text-base`,children:[y,` Dienste und Protokolle`]}),t[5]=p,t[6]=b);let x;t[7]===Symbol.for(`react.memo_cache_sentinel`)?(x=(0,d.jsx)(n,{className:`size-5`,"aria-hidden":!0}),t[7]=x):x=t[7];let S;t[8]===m?S=t[9]:(S=(0,d.jsxs)(`button`,{type:`button`,onClick:m,className:`flex h-12 items-center gap-3 rounded-lg border border-linie px-4 text-left text-base`,children:[x,` Einstellungen`]}),t[8]=m,t[9]=S);let C;t[10]!==b||t[11]!==S||t[12]!==f?(C=(0,d.jsxs)(s,{side:`bottom`,className:`border-linie bg-panel pb-[calc(1rem+env(safe-area-inset-bottom))]`,children:[_,(0,d.jsxs)(`div`,{className:`flex flex-col gap-2 px-4`,children:[f,v,b,S]})]}),t[10]=b,t[11]=S,t[12]=f,t[13]=C):C=t[13];let w;return t[14]!==g||t[15]!==C?(w=(0,d.jsx)(l,{open:!0,onOpenChange:g,children:C}),t[14]=g,t[15]=C,t[16]=w):w=t[16],w}export{f as MehrMenue};
|
||||
import{c as e,s as t}from"./button-Dd8hfusv.js";import{F as n,I as r,L as i}from"./index-e_N1YCsL.js";import{a,i as o,n as s,r as c,t as l}from"./sheet-DWG2Q04V.js";var u=t(),d=e();function f(e){let t=(0,u.c)(17),{verbindung:f,onDienste:p,onEinstellungen:m,onSchliessen:h}=e,g;t[0]===h?g=t[1]:(g=e=>!e&&h(),t[0]=h,t[1]=g);let _;t[2]===Symbol.for(`react.memo_cache_sentinel`)?(_=(0,d.jsxs)(o,{children:[(0,d.jsx)(a,{className:`schild text-lg`,children:`Mehr`}),(0,d.jsx)(c,{className:`sr-only`,children:`Weitere Bereiche`})]}),t[2]=_):_=t[2];let v;t[3]===Symbol.for(`react.memo_cache_sentinel`)?(v=(0,d.jsxs)(`a`,{href:`/hermes-ui/`,target:`_blank`,rel:`noopener`,className:`flex h-12 items-center gap-3 rounded-lg border border-linie px-4 text-base`,children:[(0,d.jsx)(i,{className:`size-5`,"aria-hidden":!0}),` Hermes-Dashboard öffnen`]}),t[3]=v):v=t[3];let y;t[4]===Symbol.for(`react.memo_cache_sentinel`)?(y=(0,d.jsx)(r,{className:`size-5`,"aria-hidden":!0}),t[4]=y):y=t[4];let b;t[5]===p?b=t[6]:(b=(0,d.jsxs)(`button`,{type:`button`,onClick:p,className:`flex h-12 items-center gap-3 rounded-lg border border-linie px-4 text-left text-base`,children:[y,` Dienste und Protokolle`]}),t[5]=p,t[6]=b);let x;t[7]===Symbol.for(`react.memo_cache_sentinel`)?(x=(0,d.jsx)(n,{className:`size-5`,"aria-hidden":!0}),t[7]=x):x=t[7];let S;t[8]===m?S=t[9]:(S=(0,d.jsxs)(`button`,{type:`button`,onClick:m,className:`flex h-12 items-center gap-3 rounded-lg border border-linie px-4 text-left text-base`,children:[x,` Einstellungen`]}),t[8]=m,t[9]=S);let C;t[10]!==b||t[11]!==S||t[12]!==f?(C=(0,d.jsxs)(s,{side:`bottom`,className:`border-linie bg-panel pb-[calc(1rem+env(safe-area-inset-bottom))]`,children:[_,(0,d.jsxs)(`div`,{className:`flex flex-col gap-2 px-4`,children:[f,v,b,S]})]}),t[10]=b,t[11]=S,t[12]=f,t[13]=C):C=t[13];let w;return t[14]!==g||t[15]!==C?(w=(0,d.jsx)(l,{open:!0,onOpenChange:g,children:C}),t[14]=g,t[15]=C,t[16]=w):w=t[16],w}export{f as MehrMenue};
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+2
-2
File diff suppressed because one or more lines are too long
Vendored
+15
-15
@@ -1,17 +1,17 @@
|
||||
<!doctype html>
|
||||
<html lang="de" class="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||
<meta name="theme-color" content="#0e1012" />
|
||||
<link rel="manifest" href="/manifest.webmanifest" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<title>MC2 · Box-Wart</title>
|
||||
<script type="module" crossorigin src="/assets/index-D17zMI0S.js"></script>
|
||||
<!doctype html>
|
||||
<html lang="de" class="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||
<meta name="theme-color" content="#0e1012" />
|
||||
<link rel="manifest" href="/manifest.webmanifest" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<title>MC2 · Box-Wart</title>
|
||||
<script type="module" crossorigin src="/assets/index-e_N1YCsL.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/assets/button-Dd8hfusv.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-C3amg33Y.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>␍
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -97,6 +97,8 @@ export interface Dienst {
|
||||
unit: string
|
||||
ok: boolean
|
||||
scope: string
|
||||
/** Bewusst abgeschaltet (systemctl disable) — kein Fehler, nur geweckt wird per Knopf. */
|
||||
schlaeft?: boolean
|
||||
}
|
||||
|
||||
export const useDienste = () =>
|
||||
|
||||
@@ -38,10 +38,15 @@ export function Dienste({ offen, onSchliessen }: { offen: boolean; onSchliessen:
|
||||
{(dienste.data?.services ?? []).map((d) => (
|
||||
<li key={d.unit} className="flex flex-wrap items-center justify-between gap-2 border-t border-linie py-2.5">
|
||||
<span className="flex min-w-0 items-center gap-2.5">
|
||||
<span className={cn("size-2.5 shrink-0 rounded-full", d.ok ? "bg-gruen" : "bg-rot")} aria-hidden />
|
||||
<span
|
||||
className={cn("size-2.5 shrink-0 rounded-full", d.ok ? "bg-gruen" : d.schlaeft ? "bg-text-3" : "bg-rot")}
|
||||
aria-hidden
|
||||
/>
|
||||
<span className="min-w-0">
|
||||
<span className="block text-[15px]">{d.name}</span>
|
||||
<span className="ziffern text-xs text-text-3">{d.unit} · {d.ok ? "läuft" : "antwortet nicht"}</span>
|
||||
<span className="ziffern text-xs text-text-3">
|
||||
{d.unit} · {d.ok ? "läuft" : d.schlaeft ? "schläft (abgeschaltet)" : "antwortet nicht"}
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<span className="flex gap-2">
|
||||
@@ -49,9 +54,13 @@ export function Dienste({ offen, onSchliessen }: { offen: boolean; onSchliessen:
|
||||
Protokoll
|
||||
</Button>
|
||||
{bestaetigen === d.unit ? (
|
||||
<Button variant="gefahr" size="sm" onClick={() => neustarten(d.unit)}>Wirklich neu starten?</Button>
|
||||
<Button variant="gefahr" size="sm" onClick={() => neustarten(d.unit)}>
|
||||
{d.schlaeft ? "Wirklich wecken?" : "Wirklich neu starten?"}
|
||||
</Button>
|
||||
) : (
|
||||
<Button variant="outline" size="sm" onClick={() => setBestaetigen(d.unit)}>Neu starten</Button>
|
||||
<Button variant="outline" size="sm" onClick={() => setBestaetigen(d.unit)}>
|
||||
{d.schlaeft ? "Wecken" : "Neu starten"}
|
||||
</Button>
|
||||
)}
|
||||
</span>
|
||||
</li>
|
||||
|
||||
Reference in New Issue
Block a user