Automatischer Push: 45 Datei(en) geändert
- .claude/agents/planer.md - .claude/agents/quorum-stimme.md - .claude/skills/bookstack-upload/SKILL.md - .claude/skills/bookstack-upload/scripts/bookstack/archiv.py - .claude/skills/bookstack-upload/scripts/bookstack/auswahl.py - .claude/skills/bookstack-upload/scripts/bookstack/beschreibung.py - .claude/skills/bookstack-upload/scripts/bookstack/bilder.py - .claude/skills/bookstack-upload/scripts/bookstack/ergebnis.py - .claude/skills/bookstack-upload/scripts/bookstack/hochladen.py - .claude/skills/bookstack-upload/scripts/bookstack/konvertierung.py - .claude/skills/bookstack-upload/scripts/bookstack/struktur.py - .claude/skills/bookstack-upload/scripts/bookstack/verweise.py - … und 33 weitere Erzeugt vom PostToolUse-Hook .vault-tools/auto-push/auto_push.py. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
1 parent
60dee0ab68
commit
deec79a6ea
45 files changed
+8645
-262
No files matched your search
@@ -55,7 +55,10 @@ NR = "- Notizen mit Tag needs-review: "
|
||||
RV = "- Notizen mit Tag review ohne review-done: "
|
||||
PR = "- Regelwerk-Dateien mit status: pending-review: "
|
||||
SI = f"- Sitzungsdateien AI/sessions/{HEUTE}-*.md: "
|
||||
WA = "- Waisen außerhalb der Ausnahmen: "
|
||||
FEHLERZEILE = "Sitzungsstart-Hook:"
|
||||
WAISEN = HIER.parent / "linkcheck" / "waisen.py"
|
||||
AUSNAHMEN = HIER.parent / "linkcheck" / "waisen-ausnahmen.txt"
|
||||
|
||||
|
||||
def schreibe(vault: Path, rel: str, inhalt: str | bytes) -> None:
|
||||
@@ -74,6 +77,8 @@ def baue_grundlinie(v: Path) -> None:
|
||||
schreibe(v, f"AI/sessions/{GESTERN}-10.md", "---\ntype: session\n---\n")
|
||||
schreibe(v, "Notizen/sauber.md",
|
||||
"---\ntype: note\ntags: [thema]\n---\n\nKein Tag hier, nur das Wort review ohne Raute.\n")
|
||||
# waisen.py braucht einen Obsidian-Vault; ohne Filter hat die Grundlinie sechs Waisen.
|
||||
schreibe(v, ".obsidian/app.json", '{"userIgnoreFilters": []}')
|
||||
|
||||
|
||||
def grundzeilen(v: Path) -> list[str]:
|
||||
@@ -86,10 +91,11 @@ def grundzeilen(v: Path) -> list[str]:
|
||||
RV + "0",
|
||||
PR + "0",
|
||||
SI + f"1 ({HEUTE}-10.md)",
|
||||
WA + "6",
|
||||
]
|
||||
|
||||
|
||||
def kopiere_hook(v: Path, linkcheck_kopieren: bool = True) -> Path:
|
||||
def kopiere_hook(v: Path, linkcheck_kopieren: bool = True, waisen_kopieren: bool = True) -> Path:
|
||||
"""Kopiert den Hook (und optional linkcheck.py) in den Wegwerf-Vault.
|
||||
|
||||
Seit der Nachbesserung Runde 2 bestimmt sitzungsstart.py seine Vault-
|
||||
@@ -102,10 +108,13 @@ def kopiere_hook(v: Path, linkcheck_kopieren: bool = True) -> Path:
|
||||
ziel.mkdir(parents=True, exist_ok=True)
|
||||
skript = ziel / HOOK.name
|
||||
shutil.copy2(HOOK, skript)
|
||||
lc_ziel = v / ".vault-tools" / "linkcheck"
|
||||
lc_ziel.mkdir(parents=True, exist_ok=True)
|
||||
if linkcheck_kopieren:
|
||||
lc_ziel = v / ".vault-tools" / "linkcheck"
|
||||
lc_ziel.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy2(LINKCHECK, lc_ziel / "linkcheck.py")
|
||||
if waisen_kopieren:
|
||||
shutil.copy2(WAISEN, lc_ziel / "waisen.py")
|
||||
shutil.copy2(AUSNAHMEN, lc_ziel / "waisen-ausnahmen.txt")
|
||||
return skript
|
||||
|
||||
|
||||
@@ -139,6 +148,7 @@ class Fall:
|
||||
# die gezielt eine kaputte oder ungewoehnliche stdin-Form pruefen wollen.
|
||||
stdin: Callable[[Path], bytes] | None = None
|
||||
linkcheck_kopieren: bool = True
|
||||
waisen_kopieren: bool = True
|
||||
# None: Subprozess erbt die Umgebung dieses Treibers unveraendert. Gesetzt:
|
||||
# ersetzt die Umgebung vollstaendig (Pruefbefund Runde 2).
|
||||
umgebung: Callable[[Path], dict[str, str]] | None = None
|
||||
@@ -309,7 +319,9 @@ FAELLE: list[Fall] = [
|
||||
Fall("leer | Vault ohne jeden Ordner",
|
||||
lambda v: [shutil.rmtree(p) for p in list(v.iterdir())],
|
||||
[TN + "fehlt", IN + "Ordner Inbox/ fehlt", NR + "0", RV + "0",
|
||||
PR + "Ordner AI/Regelwerk/ fehlt", SI + "Ordner AI/sessions/ fehlt"]),
|
||||
PR + "Ordner AI/Regelwerk/ fehlt", SI + "Ordner AI/sessions/ fehlt"],
|
||||
verboten=[WA],
|
||||
praefixe=["Sitzungsstart-Hook: Waisen: RuntimeError: waisen.py Exit 2: Waisen - ABGEBROCHEN: kein Obsidian-Vault"]),
|
||||
Fall("leer | stdin leer", nichts, None, stdin=lambda v: b""),
|
||||
Fall("falscher Typ| stdin kein JSON", nichts, None, stdin=lambda v: b"kein json"),
|
||||
Fall("kodierung | stdin ungueltiges UTF-8", nichts, None, stdin=lambda v: b"\xff\xfe{"),
|
||||
@@ -332,10 +344,34 @@ FAELLE: list[Fall] = [
|
||||
umgebung=ohne_pythonioencoding),
|
||||
Fall("umgebung | linkcheck.py fehlt", nichts,
|
||||
[DA, TN + "vorhanden", IN + "1 (offen.md)", PR + "0", SI + f"1 ({HEUTE}-10.md)"],
|
||||
verboten=[NR, RV],
|
||||
praefixe=["Sitzungsstart-Hook: needs-review/review: RuntimeError: linkcheck.py nicht importierbar"],
|
||||
verboten=[NR, RV, WA],
|
||||
praefixe=["Sitzungsstart-Hook: needs-review/review: RuntimeError: linkcheck.py nicht importierbar",
|
||||
"Sitzungsstart-Hook: Waisen: RuntimeError: waisen.py Exit 2: Waisen - ABGEBROCHEN: linkcheck.py nicht importierbar"],
|
||||
stdin=lambda v: b"{}",
|
||||
linkcheck_kopieren=False),
|
||||
Fall("waisen | verlinkte Notiz senkt die Zahl",
|
||||
lambda v: schreibe(v, "Notizen/verweis.md", "[[Notizen/sauber]]\n"),
|
||||
[WA + "5"]),
|
||||
Fall("waisen | Waise an erster und an letzter Stelle",
|
||||
lambda v: (schreibe(v, "0-erste/a.md", "x\n"), schreibe(v, "zz-letzte/z.md", "x\n")),
|
||||
[WA + "8"]),
|
||||
Fall("waisen | Muster aus der Ausnahmedatei greift",
|
||||
lambda v: schreibe(v, "Bookstack/archiv/seite.md", "x\n"),
|
||||
[WA + "6"]),
|
||||
Fall("waisen | waisen.py fehlt", nichts,
|
||||
[DA, TN + "vorhanden", IN + "1 (offen.md)", NR + "0", RV + "0", PR + "0", SI + f"1 ({HEUTE}-10.md)"],
|
||||
verboten=[WA],
|
||||
praefixe=["Sitzungsstart-Hook: Waisen: RuntimeError: waisen.py fehlt"],
|
||||
waisen_kopieren=False),
|
||||
Fall("waisen | kaputte app.json meldet Fehler statt Zahl",
|
||||
lambda v: schreibe(v, ".obsidian/app.json", "{kaputt"),
|
||||
[DA, TN + "vorhanden", NR + "0", SI + f"1 ({HEUTE}-10.md)"],
|
||||
verboten=[WA],
|
||||
praefixe=["Sitzungsstart-Hook: Waisen: RuntimeError: waisen.py Exit 2: Waisen - ABGEBROCHEN: .obsidian/app.json nicht lesbar"]),
|
||||
Fall("umgebung | ohne PYTHONIOENCODING zaehlt Waisen mit Umlaut im Namen",
|
||||
lambda v: schreibe(v, "Notizen/Übersicht 🚀.md", "x\n"),
|
||||
[WA + "7"],
|
||||
umgebung=ohne_pythonioencoding),
|
||||
]
|
||||
|
||||
|
||||
@@ -412,7 +448,7 @@ def frische_kopie(basis: Path, arbeit: Path) -> Path:
|
||||
def lauf_fall(fall: Fall, basis: Path, arbeit: Path) -> tuple[bool, str]:
|
||||
v = frische_kopie(basis, arbeit)
|
||||
fall.aendern(v)
|
||||
skript = kopiere_hook(v, fall.linkcheck_kopieren)
|
||||
skript = kopiere_hook(v, fall.linkcheck_kopieren, fall.waisen_kopieren)
|
||||
if fall.stdin is None:
|
||||
eingabe = json.dumps({"session_id": "faelle", "cwd": str(v),
|
||||
"hook_event_name": "SessionStart", "source": "startup"}).encode("utf-8")
|
||||
@@ -501,7 +537,9 @@ def ip_datei_gesperrt(v: Path) -> tuple[bool, str]:
|
||||
zeilen = im_prozess(modul, v)
|
||||
if zeilen is None:
|
||||
return False, " keine gueltige Ausgabe"
|
||||
erwartet = grundzeilen(v) + ["Sitzungsstart-Hook: 1 Datei(en) nicht lesbar (erste: Notizen/gesperrt.md)"]
|
||||
# gesperrt.md ist für waisen.py lesbar und die siebte Waise.
|
||||
erwartet = [z for z in grundzeilen(v) if not z.startswith(WA)] + [WA + "7"]
|
||||
erwartet.append("Sitzungsstart-Hook: 1 Datei(en) nicht lesbar (erste: Notizen/gesperrt.md)")
|
||||
probleme = bewerte(zeilen, erwartet, [], [])
|
||||
return not probleme, "\n".join(" " + p for p in probleme)
|
||||
|
||||
@@ -540,11 +578,27 @@ def ip_ordner_gesperrt(v: Path) -> tuple[bool, str]:
|
||||
return not probleme, "\n".join(" " + p for p in probleme)
|
||||
|
||||
|
||||
def ip_waisen_zeitgrenze(v: Path) -> tuple[bool, str]:
|
||||
"""Die Zeitgrenze lässt sich von außen nicht billig überschreiten:
|
||||
im Prozess auf eine Millisekunde gesetzt, startet waisen.py nicht rechtzeitig."""
|
||||
skript = kopiere_hook(v)
|
||||
modul = lade_hook("hook_waisen_zeitgrenze", skript)
|
||||
modul.ZEITGRENZE_WAISEN_S = 0.001
|
||||
zeilen = im_prozess(modul, v)
|
||||
if zeilen is None:
|
||||
return False, " keine gueltige Ausgabe"
|
||||
erwartet = [z for z in grundzeilen(v) if not z.startswith(WA)]
|
||||
erwartet.append("Sitzungsstart-Hook: Waisen: RuntimeError: waisen.py nach 0.001 s abgebrochen, nicht gezählt")
|
||||
probleme = bewerte(zeilen, erwartet, [WA], [])
|
||||
return not probleme, "\n".join(" " + p for p in probleme)
|
||||
|
||||
|
||||
IM_PROZESS = [
|
||||
("absturz | ein Punkt wirft", ip_punkt_wirft),
|
||||
("absturz | Hauptablauf wirft", ip_hauptablauf_wirft),
|
||||
("lesen | Datei nicht lesbar", ip_datei_gesperrt),
|
||||
("lesen | Ordner nicht lesbar", ip_ordner_gesperrt),
|
||||
("waisen | Zeitgrenze ueberschritten", ip_waisen_zeitgrenze),
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user