test_p7_final_output.py 3.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. from content_agent.run_service import RunService
  2. from content_agent.schemas import RunStartRequest
  3. from tests.p1_helpers import FakeQueryVariantClient, REAL_SOURCE_FIXTURE
  4. def _start_mock_run(tmp_path):
  5. service = RunService(
  6. runtime_root=tmp_path / "runtime" / "v1",
  7. query_variant_client=FakeQueryVariantClient(),
  8. )
  9. state = service.start_run(
  10. RunStartRequest(platform_mode="mock", source=str(REAL_SOURCE_FIXTURE))
  11. )
  12. assert state["status"] == "success"
  13. return service, state["run_id"]
  14. def test_rejected_content_is_visible_but_not_pooled(tmp_path):
  15. service, run_id = _start_mock_run(tmp_path)
  16. final_output = service.read_json(run_id, "final_output.json")
  17. content_ids = {asset["platform_content_id"] for asset in final_output["content_assets"]}
  18. reject_ids = {record["decision_target_id"] for record in final_output["reject_records"]}
  19. assert final_output["summary"]["rejected_content_count"] == len(final_output["reject_records"])
  20. assert reject_ids
  21. assert not reject_ids & content_ids
  22. assert final_output["validation_status"] == "pass"
  23. assert final_output["summary"]["run_path_complete"] is True
  24. assert final_output["summary"]["trace_complete"] is True
  25. def test_reject_records_carry_source_evidence_refs(tmp_path):
  26. service, run_id = _start_mock_run(tmp_path)
  27. final_output = service.read_json(run_id, "final_output.json")
  28. reject = final_output["reject_records"][0]
  29. assert "source_evidence" not in reject
  30. assert reject["source_evidence_ref"]["decision_id"] == reject["decision_id"]
  31. assert reject["source_evidence_ref"]["decision_target_id"] == reject["decision_target_id"]
  32. decisions = {
  33. decision["decision_id"]: decision
  34. for decision in service.read_jsonl(run_id, "rule_decisions.jsonl")
  35. }
  36. source_evidence = decisions[reject["decision_id"]]["source_evidence"]
  37. assert source_evidence["source_post_id"]
  38. assert source_evidence["discovered_platform_content_id"]
  39. assert service.validate_run(run_id)["status"] == "pass"
  40. def test_run_service_rewrites_final_output_with_final_validation_status(tmp_path):
  41. service, run_id = _start_mock_run(tmp_path)
  42. final_output = service.read_json(run_id, "final_output.json")
  43. validation = service.validate_run(run_id)
  44. assert validation["status"] == "pass"
  45. assert final_output["validation_status"] == validation["status"]
  46. assert final_output["summary"]["run_path_complete"] is True
  47. assert final_output["summary"]["trace_complete"] is True
  48. def test_final_output_carries_v4_explanation_records(tmp_path):
  49. service, run_id = _start_mock_run(tmp_path)
  50. final_output = service.read_json(run_id, "final_output.json")
  51. v4_decision_records = [
  52. record
  53. for record in final_output["decision_records"]
  54. if (record.get("v4_explanation") or {}).get("scorecard_schema_version") == "v4_scorecard.v1"
  55. ]
  56. assert v4_decision_records
  57. for record in v4_decision_records:
  58. assert "scorecard" not in record
  59. assert "decision_replay_data" not in record
  60. assert "source_evidence" not in record
  61. explanation = record["v4_explanation"]
  62. assert explanation["schema_version"] == "v4_decision_explanation.v1"
  63. assert explanation["scorecard_schema_version"] == "v4_scorecard.v1"
  64. assert explanation["score"] == record["score"]
  65. assert "allow_walk" in explanation
  66. assert "walk_gate_snapshot" not in explanation
  67. v4_ids = {record["decision_id"] for record in v4_decision_records}
  68. section_records = (
  69. final_output["content_assets"]
  70. + final_output["review_records"]
  71. + final_output["reject_records"]
  72. )
  73. assert [
  74. record
  75. for record in section_records
  76. if record.get("decision_id") in v4_ids and record.get("v4_explanation")
  77. ]