Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3669a6e7dc | ||
|
|
cd54fe4a0f | ||
|
|
1e7a6d974f | ||
|
|
61f226e86d | ||
|
|
6809d357c0 | ||
|
|
502a6010f1 |
+3
-1
@@ -26,9 +26,11 @@ DISCOVER_TTL = int(os.environ.get("MC_DISCOVER_TTL", "43200")) # 12 h
|
||||
# Hinweis: --prompt-cache/--prompt-cache-all sind llama-CLI-Flags, NICHT llama-server —
|
||||
# llama-server lehnt sie ab ("invalid argument") und startet dann nicht. Prompt-Caching
|
||||
# macht llama-server ohnehin automatisch pro Slot (KV-Reuse).
|
||||
# --load-mode none = das frühere --no-mmap; das alte Flag ist seit llama.cpp b10936 weg
|
||||
# ("invalid argument", jedes Modell stirbt beim Start — gelernt 13./17.09.2026).
|
||||
_DEFAULT_CMD_TEMPLATE = (
|
||||
"llama-server -m {model} --host 127.0.0.1 --port ${PORT} "
|
||||
"-c {ctx} -ngl 999 -fa on --no-mmap"
|
||||
"-c {ctx} -ngl 999 -fa on --load-mode none"
|
||||
)
|
||||
CMD_TEMPLATE = os.environ.get("MC_CMD_TEMPLATE", _DEFAULT_CMD_TEMPLATE)
|
||||
if "{model}" not in CMD_TEMPLATE:
|
||||
|
||||
@@ -717,10 +717,15 @@ def _hermes_update_cmd() -> str:
|
||||
# grün sein. Früher schluckte das `;` vor dem Neustart jeden Update-Fehler: Job rc=0,
|
||||
# Badge blieb, User sah „done aber nichts passiert" (Update scheiterte real an einem
|
||||
# verwaisten .git/index.lock). Jetzt: RC festhalten, Dienste immer starten, RC melden.
|
||||
# --no-gateway-restart (17.09.2026): `hermes update` startet das Gateway sonst selbst neu und
|
||||
# endet mit Exit 1, wenn sein Fleet-Check danach keine Zeilen sieht (#93406) — unter systemd
|
||||
# bei uns der Normalfall. Die &&-Kette brach ab (kein doctor, kein /hermes-ui/-Build), der
|
||||
# Job war rot, autoupdate.sh rollte zurück und pinnte — bei GRÜNEM Gehirn-Check (06./17.09.).
|
||||
# Der Neustart passiert unten ohnehin; Richter bleibt der Postcheck.
|
||||
return ("RC=0; "
|
||||
f"bash {backup} || true; "
|
||||
f"systemctl --user stop hermes-builtin-ui || true; "
|
||||
f"{{ cd {path} && {py} -m hermes_cli.main update --yes "
|
||||
f"{{ cd {path} && {py} -m hermes_cli.main update --yes --no-gateway-restart "
|
||||
f"&& {py} -m hermes_cli.main doctor "
|
||||
f"&& {build_cmd}; }} || RC=1; "
|
||||
f"systemctl --user reset-failed hermes-builtin-ui 2>/dev/null; "
|
||||
|
||||
@@ -7,7 +7,7 @@ set -u
|
||||
MODEL="${BRAIN_GGUF:-/srv/models/Qwen3.6-35B-A3B-MTP-GGUF/Qwen3.6-35B-A3B-UD-Q4_K_M.gguf}"
|
||||
BIN="${BENCH_BIN:-/opt/llamacpp-vulkan/llama-server}"
|
||||
PORT="${BENCH_PORT:-5899}"
|
||||
BASE="-c 65536 -ngl 999 -fa on --no-mmap --jinja --parallel 1"
|
||||
BASE="-c 65536 -ngl 999 -fa on --load-mode none --jinja --parallel 1"
|
||||
|
||||
run() { # $1=name $2=extra-flags
|
||||
echo "=== $1 ==="
|
||||
|
||||
@@ -13,7 +13,7 @@ PORT="${BENCH_PORT:-5899}"
|
||||
CTX="${BENCH_CTX:-32768}"
|
||||
|
||||
echo "=== Bench: $(basename "$MODEL") (ctx $CTX${EXTRA:+, $EXTRA}) ==="
|
||||
$BIN -m "$MODEL" --host 127.0.0.1 --port "$PORT" -c "$CTX" -ngl 999 -fa on --no-mmap --jinja $EXTRA \
|
||||
$BIN -m "$MODEL" --host 127.0.0.1 --port "$PORT" -c "$CTX" -ngl 999 -fa on --load-mode none --jinja $EXTRA \
|
||||
>/tmp/model-bench-server.log 2>&1 &
|
||||
PID=$!
|
||||
trap 'kill $PID 2>/dev/null; wait $PID 2>/dev/null' EXIT
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Prüfstand für Hirn-Kandidaten (17.09.2026). Kandidat läuft standalone auf :5899 — der Live-Stack bleibt unberührt —,
|
||||
Baselines laufen über llama-swap :8080. Je Betriebsart: Kurz- und 13k-Tiefenmessung (Prefill/Decode/Draft-Akzeptanz),
|
||||
Tool-Calling direkt (3 Aufgaben, Denken an), Deutsch- und JSON-Probe (Denken aus) und der Tool-Smoke durch den ECHTEN
|
||||
Hermes-Agenten (`hermes chat --provider pruefstand -m kandidat`; Provider `pruefstand` -> http://127.0.0.1:5899/v1 muss in
|
||||
`providers:` der Hermes-Config stehen). Aufruf auf der Box: python3 pruefstand-hirn.py [baseline] [nemo] [u38] [u36]
|
||||
(Kandidaten-Pfade unten anpassen). Ergebnis: ~/pruefstand-<datum>.json + Log auf stdout. Lehren: Denk-Modelle brauchen
|
||||
für Tool-Aufrufe >=1500 Tokens Budget, /no_think wirkt bei Qwen 3.6 nicht (chat_template_kwargs.enable_thinking=false);
|
||||
der erste Lauf nach dem Laden ist ~40 % langsamer (Warmlauf verwerfen)."""
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import urllib.request
|
||||
|
||||
BIN = "/opt/llamacpp-vulkan/llama-server"; PORT = 5899
|
||||
BASE = ["-c", "65536", "-ngl", "999", "-fa", "on", "--load-mode", "none", "--jinja", "--parallel", "1", "-ctk", "q8_0", "-ctv", "q8_0"]
|
||||
M = "/srv/models"
|
||||
DFLASH_36 = f"{M}/Qwen3.6-35B-A3B-DFlash-GGUF/giocom-Qwen3.6-35B-A3B-DFlash-Q8_0.gguf"
|
||||
DFLASH2_38 = f"{M}/Qwen3.8-27B-DFlash2-GGUF/Qwen3.8-27B-DFlash2-Q4_K_M.gguf"
|
||||
NEMO = f"{M}/Nemotron-3.5-Lightning-30B-A3B-GGUF/NVIDIA-Nemotron-3.5-Lightning-30B-A3B-Q4_0.gguf"
|
||||
NEMO_MTP = f"{M}/Nemotron-3.5-Lightning-30B-A3B-GGUF/mtp-NVIDIA-Nemotron-3.5-Lightning-30B-A3B-Q8_0.gguf"
|
||||
U38 = f"{M}/Qwen3.8-27B-Uncensored-GGUF/Qwen3.8-27B-Uncensored-Q4_K_M.gguf"
|
||||
U36 = f"{M}/Qwen3.6-35B-A3B-Uncensored-GGUF/Qwen3.6-35B-A3B-Uncensored-HauhauCS-Aggressive-Q4_K_M.gguf"
|
||||
HERMES = os.path.expanduser("~/.local/bin/hermes")
|
||||
OUT = os.path.expanduser("~/pruefstand-2026-09-17.json")
|
||||
RESULTS = []
|
||||
|
||||
|
||||
def log(*a):
|
||||
print(*a, flush=True)
|
||||
|
||||
|
||||
def post(url, payload, timeout=900):
|
||||
r = urllib.request.Request(url, data=json.dumps(payload).encode(), headers={"Content-Type": "application/json"})
|
||||
return json.loads(urllib.request.urlopen(r, timeout=timeout).read())
|
||||
|
||||
|
||||
def chat(base, model, messages, max_tokens=200, tools=None, think=True):
|
||||
p = {"model": model, "temperature": 0, "max_tokens": max_tokens, "messages": messages}
|
||||
if not think:
|
||||
p["chat_template_kwargs"] = {"enable_thinking": False}
|
||||
if tools:
|
||||
p["tools"] = tools
|
||||
p["tool_choice"] = "auto"
|
||||
t0 = time.time()
|
||||
j = post(f"{base}/v1/chat/completions", p)
|
||||
j["_wall"] = time.time() - t0
|
||||
return j
|
||||
|
||||
|
||||
PARA = ("Notiz {i}: Die Box läuft mit llama-swap auf Port 8080, das Hirn ist ein Mixture-of-Experts-Modell mit drei Milliarden "
|
||||
"aktiven Parametern, der Coder ein dichtes 27B-Modell mit Draft-Beschleunigung. Lucy hört über Parakeet, spricht über "
|
||||
"pocket-tts und meldet sich per Telegram. Der Sonntags-Job aktualisiert Router, Engine und Agent und rollt bei Rot zurück. ")
|
||||
DEPTH_PROMPT = "".join(PARA.format(i=i) for i in range(130)) + \
|
||||
"\n\nFrage: Fasse in drei Sätzen zusammen, was in den Notizen steht, und nenne die Nummer der letzten Notiz."
|
||||
|
||||
TOOLS = [
|
||||
{"type": "function", "function": {"name": "terminal", "description": "Führt einen Shell-Befehl auf der Box aus und gibt stdout zurück.",
|
||||
"parameters": {"type": "object", "properties": {"command": {"type": "string"}}, "required": ["command"]}}},
|
||||
{"type": "function", "function": {"name": "read_file", "description": "Liest eine Datei und gibt den Inhalt zurück.",
|
||||
"parameters": {"type": "object", "properties": {"path": {"type": "string"}}, "required": ["path"]}}},
|
||||
{"type": "function", "function": {"name": "send_telegram", "description": "Schickt dem Nutzer eine Telegram-Nachricht.",
|
||||
"parameters": {"type": "object", "properties": {"text": {"type": "string"}}, "required": ["text"]}}},
|
||||
]
|
||||
TOOL_TASKS = [
|
||||
("Wie viel freier Speicher ist auf /srv/models? Nutze das passende Werkzeug.", "terminal", r"df"),
|
||||
("Lies die Datei /etc/hostname und sag mir, wie die Box heißt.", "read_file", r"/etc/hostname"),
|
||||
("Schick mir per Telegram die Nachricht: Prüfstand läuft.", "send_telegram", r"Pr.fstand"),
|
||||
]
|
||||
|
||||
|
||||
def timings(j):
|
||||
t = j.get("timings") or {}
|
||||
acc = (t.get("draft_n_accepted", 0) / t["draft_n"]) if t.get("draft_n") else None
|
||||
return {"pp_n": t.get("prompt_n"), "pp_s": round((t.get("prompt_ms") or 0) / 1000, 1), "pp_tps": round(t.get("prompt_per_second") or 0),
|
||||
"tg_n": t.get("predicted_n"), "tg_tps": round(t.get("predicted_per_second") or 0, 1), "acc": None if acc is None else round(acc, 2)}
|
||||
|
||||
|
||||
def save():
|
||||
json.dump(RESULTS, open(OUT, "w"), indent=1, ensure_ascii=False)
|
||||
|
||||
|
||||
def probes(base, model, label, with_hermes, hermes_args):
|
||||
res = {"label": label}
|
||||
chat(base, model, [{"role": "user", "content": "Sag kurz hallo."}], 32) # Warmlauf
|
||||
j = chat(base, model, [{"role": "user", "content": "Erkläre in fünf Sätzen, was ein Mixture-of-Experts-Modell ist."}], 200)
|
||||
res["kurz"] = timings(j); log(f" kurz : {res['kurz']}")
|
||||
j = chat(base, model, [{"role": "user", "content": DEPTH_PROMPT}], 160)
|
||||
res["tiefe"] = timings(j); log(f" 13k : {res['tiefe']}")
|
||||
tc = []
|
||||
for q, want_fn, want_arg in TOOL_TASKS:
|
||||
try:
|
||||
j = chat(base, model, [{"role": "user", "content": q}], 1500, TOOLS)
|
||||
msg = j["choices"][0]["message"]
|
||||
calls = msg.get("tool_calls") or []
|
||||
ok = any(c["function"]["name"] == want_fn and re.search(want_arg, c["function"].get("arguments", "")) for c in calls)
|
||||
raw = "" if calls else (msg.get("content") or "")[:120].replace("\n", " ")
|
||||
tc.append({"task": want_fn, "ok": ok, "calls": [(c["function"]["name"], c["function"].get("arguments", "")[:80]) for c in calls], "raw": raw})
|
||||
except Exception as e:
|
||||
tc.append({"task": want_fn, "ok": False, "error": str(e)[:120]})
|
||||
res["tools_direkt"] = tc
|
||||
log(f" tools: {sum(1 for t in tc if t['ok'])}/3 " + "; ".join(f"{t['task']}={'✓' if t['ok'] else '✗'}" for t in tc))
|
||||
for t in tc:
|
||||
if not t["ok"]:
|
||||
log(f" {t['task']}: calls={t.get('calls')} raw={t.get('raw', '')!r} {t.get('error', '')}")
|
||||
j = chat(base, model, [{"role": "user", "content": "Antworte auf Deutsch in genau drei Sätzen: Warum braucht ein Heimserver ein Backup?"}], 300, think=False)
|
||||
m = j["choices"][0]["message"]
|
||||
txt = (m.get("content") or "").strip() or ("[nur reasoning] " + (m.get("reasoning_content") or "")[:200])
|
||||
res["deutsch"] = txt[:400]; log(f" de : {txt[:160]!r}")
|
||||
j = chat(base, model, [{"role": "user", "content": 'Antworte NUR mit JSON, ohne Erklärung: {"modell": "<dein Name>", "ok": true}'}], 120, think=False)
|
||||
m = j["choices"][0]["message"]
|
||||
txt = (m.get("content") or "").strip()
|
||||
try:
|
||||
json.loads(txt[txt.find("{"): txt.rfind("}") + 1]); js = True
|
||||
except Exception:
|
||||
js = False
|
||||
res["json_ok"] = js; log(f" json : {'✓' if js else '✗'} {txt[:80]!r}")
|
||||
if with_hermes:
|
||||
hz = []
|
||||
for q, want in [("Führe im Terminal exakt den Befehl echo pruefstand-ok aus und gib mir nur dessen Ausgabe zurück.", "pruefstand-ok"),
|
||||
("Welche Verzeichnisse liegen direkt unter /srv/models? Nenne mir drei davon.", "GGUF")]:
|
||||
t0 = time.time()
|
||||
try:
|
||||
p = subprocess.run([HERMES, "chat", *hermes_args, "-Q", "--oneshot", "--max-turns", "6", "-q", q],
|
||||
capture_output=True, text=True, timeout=900)
|
||||
out = (p.stdout + p.stderr)[-600:]
|
||||
except subprocess.TimeoutExpired:
|
||||
out = "TIMEOUT"
|
||||
ok = want.lower() in out.lower()
|
||||
hz.append({"ok": ok, "s": round(time.time() - t0), "tail": out[-160:].replace("\n", " ")})
|
||||
log(f" hermes: {'✓' if ok else '✗'} {round(time.time() - t0)} s {out[-120:].replace(chr(10), ' ')!r}")
|
||||
res["hermes"] = hz
|
||||
RESULTS.append(res); save()
|
||||
|
||||
|
||||
def start_server(model, extra):
|
||||
cmd = [BIN, "-m", model, "--host", "127.0.0.1", "--port", str(PORT), *BASE, *extra]
|
||||
logf = open("/tmp/pruefstand-server.log", "w")
|
||||
p = subprocess.Popen(cmd, stdout=logf, stderr=subprocess.STDOUT)
|
||||
t0 = time.time()
|
||||
for _ in range(150):
|
||||
time.sleep(2)
|
||||
if p.poll() is not None:
|
||||
tail = open("/tmp/pruefstand-server.log", errors="replace").read()[-500:]
|
||||
return None, f"LOAD-CRASH rc={p.returncode}: {tail.strip()[-300:]}"
|
||||
try:
|
||||
if b"ok" in urllib.request.urlopen(f"http://127.0.0.1:{PORT}/health", timeout=2).read():
|
||||
return p, round(time.time() - t0)
|
||||
except Exception:
|
||||
pass
|
||||
p.kill()
|
||||
return None, "TIMEOUT beim Laden"
|
||||
|
||||
|
||||
def candidate(label, model, extra, with_hermes):
|
||||
log(f"\n=== {label}"); log(f" {os.path.basename(model)} {' '.join(extra)}")
|
||||
if not os.path.exists(model):
|
||||
log(" FEHLT: Datei nicht da"); RESULTS.append({"label": label, "fehler": "Datei fehlt"}); save(); return
|
||||
p, info = start_server(model, extra)
|
||||
if p is None:
|
||||
log(f" {info}"); RESULTS.append({"label": label, "fehler": info}); save(); return
|
||||
log(f" geladen in {info} s")
|
||||
try:
|
||||
probes(f"http://127.0.0.1:{PORT}", "kandidat", label, with_hermes, ["--provider", "pruefstand", "-m", "kandidat"])
|
||||
except Exception as e:
|
||||
log(f" FEHLER in Proben: {e}"); RESULTS.append({"label": label, "fehler": str(e)[:200]}); save()
|
||||
finally:
|
||||
p.terminate()
|
||||
try:
|
||||
p.wait(timeout=60)
|
||||
except Exception:
|
||||
p.kill()
|
||||
time.sleep(3)
|
||||
|
||||
|
||||
which = set(sys.argv[1:]) or {"baseline", "nemo", "u38", "u36"}
|
||||
if "baseline" in which:
|
||||
log("\n=== BASELINE fast (live, llama-swap)"); probes("http://127.0.0.1:8080", "fast", "fast-live", True, ["-m", "fast"])
|
||||
log("\n=== BASELINE coder = Qwen3.8-27B+DFlash2 (live)"); probes("http://127.0.0.1:8080", "coder", "coder-live", True, ["-m", "coder"])
|
||||
if "nemo" in which:
|
||||
candidate("Nemotron 3.5 Lightning · MTP n3", NEMO, ["--spec-type", "draft-mtp", "--spec-draft-model", NEMO_MTP, "--spec-draft-n-max", "3"], True)
|
||||
candidate("Nemotron 3.5 Lightning · ohne Spec", NEMO, [], False)
|
||||
if "u38" in which:
|
||||
candidate("Qwen3.8-27B-Uncensored · MTP fused n2", U38, ["--spec-type", "draft-mtp", "--spec-draft-n-max", "2"], True)
|
||||
candidate("Qwen3.8-27B-Uncensored · DFlash2 (z-lab) n3", U38, ["--spec-type", "draft-dflash", "--spec-draft-model", DFLASH2_38, "--spec-draft-n-max", "3"], False)
|
||||
candidate("Qwen3.8-27B-Uncensored · ohne Spec", U38, [], False)
|
||||
if "u36" in which:
|
||||
candidate("Qwen3.6-35B-A3B-Uncensored-Aggressive · DFlash (giocom)", U36, ["--spec-type", "draft-dflash", "--spec-draft-model", DFLASH_36], True)
|
||||
candidate("Qwen3.6-35B-A3B-Uncensored-Aggressive · ohne Spec", U36, [], False)
|
||||
log("\nPRUEFSTAND_DONE")
|
||||
@@ -9,8 +9,14 @@ models:
|
||||
# Q8_0 kostet 0 t/s, MTP n-max 3 = +26% vs. ohne Spec. (Q4_K-KV stand mal im Template,
|
||||
# lief aber NIE live — bewusst bei Q8_0 geblieben: Qualität vor ein paar GB, seit der
|
||||
# Warm-Set-Diät 07.07. ist RAM nicht mehr der Engpass.)
|
||||
# 17.09.2026: Uncensored-Variante (HauhauCS Aggressive, Q4_K_M) mit demselben giocom-DFlash-Draft. Prüfstand: 100,8 t/s
|
||||
# @13k (Original 92,8), Prefill 13,1 s, Tools 11/12 (1 Denk-Ausreißer), Hermes-Smoke grün. Original bleibt in
|
||||
# Qwen3.6-35B-A3B-MTP-GGUF liegen — Rückweg = Pfad zurück.
|
||||
# --reasoning-budget 2048 (17.09.2026): Deckel für Denk-Tokens — die abliterierte Variante hatte im Prüfstand 1/12
|
||||
# Denk-Ausreißer ohne Antwort; mit Deckel wird daraus eine kürzer bedachte Antwort statt Stille. Normale Denkphasen
|
||||
# des Hirns liegen bei ein paar hundert Tokens.
|
||||
cmd: |
|
||||
llama-server -m /srv/models/Qwen3.6-35B-A3B-MTP-GGUF/Qwen3.6-35B-A3B-UD-Q4_K_M.gguf --host 127.0.0.1 --port ${PORT} -c 131072 -ngl 999 -fa on --no-mmap --jinja --parallel 2 -cram 16384 -ctk q8_0 -ctv q8_0 --spec-type draft-dflash --spec-draft-model /srv/models/Qwen3.6-35B-A3B-DFlash-GGUF/giocom-Qwen3.6-35B-A3B-DFlash-Q8_0.gguf
|
||||
llama-server -m /srv/models/Qwen3.6-35B-A3B-Uncensored-GGUF/Qwen3.6-35B-A3B-Uncensored-HauhauCS-Aggressive-Q4_K_M.gguf --host 127.0.0.1 --port ${PORT} -c 131072 -ngl 999 -fa on --load-mode none --jinja --parallel 2 -cram 16384 -ctk q8_0 -ctv q8_0 --spec-type draft-dflash --spec-draft-model /srv/models/Qwen3.6-35B-A3B-DFlash-GGUF/giocom-Qwen3.6-35B-A3B-DFlash-Q8_0.gguf --reasoning-budget 2048
|
||||
ttl: 0
|
||||
aliases:
|
||||
- hermes
|
||||
@@ -27,8 +33,11 @@ models:
|
||||
# Unser neuer Haupt-Coder mit 262k Kontext, Thinking Mode und extrem sauberer Code-Qualität.
|
||||
# DFlash2-Draft (z-lab, Q4_K_M) seit 04.09.2026: gemessen 12,6 -> 31 t/s (Akzeptanz 0,78, n-max 3 default;
|
||||
# n-max 5 und f16-KV bringen nichts, Q4-Draft = Q8-Draft). Braucht llama.cpp >= 28.08. (PR 27342 + Vulkan-Fix 27812).
|
||||
# 17.09.2026: Uncensored-Variante (JonathanColetti, Heretic-Abliteration: KL 0,12, Refusals 98->12/100, Benchmarks -0,5)
|
||||
# mit demselben DFlash2-Draft (Akzeptanz 0,82 @13k). Prüfstand: 30,4 t/s @13k (Original 26,2), Tools 6/6, Coding 3/3,
|
||||
# Hermes-Smoke grün. Original bleibt in Qwen3.8-27B-GGUF liegen — Rückweg = beide Pfade zurück.
|
||||
cmd: |
|
||||
llama-server -m /srv/models/Qwen3.8-27B-GGUF/Qwen3.8-27B-Q4_K_M.gguf --host 127.0.0.1 --port ${PORT} -c 131072 -ngl 999 -fa on --no-mmap --mmproj /srv/models/Qwen3.8-27B-GGUF/mmproj-BF16.gguf --jinja --parallel 1 -cram 16384 -ctk q8_0 -ctv q8_0 --spec-type draft-dflash --spec-draft-model /srv/models/Qwen3.8-27B-DFlash2-GGUF/Qwen3.8-27B-DFlash2-Q4_K_M.gguf
|
||||
llama-server -m /srv/models/Qwen3.8-27B-Uncensored-GGUF/Qwen3.8-27B-Uncensored-Q4_K_M.gguf --host 127.0.0.1 --port ${PORT} -c 131072 -ngl 999 -fa on --load-mode none --mmproj /srv/models/Qwen3.8-27B-Uncensored-GGUF/mmproj-Qwen3.8-27B-Uncensored-F16.gguf --jinja --parallel 1 -cram 16384 -ctk q8_0 -ctv q8_0 --spec-type draft-dflash --spec-draft-model /srv/models/Qwen3.8-27B-DFlash2-GGUF/Qwen3.8-27B-DFlash2-Q4_K_M.gguf
|
||||
ttl: 5400
|
||||
aliases:
|
||||
- coder
|
||||
@@ -44,7 +53,7 @@ models:
|
||||
# Meta Muse Glimmer 30B: Dichtes 30B-Agenten-Modell mit DFlash-Speculative-Drafting
|
||||
# und 1.8B Perception Multimodal Projector. Ideal als Runtime-Debugger & Fehler-Diagnostiker.
|
||||
cmd: |
|
||||
llama-server -m /srv/models/Muse-Glimmer-30B-GGUF/Muse-Glimmer-30B-UD-Q4_K_XL.gguf --host 127.0.0.1 --port ${PORT} -c 65536 -ngl 999 -fa on --no-mmap --mmproj /srv/models/Muse-Glimmer-30B-GGUF/mmproj-kquant.gguf --jinja --spec-type draft-dflash --spec-draft-model /srv/models/Muse-Glimmer-30B-GGUF/dflash-kquant.gguf
|
||||
llama-server -m /srv/models/Muse-Glimmer-30B-GGUF/Muse-Glimmer-30B-UD-Q4_K_XL.gguf --host 127.0.0.1 --port ${PORT} -c 65536 -ngl 999 -fa on --load-mode none --mmproj /srv/models/Muse-Glimmer-30B-GGUF/mmproj-kquant.gguf --jinja --spec-type draft-dflash --spec-draft-model /srv/models/Muse-Glimmer-30B-GGUF/dflash-kquant.gguf
|
||||
ttl: 600
|
||||
aliases:
|
||||
- debugger
|
||||
@@ -55,7 +64,7 @@ models:
|
||||
context: 65536
|
||||
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 --no-mmap -c 8192
|
||||
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
|
||||
aliases:
|
||||
- embed
|
||||
@@ -63,7 +72,7 @@ models:
|
||||
# heavy (B5-Entscheid 03.07.) + nächtlicher CHEF-GUTACHTER (04:30-Cron). 60 GB —
|
||||
# passt seit der Warm-Set-Diät (07.07., vision on-demand) wieder NEBEN Hirn+embed.
|
||||
cmd: |
|
||||
llama-server -m /srv/models/gpt-oss-120b-GGUF/gpt-oss-120b-mxfp4-00001-of-00003.gguf --host 127.0.0.1 --port ${PORT} -c 32768 -ngl 999 -fa on --no-mmap --jinja --cache-reuse 256 -cram 16384
|
||||
llama-server -m /srv/models/gpt-oss-120b-GGUF/gpt-oss-120b-mxfp4-00001-of-00003.gguf --host 127.0.0.1 --port ${PORT} -c 32768 -ngl 999 -fa on --load-mode none --jinja --cache-reuse 256 -cram 16384
|
||||
ttl: 600
|
||||
# 04.09.2026: Rolle `heavy` an Qwen3.8-27B abgegeben (AA-Index 52 vs 24, 17 statt 60 GB, 31 t/s mit DFlash2).
|
||||
# Ohne Alias = Rollback-Reserve, direkt als `gpt-oss-120b` ansprechbar.
|
||||
@@ -74,7 +83,7 @@ models:
|
||||
context: 32768
|
||||
Qwen3-VL-30B-A3B-Instruct:
|
||||
cmd: |
|
||||
llama-server -m /srv/models/Qwen3-VL-30B-A3B-Instruct-GGUF/Qwen3-VL-30B-A3B-Instruct-Q4_K_M.gguf --host 127.0.0.1 --port ${PORT} -c 32768 -ngl 999 -fa on --no-mmap --mmproj /srv/models/Qwen3-VL-30B-A3B-Instruct-GGUF/mmproj-F16.gguf --jinja
|
||||
llama-server -m /srv/models/Qwen3-VL-30B-A3B-Instruct-GGUF/Qwen3-VL-30B-A3B-Instruct-Q4_K_M.gguf --host 127.0.0.1 --port ${PORT} -c 32768 -ngl 999 -fa on --load-mode none --mmproj /srv/models/Qwen3-VL-30B-A3B-Instruct-GGUF/mmproj-F16.gguf --jinja
|
||||
ttl: 900
|
||||
aliases:
|
||||
- vision
|
||||
@@ -87,7 +96,7 @@ models:
|
||||
# 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.
|
||||
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 --no-mmap -c 8192
|
||||
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
|
||||
aliases:
|
||||
- reranker
|
||||
|
||||
+13
-1
@@ -53,6 +53,12 @@ Neue Fallen: hier eintragen, mit Datum und Symptom._
|
||||
- **`pkill -f` über SSH matcht die eigene Remote-Shell** → Muster als `'[g]en…'` klammern.
|
||||
- **Deploy restartet voice-service** → Übernacht-Jobs mit STT-QA-Gate brauchen
|
||||
Wiederanlauf-Logik (Backoff-Retry im hear()-Pfad).
|
||||
- **llama.cpp streicht Flags ohne Vorwarnung:** `--no-mmap` gibt es seit b10936 nicht mehr
|
||||
(`error: invalid argument`) → JEDES Modell stirbt 2 s nach dem Start, llama-swap meldet nur
|
||||
„upstream command exited prematurely", der Stack-Check nur „rot". Ersatz: `--load-mode none`
|
||||
(gleiche Leistung, gemessen 17.09.2026: Coder 32 t/s, Hirn 85 t/s). Vor einem Engine-Sprung
|
||||
jede Config-Kommandozeile mit dem neuen `llama-server` parsen lassen (Port 5899, `timeout 6`,
|
||||
`${PORT}` ersetzen) — Argumentfehler kommen sofort, vor dem Laden.
|
||||
|
||||
## Hermes
|
||||
|
||||
@@ -68,7 +74,7 @@ Neue Fallen: hier eintragen, mit Datum und Symptom._
|
||||
- **Cron-Fallen:** kein TZ-Feld (next_run_at = System-TZ zum Anlege-Zeitpunkt; nach
|
||||
TZ-Wechsel `cron edit --schedule "<gleich>"` zum Neuberechnen) · Prompt/Positionsargumente
|
||||
MÜSSEN vor die Flags · `--script` allein reicht nicht (braucht Prompt oder Skill) ·
|
||||
Cron-Kontext hat `HERMES_CRON_SESSION=1` und `approvals.cron_mode: deny`.
|
||||
Cron-Kontext hat `HERMES_CRON_SESSION=1` (`approvals.cron_mode` ist seit dem KISS-Umbau `auto`, nicht mehr `deny`).
|
||||
- **Feed-Skripte: Pipe + Heredoc gleichzeitig = Heredoc gewinnt stdin** → JSON via Temp-Datei
|
||||
übergeben. Außerdem ehrlichen Blind-Pfad einbauen (API kaputt → „AUSGEFALLEN", nicht „0 Funde").
|
||||
- **Hooks:** Consent persistiert NUR über CLI-/Gateway-Start mit `HERMES_ACCEPT_HOOKS=1`;
|
||||
@@ -84,6 +90,12 @@ Neue Fallen: hier eintragen, mit Datum und Symptom._
|
||||
Erst `git add -A`, dann `git diff --cached`, „Diff leer → STOPP".
|
||||
- **Werkstatt-Gate:** `git -C ~/mission-control-v2 status --porcelain -uno` MUSS leer sein
|
||||
(curl /api/health allein ist ein Loch — alter Code läuft im RAM weiter).
|
||||
- **`hermes update` meldet Exit 1 trotz Erfolg:** nach seinem eigenen Gateway-Neustart erwartet es
|
||||
Zeilen vom „Fleet version check"; unter systemd kommen keine → Exit 1 (#93406). Der MC2-Job
|
||||
bricht dann die `&&`-Kette ab (kein doctor, UI ohne `/hermes-ui/`-Basis), autoupdate.sh rollt
|
||||
zurück und PINNT — obwohl der Gehirn-Check grün war (06. und 17.09.2026). Deshalb
|
||||
`--no-gateway-restart`: Neustart und Urteil gehören dem Job. Pins stehen in
|
||||
`/srv/models/mc2-pins.json` und werden NUR von Hand gelöst — gepinnt = still eingefroren.
|
||||
|
||||
|
||||
## Lucy / Windows-PC
|
||||
|
||||
@@ -62,8 +62,8 @@ keine zweite Liste anlegen. Verdikte werden NICHT als „offen" geführt → [VE
|
||||
|
||||
## Lucy
|
||||
|
||||
- **Raphael-Umbau (04.09.2026) — zwei Branches offen, Reihenfolge zählt (Branch → Ampel →
|
||||
User-Merge → deploy.sh bzw. `npm run dist`, NICHT übers Auftragsbuch):** erst MC2
|
||||
- **Raphael-Umbau (04.09.2026) — AUSGEROLLT 19:10 (MC2 `f9f2e11` deployt, Lucy `be686c4` gebaut),
|
||||
Details [RAPHAEL.md](RAPHAEL.md) „Ausgerollt". Ursprünglicher Plan:** erst MC2
|
||||
`wartung/lucy-stimme-proxy-raphael` (Proxy `/api/lucy/stimme/*`), dann Lucy
|
||||
`feature/raphael-innere-stimme` (HUD-Client, Stimme von der Box). Danach Hand-Schritte auf der
|
||||
Box: `pocket_server.py` nach `~/.lucy-stimme` syncen (OpenAI-Fassade), Hermes-TTS auf
|
||||
@@ -76,9 +76,17 @@ keine zweite Liste anlegen. Verdikte werden NICHT als „offen" geführt → [VE
|
||||
blieben: `deploy/werkstatt-SOUL.md` + `projektstart-SOUL.md` (Werkstatt-Persona, seit Kanban-Aus
|
||||
ohnehin tot — eigener Aufräum-Faden), Chronik-Kategorie „auftragsbuch" (historische Einträge).
|
||||
Auf der Box: `mc2-bagatell.timer` deaktiviert, PC-Executor-URL in `~/.hermes/config.yaml` auf .22.
|
||||
- **Ampel-Runner tot seit 28.08.:** alle Läufe „Waiting to run", kein act_runner auf der Box, Gitea-LXC 104
|
||||
prüfen (`act_runner`-Dienst). Bis dahin gelten lokale Gates.
|
||||
- **Nach dem Ohr-Test:** VERDIKTE.md-Einträge „Electron, nicht Tauri" (Begründung Overlay
|
||||
entfällt) und „STT läuft auf der BOX / Stimme lokal" ersetzen; Lucy-Repo-Altlasten
|
||||
(`mini-stimme/`, Kokoro-Notebooks, `Lucy-Startklar.bat` mit totem Pfad) mit User-Ja räumen.
|
||||
- **Nächster Stimm-Kandidat: Qwen3-TTS über audio.cpp (Vulkan)** — Einstieg liegt bereit: Binaries
|
||||
v0.7.1 unter `~/audiocpp-test/bin` auf der Box (audiocpp_cli/audiocpp_server, Vulkan), Modelle von
|
||||
`huggingface.co/audio-cpp/audio.cpp-gguf` (Qwen3-TTS-12Hz-1.7B-Base q8_0 2,7 GB; CustomVoice/VoiceDesign
|
||||
ebenfalls), CLI: `--task tts --family qwen3_tts --backend vulkan --voice-ref <wav> --reference-text <Transkript>
|
||||
--language de`. Prüfstand: `lucy-tts/referenz/zonos2_bench.py` um einen audio.cpp-Aufrufer erweitern
|
||||
(Server: `POST /v1/audio/speech`). Messlatte = pocket neu: TTFB 1,25 s, RTF 0,97, WER 10 %, 0 Kollaps.
|
||||
- **Eigene Fäden, nicht im Umbau:** pocket-tts 2.1 → 3.1 auf der Box + Lucy-Klon mit dem neuen
|
||||
Trainingscode nachtrainieren (ersetzt Mini-Lucy v2) · Streaming-STT (Nemotron 3.5 ASR
|
||||
Streaming 0.6B oder Voxtral Realtime) als Opt-in im Voice-Sidecar, gegen Parakeet messen.
|
||||
|
||||
@@ -106,6 +106,23 @@ beschreibt nur noch den manuellen Weg. Wer `wartung/auftragsbuch-ausbau` merged,
|
||||
**Nächster Hebel (braucht User-Ja, systemd-Unit):** `Environment=LUCY_WORKERS=2` und
|
||||
`OMP_NUM_THREADS` 4 → 8 in `lucy-stimme.service` — der PC-Pfad lief mit 2 Workern.
|
||||
|
||||
## Ausgerollt (04.09.2026, 19:10, auf User-Anweisung „deploye erstmal den Stand")
|
||||
|
||||
- **MC2 main = `f9f2e11`** (Proxy `/api/lucy/stimme/*` + Auftragsbuch-Ausbau + Doku), per `deploy.sh`
|
||||
auf der Box; Health, Proxy-Health (workers=2), Frontend, alle Dienste grün. Die Ampel war seit
|
||||
28.08. ohne Runner („Waiting to run") — Gate waren die lokalen Läufe: eslint 0 Fehler, 59 Tests,
|
||||
tsc + vite build, py_compile, ruff.
|
||||
- **Lucy main = `be686c4`**, dist am PC gebaut (`npm ci && npm run dist`), Box-Checkout `~/lucy` nachgezogen,
|
||||
`~/.lucy-stimme/app/pocket_server.py` identisch mit dem Repo (Sperren-Fix live).
|
||||
- **Stimmserver:** Referenz **Artoria v2**, `OMP_NUM_THREADS=8`, `LUCY_WORKERS=2` (User-Ja); gemessen
|
||||
TTFB median 1,25 s (vorher 2,04), RTF 0,97 (vorher 1,64), 0 Kollaps, 0 Drift, Ähnlichkeit 0,98.
|
||||
‼️ Die Box kann NICHT klonen (nur das Modell ohne Voice-Cloning im Cache, kein HF-Token) — Klon-Zustände
|
||||
werden am PC exportiert (Anleitung `lucy-tts/referenz/README.md`, Abschnitt 5). Rückfall-Dateien
|
||||
(`ref.mp3.bak-saber-alt`, `lucy_voice_saber-alt.safetensors`, Unit-Backup) liegen daneben.
|
||||
- **ZONOS2 geprüft und verworfen** (Sandkasten `~/zonos2-test`, Server gestoppt): Vulkan-Tempo top
|
||||
(TTFB 0,88 s), aber deutscher Klon unzuverlässig (WER 35 %, 8/30 Läufe Brabbeln, kühlerer Sampler
|
||||
schlimmer). Nächster Kandidat: Qwen3-TTS über audio.cpp (Vulkan), gleicher Prüfstand.
|
||||
|
||||
## Mobil: Telegram ist die Tür, die Stimme ist dieselbe
|
||||
|
||||
Der User will Raphael-Lucy **auch auf dem Handy, gleiche Stimme, gleiches Skillset**. Das ist
|
||||
|
||||
+28
-13
@@ -1,7 +1,8 @@
|
||||
# Stack-Wahrheiten — Infrastruktur, Dienste, Modelle
|
||||
|
||||
_Live gegen die Box verifiziert am **19.08.2026** (Dienste-Liste, llama-swap-Config, hermes
|
||||
--version v0.20.4, llama.cpp b10502, /api/health). Bei Widerspruch zu älteren Docs gewinnt
|
||||
--version, /api/health); Engine, Hermes und llama-swap-Config nachgemessen am **17.09.2026**
|
||||
(llama.cpp b11026, Hermes v0.21.3, `--load-mode none`). Bei Widerspruch zu älteren Docs gewinnt
|
||||
diese Datei. Wer sie ändert: erst messen, dann schreiben._
|
||||
|
||||
## Maschinen & Zugänge
|
||||
@@ -28,11 +29,11 @@ diese Datei. Wer sie ändert: erst messen, dann schreiben._
|
||||
|
||||
| Dienst | Port | Zweck |
|
||||
|---|---|---|
|
||||
| `llama-swap` (System-Dienst) | `:8080` | Modell-Router; Engine = llama.cpp **Vulkan/RADV** (`/opt/llamacpp-vulkan`, b10502) |
|
||||
| `llama-swap` (System-Dienst) | `:8080` | Modell-Router; Engine = llama.cpp **Vulkan/RADV** (`/opt/llamacpp-vulkan`, b11026 seit 17.09.) |
|
||||
| `mission-control-2` (User) | `:9001` | MC2 Cockpit (FastAPI + React Frontend) & Steuerpult |
|
||||
| `mc2-gateway` (User) | `:9010` | `/v1`-Datenpfad (model:auto Routing + native Bildweiche) |
|
||||
| `mc2-steward` (User) | — | Hintergrundwächter (Re-Warm, Health-Sentry, Mem0-Dedupe) |
|
||||
| `hermes-gateway` (User) | `:8642` | Hermes Agent Core API (v0.20.4, Bot Mode) |
|
||||
| `hermes-gateway` (User) | `:8642` | Hermes Agent Core API (v0.21.3, Bot Mode) |
|
||||
| `hermes-builtin-ui` (User) | `:9119` (loopback) | Eingebaute Hermes-GUI; LAN-Zugang via MC2-Proxy `/hermes-ui/` |
|
||||
| `mem0-service` (User) | `:8765` | Semantischer Chroma-Gedächtnis-Sidecar |
|
||||
| `voice-service` (User) | `:8650` | STT (faster-whisper) + TTS (Piper/Chatterbox) |
|
||||
@@ -48,15 +49,22 @@ Qwen3.6-35B-A3B + Qwen3-Embedding-0.6B + Qwen3-Reranker-0.6B. Sonst NICHTS dauer
|
||||
|
||||
| Alias/Rolle | Modell | ttl | Notizen |
|
||||
|---|---|---|---|
|
||||
| `hermes` + `fast` | Qwen3.6-35B-A3B (UD-Q4_K_M, DFlash) | 0 | Agent-Hirn. `-c 131072 --parallel 2` → **65536/Slot**, KV **q8_0**, ~70–90 t/s |
|
||||
| `coder` | Qwen3.8-27B (Q4_K_M, mmproj BF16) | 5400 | **131072 ctx** — `--parallel 1`, der Coder bekommt den ganzen Slot (34a9862). Multimodal, ~12,7 t/s (dicht = bandbreitengebunden) |
|
||||
| `hermes` + `fast` | Qwen3.6-35B-A3B **Uncensored** (HauhauCS Aggressive, Q4_K_M, giocom-DFlash) — seit 17.09.2026 | 0 | Agent-Hirn. `-c 131072 --parallel 2` → **65536/Slot**, KV **q8_0**, ~94–101 t/s (Prüfstand 17.09.). Original (MTP-GGUF UD-Q4_K_M) liegt daneben, Rückweg = Pfad |
|
||||
| `coder` | Qwen3.8-27B **Uncensored** (JonathanColetti/Heretic, Q4_K_M, eigene mmproj F16) — seit 17.09.2026 | 5400 | **131072 ctx** — `--parallel 1`, der Coder bekommt den ganzen Slot (34a9862). Multimodal, **~32 t/s mit DFlash2-Draft** (17.09.), ohne Draft 12,7 (dicht = bandbreitengebunden) |
|
||||
| `debugger` | Muse-Glimmer-30B (Q4_K_XL, DFlash) | 600 | 65536 ctx; Runtime-Diagnostik & Fehler-Debugger (multimodal) |
|
||||
| `vision` | Qwen3-VL-30B-A3B-Instruct (Q4_K_M) | 900 | 32768 ctx; Multimodal-Augen (On-Demand) |
|
||||
| `heavy` | **= Qwen3.8-27B** (zweiter Alias des Coders, seit 04.09.) | 5400 | Planen/Review (OpenChamber) + chat-Lane des Gateways. gpt-oss-120b (60 GB, AA-Index 24 vs 52) liegt ohne Rolle als Rollback bereit, direkt als `gpt-oss-120b` ansprechbar |
|
||||
| `reranker` | Qwen3-Reranker-0.6B (q8_0, Mungert) | 0 | Sortiert Suchtreffer nach echter Relevanz (`/v1/rerank`) |
|
||||
| `embed` | Qwen3-Embedding-0.6B (f16) | 0 | Vektorisierung für Suche/Sortierung |
|
||||
|
||||
> **Diese sieben sind ALLES** — abgeglichen mit `/etc/llama-swap/config.yaml` am 27.08.2026.
|
||||
> **Diese sieben sind ALLES** — abgeglichen mit `/etc/llama-swap/config.yaml` am 27.08.2026 (Pfade 17.09.2026).
|
||||
>
|
||||
> **Prüfstand 17.09.2026** (`deploy/bench/pruefstand-hirn.py`; Kandidat auf `:5899`, Hermes spricht per `--provider pruefstand`
|
||||
> aus `providers:` der Hermes-Config dagegen — Live-Stack bleibt unberührt): Uncensored-3.6 = 100,8 t/s @13k (Original 92,8),
|
||||
> Tools 11/12, Hermes-Smoke grün · Uncensored-27B = 30,4 t/s @13k (Original 26,2), Tools 6/6, Coding 3/3 · **Nemotron 3.5 Lightning
|
||||
> 30B-A3B** (Q4_0 + MTP-Draft, `/srv/models/Nemotron-3.5-Lightning-30B-A3B-GGUF/`) = Hirn-Klasse: 10,5 s Prefill @13k, 91,8 t/s,
|
||||
> Tools 3/3, Hermes grün — liegt als Reserve-Kandidat bereit, nicht besetzt. ‼ **Bild + DFlash2 = HTTP 500** („failed to process
|
||||
> speculative batch") beim Coder — Vorbestand seit 04.09., unabhängig vom Modell; Bilder laufen über die Gateway-Bildweiche zu `vision`.
|
||||
> Frühere Tabellen führten zusätzlich `kritiker` (Devstral-Small-2-24B), `scout` (GLM-4.6V-Flash),
|
||||
> `dense-planer` und `doctor`. Die gibt es nicht mehr: die Modell-Konsolidierung (`9a35be9`, 19.08.)
|
||||
> warf sie aus llama-swap, und `fremdblick.sh` — der einzige Aufrufer des Kritikers — fiel mit dem
|
||||
@@ -68,11 +76,15 @@ Config: `/etc/llama-swap/config.yaml` (sudo zum Schreiben).
|
||||
|
||||
## Hermes (Agent)
|
||||
|
||||
- **v0.20.6** (2026.8.27, git-Install `~/.hermes/hermes-agent`), Config `~/.hermes/config.yaml`, Persona `~/.hermes/SOUL.md` = **Lucy**.
|
||||
- **v0.21.3** (2026.9.14; git-Install `~/.hermes/hermes-agent`, main @ dd13b475 vom 17.09.2026), Config `~/.hermes/config.yaml`, Persona `~/.hermes/SOUL.md` = **Lucy**.
|
||||
- **Bot-Roster: leer** (live geprüft 27.08.2026). Hermes *kann* mehrere Bots, genutzt wird es nicht —
|
||||
die Profile fahren `hermes`, `fast` und `vision`. Frühere Fassungen behaupteten hier einen Roster
|
||||
mit `Coder`/`Qwen3-Coder-Next` und `Debugger`; beides trifft nicht zu.
|
||||
- `approvals.mode: smart`, `approvals.cron_mode: deny`.
|
||||
- `approvals.mode: 'off'`, `approvals.cron_mode: auto` — **User-Entscheid** (so seit spätestens dem KISS-Umbau
|
||||
21.08.2026, bestätigt 17.09.2026: „approvals bleibt off"). Lucy fragt nicht nach Freigaben; die Grenze ziehen
|
||||
ufw, PC-Executor-Token und command_allowlist (siehe Security). Frühere Fassungen nannten `smart`/`deny` (Stand 03.07.).
|
||||
- Config-Schema **v45** (migriert 17.09.2026): `connections`-Toolset (Nous-Konnektoren, `manage_connections`) bewusst in
|
||||
`agent.disabled_toolsets`; Curator archiviert ungenutzte Skills nach 30 Tagen (`skills/.archive/`, `hermes curator restore`).
|
||||
- MCP-Server (aus `~/mission-control-v2/mcp/`): mission-control-stack, hermes-pc-control, hermes-web-fetch, mcp_voice.
|
||||
(`mission-control-memory` ist am 27.08.2026 entfallen — Hermes führt sein Gedächtnis selbst.)
|
||||
|
||||
@@ -97,10 +109,12 @@ Config: `/etc/llama-swap/config.yaml` (sudo zum Schreiben).
|
||||
| 10 9, 16.08. | **Gedaechtnis-Check** (einmalig: Gedächtnis-Schutt räumen, alte Einträge bereinigen) |
|
||||
| So 04:30 | **Auto-Update** Router→Engine→Hermes (Fangnetz: Backup→Postcheck→Auto-Rollback+Pin) |
|
||||
|
||||
**`mc2-autoupdate.timer` ist AN (User-Entscheid 10.07.,** ersetzt „nur bestätigt" vom 04.07.):
|
||||
Fremd-Software-Updates (Router/Engine/Hermes) dürfen automatisch laufen; der User klickt sie
|
||||
zusätzlich oft manuell im Wartungs-Drawer. deploy.sh enablet den Timer bewusst NICHT selbst —
|
||||
der Schaltzustand wird nur von Hand geändert. Manueller Lauf: `bash deploy/autoupdate.sh`.
|
||||
**Sonntags-Update = Hermes-Cron `0ec52231783b`** (`~/.hermes/scripts/sonntags-update.sh` →
|
||||
`deploy/autoupdate.sh`, seit dem KISS-Umbau 21.08.); `mc2-autoupdate.timer` ist disabled — gewollt.
|
||||
Fremd-Software-Updates (Router/Engine/Hermes) dürfen automatisch laufen (User-Entscheid 10.07.); der
|
||||
User klickt sie zusätzlich oft manuell im Wartungs-Drawer. Rot ⇒ Rollback + Pin in
|
||||
`/srv/models/mc2-pins.json`; gepinnte Ebenen werden **still übersprungen**, bis der Pin von Hand
|
||||
gelöst wird (06.–17.09.2026 stand die Box so zwei Wochen still). Manueller Lauf: `bash deploy/autoupdate.sh`.
|
||||
OS-Sicherheitsupdates laufen separat via unattended-upgrades.
|
||||
|
||||
## Security (Stufe 0, live)
|
||||
@@ -109,7 +123,8 @@ PC-Executor nur mit Bearer `HERMES_PC_TOKEN` (fail-closed) · ufw default deny,
|
||||
LAN→22/9001/8080 (+Alt-Port 7681) · Prompt-Injection-Guard `mcp/guard.py` (wrappt
|
||||
Web-/Bildschirm-Text) · mc2-memory lernt nicht aus untrusted Turns · command_allowlist =
|
||||
5 exakt gepinnte curls (fnmatch; Shell-Operatoren hart geblockt — NIE offenes `curl *`) ·
|
||||
Box-sudo braucht Passwort; NOPASSWD nur für update-engine/swap (`/etc/sudoers.d/mc2-autonomie`).
|
||||
Box-sudo ist **NOPASSWD: ALL** (live `sudo -n -l`, 04.09. und 17.09.2026); die alte Whitelist in
|
||||
`/etc/sudoers.d/mc2-autonomie` (update-engine/swap, Dienst-Restarts, journalctl) steht daneben weiter.
|
||||
**Security-Config (approvals/Tokens/ufw) NIE ohne explizites User-Ja ändern.**
|
||||
|
||||
## Deploy & Pipeline
|
||||
|
||||
@@ -84,8 +84,10 @@ einen User-Entscheid — kein „Best Practice sagt aber…" (siehe ARBEITSWEISE
|
||||
- **Zed ACP / Hermes-im-Editor: NICHT machen.** Editor-Agent + Box-coder-Modell + AGENTS.md
|
||||
ist der Sweet Spot; Hermes dazwischen = 70-KB-Prompt-Overhead. (Zed selbst ist inzwischen
|
||||
vom PC entfernt — Hermes Desktop übernahm.)
|
||||
- **`approvals.cron_mode: deny` bleibt** (Autonomie-Härtung 1c, User wählte Option A):
|
||||
Gefahr-Befehle + execute_code sind im Cron-/Autonom-Kontext geblockt, interaktiv `smart`.
|
||||
- **Approvals bleiben AUS** (`approvals.mode: 'off'`, `cron_mode: auto`; so seit spätestens dem KISS-Umbau
|
||||
21.08.2026, vom User am 17.09.2026 bestätigt). Die Schutzlinie liegt außen — ufw, PC-Executor-Token,
|
||||
command_allowlist — nicht in der Freigabe-Frage. *Überholt damit:* „`approvals.cron_mode: deny` bleibt"
|
||||
(Autonomie-Härtung 1c, Option A: Gefahr-Befehle + execute_code im Cron-Kontext geblockt, interaktiv `smart`).
|
||||
- **Fremd-Kritik via `fremdblick.sh`** (Ein-Schuss an leichtes Fremdmodell), NIE via
|
||||
delegate_task→heavy (64k-Floor + Lade-Tod). Raster: prose=GLM-4.7-Flash (kritiker),
|
||||
code=Coder-Next. Harte Regel: **REPRODUZIERT-ODER-ABGELEHNT** — Freispruch nur mit
|
||||
|
||||
Reference in New Issue
Block a user