"""Applique les correctifs de syntaxe (agents) au catalogue — etape 3 de la reparation. Lit pcp/data/catalogue_enrich/syntax_patch/__.json, valide (ASCII, commande existante, champ syntax non vide), applique au catalogue les patchs changed=true, et trace tout dans le champ `syntax_repair` de la commande (provenance + confiance + notes). Les `discrepancies` signalees par les agents sont conservees pour une passe ulterieure sur args/keywords. Usage : python scripts/apply_syntax_patch.py [--dry-run] """ from __future__ import annotations import argparse import json import re from pathlib import Path ROOT = Path(__file__).resolve().parents[1] CATALOGUE = ROOT / "pcp" / "resources" / "pcp_catalogue.json" PATCH_DIR = ROOT / "pcp" / "data" / "catalogue_enrich" / "syntax_patch" def safe_name(name: str) -> str: return re.sub(r"[^A-Za-z0-9_]+", "_", name).strip("_") def main() -> int: ap = argparse.ArgumentParser() ap.add_argument("--dry-run", action="store_true") args = ap.parse_args() cat = json.loads(CATALOGUE.read_text(encoding="utf-8")) by_key = {f"{c['doc']}__{safe_name(c['name'])}": c for c in cat["commands"]} assert len(by_key) == len(cat["commands"]), "cles doc__nom non uniques" patches = sorted(PATCH_DIR.glob("*.json")) applied, unchanged, problems = 0, 0, [] for p in patches: try: patch = json.loads(p.read_text(encoding="utf-8")) except json.JSONDecodeError as e: problems.append(f"{p.name}: JSON invalide ({e})") continue key = p.stem cmd = by_key.get(key) if cmd is None: problems.append(f"{p.name}: commande inconnue au catalogue") continue syntax = patch.get("syntax", "") if not patch.get("changed"): unchanged += 1 continue if not syntax.strip(): problems.append(f"{p.name}: changed=true mais syntax vide") continue bad = [c for c in syntax if ord(c) > 127] if bad: problems.append(f"{p.name}: non-ASCII dans syntax: {set(bad)}") continue long_lines = [l for l in syntax.split("\n") if len(l) > 100] if long_lines: problems.append(f"{p.name}: ligne(s) > 100 colonnes") continue if not args.dry_run: cmd["syntax"] = syntax cmd["syntax_repair"] = { "source": "manuel re-extrait (text_layout), agent 2026-06-10", "confidence": patch.get("confidence", ""), "notes": patch.get("notes", ""), "discrepancies": patch.get("discrepancies", []), } applied += 1 print(f"{len(patches)} patchs : {applied} appliques, {unchanged} sans changement, " f"{len(problems)} problemes") for pb in problems: print(f" PROBLEME {pb}") if not args.dry_run and applied: CATALOGUE.write_text( json.dumps(cat, ensure_ascii=False, indent=1), encoding="utf-8") print(f"catalogue ecrit : {CATALOGUE}") return 1 if problems else 0 if __name__ == "__main__": raise SystemExit(main())