|
|
@@ -0,0 +1,200 @@
|
|
|
+# V4 M4 游走消费 allow_walk Brief Index
|
|
|
+
|
|
|
+状态:本目录覆盖 V4 M4——把 M3 已产出的 `decision_replay_data.allow_walk` 从“记录字段”升级为 `walk_engine` 的实际游走准入口径。M4 只规划游走消费、walk runtime 可回放证据、walk policy/config validator 和 replay 验收;不修改 M3 Gemini/评分、不修改 M5 Web/API、不新增 DB 表或正式列。
|
|
|
+
|
|
|
+## 目标定位
|
|
|
+
|
|
|
+M4 的目标是让所有扩展游走都能被 M3 决策产物解释和回放:
|
|
|
+
|
|
|
+1. `allow_walk=true` 成为 V4 内容出边的唯一准入信号。
|
|
|
+2. `query_next_page`、`hashtag_to_query`、`author_to_works` 都必须消费 `allow_walk`。
|
|
|
+3. `allow_walk=false` 的 V4 内容不得触发翻页、tag 回灌或作者作品拉取。
|
|
|
+4. `walk_actions.raw_payload` 必须保留 `allow_walk/allow_walk_reason/walk_gate_snapshot` 消费证据。
|
|
|
+5. runtime validator 能跨文件证明 walk action 与 V4 decision gate 一致。
|
|
|
+6. DB/runtime 继续复用 JSON 容器,不新增 DB 表或正式列。
|
|
|
+
|
|
|
+M4 完成后,M5 可以直接解释“为什么这条内容没有继续游走”,而不需要重新计算 M3 分数或反推 `decision_action`。
|
|
|
+
|
|
|
+## 子 brief 执行口径(A→E 线性)
|
|
|
+
|
|
|
+| 子 brief | 文件 | 核心交付 | 依赖 |
|
|
|
+|---|---|---|---|
|
|
|
+| **M4A** | `M4A_Allow_Walk_Consumer_And_Edge_Gate_Contract.md` | `walk_engine` 读取 `allow_walk` 的统一 helper 与 edge permission 合同 | M3 scorecard producer、现有 `walk_engine` |
|
|
|
+| **M4B** | `M4B_Query_Next_Page_Tag_And_Author_Walk_Gate_Contract.md` | 翻页、tag 回灌、作者作品三条边的 V4 gate 消费细节 | M4A、walk policy、platform profiles |
|
|
|
+| **M4C** | `M4C_Walk_Policy_JSON_Excel_Validator_Contract.md` | `walk_policy.json` / 游走 Excel / config validator 的 M4 gate 合同 | M4A-M4B、现有 config gate |
|
|
|
+| **M4D** | `M4D_Runtime_Validation_DB_And_Source_Path_Replay_Contract.md` | runtime validator、DB JSON 容器、source path / walk action 可回放合同 | M4A-M4C、DB runtime |
|
|
|
+| **M4E** | `M4E_Acceptance_Commands_And_Subagent_Audit.md` | Unit Test、Integrated Test、DB 只读验证、config gate、Subagent 审计汇总 | M4A-M4D |
|
|
|
+
|
|
|
+## 不处理范围(红线)
|
|
|
+
|
|
|
+- 不改 M3 Gemini prompt、parser、technical failure 策略。
|
|
|
+- 不改 M3 `query_relevance_score/platform_performance_score/score` 阈值。
|
|
|
+- 不改 M3 `allow_walk=true` 阈值:`query>=70 && platform>=65 && score>=70`。
|
|
|
+- 不改 M2 平台 client、搜索 limit、快手接入、视频号 retry、抖音/视频号/快手抓取能力。
|
|
|
+- 不新增作者画像评分、tag relevance LLM、二跳回灌或新平台能力。
|
|
|
+- 不改 M5 final output、strategy review、dashboard/Web/API 展示解释。
|
|
|
+- 不新增 DB 表或正式列;M4 消费证据进入 JSON 容器。
|
|
|
+- 不把 `decision_action=ADD_TO_CONTENT_POOL` 继续等价为“可游走”。
|
|
|
+- 不破坏非 V4 历史 decision 的旧 `decision_action + edge_permissions` 行为。
|
|
|
+- 文档阶段只新增本目录 Markdown;不修改业务代码、DB schema、JSON 配置或 Excel。
|
|
|
+
|
|
|
+## 现有证据(共享,子 brief 各自细引)
|
|
|
+
|
|
|
+- 代码线 subagent 只读审计:`content_agent/business_modules/rule_judgment/evaluator.py::_decide_v4` 已计算 `allow_walk = _v4_allow_walk(...)`,并写入 `decision_replay_data`。
|
|
|
+- 代码线 subagent 只读审计:`evaluator._v4_allow_walk(...)` 阈值是 `query >= 70`、`platform >= 65`、`score >= 70`。
|
|
|
+- 代码线 subagent 只读审计:`content_agent/business_modules/run_record/validation.py::_check_v4_walk_gate_contract` 只校验 `allow_walk` 存在、bool、true 阈值,不校验 `walk_actions` 是否遵守。
|
|
|
+- 代码线 subagent 只读审计:`content_agent/business_modules/walk_engine.py::_edge_permission_for` 当前只看 `decision_action` 和 `search_query_effect_status == rule_blocked`,未读取 `decision_replay_data.allow_walk`。
|
|
|
+- 代码线 subagent 只读审计:`walk_engine._can_fetch_next_page(...)` 当前只要求 query effect 为 `success`;`query_next_page` 可能在 `allow_walk=false` 时继续翻页。
|
|
|
+- 代码线 subagent 只读审计:`tests/test_rule_pack_reading.py` 已有 `query=80/platform=60/score=70` 的 V4 case,`decision_action=ADD_TO_CONTENT_POOL` 但 `allow_walk=false`;这是 M4 必须消费的关键反例。
|
|
|
+- JSON/config 线 subagent 只读审计:`product_documents/规则包/douyin_rule_packs.v1.json` 与规则包 Excel 已切到 V4 scorecard,M4 不需要再改主 rule pack 评分口径。
|
|
|
+- JSON/config 线 subagent 只读审计:`tech_documents/数据接口与来源/walk_policy.json` 仍只有 `edge_permissions`,按 `ADD_TO_CONTENT_POOL/KEEP_CONTENT_FOR_REVIEW/REJECT_CONTENT` 放行,没有 `requires_allow_walk` 或 `v4_allow_walk_denied` 配置。
|
|
|
+- JSON/config 线 subagent 只读审计:`tech_documents/游走策略/游走策略配置表.xlsx` 仍只有 `walk_edge_catalog`、`walk_rule_pack_binding`、`walk_fact_contract`,未检出 `allow_walk/walk_gate_snapshot`。
|
|
|
+- JSON/config 线 subagent 只读审计:三平台 profile 当前状态为抖音 page/author/tag supported,快手 page/author blocked 但 tag supported weak,视频号 page/tag supported 但 author blocked。
|
|
|
+- DB/runtime 线 subagent 只读审计:`content_agent_rule_decisions` 已有 `scorecard/decision_replay_data/raw_payload` JSON 列;`content_agent_walk_actions`、`content_agent_source_path_records`、`content_agent_search_clues` 均有 `raw_payload` JSON。
|
|
|
+- DB/runtime 线 subagent 只读审计:`content_agent/integrations/database_runtime.py::JSON_COLUMNS_BY_TABLE` 已把 `decision_replay_data`、`walk_actions.raw_payload`、`source_path_records.raw_payload`、`search_clues.raw_payload` 列为 JSON 容器。
|
|
|
+- DB/runtime 线 subagent 只读验证:`uv run python scripts/validate_schema_registry.py` 通过;`uv run pytest -q -p no:cacheprovider tests/test_database_runtime.py tests/test_v4_m3_scoring_replay.py tests/test_walk_actions_runtime.py` 通过 37 个测试。
|
|
|
+- DB/runtime 线 subagent 只读验证:`validate_content_agent_db.py --allow-missing-tables` 本轮连接阶段返回 MySQL `2013 Lost connection to MySQL server during query`,M4 实现验收必须重跑。
|
|
|
+
|
|
|
+## 数据合同(汇总,子 brief 各自细化)
|
|
|
+
|
|
|
+M4 消费的 V4 decision replay:
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "decision_id": "d_001",
|
|
|
+ "decision_action": "ADD_TO_CONTENT_POOL",
|
|
|
+ "scorecard": {
|
|
|
+ "schema_version": "v4_scorecard.v1",
|
|
|
+ "query_relevance_score": 80,
|
|
|
+ "platform_performance_score": 60,
|
|
|
+ "total_score": 70
|
|
|
+ },
|
|
|
+ "decision_replay_data": {
|
|
|
+ "allow_walk": false,
|
|
|
+ "allow_walk_reason": "v4_query_and_platform_pass",
|
|
|
+ "walk_gate_snapshot": {
|
|
|
+ "query_relevance_score": 80,
|
|
|
+ "platform_performance_score": 60,
|
|
|
+ "score": 70
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+M4 `walk_actions.raw_payload` 消费证据:
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "decision_id": "d_001",
|
|
|
+ "decision_action": "ADD_TO_CONTENT_POOL",
|
|
|
+ "allow_walk": false,
|
|
|
+ "allow_walk_reason": "v4_query_and_platform_pass",
|
|
|
+ "walk_gate_snapshot": {
|
|
|
+ "query_relevance_score": 80,
|
|
|
+ "platform_performance_score": 60,
|
|
|
+ "score": 70
|
|
|
+ },
|
|
|
+ "walk_gate_status": "denied",
|
|
|
+ "walk_gate_reason_code": "v4_allow_walk_denied"
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+M4 walk policy 建议结构:
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "v4_walk_gate": {
|
|
|
+ "requires_allow_walk": true,
|
|
|
+ "deny_reason_code": "v4_allow_walk_denied",
|
|
|
+ "applies_to_edges": [
|
|
|
+ "query_next_page",
|
|
|
+ "hashtag_to_query",
|
|
|
+ "author_to_works"
|
|
|
+ ],
|
|
|
+ "source_field": "rule_decisions.jsonl[].decision_replay_data.allow_walk"
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+## M4 已拍板口径
|
|
|
+
|
|
|
+- V4 出边准入以 `decision_replay_data.allow_walk` 为准。
|
|
|
+- `allow_walk=false` 时不触发 `query_next_page/hashtag_to_query/author_to_works`。
|
|
|
+- 非 V4 decision 沿用现有 `decision_action + walk_policy.edge_permissions`。
|
|
|
+- 平台 profile blocked 优先于 allow_walk gate:blocked edge 显式 skip 且不调平台。
|
|
|
+- 预算耗尽仍使用 `budget_exhausted`,不要被 `v4_allow_walk_denied` 覆盖。
|
|
|
+- `walk_actions.raw_payload` 要写消费证据,便于 M5 解释。
|
|
|
+- M4 不重算 M3 分数,不读取 Gemini/platform raw 字段重新判断。
|
|
|
+- DB 不 migration;所有 M4 新证据进入 JSON 容器。
|
|
|
+- 开工前待拍板项:无,按 V4 正式计划已拍板口径执行。
|
|
|
+
|
|
|
+## 验证命令(汇总)
|
|
|
+
|
|
|
+```bash
|
|
|
+uv run pytest tests/test_walk_engine_author.py tests/test_walk_engine_tag.py tests/test_walk_engine_pagination.py -q
|
|
|
+uv run pytest tests/test_v4_walk_contract.py tests/test_v4_validator_contract.py tests/test_v4_m4_walk_replay.py -q
|
|
|
+uv run pytest tests/test_database_runtime.py tests/test_v4_m3_scoring_replay.py tests/test_walk_actions_runtime.py -q
|
|
|
+uv run pytest tests/test_case_replay.py tests/test_walk_profile_degradation.py -q
|
|
|
+uv run python scripts/validate_content_agent_db.py --allow-missing-tables
|
|
|
+uv run python scripts/validate_schema_registry.py
|
|
|
+uv run python scripts/validate_rule_pack_config.py
|
|
|
+uv run python scripts/validate_v4_config_contract.py
|
|
|
+uv run --with openpyxl python scripts/build_config_from_excel.py --check
|
|
|
+uv run --with openpyxl python scripts/validate_config_excel_sync.py
|
|
|
+python3 scripts/run_config_gate.py
|
|
|
+uv run pytest -q
|
|
|
+```
|
|
|
+
|
|
|
+## Unit Test(汇总)
|
|
|
+
|
|
|
+- `tests/test_walk_engine_author.py`
|
|
|
+ - `ADD_TO_CONTENT_POOL + allow_walk=false` 不调用 `fetch_author_works`。
|
|
|
+ - `allow_walk=false` 写 `v4_allow_walk_denied` skip。
|
|
|
+ - `allow_walk=true` 保持作者作品成功、去重、search query lineage。
|
|
|
+ - 非 V4 decision 保持旧行为。
|
|
|
+- `tests/test_walk_engine_tag.py`
|
|
|
+ - `allow_walk=false` 不生成 tag query。
|
|
|
+ - `allow_walk=true` 保留 tag query。
|
|
|
+ - blocked tag、预算耗尽、profile blocked 行为不变。
|
|
|
+- `tests/test_walk_engine_pagination.py`
|
|
|
+ - `success + has_more + cursor + allow_walk=false` 不生成 page query。
|
|
|
+ - `allow_walk=true` 仍生成 page query。
|
|
|
+- `tests/test_v4_walk_contract.py`
|
|
|
+ - V4 gate config 存在。
|
|
|
+ - deny reason 为 `v4_allow_walk_denied`。
|
|
|
+ - 三平台 edge status 仍为 `supported/blocked`。
|
|
|
+- `tests/test_v4_validator_contract.py`
|
|
|
+ - validator 拒绝 `allow_walk=false` 却产生成功扩展 action。
|
|
|
+ - validator 拒绝 V4 walk action 缺 `walk_gate_snapshot` 消费证据。
|
|
|
+
|
|
|
+## Integrated Test
|
|
|
+
|
|
|
+- 新增 `tests/test_v4_m4_walk_replay.py`。
|
|
|
+- 构造两条 V4 decision:
|
|
|
+ - `ADD_TO_CONTENT_POOL + allow_walk=true`。
|
|
|
+ - `ADD_TO_CONTENT_POOL + allow_walk=false`。
|
|
|
+- 运行 `run_bounded_walk(...)`。
|
|
|
+- 验证只有 `allow_walk=true` 内容触发 page/tag/author 扩展。
|
|
|
+- 验证 `allow_walk=false` 内容产生 `v4_allow_walk_denied` skip 或 path stop,不调用平台作者接口。
|
|
|
+- 用 `LocalRuntimeFileStore + validate_run()` 验证 runtime 通过。
|
|
|
+- 用 `DatabaseRuntimeStore` fake connection 写入 `rule_decisions/walk_actions/source_path_records/search_clues/search_queries`,验证 raw_payload 保留 M4 gate 证据。
|
|
|
+- 保持快手/视频号 profile blocked replay 通过:profile blocked 优先,不因 allow_walk 误调用 blocked 作者作品接口。
|
|
|
+
|
|
|
+## 失败归因(汇总)
|
|
|
+
|
|
|
+- `allow_walk=false` 仍触发作者作品:先查 `_edge_permission_for(...)` 是否识别 V4 scorecard。
|
|
|
+- `allow_walk=false` 仍触发翻页:先查 `_query_effect_by_search_query_id(...)` 与 `_can_fetch_next_page(...)` 是否读取 query 下 allow_walk。
|
|
|
+- tag skip reason 错误:先查 `video_to_hashtag` deny 是否区分 `v4_allow_walk_denied`、`review_tag_expansion_disabled`、`blocked_by_rule_decision`。
|
|
|
+- 平台 blocked 被误调用:先查 `edge_supported(profile, edge_id)` 是否仍在 allow_walk gate 之前。
|
|
|
+- 预算 skip 被覆盖:先查预算判断顺序,预算耗尽仍应写 `budget_exhausted`。
|
|
|
+- validator 未发现错误扩展:先查是否将 walk action 与 decision id / content id 建立关联。
|
|
|
+- DB 写入后证据丢失:先查 `walk_actions.raw_payload` 与 `source_path_records.raw_payload` 是否包含 gate context。
|
|
|
+- config gate 未覆盖 M4:先查 `validate_v4_config_contract.py` 是否校验 `v4_walk_gate`。
|
|
|
+- DB 只读验证失败:本轮已见 MySQL 2013 断线,先重跑 `validate_content_agent_db.py --allow-missing-tables` 并记录结果。
|
|
|
+
|
|
|
+## sub-agent 交叉验证要点
|
|
|
+
|
|
|
+- 旧 subagent 关闭请求:`019ec6e4-8ae9-7fb3-ae13-b9ed17baa2ae`、`019ec6e4-8b67-77d3-a996-a55c790342a5`、`019ec6e4-8bd1-7d90-91cd-89ed292fb7fe` 均返回 `not found`。
|
|
|
+- 新代码线 subagent:`019ec71d-079d-7f81-821e-ff9b9cac4498`(Bohr)确认 M3 已产 `allow_walk`,M4 `walk_engine` 未消费,最大缺口是 `query_next_page` 仍只看 query effect。
|
|
|
+- 新 JSON/config 线 subagent:`019ec71d-2a9c-7f61-af9c-3963a56afe8a`(Newton)确认 rule pack 已 V4,walk policy/游走 Excel 缺 M4 allow_walk gate,config validator 需补强。
|
|
|
+- 新 DB/runtime 线 subagent:`019ec71d-4904-7212-8d45-2d9e0504aa13`(Nietzsche)确认 DB 不需要 migration,JSON 容器足够,但 DB validator 本轮 MySQL 2013 断线,验收必须重跑。
|