regelwerk_check: Pruefung 7 meldet unsichtbare Zeichen in gespeicherten Workflows
Jedes Zeichen der Kategorie Cc ausser LF und jedes der Kategorie Cf in .claude/workflows/**/*.js, gelesen als Bytes. Anlass: plankritik.js mit CRLF scheiterte am Workflow-Werkzeug. Der Hook nach dem Bearbeiten loest auch bei Workflows aus. Regressionslauf 28/28 angeschlagen, 6/6 stumm; Hook-Treiber 58/58; Vorfall in exakter Form gemeldet (U+000D). Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
3082ab5b75
commit
e50c8296d7
7 files changed
+184
-13
No files matched your search
@@ -66,6 +66,11 @@ def baue_grundlinie(ziel: Path) -> None:
|
||||
unter = ziel / ".claude" / "skills" / skill.parent.name
|
||||
unter.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy2(skill, unter / "SKILL.md")
|
||||
# Prüfung 7 liest die gespeicherten Workflows. copy2 kopiert Bytes, die Grundlinie
|
||||
# trägt also dieselben Zeilenenden wie der Vault.
|
||||
(ziel / ".claude" / "workflows").mkdir(parents=True)
|
||||
for f in (VAULT / ".claude" / "workflows").glob("*.js"):
|
||||
shutil.copy2(f, ziel / ".claude" / "workflows" / f.name)
|
||||
|
||||
# jede Zeile status: pending-review auf status: reference normalisieren.
|
||||
# Ohne das bricht der Lauf nach jeder Selbstpflege an der Grundlinie ab,
|
||||
@@ -332,6 +337,71 @@ def g_link_im_codeblock(v: Path) -> None:
|
||||
f.write_text(t + "\n".join(zeilen), encoding="utf-8")
|
||||
|
||||
|
||||
# Steuerzeichen entstehen nur ueber Codepunkte, nie als Escape-Folge im Quelltext: Die
|
||||
# Schreibschicht hat solche Folgen schon still in echte Zeichen verwandelt
|
||||
# (codeworkflow.md, "Escape-Folgen und unsichtbare Zeichen").
|
||||
CR = bytes([13])
|
||||
LF = bytes([10])
|
||||
|
||||
|
||||
def _workflows(v: Path) -> list[Path]:
|
||||
dateien = sorted((v / ".claude" / "workflows").glob("*.js"))
|
||||
assert len(dateien) >= 2, "die Grundlinie braucht mindestens zwei gespeicherte Workflows"
|
||||
return dateien
|
||||
|
||||
|
||||
def _haenge_an(f: Path, zusatz: bytes) -> None:
|
||||
f.write_bytes(f.read_bytes() + zusatz)
|
||||
|
||||
|
||||
def s_workflow_crlf_erste_datei(v: Path) -> None:
|
||||
f = _workflows(v)[0]
|
||||
f.write_bytes(f.read_bytes().replace(LF, CR + LF))
|
||||
|
||||
|
||||
def s_workflow_cr_letzte_datei_letzte_zeile(v: Path) -> None:
|
||||
f = _workflows(v)[-1]
|
||||
f.write_bytes(f.read_bytes().rstrip(LF) + CR + LF)
|
||||
|
||||
|
||||
def s_workflow_nul(v: Path) -> None:
|
||||
_haenge_an(_workflows(v)[0], b"// " + bytes([0]) + LF)
|
||||
|
||||
|
||||
def s_workflow_bidi(v: Path) -> None:
|
||||
_haenge_an(_workflows(v)[0], ("// " + chr(0x202E) + "x").encode("utf-8") + LF)
|
||||
|
||||
|
||||
def s_workflow_bom(v: Path) -> None:
|
||||
f = _workflows(v)[-1]
|
||||
f.write_bytes(chr(0xFEFF).encode("utf-8") + f.read_bytes())
|
||||
|
||||
|
||||
def s_workflow_tab(v: Path) -> None:
|
||||
_haenge_an(_workflows(v)[0], b"//" + bytes([9]) + b"x" + LF)
|
||||
|
||||
|
||||
def s_workflow_kein_utf8(v: Path) -> None:
|
||||
_haenge_an(_workflows(v)[0], b"// " + bytes([0xFF]) + LF)
|
||||
|
||||
|
||||
def s_workflow_unterordner(v: Path) -> None:
|
||||
unter = v / ".claude" / "workflows" / "unter"
|
||||
unter.mkdir()
|
||||
(unter / "tief.js").write_bytes(b"a" + CR + LF)
|
||||
|
||||
|
||||
def g_workflow_typografie(v: Path) -> None:
|
||||
"""Kein Schaden: typografische Zeichen und Umlaute sind keine Steuerzeichen."""
|
||||
zeichen = "".join(chr(c) for c in (0x201E, 0x201C, 0x2013, 0x2014, 0x2026, 0xE4, 0x20AC))
|
||||
_haenge_an(_workflows(v)[0], ("// " + zeichen).encode("utf-8") + LF)
|
||||
|
||||
|
||||
def g_workflow_ordner_fehlt(v: Path) -> None:
|
||||
"""Kein Schaden: ohne Ordner gibt es nichts zu pruefen."""
|
||||
shutil.rmtree(v / ".claude" / "workflows")
|
||||
|
||||
|
||||
# Gegenfaelle: duerfen NICHT anschlagen. Ohne sie waere die Codeblock-
|
||||
# Erkennung selbst ungeprueft — neuer Code in einer Fix-Runde bekommt
|
||||
# seinen eigenen Fall (pruefwerkzeuge.md, Abschnitt 5).
|
||||
@@ -340,6 +410,8 @@ GEGENFAELLE = [
|
||||
("anfuehrung | effort in Anführungszeichen", g_effort_anfuehrung),
|
||||
("zusatzspalte | Spalte mit Backtick-Wert hinter Effort", g_zusatzspalte),
|
||||
("zweiter-backtick | Effort-Zelle mit zweitem Backtick-Wert", g_zweiter_backtick),
|
||||
("typografie | Anführung, Striche, Umlaut im Workflow", g_workflow_typografie),
|
||||
("ordner-fehlt | kein Workflow-Ordner", g_workflow_ordner_fehlt),
|
||||
]
|
||||
|
||||
|
||||
@@ -364,6 +436,14 @@ FAELLE = [
|
||||
("umgebung | Effort-Spalte fehlt", s_effort_spalte_fehlt, "Effort-Spalte der Rollentabelle nicht auffindbar"),
|
||||
("verweis | Effort-Zelle ohne Wert", s_effort_verweis_leer, "Rollentabelle nennt für 'pruefer' keinen Effort"),
|
||||
("freigabe | status: pending-review", s_effort_freigabe_pending, "Freigabe steht aus"),
|
||||
("zeichen | CRLF in der ERSTEN Workflowdatei", s_workflow_crlf_erste_datei, "U+000D"),
|
||||
("zeichen | CR in der LETZTEN Zeile der LETZTEN Workflowdatei", s_workflow_cr_letzte_datei_letzte_zeile, "U+000D"),
|
||||
("zeichen | NUL", s_workflow_nul, "U+0000"),
|
||||
("zeichen | Bidi-Umkehr", s_workflow_bidi, "U+202E"),
|
||||
("zeichen | BOM am Dateianfang", s_workflow_bom, "Zeile 1, Spalte 1: U+FEFF"),
|
||||
("zeichen | Tab", s_workflow_tab, "U+0009"),
|
||||
("kodierung | Workflow ist kein UTF-8", s_workflow_kein_utf8, "nicht als UTF-8 lesbar"),
|
||||
("zusaetzlich| CR in einem Unterordner", s_workflow_unterordner, ".claude/workflows/unter/tief.js"),
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user