File size: 3,179 Bytes
5043c6f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
"""Applique les correctifs de syntaxe (agents) au catalogue — etape 3 de la reparation.

Lit pcp/data/catalogue_enrich/syntax_patch/<doc>__<NAME>.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())