Files
mercadodevida/scripts/fix_gate_schema.py
2026-08-21 21:03:28 +02:00

97 lines
3.1 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Normalize gate artifact JSON schema — minimal `agent` field fix.
History: F-123..F-135 (13 features x 3 gate files = 39 files) were closed
with the wrong field name (`reviewer` instead of `agent`). `verify.sh`
rejects those files because it checks `obj.get('agent') == '<role>'`.
This script is idempotent: it adds `agent` from the legacy `reviewer`
field (when present and matching) without touching any other field.
Re-running it on an already-normalized file is a no-op. `stage` is not
required by `verify.sh`, so we leave it alone.
Usage:
python3 scripts/fix_gate_schema.py # all artifacts
python3 scripts/fix_gate_schema.py F-123 F-124 # specific features
python3 scripts/fix_gate_schema.py --dry-run # preview only
"""
from __future__ import annotations
import json
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
ARTIFACTS_DIR = ROOT / 'work' / 'artifacts'
FILE_TO_AGENT = {
'reviewer.json': 'reviewer',
'security.json': 'security',
'qa.json': 'qa',
}
def normalize(feature_dir: Path, dry_run: bool = False) -> list[str]:
"""Normalize gate files in `feature_dir`. Returns list of changes made."""
changes: list[str] = []
fid = feature_dir.name
for filename, expected_agent in FILE_TO_AGENT.items():
path = feature_dir / filename
if not path.is_file():
continue
try:
data = json.loads(path.read_text(encoding='utf-8'))
except Exception:
continue
if data.get('agent') == expected_agent:
continue # already correct, no-op
legacy = data.get('reviewer')
if isinstance(legacy, str) and legacy == expected_agent:
data['agent'] = legacy
changes.append(f"{fid}/{filename}: copied agent='{expected_agent}' from legacy 'reviewer' field")
else:
data['agent'] = expected_agent
changes.append(f"{fid}/{filename}: set agent='{expected_agent}'")
if not dry_run:
path.write_text(
json.dumps(data, indent=2, ensure_ascii=False) + '\n',
encoding='utf-8',
)
return changes
def main() -> int:
args = [a for a in sys.argv[1:] if not a.startswith('--')]
dry_run = '--dry-run' in sys.argv
if args:
targets = [ARTIFACTS_DIR / a for a in args]
for t in targets:
if not t.is_dir():
print(f"[WARN] {t} is not a directory, skipping")
targets = [t for t in targets if t.is_dir()]
else:
targets = sorted(p for p in ARTIFACTS_DIR.iterdir() if p.is_dir())
total_changes: list[str] = []
for d in targets:
total_changes.extend(normalize(d, dry_run=dry_run))
if not total_changes:
print('[OK] All gate files already conform to schema (agent field present)')
return 0
verb = 'Would fix' if dry_run else 'Fixed'
print(f"{verb} {len(total_changes)} file(s):")
for c in total_changes:
print(f" - {c}")
return 0
if __name__ == '__main__':
sys.exit(main())