mirror of
https://github.com/Klotzkette/claude-fuer-deutsches-recht
synced 2026-06-09 10:03:19 +00:00
Zahl-Komma-Zahl-Sequenzen aus Skill- und Plugin-Descriptions entfernt
Der Cowork-Plugin-Validator lehnte ZIPs ab, sobald eine description-Zeile eine Sequenz wie 'BGHZ 217, 129' oder '§§ 5, 6 DDG' enthielt. Diese Sequenzen sind nun durch 'Rn', 'und' oder Schraegstrich-Notation ersetzt. Aenderungen - 16 SKILL.md Frontmatter-Descriptions umgeschrieben - 1 plugin.json Description (produktrecht) umgeschrieben - Validator scripts/validate-plugin-structure.mjs lehnt Zahl-Komma-Zahl in description-Feldern jetzt explizit ab - Hilfsskript scripts/fix-comma-numbers-in-descriptions.py fuer kuenftige Massenkorrekturen hinzugefuegt
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Ersetzt Komma-Zahl-Sequenzen in SKILL.md und plugin.json descriptions.
|
||||
|
||||
Hintergrund: Der Cowork-Plugin-Validator bricht bei Sequenzen wie `Zahl, Zahl`
|
||||
im description-Feld (z. B. `BGHZ 217, 129` oder `§§ 5, 6 DDG`). Dieses Skript
|
||||
ersetzt das Komma in solchen Sequenzen durch ein Wort (`und`) oder eine
|
||||
Randnummern-Notation (`Rn`), abhaengig vom Kontext.
|
||||
|
||||
Regeln:
|
||||
- `BGHZ <Zahl>, <Zahl>` -> `BGHZ <Zahl> Rn <Zahl>`
|
||||
- `§§ <Zahl>, <Zahl>` -> `§§ <Zahl> und <Zahl>`
|
||||
- generisch `<Zahl>, <Zahl>` -> `<Zahl> und <Zahl>`
|
||||
|
||||
Wird nur auf die `description`-Zeile im YAML-Frontmatter von SKILL.md und auf
|
||||
das `description`-Feld in plugin.json angewandt.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
REPO = Path(__file__).resolve().parent.parent
|
||||
|
||||
# Order matters: BGHZ first, then §§, then generic.
|
||||
PATTERNS = [
|
||||
(re.compile(r"(BGHZ\s+\d+)\s*,\s*(\d+)"), r"\1 Rn \2"),
|
||||
(re.compile(r"(§§\s*\d+[a-z]?)\s*,\s*(\d+[a-z]?)"), r"\1 und \2"),
|
||||
(re.compile(r"(\b\d+[a-z]?)\s*,\s*(\d+[a-z]?\b)"), r"\1 und \2"),
|
||||
]
|
||||
|
||||
|
||||
def fix_text(text: str) -> str:
|
||||
# Apply each pattern repeatedly until stable, to chain through lists.
|
||||
for pat, repl in PATTERNS:
|
||||
prev = None
|
||||
while prev != text:
|
||||
prev = text
|
||||
text = pat.sub(repl, text)
|
||||
return text
|
||||
|
||||
|
||||
def fix_skill_md(path: Path) -> bool:
|
||||
src = path.read_text(encoding="utf-8")
|
||||
lines = src.split("\n")
|
||||
if not lines or lines[0].strip() != "---":
|
||||
return False
|
||||
changed = False
|
||||
in_fm = True
|
||||
out = [lines[0]]
|
||||
i = 1
|
||||
while i < len(lines):
|
||||
line = lines[i]
|
||||
if in_fm and line.strip() == "---":
|
||||
in_fm = False
|
||||
out.append(line)
|
||||
i += 1
|
||||
continue
|
||||
if in_fm and line.startswith("description:"):
|
||||
# description value may be quoted on one line
|
||||
m = re.match(r'^(description:\s*)(.*)$', line)
|
||||
if m:
|
||||
prefix, value = m.group(1), m.group(2)
|
||||
fixed = fix_text(value)
|
||||
if fixed != value:
|
||||
changed = True
|
||||
out.append(prefix + fixed)
|
||||
i += 1
|
||||
continue
|
||||
out.append(line)
|
||||
i += 1
|
||||
if changed:
|
||||
path.write_text("\n".join(out), encoding="utf-8")
|
||||
return changed
|
||||
|
||||
|
||||
def fix_plugin_json(path: Path) -> bool:
|
||||
try:
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
except Exception:
|
||||
return False
|
||||
desc = data.get("description")
|
||||
if not isinstance(desc, str):
|
||||
return False
|
||||
fixed = fix_text(desc)
|
||||
if fixed == desc:
|
||||
return False
|
||||
data["description"] = fixed
|
||||
path.write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
||||
return True
|
||||
|
||||
|
||||
def main() -> int:
|
||||
changed_skills = []
|
||||
for p in REPO.rglob("SKILL.md"):
|
||||
if any(part in {"node_modules", ".git"} for part in p.parts):
|
||||
continue
|
||||
if fix_skill_md(p):
|
||||
changed_skills.append(p.relative_to(REPO))
|
||||
changed_plugins = []
|
||||
for p in REPO.glob("*/.claude-plugin/plugin.json"):
|
||||
if fix_plugin_json(p):
|
||||
changed_plugins.append(p.relative_to(REPO))
|
||||
print(f"SKILL.md geaendert: {len(changed_skills)}")
|
||||
for p in changed_skills:
|
||||
print(f" - {p}")
|
||||
print(f"plugin.json geaendert: {len(changed_plugins)}")
|
||||
for p in changed_plugins:
|
||||
print(f" - {p}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -182,6 +182,10 @@ function checkSkills() {
|
||||
if (/[<>]/.test(v)) {
|
||||
errors.push(`${rel(skill)}: description contains forbidden XML-style brackets`);
|
||||
}
|
||||
// Cowork-Validator bricht bei Zahl-Komma-Zahl-Sequenzen in description (z. B. 'BGHZ 217, 129').
|
||||
if (/\d\s*,\s*\d/.test(v)) {
|
||||
errors.push(`${rel(skill)}: description darf keine Zahl-Komma-Zahl-Sequenz enthalten (Cowork-Validator bricht); nutze 'Rn', 'und' oder '/'`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -198,6 +202,10 @@ function checkPluginManifests() {
|
||||
if (data.name && !/^[a-z0-9-]+$/.test(data.name)) {
|
||||
errors.push(`${rel(m)}: name '${data.name}' must be kebab-case`);
|
||||
}
|
||||
// Cowork-Validator bricht bei Zahl-Komma-Zahl-Sequenzen in description (z. B. 'BGHZ 217, 129').
|
||||
if (typeof data.description === 'string' && /\d\s*,\s*\d/.test(data.description)) {
|
||||
errors.push(`${rel(m)}: description darf keine Zahl-Komma-Zahl-Sequenz enthalten (Cowork-Validator bricht); nutze 'Rn', 'und' oder '/'`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user