Erste Fassung: Claude-Werkzeuge aus dem Vault

.vault-tools (ohne trading-plattform-pruefung und watermarks-remover),
.claude/agents, .claude/skills, .claude/workflows, .claude/settings.json.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Pascal MichelandClaude Opus 5.5 committed 2026-10-14 11:27:59 +02:00
commit fa1c26b407
137 files changed
+43926

No files matched your search

+98
View File
@@ -0,0 +1,98 @@
"""Baut die schlanke Kopie eines Projektbaums fuer den Byte-Vergleich -- Ausschluesse nur als Pfade vom Wurzelordner.
Ersteller: Pascal Michel
Erstellt: 2026-09-17
Doku: .vault-tools/plan-kopie/LIESMICH.md
Aufruf: python kopie_bauen.py <projekt> <ziel> --ohne <relpfad> [<relpfad> ...]
Warum Pfade und keine Namen: Ein Ausschluss von "jedem Ordner namens data" hat am 2026-09-17 auch das Paket
trading/data getroffen. Nach dem Kopieren vergleicht das Skript deshalb die Python-Pakete (Ordner mit __init__.py)
beider Baeume und meldet jedes, das in der Kopie fehlt und nicht unter einem ausgeschlossenen Pfad liegt.
Das Ziel darf nicht existieren; Verknuepfungen und Junctions werden nicht verfolgt, sondern uebersprungen.
"""
import argparse
import os
import shutil
import sys
from pathlib import Path
def _relativ(pfad: Path, wurzel: Path) -> str:
return pfad.relative_to(wurzel).as_posix()
def _pakete(wurzel: Path, ohne: set[str]) -> set[str]:
gefunden = set()
for ordner, unterordner, dateien in os.walk(wurzel):
rel = _relativ(Path(ordner), wurzel)
unterordner[:] = [
name for name in unterordner
if (f"{rel}/{name}" if rel != "." else name) not in ohne
and not Path(ordner, name).is_symlink()
and not Path(ordner, name).is_junction()
]
if "__init__.py" in dateien:
gefunden.add(rel)
return gefunden
def main() -> int:
parser = argparse.ArgumentParser(allow_abbrev=False)
parser.add_argument("projekt", type=Path)
parser.add_argument("ziel", type=Path)
parser.add_argument("--ohne", nargs="*", default=[], help="relative Pfade vom Wurzelordner, mit /")
args = parser.parse_args()
projekt = args.projekt.resolve()
ziel = args.ziel.resolve()
if not projekt.is_dir():
print(f"BEFUND Projekt {projekt} ist kein Ordner")
return 2
if ziel.exists():
print(f"BEFUND Ziel {ziel} existiert schon -- erst ansehen, dann selbst loeschen")
return 2
ohne = {eintrag.replace("\\", "/").strip("/") for eintrag in args.ohne}
befunde = []
for eintrag in sorted(ohne):
if "/" not in eintrag and not (projekt / eintrag).exists():
befunde.append(f"Ausschluss '{eintrag}' gibt es im Wurzelordner nicht -- ein Name statt eines Pfads?")
elif not (projekt / eintrag).exists():
befunde.append(f"Ausschluss '{eintrag}' gibt es nicht")
uebersprungen = []
def ignoriere(ordner: str, namen: list[str]) -> list[str]:
rel = _relativ(Path(ordner), projekt)
raus = []
for name in namen:
pfad = Path(ordner, name)
relpfad = name if rel == "." else f"{rel}/{name}"
if relpfad in ohne or name == "__pycache__":
raus.append(name)
elif pfad.is_symlink() or pfad.is_junction():
uebersprungen.append(relpfad)
raus.append(name)
return raus
shutil.copytree(projekt, ziel, ignore=ignoriere)
fehlend = sorted(_pakete(projekt, ohne) - _pakete(ziel, set()))
for paket in fehlend:
befunde.append(f"Paket '{paket}' fehlt in der Kopie")
dateien = sum(len(d) for _, _, d in os.walk(ziel))
print(f"{dateien} Dateien kopiert, {len(ohne)} Pfade ausgeschlossen, "
f"{len(uebersprungen)} Verknuepfungen uebersprungen, {len(_pakete(ziel, set()))} Pakete in der Kopie.")
for zeile in uebersprungen:
print(f"HINWEIS Verknuepfung uebersprungen: {zeile}")
for zeile in befunde:
print(f"BEFUND {zeile}")
print(f"{len(befunde)} Befund(e).")
return 1 if befunde else 0
if __name__ == "__main__":
sys.exit(main())