|
@@ -8,6 +8,7 @@ from content_agent.business_modules import content_discovery, platform_access, r
|
|
|
from content_agent.business_modules.content_discovery import pattern_recall
|
|
from content_agent.business_modules.content_discovery import pattern_recall
|
|
|
from content_agent.constants import RUNTIME_RECORD_SCHEMA_VERSION
|
|
from content_agent.constants import RUNTIME_RECORD_SCHEMA_VERSION
|
|
|
from content_agent.errors import ContentAgentError
|
|
from content_agent.errors import ContentAgentError
|
|
|
|
|
+from content_agent.integrations.walk_strategy_json import WalkStrategyStore
|
|
|
from content_agent.interfaces import (
|
|
from content_agent.interfaces import (
|
|
|
CategoryMatchClient,
|
|
CategoryMatchClient,
|
|
|
DecodeClient,
|
|
DecodeClient,
|
|
@@ -47,6 +48,8 @@ def run_bounded_walk(
|
|
|
poll_interval_seconds: float = 5.0,
|
|
poll_interval_seconds: float = 5.0,
|
|
|
) -> dict[str, list[dict[str, Any]]]:
|
|
) -> dict[str, list[dict[str, Any]]]:
|
|
|
created_at = datetime.now(timezone.utc).isoformat()
|
|
created_at = datetime.now(timezone.utc).isoformat()
|
|
|
|
|
+ walk_strategy = WalkStrategyStore().load_walk_strategy()
|
|
|
|
|
+ content_pack_id = policy_bundle["rule_pack_id"]
|
|
|
context = {
|
|
context = {
|
|
|
"search_queries": list(search_queries),
|
|
"search_queries": list(search_queries),
|
|
|
"discovered_content_items": list(discovered_content_items),
|
|
"discovered_content_items": list(discovered_content_items),
|
|
@@ -58,10 +61,15 @@ def run_bounded_walk(
|
|
|
next_decision_index = len(rule_decisions) + 1
|
|
next_decision_index = len(rule_decisions) + 1
|
|
|
next_recall_index = len(discovered_content_items) + 1
|
|
next_recall_index = len(discovered_content_items) + 1
|
|
|
|
|
|
|
|
- query_rows = _pagination_queries(run_id, policy_run_id, context["search_queries"], discovered_content_items, created_at)
|
|
|
|
|
- query_rows.extend(
|
|
|
|
|
- _tag_queries(run_id, policy_run_id, discovered_content_items, rule_decisions, created_at)
|
|
|
|
|
|
|
+ query_rows = _pagination_queries(
|
|
|
|
|
+ run_id, policy_run_id, context["search_queries"], discovered_content_items, rule_decisions, created_at
|
|
|
)
|
|
)
|
|
|
|
|
+ tag_rows, tag_skipped_actions = _tag_queries(
|
|
|
|
|
+ run_id, policy_run_id, discovered_content_items, rule_decisions, created_at,
|
|
|
|
|
+ walk_strategy=walk_strategy, content_pack_id=content_pack_id,
|
|
|
|
|
+ )
|
|
|
|
|
+ query_rows.extend(tag_rows)
|
|
|
|
|
+ context["walk_actions"].extend(tag_skipped_actions)
|
|
|
if query_rows:
|
|
if query_rows:
|
|
|
runtime.append_jsonl(run_id, "search_queries.jsonl", query_rows)
|
|
runtime.append_jsonl(run_id, "search_queries.jsonl", query_rows)
|
|
|
context["search_queries"].extend(query_rows)
|
|
context["search_queries"].extend(query_rows)
|
|
@@ -88,7 +96,10 @@ def run_bounded_walk(
|
|
|
next_decision_index += len(batch["rule_decisions"])
|
|
next_decision_index += len(batch["rule_decisions"])
|
|
|
next_recall_index += len(batch["discovered_content_items"])
|
|
next_recall_index += len(batch["discovered_content_items"])
|
|
|
context["walk_actions"].extend(
|
|
context["walk_actions"].extend(
|
|
|
- _query_actions(query_rows, batch.get("query_failures", []), created_at)
|
|
|
|
|
|
|
+ _query_actions(
|
|
|
|
|
+ query_rows, batch.get("query_failures", []), created_at,
|
|
|
|
|
+ walk_strategy=walk_strategy, content_pack_id=content_pack_id,
|
|
|
|
|
+ )
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
author_batch = _execute_author_edges(
|
|
author_batch = _execute_author_edges(
|
|
@@ -97,6 +108,8 @@ def run_bounded_walk(
|
|
|
pattern_seed_pack=pattern_seed_pack,
|
|
pattern_seed_pack=pattern_seed_pack,
|
|
|
source_context=source_context,
|
|
source_context=source_context,
|
|
|
discovered_content_items=context["discovered_content_items"],
|
|
discovered_content_items=context["discovered_content_items"],
|
|
|
|
|
+ rule_decisions=context["rule_decisions"],
|
|
|
|
|
+ walk_strategy=walk_strategy,
|
|
|
policy_bundle=policy_bundle,
|
|
policy_bundle=policy_bundle,
|
|
|
platform_client=platform_client,
|
|
platform_client=platform_client,
|
|
|
runtime=runtime,
|
|
runtime=runtime,
|
|
@@ -197,6 +210,8 @@ def _execute_author_edges(
|
|
|
pattern_seed_pack: dict[str, Any],
|
|
pattern_seed_pack: dict[str, Any],
|
|
|
source_context: dict[str, Any],
|
|
source_context: dict[str, Any],
|
|
|
discovered_content_items: list[dict[str, Any]],
|
|
discovered_content_items: list[dict[str, Any]],
|
|
|
|
|
+ rule_decisions: list[dict[str, Any]],
|
|
|
|
|
+ walk_strategy: dict[str, Any],
|
|
|
policy_bundle: dict[str, Any],
|
|
policy_bundle: dict[str, Any],
|
|
|
platform_client: PlatformSearchClient,
|
|
platform_client: PlatformSearchClient,
|
|
|
runtime: RuntimeFileStore,
|
|
runtime: RuntimeFileStore,
|
|
@@ -214,6 +229,8 @@ def _execute_author_edges(
|
|
|
if not callable(fetch_author_works):
|
|
if not callable(fetch_author_works):
|
|
|
return _empty_batch()
|
|
return _empty_batch()
|
|
|
|
|
|
|
|
|
|
+ decision_by_content_id = _decision_by_content_id(rule_decisions)
|
|
|
|
|
+ binding, _ = _resolve_edge_binding("author_to_works", walk_strategy)
|
|
|
author_items = _unique_authors(discovered_content_items)[:2]
|
|
author_items = _unique_authors(discovered_content_items)[:2]
|
|
|
platform_results: list[dict[str, Any]] = []
|
|
platform_results: list[dict[str, Any]] = []
|
|
|
walk_actions: list[dict[str, Any]] = []
|
|
walk_actions: list[dict[str, Any]] = []
|
|
@@ -222,6 +239,31 @@ def _execute_author_edges(
|
|
|
if not author_id:
|
|
if not author_id:
|
|
|
continue
|
|
continue
|
|
|
action_id = _walk_action_id(run_id, policy_run_id, "author_to_works", author_id, "works")
|
|
action_id = _walk_action_id(run_id, policy_run_id, "author_to_works", author_id, "works")
|
|
|
|
|
+ decision = decision_by_content_id.get(item.get("platform_content_id"))
|
|
|
|
|
+ if not _can_expand_from_decision(decision, "author_to_works"):
|
|
|
|
|
+ walk_actions.append(
|
|
|
|
|
+ _walk_action(
|
|
|
|
|
+ run_id,
|
|
|
|
|
+ policy_run_id,
|
|
|
|
|
+ action_id,
|
|
|
|
|
+ "author_to_works",
|
|
|
|
|
+ "author",
|
|
|
|
|
+ "Author",
|
|
|
|
|
+ author_id,
|
|
|
|
|
+ "AuthorWorksPage",
|
|
|
|
|
+ author_id,
|
|
|
|
|
+ "fetch_author_works",
|
|
|
|
|
+ "skipped",
|
|
|
|
|
+ created_at,
|
|
|
|
|
+ reason_code="blocked_by_rule_decision",
|
|
|
|
|
+ budget_tier="blocked",
|
|
|
|
|
+ rule_pack_binding=binding,
|
|
|
|
|
+ rule_pack_execution=_execution_record(decision, content_pack_id=policy_bundle["rule_pack_id"]),
|
|
|
|
|
+ raw_extra=_decision_context(decision),
|
|
|
|
|
+ )
|
|
|
|
|
+ )
|
|
|
|
|
+ continue
|
|
|
|
|
+ budget_tier = _walk_budget_for_decision(decision)
|
|
|
try:
|
|
try:
|
|
|
works = fetch_author_works(
|
|
works = fetch_author_works(
|
|
|
{
|
|
{
|
|
@@ -246,6 +288,10 @@ def _execute_author_edges(
|
|
|
"failed",
|
|
"failed",
|
|
|
created_at,
|
|
created_at,
|
|
|
reason_code=type(exc).__name__,
|
|
reason_code=type(exc).__name__,
|
|
|
|
|
+ budget_tier=budget_tier,
|
|
|
|
|
+ rule_pack_binding=binding,
|
|
|
|
|
+ rule_pack_execution=_execution_record(decision, content_pack_id=policy_bundle["rule_pack_id"]),
|
|
|
|
|
+ raw_extra=_decision_context(decision),
|
|
|
)
|
|
)
|
|
|
)
|
|
)
|
|
|
continue
|
|
continue
|
|
@@ -263,6 +309,10 @@ def _execute_author_edges(
|
|
|
"fetch_author_works",
|
|
"fetch_author_works",
|
|
|
"success",
|
|
"success",
|
|
|
created_at,
|
|
created_at,
|
|
|
|
|
+ budget_tier=budget_tier,
|
|
|
|
|
+ rule_pack_binding=binding,
|
|
|
|
|
+ rule_pack_execution=_execution_record(decision, content_pack_id=policy_bundle["rule_pack_id"]),
|
|
|
|
|
+ raw_extra=_decision_context(decision),
|
|
|
)
|
|
)
|
|
|
)
|
|
)
|
|
|
for index, work in enumerate(works[:3], start=1):
|
|
for index, work in enumerate(works[:3], start=1):
|
|
@@ -319,9 +369,11 @@ def _pagination_queries(
|
|
|
policy_run_id: str,
|
|
policy_run_id: str,
|
|
|
search_queries: list[dict[str, Any]],
|
|
search_queries: list[dict[str, Any]],
|
|
|
discovered_content_items: list[dict[str, Any]],
|
|
discovered_content_items: list[dict[str, Any]],
|
|
|
|
|
+ rule_decisions: list[dict[str, Any]],
|
|
|
created_at: str,
|
|
created_at: str,
|
|
|
) -> list[dict[str, Any]]:
|
|
) -> list[dict[str, Any]]:
|
|
|
query_by_id = {row["search_query_id"]: row for row in search_queries}
|
|
query_by_id = {row["search_query_id"]: row for row in search_queries}
|
|
|
|
|
+ query_effect_by_id = _query_effect_by_search_query_id(discovered_content_items, rule_decisions)
|
|
|
seen: set[str] = set()
|
|
seen: set[str] = set()
|
|
|
rows: list[dict[str, Any]] = []
|
|
rows: list[dict[str, Any]] = []
|
|
|
for item in discovered_content_items:
|
|
for item in discovered_content_items:
|
|
@@ -329,6 +381,8 @@ def _pagination_queries(
|
|
|
cursor = item.get("next_cursor")
|
|
cursor = item.get("next_cursor")
|
|
|
if not item.get("has_more") or not cursor or search_query_id in seen:
|
|
if not item.get("has_more") or not cursor or search_query_id in seen:
|
|
|
continue
|
|
continue
|
|
|
|
|
+ if not _can_fetch_next_page(search_query_id, query_effect_by_id):
|
|
|
|
|
+ continue
|
|
|
source = query_by_id.get(search_query_id)
|
|
source = query_by_id.get(search_query_id)
|
|
|
if not source:
|
|
if not source:
|
|
|
continue
|
|
continue
|
|
@@ -356,13 +410,49 @@ def _tag_queries(
|
|
|
items: list[dict[str, Any]],
|
|
items: list[dict[str, Any]],
|
|
|
decisions: list[dict[str, Any]],
|
|
decisions: list[dict[str, Any]],
|
|
|
created_at: str,
|
|
created_at: str,
|
|
|
-) -> list[dict[str, Any]]:
|
|
|
|
|
- decision_by_content_id = {row["decision_target_id"]: row for row in decisions}
|
|
|
|
|
|
|
+ *,
|
|
|
|
|
+ walk_strategy: dict[str, Any],
|
|
|
|
|
+ content_pack_id: str,
|
|
|
|
|
+) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]:
|
|
|
|
|
+ decision_by_content_id = _decision_by_content_id(decisions)
|
|
|
|
|
+ binding, _ = _resolve_edge_binding("hashtag_to_query", walk_strategy)
|
|
|
rows: list[dict[str, Any]] = []
|
|
rows: list[dict[str, Any]] = []
|
|
|
|
|
+ skipped_actions: list[dict[str, Any]] = []
|
|
|
seen: set[str] = set()
|
|
seen: set[str] = set()
|
|
|
for item in items:
|
|
for item in items:
|
|
|
- decision = decision_by_content_id.get(item.get("platform_content_id")) or {}
|
|
|
|
|
- if decision.get("search_query_effect_status") not in {"success", "pending"}:
|
|
|
|
|
|
|
+ decision = decision_by_content_id.get(item.get("platform_content_id"))
|
|
|
|
|
+ if not decision:
|
|
|
|
|
+ continue
|
|
|
|
|
+ if not _can_expand_from_decision(decision, "hashtag_to_query"):
|
|
|
|
|
+ if item.get("tags"):
|
|
|
|
|
+ reason_code = (
|
|
|
|
|
+ "review_tag_expansion_disabled"
|
|
|
|
|
+ if decision.get("decision_action") == "KEEP_CONTENT_FOR_REVIEW"
|
|
|
|
|
+ else "blocked_by_rule_decision"
|
|
|
|
|
+ )
|
|
|
|
|
+ skipped_actions.append(
|
|
|
|
|
+ _walk_action(
|
|
|
|
|
+ run_id,
|
|
|
|
|
+ policy_run_id,
|
|
|
|
|
+ _walk_action_id(
|
|
|
|
|
+ run_id, policy_run_id, "hashtag_to_query", item["platform_content_id"], "tags"
|
|
|
|
|
+ ),
|
|
|
|
|
+ "hashtag_to_query",
|
|
|
|
|
+ "tag_query",
|
|
|
|
|
+ "Content",
|
|
|
|
|
+ item["platform_content_id"],
|
|
|
|
|
+ "SearchQuery",
|
|
|
|
|
+ "tag_query_skipped",
|
|
|
|
|
+ "create_tag_query",
|
|
|
|
|
+ "skipped",
|
|
|
|
|
+ created_at,
|
|
|
|
|
+ reason_code=reason_code,
|
|
|
|
|
+ budget_tier="blocked",
|
|
|
|
|
+ rule_pack_binding=binding,
|
|
|
|
|
+ rule_pack_execution=_execution_record(decision, content_pack_id=content_pack_id),
|
|
|
|
|
+ raw_extra=_decision_context(decision),
|
|
|
|
|
+ )
|
|
|
|
|
+ )
|
|
|
continue
|
|
continue
|
|
|
for tag in item.get("tags") or []:
|
|
for tag in item.get("tags") or []:
|
|
|
normalized = str(tag).lstrip("#").strip()
|
|
normalized = str(tag).lstrip("#").strip()
|
|
@@ -386,14 +476,17 @@ def _tag_queries(
|
|
|
)
|
|
)
|
|
|
)
|
|
)
|
|
|
if len(rows) >= 1:
|
|
if len(rows) >= 1:
|
|
|
- return rows
|
|
|
|
|
- return rows
|
|
|
|
|
|
|
+ return rows, skipped_actions
|
|
|
|
|
+ return rows, skipped_actions
|
|
|
|
|
|
|
|
|
|
|
|
|
def _query_actions(
|
|
def _query_actions(
|
|
|
query_rows: list[dict[str, Any]],
|
|
query_rows: list[dict[str, Any]],
|
|
|
query_failures: list[dict[str, Any]],
|
|
query_failures: list[dict[str, Any]],
|
|
|
created_at: str,
|
|
created_at: str,
|
|
|
|
|
+ *,
|
|
|
|
|
+ walk_strategy: dict[str, Any],
|
|
|
|
|
+ content_pack_id: str,
|
|
|
) -> list[dict[str, Any]]:
|
|
) -> list[dict[str, Any]]:
|
|
|
failure_ids = {row["search_query_id"] for row in query_failures}
|
|
failure_ids = {row["search_query_id"] for row in query_failures}
|
|
|
actions: list[dict[str, Any]] = []
|
|
actions: list[dict[str, Any]] = []
|
|
@@ -403,6 +496,7 @@ def _query_actions(
|
|
|
if row.get("search_query_generation_method") == "tag_query"
|
|
if row.get("search_query_generation_method") == "tag_query"
|
|
|
else "query_next_page"
|
|
else "query_next_page"
|
|
|
)
|
|
)
|
|
|
|
|
+ binding, _ = _resolve_edge_binding(edge_id, walk_strategy)
|
|
|
actions.append(
|
|
actions.append(
|
|
|
_walk_action(
|
|
_walk_action(
|
|
|
row["run_id"],
|
|
row["run_id"],
|
|
@@ -426,6 +520,12 @@ def _query_actions(
|
|
|
"failed" if row["search_query_id"] in failure_ids else "success",
|
|
"failed" if row["search_query_id"] in failure_ids else "success",
|
|
|
created_at,
|
|
created_at,
|
|
|
page_cursor=row.get("page_cursor"),
|
|
page_cursor=row.get("page_cursor"),
|
|
|
|
|
+ rule_pack_binding=binding,
|
|
|
|
|
+ rule_pack_execution={
|
|
|
|
|
+ "executed": True,
|
|
|
|
|
+ "executed_rule_pack_id": content_pack_id,
|
|
|
|
|
+ "reason": "content_decision_reused_for_walk_gate",
|
|
|
|
|
+ },
|
|
|
)
|
|
)
|
|
|
)
|
|
)
|
|
|
return actions
|
|
return actions
|
|
@@ -477,8 +577,12 @@ def _walk_action(
|
|
|
*,
|
|
*,
|
|
|
page_cursor: str | None = None,
|
|
page_cursor: str | None = None,
|
|
|
reason_code: str | None = None,
|
|
reason_code: str | None = None,
|
|
|
|
|
+ budget_tier: str | None = None,
|
|
|
|
|
+ rule_pack_binding: dict[str, Any] | None = None,
|
|
|
|
|
+ rule_pack_execution: dict[str, Any] | None = None,
|
|
|
|
|
+ raw_extra: dict[str, Any] | None = None,
|
|
|
) -> dict[str, Any]:
|
|
) -> dict[str, Any]:
|
|
|
- return with_raw_payload(
|
|
|
|
|
|
|
+ row = with_raw_payload(
|
|
|
{
|
|
{
|
|
|
"record_schema_version": RUNTIME_RECORD_SCHEMA_VERSION,
|
|
"record_schema_version": RUNTIME_RECORD_SCHEMA_VERSION,
|
|
|
"run_id": run_id,
|
|
"run_id": run_id,
|
|
@@ -492,13 +596,112 @@ def _walk_action(
|
|
|
"to_node_id": to_node_id,
|
|
"to_node_id": to_node_id,
|
|
|
"walk_action": walk_action,
|
|
"walk_action": walk_action,
|
|
|
"walk_status": walk_status,
|
|
"walk_status": walk_status,
|
|
|
- "budget_tier": "normal" if walk_status == "success" else "low_budget",
|
|
|
|
|
|
|
+ "budget_tier": budget_tier or ("normal" if walk_status == "success" else "low_budget"),
|
|
|
"depth": 1,
|
|
"depth": 1,
|
|
|
"page_cursor": page_cursor,
|
|
"page_cursor": page_cursor,
|
|
|
"reason_code": reason_code,
|
|
"reason_code": reason_code,
|
|
|
|
|
+ "rule_pack_id": (rule_pack_binding or {}).get("rule_pack_id"),
|
|
|
|
|
+ "rule_pack_version": (rule_pack_binding or {}).get("rule_pack_version"),
|
|
|
"created_at": created_at,
|
|
"created_at": created_at,
|
|
|
}
|
|
}
|
|
|
)
|
|
)
|
|
|
|
|
+ row["raw_payload"]["rule_pack_binding"] = rule_pack_binding or {}
|
|
|
|
|
+ row["raw_payload"]["rule_pack_execution"] = rule_pack_execution or {}
|
|
|
|
|
+ if raw_extra:
|
|
|
|
|
+ row["raw_payload"].update(raw_extra)
|
|
|
|
|
+ return row
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def _decision_by_content_id(rule_decisions: list[dict[str, Any]]) -> dict[str, dict[str, Any]]:
|
|
|
|
|
+ return {row["decision_target_id"]: row for row in rule_decisions}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def _query_effect_by_search_query_id(
|
|
|
|
|
+ discovered_content_items: list[dict[str, Any]],
|
|
|
|
|
+ rule_decisions: list[dict[str, Any]],
|
|
|
|
|
+) -> dict[str, str]:
|
|
|
|
|
+ decision_by_content_id = _decision_by_content_id(rule_decisions)
|
|
|
|
|
+ statuses_by_query: dict[str, set[str]] = {}
|
|
|
|
|
+ for item in discovered_content_items:
|
|
|
|
|
+ decision = decision_by_content_id.get(item.get("platform_content_id"))
|
|
|
|
|
+ if not decision:
|
|
|
|
|
+ continue
|
|
|
|
|
+ query_sources = item.get("query_sources") or [{"search_query_id": item.get("search_query_id")}]
|
|
|
|
|
+ for query_source in query_sources:
|
|
|
|
|
+ search_query_id = query_source.get("search_query_id")
|
|
|
|
|
+ if search_query_id:
|
|
|
|
|
+ statuses_by_query.setdefault(search_query_id, set()).add(
|
|
|
|
|
+ decision.get("search_query_effect_status")
|
|
|
|
|
+ )
|
|
|
|
|
+ effects: dict[str, str] = {}
|
|
|
|
|
+ for search_query_id, statuses in statuses_by_query.items():
|
|
|
|
|
+ for status in ("success", "pending", "rule_blocked", "failed"):
|
|
|
|
|
+ if status in statuses:
|
|
|
|
|
+ effects[search_query_id] = status
|
|
|
|
|
+ break
|
|
|
|
|
+ return effects
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def _can_fetch_next_page(search_query_id: str, query_effect_by_id: dict[str, str]) -> bool:
|
|
|
|
|
+ return query_effect_by_id.get(search_query_id) == "success"
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def _walk_budget_for_decision(decision: dict[str, Any] | None) -> str:
|
|
|
|
|
+ if not decision or decision.get("search_query_effect_status") == "rule_blocked":
|
|
|
|
|
+ return "blocked"
|
|
|
|
|
+ action = decision.get("decision_action")
|
|
|
|
|
+ if action == "ADD_TO_CONTENT_POOL":
|
|
|
|
|
+ return "normal"
|
|
|
|
|
+ if action == "KEEP_CONTENT_FOR_REVIEW":
|
|
|
|
|
+ return "low_budget"
|
|
|
|
|
+ return "blocked"
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def _can_expand_from_decision(decision: dict[str, Any] | None, edge_id: str) -> bool:
|
|
|
|
|
+ if not decision or decision.get("search_query_effect_status") == "rule_blocked":
|
|
|
|
|
+ return False
|
|
|
|
|
+ action = decision.get("decision_action")
|
|
|
|
|
+ if edge_id == "author_to_works":
|
|
|
|
|
+ return action in {"ADD_TO_CONTENT_POOL", "KEEP_CONTENT_FOR_REVIEW"}
|
|
|
|
|
+ if edge_id == "hashtag_to_query":
|
|
|
|
|
+ return action == "ADD_TO_CONTENT_POOL"
|
|
|
|
|
+ return False
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def _binding_by_edge_id(walk_strategy: dict[str, Any]) -> dict[str, dict[str, Any]]:
|
|
|
|
|
+ return {row["edge_id"]: row for row in walk_strategy.get("walk_rule_pack_binding", [])}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def _resolve_edge_binding(
|
|
|
|
|
+ edge_id: str, walk_strategy: dict[str, Any]
|
|
|
|
|
+) -> tuple[dict[str, Any], str | None]:
|
|
|
|
|
+ binding = _binding_by_edge_id(walk_strategy).get(edge_id)
|
|
|
|
|
+ if not binding:
|
|
|
|
|
+ return {}, "edge_binding_missing"
|
|
|
|
|
+ return binding, None
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def _execution_record(decision: dict[str, Any] | None, *, content_pack_id: str) -> dict[str, Any]:
|
|
|
|
|
+ if decision:
|
|
|
|
|
+ return {
|
|
|
|
|
+ "executed": True,
|
|
|
|
|
+ "executed_rule_pack_id": decision.get("rule_pack_id") or content_pack_id,
|
|
|
|
|
+ "reason": "content_decision_reused_for_walk_gate",
|
|
|
|
|
+ }
|
|
|
|
|
+ return {
|
|
|
|
|
+ "executed": False,
|
|
|
|
|
+ "executed_rule_pack_id": None,
|
|
|
|
|
+ "reason": "future_pack_not_enabled",
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def _decision_context(decision: dict[str, Any] | None) -> dict[str, Any]:
|
|
|
|
|
+ if not decision:
|
|
|
|
|
+ return {"decision_action": None, "search_query_effect_status": None}
|
|
|
|
|
+ return {
|
|
|
|
|
+ "decision_action": decision.get("decision_action"),
|
|
|
|
|
+ "search_query_effect_status": decision.get("search_query_effect_status"),
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
|
|
|
def _merge_batch(context: dict[str, list[dict[str, Any]]], batch: dict[str, list[dict[str, Any]]]) -> None:
|
|
def _merge_batch(context: dict[str, list[dict[str, Any]]], batch: dict[str, list[dict[str, Any]]]) -> None:
|