# STRING PPI Task 6:Manifest、状态、诊断与 provenance 闭环验证 日期:2026-07-21 ## 范围 本任务仅闭环 PPI 的 preflight decision、实际执行 manifest、状态读取、诊断码和 provenance 契约。未修改 STRING 物种选择算法、调度器、Ortholog 算法或 Ka/Ks。 ## 行为 Gate - `confirmation_required`、`needs_reference_data`、`needs_ortholog` 等等待态只追加 `reproducibility/{prefix}.ppi.preflight_decisions.jsonl`,不得生成失败的 PPI stage manifest。 - 实际提交的 PPI,无论成功或失败,manifest 均须记录同一份 `ppi_provenance_v1`:原始目标物种、规范学名、目标树 taxon、选定 STRING taxon、选择模式、snapshot version/id/hash、用户确认、Ortholog reference/path、归一化标签。 - API、CLI、status 和 diagnosis 使用同一身份字段,不各自推断或复制另一套 schema。 - `exact_string`、`tree_nearest`、`model_fallback`、`unresolved`、`resource_error` 映射为稳定诊断码。 - status 读取历史 manifest 时不得重新计算或改写 snapshot。 - CLI 异常及后端非零退出仍须落盘 `status: failed` 的 manifest。 ## TDD 证据 ### RED 首次执行 `tests/unit/test_ppi_provenance_task6.py` 时,9 项测试全部失败,确认缺失项包括等待态决策记录、稳定诊断码、skill/backend 失败 manifest、status provenance 等。随后补充实际 diagnosis 读取场景,也先确认其失败,再进入实现。 ### GREEN 实现后聚焦测试结果: ```text tests/unit/test_ppi_provenance_task6.py 11 passed in 12.37s ``` 相关 Python 文件 `py_compile` 校验通过: - `gfa_core/ppi_provenance.py` - `apps/web/pipeline_backend.py` - `skills/ppi/run.py` - `gfa_core/mas/tools/stage_status.py` - `gfa_core/mas/agents/diagnosis.py` ### 限定回归 限定回归覆盖 Task 3/4/5B 的 PPI 身份、snapshot、数值 taxon 与 Ortholog owner 行为。 首次结果为 42/49 通过、7 项失败。7 项均由同一处局部回归造成:`_read_job_species_identity()` 已构造 `response`,但漏写 `return response`,使带 `config.xlsx` 的身份解析得到 `None`。补回该返回语句后,原样重跑同一测试集合: ```text collected 49 items 49 passed in 13.96s ``` 覆盖文件: - `tests/unit/test_ppi_provenance_task6.py` - `tests/unit/test_ppi_id_resolution.py` - `tests/unit/test_ppi_snapshot_preflight_task3.py` - `tests/unit/test_ppi_numeric_taxon_task4.py` - `tests/unit/test_ppi_ortholog_owner_identity_task5b.py` ## 改动文件 - `gfa_core/ppi_provenance.py`:唯一 provenance schema、snapshot hash、稳定诊断码、preflight decision 记录和 manifest 注入。 - `apps/web/pipeline_backend.py`:preflight 决策落盘;执行前生成 provenance;成功/失败 manifest 闭环;修复遗漏的 `return response`。 - `skills/ppi/run.py`:接收 provenance;成功和失败均生成 manifest;CLI 异常也生成失败 manifest。 - `gfa_core/mas/tools/stage_status.py`:原样暴露历史 manifest 中的 PPI provenance。 - `gfa_core/mas/agents/diagnosis.py`:从 manifest provenance 生成稳定 PPI 身份诊断。 - `gfa_core/schemas/stages/ppi_contract_v1.md`:记录等待态、执行态、schema、诊断码和 CLI 契约。 - `tests/unit/test_ppi_provenance_task6.py`:Task 6 聚焦测试。 ## 执行边界与结论 本任务未启动或重启任何服务,未提交真实分析任务,未执行真实网络验证,未执行 Task 7,也未运行全量测试。基于 11 项聚焦测试和 49 项限定回归,Task 6 的代码级 Gate 已通过;运行态/真实数据 Gate 留待后续授权任务。 ## REVISE:审查阻断修复 审查提出三个阻断,本轮仍按 RED→GREEN 修复: 1. PPI Skill 失败返回值与落盘 manifest 统一使用 `status: failed`,CLI 也以该状态判定失败,不再出现内存态 `error`、文件态 `failed` 的分裂。 2. `pipeline_backend` 的 PPI 执行区新增单一失败出口。unsupported species、scope 不存在/不可读、mapping 无目标 source ID、scoped member ID 缺失、多 target 无 mapping、member resolution 异常/空路径,以及无法推断物种、skill 缺失、projected ID map 缺失,均写入当前 prefix 的 `final/{prefix}.ppi.manifest.json`;manifest 强制为 `stage: ppi`、`prefix: 当前值`、`status: failed` 并附完整 provenance,不再返回通用 `find_latest_manifest` 的 `None` 或其他阶段 manifest。 3. `user_confirmation.required` 改由 `tree_nearest`/`model_fallback` 的历史选择模式决定。确认后保留 `required: true`,同时记录 `confirmed: true`。新增独立 preflight→execution 测试,逐字段比较实际提交 provenance,而非复用同一对象自证。 本轮 RED:新增后的 20 项聚焦测试中 10 项失败,准确覆盖状态分裂、8 类前置失败未写 PPI manifest、确认历史丢失。最小实现后首次为 19/20 通过;唯一失败来自测试错误地比较“尚未选择候选”的未确认 preflight 空 taxon 与已确认执行 taxon。测试随后分开验证未确认状态,并使用已确认 preflight 与 execution 做逐字段比较。 最终验证: ```text tests/unit/test_ppi_provenance_task6.py 20 passed Task 6 + Task 3/4/5B 限定回归 58 passed in 15.01s ``` 本轮仍未启动或重启服务,未提交真实任务,未执行 Task 7,未扩大到物种选择、调度、Ortholog 或 Ka/Ks 算法。 ## Deployment Gate:9010 Web 与五个 workers Task 6 代码随后部署到隔离的 9010 runtime。部署仅重启 9010 Web 和五个 `plantai_4090_9010_*` Celery worker 主进程;未停止或重启 9000/19000。 | 服务 | 旧 PID | 新 PID | 队列 | |---|---:|---:|---| | Web 9010 | 2509478 | 2523340 | — | | default | 2509695 | 2523309 | `plantai_4090_9010.default` | | heavy | 2509696 | 2523315 | `plantai_4090_9010.heavy` | | medium | 2509697 | 2523323 | `plantai_4090_9010.medium` | | light | 2509698 | 2523330 | `plantai_4090_9010.light` | | rnaseq | 2509699 | 2523341 | `plantai_4090_9010.rnaseq` | 六个新主进程的 cwd 均为: ```text /home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev ``` Web 和五个 worker 的环境均包含: ```text BBAV5_QUEUE_PREFIX=plantai_4090_9010 BBAV5_REDIS_URL=redis://localhost:6379/11 ``` 未发现替代 `PYTHONPATH`。`redis-cli -n 11 ping` 返回 `PONG`。对五个指定 worker 执行定向 `celery inspect ping` 返回 `5 nodes online`,每个均为 `pong`;定向 `active_queues` 显示每个 worker 只消费其对应的 default/heavy/medium/light/rnaseq 队列。`/api/celery/health` 也报告五个预期 9010 worker 和队列在线;DB11 中同时存在另一组命名不同的 GWAS worker,但不消费 `plantai_4090_9010.*` 队列。 禁止触碰的进程在重启前后 PID 未变化: ```text 19000 Web: 2483131 9000 default/heavy/medium/light/rnaseq: 3588799 3588807 3588814 3588821 3588830 ``` ### 在线只读检查 - `GET http://127.0.0.1:9010/docs` 返回 HTTP 200。 - live OpenAPI 包含 `/api/ppi/species-resolution` 和 `/api/stage-status`。 - 按 OpenAPI 声明参数对合成、确认不存在的 job ID 调用 `/api/stage-status`,返回 HTTP 200、`stage=ppi`、`status=not_found`、`completed=false`;调用后确认未创建合成 workspace 目录。 - 未调用任何 execute/submit/reset/download/Ortholog 路由。 目标 cwd 中的新 Python 进程实际导入路径: ```text /home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev/gfa_core/ppi_provenance.py /home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev/gfa_core/mas/tools/stage_status.py /home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev/gfa_core/mas/agents/diagnosis.py /home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev/skills/ppi/run.py ``` 动态 helper 返回的稳定码为: ```text exact_string -> ppi_string_exact tree_nearest -> ppi_string_tree_nearest model_fallback -> ppi_string_model_fallback unresolved -> ppi_string_unresolved resource_error -> ppi_string_resource_error ``` 动态构造 `tree_nearest`、已确认 provenance 得到 `user_confirmation={required: true, confirmed: true}`。 Deployment Gate 未在任何真实 Sv job 中写 failed manifest,未提交 PPI、下载、Ortholog 或其他分析任务;真实端到端执行仍保留给 Task 7。