Files
Pascal MichelandClaude Opus 5 f86a54a6e7 Automatischer Push: 46 Datei(en) geändert
- .claude/agents/planer.md
- .claude/skills/plan-executer-pruefung/SKILL.md
- .claude/workflows/plankritik.js
- .claude/workflows/planung.js
- .claude/workflows/pruefung.js
- .claude/workflows/verbrauch.js
- .claude/workflows/welle-mit-pruefung.js
- .vault-tools/plan-kopie/LIESMICH.md
- .vault-tools/plan-kopie/plan_zeichen.py
- .vault-tools/plan-kopie/rot_nachweis.py
- .vault-tools/trading-plattform-pruefung/LIESMICH.md
- .vault-tools/trading-plattform-pruefung/abendkontrolle.py
- … und 34 weitere

Erzeugt vom PostToolUse-Hook .vault-tools/auto-push/auto_push.py.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-25 04:00:02 +02:00

63 lines
2.9 KiB
Python

"""Sucht in den Codebloecken eines Plans nach Zeichen, die ein Executer nicht sehen oder nicht tippen kann.
Koordinator-Werkzeug. Frage: Steht in einem Codeblock ein Zeichen, das beim Abschreiben verloren geht?
Herkunft der Antwort: Unicode-Kategorie des Zeichens (unicodedata, Quelle: Python-Standardbibliothek).
Befund ist jedes Zeichen der Kategorien Zl, Zp, Cf, Cc (ausser \\n und \\t) und Zs ausser dem Leerzeichen --
also Zeilen- und Absatztrenner, Formatzeichen, Steuerzeichen, geschuetzte und schmale Leerzeichen.
Alle uebrigen Nicht-ASCII-Zeichen in Codebloecken werden nur gezaehlt und gezeigt (Umlaute, Gedankenstriche).
Was es nicht sieht: Zeichen ausserhalb von Codezaeunen; verwechselbare sichtbare Zeichen (kyrillisches c).
Aufruf: python plan_zeichen.py <planordner> Exit 0 ohne Befund, 2 mit Befund.
"""
import sys
import unicodedata
from collections import Counter
from pathlib import Path
def main() -> int:
# Die Windows-Konsole kodiert cp1252; ein sichtbares Zeichen wie U+2192 in der Zusammenfassung
# liess das Skript sonst mit UnicodeEncodeError abbrechen (2026-09-24, Plan AF der Trading Plattform).
sys.stdout.reconfigure(errors="backslashreplace")
plan = Path(sys.argv[1])
dateien = sorted(plan.glob("*.md"))
if not dateien:
print(f"BEFUND {plan}: keine Markdown-Dateien -- der Lauf misst nichts")
return 2
befunde = 0
sichtbar: Counter[str] = Counter()
bloecke = 0
for datei in dateien:
zeilen = datei.read_text(encoding="utf-8").replace("\r\n", "\n").split("\n")
zaun = 0
for nummer, zeile in enumerate(zeilen, start=1):
kern = zeile.lstrip()
if kern.startswith("```"):
laenge = len(kern) - len(kern.lstrip("`"))
if zaun == 0:
zaun = laenge
bloecke += 1
elif laenge >= zaun and not kern.strip("`").strip():
zaun = 0
continue
if zaun == 0:
continue
for spalte, zeichen in enumerate(zeile, start=1):
if ord(zeichen) < 128 and zeichen not in "\x0b\x0c\x1b" and (zeichen >= " " or zeichen == "\t"):
continue
kategorie = unicodedata.category(zeichen)
if kategorie in ("Zl", "Zp", "Cf", "Cc") or (kategorie == "Zs" and zeichen != " "):
name = unicodedata.name(zeichen, "?")
print(f"BEFUND {datei.name}:{nummer}:{spalte}: U+{ord(zeichen):04X} {name} ({kategorie}) in: {zeile.strip()[:110]!r}")
befunde += 1
else:
sichtbar[zeichen] += 1
print(f"{len(dateien)} Dateien, {bloecke} Codebloecke gelesen.")
print("Sichtbare Nicht-ASCII-Zeichen in Codebloecken: " + " ".join(f"{z}(U+{ord(z):04X})x{n}" for z, n in sichtbar.most_common()))
print(f"{befunde} Befund(e).")
return 2 if befunde else 0
if __name__ == "__main__":
sys.exit(main())