test_rule_pack_reading.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. from copy import deepcopy
  2. from pathlib import Path
  3. from content_agent.business_modules.rule_judgment.evaluator import decide
  4. from content_agent.errors import ErrorCode
  5. from content_agent.run_service import RunService
  6. from content_agent.schemas import RunStartRequest
  7. from tests.p1_helpers import FakeQueryVariantClient, REAL_SOURCE_FIXTURE
  8. def test_rule_pack_thresholds_drive_decision(tmp_path):
  9. service = RunService(
  10. runtime_root=tmp_path / "runtime" / "v1",
  11. query_variant_client=FakeQueryVariantClient(),
  12. )
  13. state = service.start_run(
  14. RunStartRequest(platform_mode="mock", source=str(REAL_SOURCE_FIXTURE))
  15. )
  16. run_id = state["run_id"]
  17. bundle = deepcopy(state["evidence_bundles"][0])
  18. bundle["pattern_match_result"]["query_relevance_score"] = 80
  19. bundle["content_engagement_metrics"]["platform_performance"]["platform_performance_score"] = 60
  20. decision = decide(run_id, state["policy_run_id"], 1, bundle, state["policy_bundle"])
  21. assert decision["score"] == 70
  22. assert decision["decision_action"] == "ADD_TO_CONTENT_POOL"
  23. assert decision["decision_reason_code"] == "v4_query_and_platform_pass"
  24. assert decision["decision_replay_data"]["allow_walk"] is False
  25. assert decision["policy_run_id"] == state["policy_run_id"]
  26. assert decision["strategy_version"] == "V4"
  27. def test_rule_pack_hard_gate_reason_code_drives_decision(tmp_path):
  28. service = RunService(
  29. runtime_root=tmp_path / "runtime" / "v1",
  30. query_variant_client=FakeQueryVariantClient(),
  31. )
  32. state = service.start_run(
  33. RunStartRequest(platform_mode="mock", source=str(REAL_SOURCE_FIXTURE))
  34. )
  35. run_id = state["run_id"]
  36. bundle = deepcopy(state["evidence_bundles"][0])
  37. bundle["source_evidence"] = {}
  38. decision = decide(run_id, state["policy_run_id"], 1, bundle, state["policy_bundle"])
  39. assert decision["decision_action"] == "REJECT_CONTENT"
  40. assert decision["decision_reason_code"] == "missing_source_evidence"
  41. assert decision["search_query_effect_status"] == "rule_blocked"
  42. assert decision["triggered_blocking_rules"] == ["missing_source_evidence"]
  43. assert decision["decision_replay_data"]["primary_reason_code"] == "missing_source_evidence"
  44. def test_missing_score_uses_rule_pack_missing_policy(tmp_path):
  45. service = RunService(
  46. runtime_root=tmp_path / "runtime" / "v1",
  47. query_variant_client=FakeQueryVariantClient(),
  48. )
  49. state = service.start_run(
  50. RunStartRequest(platform_mode="mock", source=str(REAL_SOURCE_FIXTURE))
  51. )
  52. run_id = state["run_id"]
  53. bundle = deepcopy(state["evidence_bundles"][0])
  54. bundle["pattern_match_result"]["query_relevance_score"] = None
  55. bundle["content_engagement_metrics"]["platform_performance"]["platform_performance_score"] = None
  56. decision = decide(run_id, state["policy_run_id"], 1, bundle, state["policy_bundle"])
  57. assert decision["decision_action"] == "TECHNICAL_RETRY_REQUIRED"
  58. assert decision["decision_reason_code"] == "v4_technical_retry_needed"
  59. assert decision["search_query_effect_status"] == "failed"
  60. assert decision["scorecard"]["score_missing"] is True
  61. def test_unknown_strategy_version_fails_before_rule_decision(tmp_path):
  62. service = RunService(
  63. runtime_root=tmp_path / "runtime" / "v1",
  64. query_variant_client=FakeQueryVariantClient(),
  65. )
  66. state = service.start_run(
  67. RunStartRequest(
  68. platform_mode="mock",
  69. strategy_version="missing_strategy",
  70. source=str(REAL_SOURCE_FIXTURE),
  71. )
  72. )
  73. assert state["status"] == "failed"
  74. assert state["error_code"] == ErrorCode.POLICY_BUNDLE_NOT_FOUND.value
  75. assert state["errors"] == ["policy bundle not found"]
  76. def test_rule_judgment_does_not_call_pattern_recall_integrations():
  77. root = Path("content_agent/business_modules/rule_judgment")
  78. text = "\n".join(path.read_text(encoding="utf-8") for path in root.rglob("*.py"))
  79. assert "decode_api" not in text
  80. assert "category_match" not in text
  81. assert "match-paths" not in text
  82. def test_disabled_future_packs_not_marked_as_active_entity_packs():
  83. from content_agent.integrations.policy_json import JsonPolicyBundleStore
  84. bundle = JsonPolicyBundleStore().load_policy_bundle("V4")
  85. assert set(bundle["rule_pack_by_entity"]) == {"Content"}
  86. for entity in ("Author", "Hashtag", "Path", "Budget"):
  87. assert entity not in bundle["rule_pack_by_entity"]