Files
management/scripts/pruefe_upstream_drift.py
T
Thore Cimbal 33a0ee7aec chore: upgrade the neckbeard baseline from v0.1.1 to v0.3.1
Three minor releases at once. Byte-identical surface: only WORKFLOW.md
actually changed (+128/-2); CLAUDE.md and the four templates are
untouched. AGENTS.md takes the new upstream prefix (+22/-2) and keeps our
project section unchanged.

The two declared-extended files were reconciled by hand, because nothing
compares them: validate.py gains upstream's check_vendored_portable, and
schema.yaml gains vendored, project_section_marker, the judged link field
and the ledger and verdict types. gen_status.py needed nothing — upstream
did not touch it. Recorded in the new HERKUNFT.md, including that this
reconciliation has no contradictor and will be forgotten next time.

Newly adopted: check_harvest.py and judge.py, plus docs/ledger/ and
docs/verdict/ with their templates. Deliberately not adopted:
check_locked.py — pruefe_sperrliste.py has done that job here since
2026-08-20, and two tools for one rule is maintenance without gain.

The v0.1.1 baseline stays where it is; docs/sources is immutable.
2026-08-21 12:00:00 +00:00

82 lines
3.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""pruefe_upstream_drift.py — Byte-Vergleich gegen die gepinnte Baseline.
Schützt die übernommenen Framework-Dateien vor stillem Umschreiben
(Entscheidung 8 im Design 2026-08-11, Frage von sorb: „wird die
AGENTS.md ggf. durch Agenten umgeschrieben?"). Die Baseline liegt unter
docs/sources/upstream/neckbeard-v0.3.1/ (siehe HERKUNFT.md dort); ein
Framework-Upgrade aktualisiert Baseline und Arbeitskopie im selben,
bewussten Commit.
Prüfungen (Fehler, Exit 1):
* byte-identische Paare laut PAARE
* AGENTS.md beginnt byte-identisch mit der Baseline-AGENTS.md und
trägt direkt danach die Marke des Projektabschnitts
Fehlt eine Baseline-Datei, ist das ein Fehler, kein Skip
(Stillstandsprüfungs-Regel: eine Prüfung ohne Gegenseite ist ungeprüft).
Usage: python scripts/pruefe_upstream_drift.py [repo-root]
"""
from __future__ import annotations
import sys
from pathlib import Path
BASELINE = "docs/sources/upstream/neckbeard-v0.3.1"
MARKE = "<!-- projektabschnitt -->"
# (Arbeitskopie, Baseline-Datei) — byte-identisch
PAARE = [
("CLAUDE.md", "CLAUDE.md"),
("WORKFLOW.md", "WORKFLOW.md"),
("docs/adr/template.md", "templates/adr-template.md"),
("docs/design/template.md", "templates/design-template.md"),
("docs/aar/template.md", "templates/aar-template.md"),
("docs/issues/template.md", "templates/issue-template.md"),
("docs/ledger/template.md", "templates/ledger-template.md"),
("docs/verdict/template.md", "templates/verdict-template.md"),
]
def main() -> int:
root = Path(sys.argv[1]) if len(sys.argv) > 1 else Path.cwd()
base = root / BASELINE
fehler: list[str] = []
for arbeit, original in PAARE:
a, b = root / arbeit, base / original
if not b.is_file():
fehler.append(f"Baseline fehlt: {BASELINE}/{original}")
continue
if not a.is_file():
fehler.append(f"Arbeitskopie fehlt: {arbeit}")
continue
if a.read_bytes() != b.read_bytes():
fehler.append(f"DRIFT: {arbeit} weicht von {BASELINE}/{original} ab")
agents, agents_base = root / "AGENTS.md", base / "AGENTS.md"
if not agents_base.is_file():
fehler.append(f"Baseline fehlt: {BASELINE}/AGENTS.md")
elif not agents.is_file():
fehler.append("Arbeitskopie fehlt: AGENTS.md")
else:
upstream = agents_base.read_bytes()
arbeit = agents.read_bytes()
if not arbeit.startswith(upstream):
fehler.append("DRIFT: AGENTS.md — Upstream-Teil (§15) ist "
"nicht mehr byte-identisch mit der Baseline")
else:
rest = arbeit[len(upstream):].decode("utf-8", "replace")
if MARKE not in rest.splitlines()[0:3]:
fehler.append(f"AGENTS.md: Marke '{MARKE}' fehlt direkt "
"nach dem Upstream-Teil")
for f in fehler:
print(f"FEHLER {f}")
print(f"pruefe_upstream_drift: {len(fehler)} Fehler")
return 1 if fehler else 0
if __name__ == "__main__":
sys.exit(main())