← Files VeraARCHIVED FILE
modules/bandi-agevolazioni/scripts/evaluate_intelligence.py
6.27 KB · Oct 2, 2026 · 00:29 UTC
#!/usr/bin/env python3
"""Run offline contract evaluations for Bandi intelligence contributions.
This harness measures structural safety, reference closure, normalization, and
expected recommendation families. It does not claim to measure legal accuracy;
live-model semantic evaluation requires reviewed, licensed case material.
"""
from __future__ import annotations
import argparse
import hashlib
import json
import logging
from pathlib import Path
from typing import Any
from intelligence_contract import (
build_intelligence_packet,
validate_intelligence_output,
)
__all__ = ["evaluate_cases", "main"]
LOGGER = logging.getLogger(__name__)
def _synthetic_state() -> tuple[dict[str, Any], dict[str, Any], dict[str, Any]]:
excerpt = "Synthetic clause for contract evaluation only."
intake = {
"reference_date": "2026-08-07",
"application": {
"title": "Synthetic call",
"issuing_authority": "Synthetic authority",
"procedure_id": "SYNTH-001",
"submission_deadline": None,
"status": "confirmed",
},
"project": {
"title": "Synthetic project",
"summary": "No reusable eligibility meaning.",
"requested_amount": "100.00",
"currency": "EUR",
"confirmation_status": "confirmed",
},
"professional_question": "What requires professional review?",
}
sources = {
"source_set_revision": 1,
"sources": [
{
"source_id": "SRC-SYNTH-001",
"source_type": "call",
"title": "Synthetic call",
"issuer": "Synthetic authority",
"authority_role": "primary",
"publication_date": "2026-07-01",
"effective_from": "2026-07-01",
"effective_to": None,
"sha256": "0" * 64,
"review_status": "reviewed",
"relationships": [],
}
],
}
workbench = {
"requirements": [
{
"requirement_id": "REQ-SYNTH-001",
"category": "eligibility",
"statement": "Synthetic requirement with no legal reuse.",
"source_refs": [
{
"source_id": "SRC-SYNTH-001",
"locator": "synthetic locator",
"excerpt": excerpt,
"excerpt_sha256": hashlib.sha256(excerpt.encode()).hexdigest(),
}
],
"applicability": "Professional review required.",
"expected_evidence": ["Synthetic evidence"],
"review_status": "confirmed",
}
],
"facts": [],
"assessments": [],
"document_checklist": [],
"expenses": [],
"form_fields": [],
"narratives": [],
"consistency_checks": [],
"issues": [],
"authority_simulation": {
"status": "not_run",
"reviewer_perspective": "",
"overall_outcome": "not_run",
"checks": [],
},
"dossier": {"disposition": "review_required"},
}
return intake, sources, workbench
def evaluate_cases(cases: list[dict[str, Any]]) -> dict[str, Any]:
"""Evaluate deterministic public contracts against representative fixtures."""
intake, sources, workbench = _synthetic_state()
results: list[dict[str, Any]] = []
for case in cases:
packet = build_intelligence_packet(
intake,
sources,
workbench,
case["task"],
case.get("subject_ids", []),
)
normalized: dict[str, Any] | None = None
error: str | None = None
try:
normalized = validate_intelligence_output(packet, case["output"])
except ValueError as exc:
error = str(exc)
valid = normalized is not None
expected_valid = bool(case["expected_valid"])
collections = {
item.get("target_collection")
for item in (normalized or {}).get("recommendations", [])
if item.get("target_collection") is not None
}
risk_flags = {
flag
for item in (normalized or {}).get("recommendations", [])
for flag in item.get("risk_flags", [])
}
expected_collections = set(case.get("expected_collections", []))
expected_risks = set(case.get("expected_risk_flags", []))
passed = (
valid == expected_valid
and (not valid or expected_collections <= collections)
and (not valid or expected_risks <= risk_flags)
and (
not valid
or all(
item.get("status") == "MODEL_SUGGESTED"
and item.get("requires_review") is True
for item in normalized.get("recommendations", [])
)
)
)
results.append(
{
"case_id": case["case_id"],
"passed": passed,
"contract_valid": valid,
"expected_valid": expected_valid,
"error": error,
}
)
passed_count = sum(item["passed"] for item in results)
return {
"schema_version": "1.0",
"scope": "offline_contract_not_legal_accuracy",
"case_count": len(results),
"passed_count": passed_count,
"pass_rate": passed_count / len(results) if results else 0.0,
"status": "passed" if passed_count == len(results) and results else "failed",
"results": results,
}
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--cases", required=True, type=Path)
args = parser.parse_args(argv)
payload = json.loads(args.cases.read_text(encoding="utf-8"))
if not isinstance(payload, list):
raise ValueError("evaluation input must be a JSON array")
report = evaluate_cases(payload)
LOGGER.info("%s", json.dumps(report, ensure_ascii=False, sort_keys=True))
return 0 if report["status"] == "passed" else 1
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, format="%(message)s")
raise SystemExit(main())
SHA-256: 656df2914d94cd7761697c0fa4501a5244ea2eb7c64d311bce598d28bbe466c0