6 Datei(en) geändert. Erzeugt von .vault-tools/auto-push/werkzeuge_spiegel.py.
127 lines
4.3 KiB
Python
127 lines
4.3 KiB
Python
"""Täglicher Lauf: committet und pusht die Anweisungsschicht und spiegelt die Werkzeuge.
|
|
|
|
Ersteller: Pascal Michel
|
|
Erstellt: 2026-09-17
|
|
Geändert: 2026-10-14 (Werkzeug-Spiegel nach claude-werkzeuge)
|
|
|
|
WARUM LOKAL UND NICHT ALS COWORK-ROUTINE
|
|
Eine Cowork-Routine läuft in Anthropics Cloud und hat weder Zugriff auf
|
|
D:\\Claude noch auf die Umgebungsvariable GITEA_TOKEN dieser Maschine (so
|
|
wörtlich in der Routinen-Doku, gelesen am 2026-09-17). Sie könnte hier
|
|
nichts committen. Deshalb die Windows-Aufgabenplanung.
|
|
|
|
WAS ES TUT
|
|
1. Genau dasselbe wie der frühere PostToolUse-Hook: die Arbeitsfunktion
|
|
aus auto_push.py, unter derselben Sperre. Der Umfang steht in der
|
|
.gitignore des Vault-Roots, nicht hier.
|
|
2. Danach, noch unter der Sperre, spiegelt werkzeuge_spiegel.py den
|
|
committeten Stand von .vault-tools/ und .claude/ in das öffentliche
|
|
Repo claude-werkzeuge. Scheitert Schritt 1, entfällt Schritt 2.
|
|
|
|
WAS ES MELDET
|
|
Jeder Lauf schreibt eine Zeile je Schritt nach lauf.log im selben Ordner,
|
|
auch ein Lauf ohne Änderung. Eine Protokolldatei, die nur bei Erfolg
|
|
schreibt, lässt sich von einer nicht gestarteten Aufgabe nicht
|
|
unterscheiden, und genau das war am 2026-09-07 beim Depotbericht das
|
|
Problem.
|
|
|
|
Exit 0: gepusht oder nichts zu tun, in beiden Schritten. Exit 1: Befund in
|
|
einem Schritt, Text steht im Protokoll. Die Aufgabenplanung zeigt den Code
|
|
als „Letztes Ergebnis".
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
import sys
|
|
import traceback
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
HIER = Path(__file__).resolve().parent
|
|
PROTOKOLL = HIER / "lauf.log"
|
|
MAX_PROTOKOLL_ZEILEN = 400
|
|
|
|
|
|
def lade(name: str):
|
|
spec = importlib.util.spec_from_file_location(name, HIER / f"{name}.py")
|
|
if spec is None or spec.loader is None:
|
|
raise RuntimeError(f"{name}.py nicht ladbar: {HIER / f'{name}.py'}")
|
|
modul = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(modul)
|
|
return modul
|
|
|
|
|
|
def schreibe(zeile: str) -> None:
|
|
stempel = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
text = f"{stempel} {zeile}\n"
|
|
try:
|
|
alt = PROTOKOLL.read_text(encoding="utf-8").splitlines(keepends=True)
|
|
except OSError:
|
|
alt = []
|
|
alt.append(text)
|
|
PROTOKOLL.write_text("".join(alt[-MAX_PROTOKOLL_ZEILEN:]), encoding="utf-8")
|
|
sys.stdout.write(text)
|
|
|
|
|
|
def vault_push(hook, wurzel: Path) -> int:
|
|
try:
|
|
vorher = hook.git(wurzel, "rev-parse", "HEAD").strip()
|
|
hook.arbeite(wurzel)
|
|
nachher = hook.git(wurzel, "rev-parse", "HEAD").strip()
|
|
except hook.GitFehler as fehler:
|
|
schreibe(f"BEFUND {fehler.kopf} | {' '.join(fehler.rumpf.split())[:400]}")
|
|
return 1
|
|
except Exception as fehler: # noqa: BLE001
|
|
schreibe(f"BEFUND unerwarteter Abbruch: {type(fehler).__name__}: {fehler}")
|
|
schreibe(" " + " ".join(traceback.format_exc().split())[:400])
|
|
return 1
|
|
|
|
if vorher == nachher:
|
|
schreibe(f"ok nichts zu tun, HEAD {nachher[:8]}")
|
|
else:
|
|
schreibe(f"ok gepusht, HEAD {vorher[:8]} -> {nachher[:8]}")
|
|
return 0
|
|
|
|
|
|
def werkzeuge_spiegeln(wurzel: Path) -> int:
|
|
try:
|
|
spiegel = lade("werkzeuge_spiegel")
|
|
status, text = spiegel.spiegele(wurzel)
|
|
except Exception as fehler: # noqa: BLE001 - SpiegelFehler und jeder Absturz sind Befunde
|
|
schreibe(f"BEFUND werkzeuge: {type(fehler).__name__}: {' '.join(str(fehler).split())[:400]}")
|
|
return 1
|
|
schreibe(f"ok werkzeuge {status}, {text}")
|
|
return 0
|
|
|
|
|
|
def main() -> int:
|
|
try:
|
|
hook = lade("auto_push")
|
|
except Exception as fehler: # noqa: BLE001
|
|
schreibe(f"BEFUND auto_push.py nicht ladbar: {type(fehler).__name__}: {fehler}")
|
|
return 1
|
|
|
|
wurzel = HIER.parents[1]
|
|
sperre = wurzel / hook.SPERRE_REL
|
|
deskriptor = hook.hole_sperre(sperre)
|
|
if deskriptor is None:
|
|
# Kein Befund: ein anderer Lauf arbeitet und nimmt alles mit.
|
|
schreibe("uebersprungen Sperre belegt, ein anderer Lauf arbeitet")
|
|
return 0
|
|
|
|
try:
|
|
if vault_push(hook, wurzel) != 0:
|
|
return 1
|
|
return werkzeuge_spiegeln(wurzel)
|
|
finally:
|
|
hook.gib_sperre_frei(deskriptor, sperre)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
sys.stdout.reconfigure(encoding="utf-8")
|
|
except AttributeError:
|
|
pass
|
|
raise SystemExit(main())
|