dotb_ai-platform/scripts/export_contract_fixtures.py
hungtran24 b1f6643796 refactor: score synchronously and drop webhook/background execution
POST /v1/lead-scoring/score now evaluates in the request, applies an overall
AI deadline, and stores the completed run only after scoring. Idempotency is
kept by (app_id, account_id, request_id) with a body fingerprint.

Removes the webhook outbox, scheduler/recovery loop, app lead_scoring
permission, credential audit events, seed_demo and generate_secret scripts,
and the tests that covered them. Trims tests to behavior of the new flow.
2026-10-09 02:44:24 +07:00

76 lines
2.5 KiB
Python

"""Generate response examples from provider serializers."""
import argparse
import asyncio
import json
from datetime import UTC, datetime
from pathlib import Path
from ai_platform.lead_scoring.application.repository import ScoringRunRecord
from ai_platform.lead_scoring.application.run_use_cases import to_run_detail
from ai_platform.lead_scoring.application.scoring import calculate_run
from ai_platform.presentation.http.routes import to_detail_json, to_json
from ai_platform.presentation.http.run_responses import RunDetail, RunSummary
from ai_platform.presentation.http.schemas import RunRequest
FIXTURES = Path(__file__).resolve().parents[1] / "contracts/lead-scoring/v2/fixtures"
NOW = datetime(2026, 9, 28, tzinfo=UTC)
RUN_ID = "22222222-2222-4222-8222-222222222222"
def write_json(name: str, value: dict, *, check: bool) -> None:
path = FIXTURES / name
expected = json.dumps(value, ensure_ascii=False, indent=2) + "\n"
if check:
if not path.exists() or path.read_text() != expected:
raise SystemExit(f"Contract fixture drift: {name}; regenerate provider examples")
else:
path.write_text(expected)
async def main(*, check: bool = False) -> None:
request = RunRequest.model_validate_json(
(FIXTURES / "run-request.json").read_text()
).model_dump(mode="json")
rule_score, breakdown = calculate_run(request)
row = ScoringRunRecord(
id=RUN_ID,
request_id=request["request_id"],
app_id="omni-local",
account_id=request["account_id"],
status="completed",
fingerprint="0" * 64,
profile_version="profile-example",
request=request,
rule_score=rule_score,
ai_score=None,
final_score=rule_score,
degraded=False,
result_mode="rules_only",
error_code=None,
breakdown=breakdown,
created_at=NOW,
completed_at=NOW,
ai_confidence=None,
ai_reasoning=None,
ai_evidence=None,
)
write_json(
"run-summary.json",
RunSummary.model_validate(to_json(row)).model_dump(mode="json"),
check=check,
)
write_json(
"run-detail.json",
RunDetail.model_validate(to_detail_json(to_run_detail(row))).model_dump(mode="json"),
check=check,
)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--check", action="store_true", help="Reject drift without writing artifacts"
)
asyncio.run(main(check=parser.parse_args().check))