161 lines
8.1 KiB
Markdown
161 lines
8.1 KiB
Markdown
# 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。
|