Phase 2 Drei-Welten-Plan: No-Progress-Bremse + Betrieb-Playbook + mem0-Lern-Buendelung
- no-progress-bremse.py: generische, turn-uebergreifende Schleifenbremse (pre/post_tool_call); Muster-Hash statt hartkodierter Fehler-Strings, Selbst-Lernen via neue-signaturen.jsonl. Schliesst die Luecke der nativen guardrails (pro Turn, nur klassifizierte Fehler). - ensure-profile-hooks.py: kann Eintraege in BESTEHENDE Event-Bloecke einfuegen (zweiter pre_tool_call-Key haette den Tabu-Guard lautlos verschluckt) + registriert Bremse. - betrieb-playbook-Skill: SSH-/Deploy-Diagnose-Checklisten (Passphrase-Falle zuerst), Triage-Regel im Steckbrief-Hook; Skill wird in alle Profile gesynct. - mc2-memory: Lern-Extraktion gebuendelt (4 Turns oder 180 s idle = EIN Lauf) statt pro Turn - Extraktion konkurrierte mit Lucys Hirn um die Slots. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,14 +1,19 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Stellt sicher, dass ein Worker-Profil die Agent-Hooks kennt (Faden 8, 13.07.2026).
|
||||
"""Stellt sicher, dass ein Worker-Profil die Agent-Hooks kennt (Faden 8, 13.07.2026;
|
||||
erweitert 19.07.2026 um die No-Progress-Bremse und Mehrfach-Eintraege pro Event).
|
||||
|
||||
Kanban-Worker laufen unter IHREM Profil (HERMES_HOME=~/.hermes/profiles/<name>) und lesen
|
||||
dessen config.yaml — NICHT die Top-Level ~/.hermes/config.yaml. Die worker-relevanten Hooks
|
||||
(box-steckbrief-inject = Box-Wissen, tabu-pfade-guard = Schreibschutz) muessen also in JEDER
|
||||
Worker-Profil-config.yaml stehen, sonst feuern sie fuer Worker nie (Bug-Fund 13.07.).
|
||||
muessen also in JEDER Worker-Profil-config.yaml stehen, sonst feuern sie fuer Worker nie
|
||||
(Bug-Fund 13.07.).
|
||||
|
||||
Idempotent + validiert + Backup. Setzt einen bestehenden `pre_verify`-Hook-Block als Anker
|
||||
voraus (haben alle von default/werkstatt geklonten Profile); fehlt er, wird sauber
|
||||
uebersprungen (exit 0), damit deploy.sh nicht bricht. Arg: Pfad zur Profil-config.yaml.
|
||||
WICHTIG (Falle, 19.07.): Ein Event darf nur EINMAL als YAML-Key existieren. Existiert
|
||||
`pre_tool_call:` bereits (tabu-pfade-guard), wird ein weiterer Eintrag IN den Block
|
||||
eingefuegt — ein zweiter `pre_tool_call:`-Key wuerde beim YAML-Laden den ersten
|
||||
verschlucken und den Tabu-Guard lautlos deaktivieren.
|
||||
|
||||
Idempotent + validiert + Backup. Anker fuer neue Event-Bloecke ist der bestehende
|
||||
`pre_verify`-Block. Arg: Pfad zur Profil-config.yaml.
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
@@ -22,10 +27,13 @@ except Exception:
|
||||
sys.exit(0)
|
||||
|
||||
AH = os.path.expanduser("~/.hermes/agent-hooks")
|
||||
WANT = {
|
||||
"pre_llm_call": f"{AH}/box-steckbrief-inject.sh",
|
||||
"pre_tool_call": f"{AH}/tabu-pfade-guard.py",
|
||||
}
|
||||
# Reihenfolge zaehlt: tabu-pfade-guard MUSS vor der Bremse stehen (Schutz vor Komfort).
|
||||
WANT = [
|
||||
("pre_llm_call", f"{AH}/box-steckbrief-inject.sh", 10),
|
||||
("pre_tool_call", f"{AH}/tabu-pfade-guard.py", 10),
|
||||
("pre_tool_call", f"{AH}/no-progress-bremse.py pre", 10),
|
||||
("post_tool_call", f"{AH}/no-progress-bremse.py post", 10),
|
||||
]
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print(" usage: ensure-profile-hooks.py <config.yaml>")
|
||||
@@ -44,22 +52,41 @@ if txt.count(anchor) != 1:
|
||||
print(f" [{os.path.basename(os.path.dirname(p))}] kein eindeutiger pre_verify-Anker — SKIP")
|
||||
sys.exit(0)
|
||||
|
||||
add = ""
|
||||
for event, cmd in WANT.items():
|
||||
if cmd not in txt:
|
||||
add += f" {event}:\n - command: {cmd}\n timeout: 10\n"
|
||||
new = txt
|
||||
changed = False
|
||||
for event, cmd, timeout in WANT:
|
||||
if cmd in new:
|
||||
continue
|
||||
entry = f" - command: {cmd}\n timeout: {timeout}\n"
|
||||
ev_line = f" {event}:\n"
|
||||
if ev_line in new:
|
||||
# Eintrag ANS ENDE des bestehenden Event-Blocks: direkt nach dem Key einfuegen
|
||||
# waere auch ok, aber hinter dem letzten Eintrag haelt die gewollte Reihenfolge.
|
||||
idx = new.index(ev_line) + len(ev_line)
|
||||
end = idx
|
||||
for line in new[idx:].splitlines(keepends=True):
|
||||
if line.startswith((" - ", " ")):
|
||||
end += len(line)
|
||||
else:
|
||||
break
|
||||
new = new[:end] + entry + new[end:]
|
||||
else:
|
||||
new = new.replace(anchor, anchor + ev_line + entry, 1)
|
||||
changed = True
|
||||
|
||||
if not add:
|
||||
if not changed:
|
||||
print(f" [{os.path.basename(os.path.dirname(p))}] Hooks schon registriert.")
|
||||
sys.exit(0)
|
||||
|
||||
new = txt.replace(anchor, anchor + add, 1)
|
||||
try:
|
||||
d = yaml.safe_load(new)
|
||||
h = d["hooks"]
|
||||
for event, cmd in WANT.items():
|
||||
assert any(cmd in x.get("command", "") for x in h.get(event, []))
|
||||
for event, cmd, _t in WANT:
|
||||
assert any(cmd == x.get("command", "") for x in h.get(event, [])), f"{event}: {cmd} fehlt"
|
||||
assert any("pre-verify-gates.sh" in x.get("command", "") for x in h["pre_verify"])
|
||||
# Tabu-Guard muss VOR der Bremse stehen (beide in pre_tool_call).
|
||||
cmds = [x.get("command", "") for x in h["pre_tool_call"]]
|
||||
assert cmds.index(f"{AH}/tabu-pfade-guard.py") < cmds.index(f"{AH}/no-progress-bremse.py pre")
|
||||
except Exception as exc:
|
||||
print(f" [{p}] Validierung fehlgeschlagen ({exc}) — config UNVERAENDERT.")
|
||||
sys.exit(0)
|
||||
|
||||
Reference in New Issue
Block a user