Review-Haertung R1/R2/R4 + Repo-Waechter (Vorfall verlorener Merge 12.07.)

R1: Steckbrief-Hook erinnert Worker an kanban_complete/kanban_block-Pflicht
    (Nacht-Karte 14.07. blockierte trotz fertiger Arbeit am fehlenden Aufruf).
R2: tabu-pfade-guard sperrt ~/.config/systemd/user fuer Worker — Unit-/
    Override-Dateien nur noch ueber angenommene Karte.
R4: Orchestrator-/Wartungs-Worktrees von /tmp nach ~/.hermes/worktrees
    (ueberleben Reboot, keine kaputten Registrierungen).
Neu: self-smoke Check 4 'Repo-Waechter' — Box-main mit Commits, die origin
    fehlen, loest Alarm aus (so ging die angenommene Karte
    wartung/lucy-annahme-fixes am 12.07. still verloren; am 15.07. als
    rescue/-Branch gerettet und wieder gemergt).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-07-15 10:04:16 +02:00
parent 1cd492eb33
commit abc8a365d2
5 changed files with 49 additions and 20 deletions
@@ -29,6 +29,7 @@ hint=""
ctx="$(cat <<EOF
[BOX-ORIENTIERUNG — du bist ein Hintergrund-Worker auf der lokalen AI-Box (Linux, Zeit UTC / lokal Europe/Berlin, locale de_DE), NICHT Lucy und kein Dev-Laptop. Du arbeitest EINE Kanban-Aufgabe ab.]
Die Modelle / das "Hirn" laufen ausschliesslich ueber den Router llama-swap auf 127.0.0.1:8080 (startet je Modell einen llama-server) bzw. das OpenAI-kompatible Gateway von MC2 auf 127.0.0.1:9001/v1 — es gibt KEINEN anderen Modell-Server, also nicht danach suchen. Weitere Dienste: hermes-gateway :8642, mem0-Gedaechtnis :8765. Der MC2-Live-Checkout ~/mission-control-v2 ist nur zum LESEN da (Schreiben/committen TABU — Code-Arbeit immer im frischen Klon deines Task-Workspaces). Grenzen (was gehoert wohin): MC2 = Steuerpult (verwalten/klicken/zusehen, KEIN Chat-UI), Lucy = Chat & Stimme (eigenes Repo), Hermes-Quelle ist TABU (Agenten-Verhalten nur ueber Config/SOUL/Skill/Hook/MCP aendern). Feste Entscheide/Verbote + volle Grenzen-Landkarte: ~/mission-control-v2/docs/wissen/ (GRENZEN/VERDIKTE/FALLEN/STACK) + ~/wissens-vault/eigenbau-landkarte.md.${hint}
PROTOKOLL-PFLICHT (15.07.): Beende deine Aufgabe IMMER mit dem Tool-Aufruf kanban_complete (fertig) oder kanban_block (Frage/Sackgasse). Eine Text-Zusammenfassung OHNE diesen Aufruf zaehlt als Absturz (Protokollverstoss) und blockiert die Karte — genau so ging am 14.07. eine fertige Arbeit verloren.
EOF
)"
+12 -6
View File
@@ -36,13 +36,18 @@ ti = payload.get("tool_input") or {}
home = os.path.realpath(os.path.expanduser("~"))
LIVE = os.path.join(home, "mission-control-v2")
SRC = os.path.join(home, ".hermes", "hermes-agent")
# R2 (Review 15.07.): systemd-User-Units. Die Nacht-Werkstatt hat am 14.07. einen Override
# DIREKT scharf geschaltet — ging gut, verletzt aber "jede Code-Zeile ist Klick-pflichtig".
# Unit-/Override-Dateien werden nur noch ueber eine angenommene Karte installiert.
SYSD = os.path.join(home, ".config", "systemd", "user")
MSG = (
"TABU (Faden 8): Schreiben an dieser Stelle ist fuer Worker gesperrt. Der Live-Checkout "
"~/mission-control-v2 und die Hermes-Quelle ~/.hermes/hermes-agent duerfen NIE veraendert "
"werden. Arbeite im FRISCHEN Klon deines Task-Workspaces; MC2-Aenderungen kommen als "
"Vorschlags-Branch (nie am Live-Checkout), Hermes-Verhalten nur ueber Config/SOUL/Skill/"
"Hook/MCP. Siehe docs/wissen/GRENZEN.md."
"TABU (Faden 8/R2): Schreiben an dieser Stelle ist fuer Worker gesperrt. Der Live-Checkout "
"~/mission-control-v2, die Hermes-Quelle ~/.hermes/hermes-agent und die systemd-User-Units "
"~/.config/systemd/user duerfen NIE direkt veraendert werden. Arbeite im FRISCHEN Klon "
"deines Task-Workspaces; MC2-Aenderungen kommen als Vorschlags-Branch, systemd-Unit-/"
"Override-Dateien werden nur ueber eine angenommene Karte installiert, Hermes-Verhalten "
"nur ueber Config/SOUL/Skill/Hook/MCP. Siehe docs/wissen/GRENZEN.md."
)
@@ -52,7 +57,7 @@ def block():
def under_tabu(path):
rp = os.path.realpath(path)
return rp == LIVE or rp == SRC or rp.startswith(LIVE + os.sep) or rp.startswith(SRC + os.sep)
return any(rp == t or rp.startswith(t + os.sep) for t in (LIVE, SRC, SYSD))
# --- Datei-Tools: Zielpfad kanonisch pruefen (zuverlaessig) -------------------------
@@ -78,6 +83,7 @@ if tool == "terminal":
tabu_forms = [
LIVE, "~/mission-control-v2", "$HOME/mission-control-v2", "${HOME}/mission-control-v2",
SRC, "~/.hermes/hermes-agent", "$HOME/.hermes/hermes-agent", "${HOME}/.hermes/hermes-agent",
SYSD, "~/.config/systemd/user", "$HOME/.config/systemd/user", "${HOME}/.config/systemd/user",
]
tabu_alt = "(?:" + "|".join(re.escape(t) for t in tabu_forms) + ")"
if not re.search(tabu_alt, cmd):
+19
View File
@@ -83,6 +83,25 @@ else
FAILED+=("Voice (Lucys Sprech-Pfad)")
fi
# ── 4) Repo-Wächter: verlorene Merges (Vorfall 12.15.07.2026) ──────────────
# Der Annahme-Runner merged+pusht nach origin/main; klemmt der Push (Gitea-Auth
# flattert) oder überschreibt eine fremde Session origin/main, trägt Box-main
# Commits, die origin fehlen — der nächste deploy-Reset VERNICHTET sie still
# (so verlor die Box die angenommene Karte 'wartung/lucy-annahme-fixes' vom
# 12.07., bemerkt erst beim Review am 15.07.). Hier täglich gegenprüfen.
LIVE_CO="$HOME/mission-control-v2"
if git -C "$LIVE_CO" fetch -q origin 2>/dev/null; then
LOST=$(git -C "$LIVE_CO" log --oneline origin/main..main 2>/dev/null | head -3 | tr '\n' ' ')
if [ -n "$LOST" ]; then
say "FAIL · Box-main trägt ungepushte Commits (Deploy würde sie vernichten): $LOST"
FAILED+=("Repo (ungepushte Commits auf Box-main: $LOST— vor dem nächsten Deploy nach origin retten)")
else
say "PASS · Repo-Wächter (Box-main == origin/main)"
fi
else
say "SKIP · Repo-Wächter (git fetch fehlgeschlagen)"
fi
# ── Meldung nur bei Rot ──────────────────────────────────────────────────────
if [ "${#FAILED[@]}" -eq 0 ]; then
say "Alle Selbst-Tests grün ($(date '+%F %H:%M'))."
+13 -11
View File
@@ -86,10 +86,12 @@ Bevor du selbst Tasks aufteilst, befragst du zwingend **`gpt-oss-120b`** nach ei
3. Fuer jeden Teil-Task entscheide: (a) Artefakt, (b) Worker (`Qwen3-Coder-Next` + `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.):
```
cd ~/mission-control-v2 && git fetch -q origin \
&& git worktree add /tmp/orch-<slug> -b orchestrator/<slug> origin/main
mkdir -p /tmp/orch-<slug>-work # Ablage fuer rohe Worker-Ausgaben
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)
@@ -98,19 +100,19 @@ Fuer jeden Bau-Teil-Task:
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 > /tmp/orch-<slug>-work/<n>.out
printf '%s' "$eingabe" | WORKER_ROLE=build ~/.hermes/scripts/worker.sh > ~/.hermes/worktrees/orch-<slug>-work/<n>.out
```
(Default-Modell ist `Qwen3-Coder-Next`. Fuer einen bewusst anderen Worker `WORKER_MODEL=<echte-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 (`/tmp/orch-<slug>/...`). Der Worker hat KEINE
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
`/tmp/orch-<slug>/` beginnen — vor dem ersten Schreiben einmal laut pruefen. NIEMALS nach
`~/.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 `/tmp/orch-<slug>` noch nicht,
`/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
@@ -148,7 +150,7 @@ Grund wie in der Werkstatt („wer seine eigenen Hausaufgaben benotet, stimmt si
**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 /tmp/orch-<slug> add -A
git -C ~/.hermes/worktrees/orch-<slug> add -A
```
Dann die Eingabe EINMAL bauen (mit `--cached`, damit die neuen Dateien drin sind):
```
@@ -159,7 +161,7 @@ ZERLEGUNG (deine Teil-Tasks, je 1 Zeile):
<1..n>
GIT-DIFF des Worktrees:
$(git -C /tmp/orch-<slug> diff --cached origin/main)"
$(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** (`Qwen3-Coder-Next`, starker Coder, vom Bauen noch geladen → KEIN Swap):
@@ -212,7 +214,7 @@ Zugriff aufs Repo. Er sieht NUR, was du ihm auf stdin gibst. Deshalb:
den Fokus. Ziel: das kleinste, das den Teil-Task eindeutig macht.
## Nach dem Commander-Entscheid (kommt als neuer Auftrag)
- „verwerfen" → `git worktree remove /tmp/orch-<slug> --force && git branch -D orchestrator/<slug>`
(+ `rm -rf /tmp/orch-<slug>-work`; Remote-Branch loeschen, falls gepusht).
- „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.
+4 -3
View File
@@ -42,7 +42,8 @@ unangenommene Branches aufbauen — erst wenn die Vor-Etappe in main ist, kommt
## Ablauf
1. **Worktree anlegen** (Slug = kurzer Kebab-Case-Name des Auftrags):
`cd ~/mission-control-v2 && git fetch origin && git worktree add /tmp/wartung-<slug> -b wartung/<slug> origin/main`
`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):
@@ -76,7 +77,7 @@ unangenommene Branches aufbauen — erst wenn die Vor-Etappe in main ist, kommt
<der Auftrag>
GIT-DIFF des Worktrees:
<git -C /tmp/wartung-<slug> diff origin/main>" | FREMDBLICK_MODE=code ~/.hermes/scripts/fremdblick.sh
<git -C ~/.hermes/worktrees/wartung-<slug> diff origin/main>" | FREMDBLICK_MODE=code ~/.hermes/scripts/fremdblick.sh
```
Das läuft auf `Qwen3-Coder-Next` (128k, code-stark, anderes Modell als der Qwen3.6-Worker,
@@ -113,7 +114,7 @@ unangenommene Branches aufbauen — erst wenn die Vor-Etappe in main ist, kommt
## Nach dem User-Entscheid (kommt als neuer Auftrag)
- „verwerfen" → `git worktree remove /tmp/wartung-<slug> --force && git branch -D wartung/<slug>`
- „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.