test_walk_strategy_config.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import json
  2. from copy import deepcopy
  3. from pathlib import Path
  4. from content_agent.integrations.walk_strategy_json import (
  5. EDGE_CATALOG_PATH,
  6. REQUIRED_SECTIONS,
  7. WalkStrategyStore,
  8. validate_walk_strategy_config,
  9. )
  10. CONFIG_PATH = Path("product_documents/抖音游走策略/douyin_walk_strategy.v1.json")
  11. def test_walk_strategy_config_loads_only_p6_runtime_source():
  12. store = WalkStrategyStore(Path("."))
  13. strategy = store.load_walk_strategy()
  14. assert strategy["strategy_id"] == "douyin_walk_strategy_v1"
  15. assert strategy["walk_strategy_version"] == "V1.0"
  16. assert strategy["walk_strategy_source_ref"]["file"] == str(CONFIG_PATH)
  17. assert strategy["source_of_truth"] == str(CONFIG_PATH)
  18. def test_walk_strategy_config_sections_and_references_are_closed():
  19. strategy = json.loads(CONFIG_PATH.read_text(encoding="utf-8"))
  20. findings = validate_walk_strategy_config(strategy, root_dir=Path("."))
  21. assert findings == []
  22. assert [section for section in REQUIRED_SECTIONS if section not in strategy] == []
  23. def test_walk_strategy_config_keeps_only_consumed_sections():
  24. # V5 M1: 边目录改由平台无关 catalog 校验;strategy 内旧段暂留为兼容副本。
  25. strategy = json.loads(CONFIG_PATH.read_text(encoding="utf-8"))
  26. assert set(REQUIRED_SECTIONS) == {
  27. "walk_rule_pack_binding",
  28. "v4_walk_gate",
  29. "walk_fact_contract",
  30. }
  31. assert [section for section in REQUIRED_SECTIONS if section not in strategy] == []
  32. assert "walk_edge_catalog" not in REQUIRED_SECTIONS
  33. def test_walk_strategy_validation_uses_platform_neutral_edge_catalog():
  34. strategy = json.loads(CONFIG_PATH.read_text(encoding="utf-8"))
  35. catalog = json.loads(EDGE_CATALOG_PATH.read_text(encoding="utf-8"))
  36. assert "walk_edge_catalog" not in strategy
  37. assert validate_walk_strategy_config(strategy, root_dir=Path(".")) == []
  38. assert {row["edge_id"] for row in catalog["walk_edge_catalog"]} == {
  39. "search_page_to_content",
  40. "video_to_author",
  41. "author_to_works",
  42. "author_work_to_content",
  43. "video_to_hashtag",
  44. "hashtag_to_query",
  45. "decision_to_asset",
  46. "path_stop",
  47. "budget_downgrade",
  48. }
  49. def test_walk_strategy_rejects_unknown_binding_and_gate_edges():
  50. strategy = json.loads(CONFIG_PATH.read_text(encoding="utf-8"))
  51. bad_binding = deepcopy(strategy)
  52. bad_binding["walk_rule_pack_binding"][0]["edge_id"] = "made_up_edge"
  53. binding_findings = validate_walk_strategy_config(bad_binding, root_dir=Path("."))
  54. assert any(finding["check_id"] == "edge_ref" for finding in binding_findings)
  55. bad_gate = deepcopy(strategy)
  56. bad_gate["v4_walk_gate"][0]["applies_to_edges"] = ["author_to_works", "made_up_edge"]
  57. gate_findings = validate_walk_strategy_config(bad_gate, root_dir=Path("."))
  58. assert any(finding["check_id"] == "v4_walk_gate_edge_ref" for finding in gate_findings)
  59. def test_walk_strategy_config_uses_clue_id_and_real_rule_packs():
  60. strategy = json.loads(CONFIG_PATH.read_text(encoding="utf-8"))
  61. facts = {row["runtime_file"]: row for row in strategy["walk_fact_contract"]}
  62. assert facts["search_clues.jsonl"]["unique_key"] == [
  63. "run_id",
  64. "policy_run_id",
  65. "clue_id",
  66. ]
  67. # M4 砍包受控变化:4 future 包及其 7 条 binding 已物理删除,仅剩内容包归属。
  68. assert {
  69. (row["rule_pack_id"], row["rule_pack_version"])
  70. for row in strategy["walk_rule_pack_binding"]
  71. } == {
  72. ("douyin_content_discovery_rule_pack_v1", "4.0.0"),
  73. }
  74. def test_walk_strategy_binding_is_loaded_from_walk_strategy():
  75. from content_agent.business_modules.walk_engine import _binding_by_edge_id
  76. from content_agent.integrations.walk_strategy_json import WalkStrategyStore
  77. walk_strategy = WalkStrategyStore().load_walk_strategy()
  78. binding_by_edge = _binding_by_edge_id(walk_strategy)
  79. # M4 砍包受控变化:仅 decision_to_asset 保留 content binding,其余边走 fallback 戳。
  80. assert set(binding_by_edge) == {"decision_to_asset"}
  81. assert binding_by_edge["decision_to_asset"]["rule_pack_id"] == "douyin_content_discovery_rule_pack_v1"