feat: coverage V2 - historical evidence miner, KB evidence model + promotion audit + revalidation, Kodebar/OSCBR limits, KB/provider panel, seed import; 1.3.2 (Hub only)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
gti
2026-09-26 08:14:57 -03:00
co-authored by Claude Sonnet 5
parent 19e145ea47
commit ac1ecccc50
41 changed files with 1418 additions and 74 deletions
+41
View File
@@ -0,0 +1,41 @@
"""Import historical ERP evidence (miner output) into the central KB. Dry-run by default; --apply commits. Local data only, no provider call.
python -m central.scripts.import_kb_history --staging /path/to/history [--apply] [--report out.json]
Runs against the database in DATABASE_URL (the Hub's PostgreSQL). Idempotent. Never touches any client database.
"""
import argparse
import json
import sys
import time
from pathlib import Path
from central.app.db import SessionLocal
from central.app.enrichment import history
def main(argv=None):
ap = argparse.ArgumentParser()
ap.add_argument("--staging", required=True)
ap.add_argument("--apply", action="store_true")
ap.add_argument("--report", default=None)
ap.add_argument("--only-current-vigente-gtins", action="store_true", help="skip GTINs without any NCM evidence")
args = ap.parse_args(argv)
files = sorted(f for f in Path(args.staging).glob("*.json") if not f.name.startswith("_"))
stagings = [json.loads(f.read_text(encoding="utf-8")) for f in files]
t0 = time.time()
obs = history.build_observations(stagings)
if args.only_current_vigente_gtins:
obs["gtins"] = {k: v for k, v in obs["gtins"].items() if v["ncm"]}
with SessionLocal() as session:
current = history.official_sets(session)
report = history.apply(session, obs, lambda v: v in current, dry_run=not args.apply)
report.update({"mode": "APPLY" if args.apply else "DRY_RUN", "clients": [s["client"] for s in stagings], "build_stats": obs["stats"], "seconds": round(time.time() - t0, 1)})
text = json.dumps(report, indent=1, default=str)
if args.report:
Path(args.report).write_text(text, encoding="utf-8")
print(text)
if __name__ == "__main__":
sys.exit(main())