# 2026-07-30 问题总结：当前代码与 PRD 的匹配度

## 1. 本次结论

本次以当前 `feature/zhangbo` 分支（`693fe6b`）为准，并与上一次审查基线
`d2154ed` 对比。代码已经从“多个脚本/Agent 拼接的日任务”明显推进到“可运行、可追踪的日批次流水线”：

- 有了按 `biz_dt` 创建的 Pipeline Run、步骤状态、锁、重试/恢复/取消、健康检查与运行页面；
- 日流程覆盖了全局树、上游需求池、分类挂靠、先验/真实 ROV/VOV、需求分级、需求扩展、找片和 AIGC 写入；
- 找片 Agent 现在以已分级需求及其视频点位为输入，并保存搜索路径、候选内容和选择结果；
- 分类节点热度保留了四类先验与真实 ROV/VOV，需求分级也保存了 reason、挂靠分类和部分后验快照。

因此，项目已经具备 PRD 的“每日自动化骨架”和一部分“需求 → 找内容”的执行能力。

但它尚未实现 PRD 定义的业务 Harness：当前的正式对象仍主要是“来源词/归属词/分级结果”，而不是可版本化的平台需求；后验还没有经过“内容覆盖与表现归因”回流到需求判断；控制台也还不能完成提问、数据查询、策略草案、影响预览和确认发布。若以 PRD 成功标准验收，当前总体匹配度约为 **45%**：运行可靠性进展较快，业务闭环与可解释决策仍是主要缺口。

> 说明：本文件只记录审查结论，不修改任何业务实现。优先级中的 P0 表示可能造成错误数据、重复外部动作或无法按部署方式运行；P1 表示核心 PRD 业务能力缺失；P2 表示产品/治理完整度问题。

## 2. PRD 模块匹配图

```mermaid
flowchart LR
    A[上游需求/先验/关联] --> B[当前：需求池同步与分类]
    B --> C[当前：树热度与需求分级]
    C --> D[当前：找片 Agent]
    D --> E[当前：AIGC 爬取计划写入]
    E -. 尚未形成内容表现归因 .-> C

    F[PRD：人/Agent反馈] -. 尚无反馈对象与入口 .-> B
    G[PRD：策略草案/预览/确认/版本] -. 仅有提示词注入 .-> C
    H[PRD：平台需求任务包] -. 尚未成为统一对象 .-> D
```

| PRD 模块 | 当前实现情况 | 匹配度 | 关键判断 |
|---|---|---:|---|
| 证据收集 | 已同步需求池、树、视频、四类先验及真实 ROV/VOV；Pipeline Run 有日期和配置快照 | 55% | 有日数据和运行记录，但原始证据未形成不可变、可引用的证据包；同数量更新会被跳过 |
| 需求认知与汇总 | 有分类 Agent、`reason`、树节点、部分多挂靠（分级结果） | 35% | 没有“原始表达 → 标准需求词 → 平台需求”的三层稳定对象、版本和关系语义 |
| 评估与供给分配 | 有四类先验、ROV/VOV diff、树热度、0–100 分级和 A/S/A/B/C/D 等级 | 40% | 尚未产出两个 0–1 决策结果、五类行动层、局部供给优先级、探索抽样和可展开贡献 |
| 发布、可视化、反馈 | 有热力图、需求详情、运行页、找片搜索/候选存储 | 40% | 不是一份供人和 Agent 共用的任务包；没有人反馈入口、完整路径/关系/评分解释与内容归因 |
| 业务协作与策略控制 | 可查看/编辑允许名单 Agent 的提示词追加内容 | 15% | 没有业务问答、直接数据分析、策略草案、影响预览、确认、版本和审计 |
| 每日运行与可恢复性 | 新增持久化 DAG、门禁、锁、Worker、Reconciler、运行页面 | 75% | 是本次最显著进步；但部署迁移、数据正确性和外部副作用幂等仍未闭合 |

## 3. 本次改动已解决或显著改善的事项

### 3.1 日批次不再只是进程内任务

`pipeline_run`、`pipeline_step_run`、`pipeline_lock`、`pipeline_outbox` 与 DAG/Worker/Reconciler 已形成控制面。每一步都有运行状态和输入日期，失败步骤会阻断下游；运行可以查看、重试、恢复或取消。这与 PRD“每天自动化执行、保留历史过程、异常不能静默发布”的方向一致。

### 3.2 需求分级失败会阻断后续动作

流水线 Gate 会检查业务失败信息，不再把分级 Agent 的异常结果直接当作可继续下发的成功结果。相较上一次审查，这是对“失败批次不能产出正式结果”的实质修复。

### 3.3 找片的过程性证据开始沉淀

`video_discovery_run/search/candidate` 已能记录：需求、搜索词、搜索原因、搜索父子关系、候选视频、选择/拒绝状态和部分评分。它是未来“寻找 Agent 输出可解释、可回查”的可用基础。

### 3.4 前台和部署形态更接近日常运营

增加了 Pipeline Run/健康状态界面、视频发现界面，以及 scheduler、worker、reconciler 的独立进程配置；容器入口也会先执行 `alembic upgrade head`。这些改变有助于把“每日计算”从手工运行转成可运营服务。

## 4. P0：应先处理的正确性和发布风险

### P0-1：找片数据表没有进入 Alembic，按当前部署会导致核心步骤缺表

**事实**

- `video_discovery_run`、`video_discovery_search`、`video_discovery_candidate` 的 DDL 位于 `sql/video_discovery_*.sql`；
- `alembic/versions/` 中没有这些表及其后续字段的迁移；
- 容器入口只执行 `alembic upgrade head`，而数据库自动 `create_all` 并不是该部署路径的保证。

**影响**

全新环境或仅按标准迁移升级的环境，流水线到 `video_discovery` 时可能直接失败。手工执行 SQL 即使暂时绕过，也会造成模型、SQL 文件、迁移历史三套事实漂移。

**建议**

把当前完整的找片表结构及所有增量字段收敛为一条或一组可重复升级的 Alembic 迁移；在 CI/预发中用空库执行 `alembic upgrade head`，再跑一次最小 Pipeline Run。

### P0-2：外部 AIGC 动作在 Outbox 记录之前发生，重试可能重复创建计划

**事实**

`_aigc_write_record()` 先调用 `publish_videos_from_discovery()`；该函数会通过 `AigcClient.create_video_crawler_plan()` 和绑定接口写入外部 AIGC 平台。外部调用完成后，才根据返回 payload 计算哈希并写入 `pipeline_outbox`。AIGC 请求中也没有传递可供对方幂等的业务键。

**影响**

进程在外部创建成功、尚未写入本地 Outbox 时中断，或超时后重试，会再次创建爬取/生成计划。这既会重复消耗资源，也会让“一个需求被哪些内容承接”难以准确追溯。

**建议**

先以稳定业务键（例如 `biz_dt + demand/task/candidate version`）创建待发送的 Outbox 事件并提交；Worker 领取事件后再调外部接口；将该业务键传给外部系统或在本地保存外部返回 ID 后再确认。重试只重放未确认事件，不能重新生成业务请求。

### P0-3：上游数据“行数相同即跳过同步”，会漏掉同数量的内容修订

**事实**

`_sync_pool_rows()` 只比较 ODPS 与 MySQL 的当天行数；两者相等即返回 `skipped_same_count=True`。即使同一天的词、权重、视频、真实 ROV/VOV 或关联发生替换，行数不变也不会执行差量同步。

**影响**

需求强度、后验表现和下游找片依据可能使用过期事实；而流水线仍显示该步骤成功，形成难以察觉的错误日快照。

**建议**

使用上游版本号、更新时间、水位线或逐行内容哈希决定是否同步；无此字段时至少执行主键/内容哈希差分。运行输出需明确记录上游版本和变更数。

### P0-4：归属边以全历史子串匹配生成，容易写入跨日和误匹配关系

**事实**

`sync_demand_belong_pool_rel()` 调用不带 `biz_dt` 的 `list_id_name_video_lists()`，对所有可见需求池记录按 `name in demand_name` 建边，并把所有命中视频合并到词上。`demand_belong_category.name` 还是全局唯一，关系边没有关系类型、来源、时间或置信度。

**影响**

短词会命中不相关长词，历史数据会混入当天关系；后续热度、视频证据和分级的输入因此不再是可说明的“当天证据”。这直接违背 PRD“上游关联保留原样、推断关系须说明”的原则。

**建议**

关系边应至少保存 `biz_dt/证据版本、relation_type、relation_source、reason、confidence、推断标记`；优先消费上游显式关联。若保留文本匹配，只能作为低置信候选，需边界匹配、日期过滤和人工/模型判定，不应直接成为正式边。

## 5. P1：核心业务闭环仍未实现

### P1-1：没有平台需求这一稳定业务对象

当前 `demand_belong_category` 是“名称全局唯一 + 单一 category_id”的归属词；`DemandGrade` 是某日分级结果；`generated_demand` 存在但未进入当前 Pipeline、API 和主界面。三者没有形成 PRD 所需的：

```text
原始需求表达（不可变证据） → 标准需求词（别名/归一） → 平台需求（稳定 ID、版本、可搜索意图）
```

因此系统无法可靠回答“这个平台需求今天为何成立、与昨天是否是同一个需求、哪些原话与别名支持它”，也无法在不覆盖历史的前提下合并、拆分和再激活。

**建议**：先定义并落地三层对象、版本和证据引用；只让平台需求成为评估、下游任务和反馈归因的中心对象。

### P1-2：多挂靠只有 ID 列表，没有业务关系图

`demand_grade_category_rel` 支持一条分级结果对应多个分类，但没有主/辅挂靠、关系语义、证据来源、reason、置信度或有效日期；原始归属词仍只能有一个分类。前台可以显示部分分类名，却不能完整解释“为什么挂在这些树枝上、哪些是上游事实、哪些是系统推断”。

**建议**：将“树骨架”和“横向关系图”分开建模。多挂靠边要有类型（主挂靠/辅助挂靠/上游关联/推断关联等）、来源、reason、置信度、版本和状态；需求详情按完整祖先路径展示所有边。

### P1-3：评分体系与 PRD 的两个 0–1 决策结果不一致

当前分类 `total_score` 是四项先验排名分之和（约 0–4）；`DemandGrade.score` 是来源内排序均值（0–100）；真实 ROV/VOV 作为 diff 和样本量展示/提示给 Agent。`DemandGrade` 仅保存 ROV 的平均值/计数快照，未保存 VOV 快照，更没有可复算的贡献项。

这与 PRD 已确认的规则不一致：

- 面向人展示统一为 0–1；
- 同时输出“需求成立度”和“局部供给优先级”；
- 后验不能因缺失被当成零，需要经过内容质量、曝光、时间、覆盖度和样本量归因；
- 决策应能展开每项贡献、扣减与 reason。

**建议**：保留全部原始维度，另建立按日版本化的 `validity_score`、`local_supply_priority`、贡献明细、数据质量/样本状态与决策 reason；用这两个结果映射保供、优先、定向验证、探索、抑制，不能由一个 0–100 等级兼任。

### P1-4：真实 ROV/VOV 还不是“需求—内容—表现”的反馈闭环

目前真实 ROV/VOV 来自需求池词级字段并聚合到词/树，找片结果虽然保存候选视频和 AIGC 计划字段，但没有需求—内容的多对多承接关系，更没有主需求/辅助需求、覆盖程度、上线时间、曝光/质量/供给量、表现归因置信度，或“次日评分受何种反馈影响”的记录。

**影响**：可看到某个词的后验 diff，但不能证明它是由哪条内容、以什么覆盖程度带来的表现；也不能反向纠偏平台需求强度。

**建议**：以平台需求为中心建立内容承接边和表现事实表；将 ROV/VOV 原值与归因判断分开。每日把有效反馈、置信度和影响值写入需求评估快照，且可从需求反查到内容与原始表现。

### P1-5：找片 Agent 并未消费统一的每日需求任务包

当前 Find Agent 从 `DemandGrade` 及 `demand_video_expansion` 读取上下文，主要依赖已分级需求和视频点位。它没有接收 PRD 规定的需求版本、全部挂靠路径和关系、两个分数、行动层、搜索/排除词、命中规则、待验证假设、证据缺口和已有内容覆盖。

**建议**：由发布模块生成唯一、可版本化的“每日需求任务包”；人和 Find Agent 都从此任务包读取，Agent 的搜索结果再写回任务包引用的需求和内容承接边。不要让两个下游各自解释 `DemandGrade`。

### P1-6：没有人反馈入口，也没有“为什么是/不是需求”的可查询业务服务

仓库中目前可见的控制能力是 Agent Prompt 的 document injection：一个 Agent 名仅保留一份可覆盖的文本和启用状态。没有用于新需求、挂靠、合并拆分、reason 错误、内容、判断或数据问题的反馈对象/API；也没有“为什么 XX 是需求/不是需求”的查询、历史运行检索或自动分析服务。

**建议**：普通反馈作为带来源、时间、对象、类型和证据的追加事件；管理指令单独进入受控工作流。问答先落到只读查询计划和结果记录，再由模型基于这些结果作答，不能只靠提示词生成解释。

### P1-7：策略修改没有草案、预览、确认和历史版本

`agent_document_injection` 以 `agent_name` 唯一键 upsert，更新会覆盖旧内容；没有编辑者、修改原因、审批状态、影响范围、模拟结果或版本号。它能调整提示词，但不能承担 PRD 的业务策略控制。

**建议**：把业务定义（维度字典、合并/拆分规则、行动层、探索额度、后验门槛等）建成版本化策略；自然语言修改先生成结构化草案和历史数据影响预览，确认后才由新日批次引用该版本。

### P1-8：全局热力图可能混合不同业务日的数据

`GlobalDemandMapView` 先读取分类树的最新日期，再独立调用不带 `biz_dt` 的需求分级接口。两类数据更新节奏不一致时，树和需求可能来自不同日期，热力图会显示为同一天的全局结果，但实际并非同一快照。

**建议**：页面先确定一个已成功完成的 Pipeline Run / `biz_dt`，随后所有树、需求、关系、评分和内容接口强制携带同一日期与策略版本；数据不完整时显示“该批次未发布”，不要回退拼接最新值。

## 6. P2：可运营性与治理完整度问题

### P2-1：Pipeline 的快照还不是完整的证据快照

Pipeline Run 记录 `biz_dt`、代码/配置快照和步骤输出，十分有价值；但输入表会持续被同步更新，尚未把每条原始事实、关系和后验以可引用 ID 封存到“每日证据包”。历史 Run 因此不能完全在原始输入已变更后复算或逐项解释。

### P2-2：找片过程有存储，但面向人的解释面没有接通

搜索词、搜索 reason、候选和决策桶已保存；`/api/video-discovery` 当前主要返回分级需求、视频点位和来源视频，而非完整的搜索图、候选评分、拒绝原因、内容承接关系和表现反馈。前台不能完整展示 PRD 中要求的“决策全过程”。

### P2-3：测试不能在当前环境运行

本机执行 `python3.11 -m pytest -q` 在收集阶段失败：当前解释器载入的 SQLAlchemy 不包含 `sqlalchemy.orm.DeclarativeBase`，而项目声明 `sqlalchemy>=2.0`。共出现 14 个收集错误，Pipeline 与 Scheduler 测试均未真正执行；pytest 同时提示当前环境不识别 `asyncio_mode` 配置。

这更像是环境依赖没有按项目要求安装，而非已证明的业务逻辑失败，但它仍阻断了本地/CI 对本次改动的可信验证。

**建议**：固定 Python 与依赖锁定方式，在 CI 使用干净环境安装 `pyproject.toml`/requirements；增加空库迁移、单日最小流水线、外部副作用幂等、同数量内容变化、跨日关系隔离的集成测试。

### P2-4：现有质量检查发现历史文档格式问题

`git diff --check d2154ed..HEAD` 报告已有文件 `problem/2026-07-24_问题总结.md` 在 EOF 有多余空行。它不影响运行，但说明提交前的基础质量检查没有全绿。

## 7. 建议的修复顺序

```mermaid
flowchart TD
    A[P0：可信运行] --> B[迁移收敛：空库可升级]
    A --> C[外部动作先出箱后发送]
    A --> D[输入按版本/哈希差分]
    A --> E[关系按日期与语义建边]

    B --> F[P1：定义平台需求与证据包]
    C --> F
    D --> F
    E --> F
    F --> G[双 0–1 评估 + 五类行动层]
    G --> H[统一每日任务包]
    H --> I[需求—内容—表现归因]
    I --> J[人反馈、问答与策略版本控制]
```

建议按以下四个阶段推进：

1. **先使日运行可信**：解决 P0-1 至 P0-4，并用空库迁移、同数量更新、失败重试和重复外部调用测试作为发布门禁。
2. **再统一业务对象**：定义证据包、原始表达、标准需求词、平台需求、树边/图边和版本；停止把字符串子串匹配直接当正式业务关系。
3. **再建立可解释决策与下游契约**：输出两个 0–1 分数、行动层和统一任务包，热力图只消费该已发布任务包的同一批次快照。
4. **最后闭合学习与协作**：建立内容承接和表现归因，再加入人的反馈、为什么问答、策略草案/影响预览/确认/审计。

## 8. 本次审查验证记录

| 检查 | 结果 | 说明 |
|---|---|---|
| 工作区状态 | 通过 | 审查开始时未见未提交业务代码改动；本次仅新增本文件 |
| `git diff --check d2154ed..HEAD` | 有告警 | 发现 2026-07-24 旧问题总结文件 EOF 多余空行 |
| `python3.11 -m pytest -q` | 未通过 | 14 个测试收集错误，当前环境 SQLAlchemy 版本低于项目所需 2.x；测试未进入业务断言 |
| 代码静态核对 | 完成 | 核对了 Pipeline DAG/门禁、迁移、部署入口、数据同步、关系同步、评分、Find Agent、AIGC 外部写入、API 与前台取数 |

