Files
PlantAI-dev/docs/validation/2026-07-21-string-ppi-task7-live-e2e.md
2026-08-03 18:42:47 +08:00

583 lines
33 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# STRING PPI Task 7:真实 9010 E2E
日期:2026-07-21
目标:`job_1784552755238_b8762f` / `Sv.HKL`
结果:**PASSED — 真实 Ortholog → PPI 主链与最终 9 项矩阵通过**
## 结论
最终 attempt 5 已通过真实 9010 API 完成 `preflight → PPI-owned Ortholog → ready_reference_mapping → PPI`。PPI 使用 STRING TaxID `4555` 查询、本地 normalization label `string_taxon_4555`,解析 6/6 个基因并获得 15 条互作;scoped Manifest 为 `success`,stage status 为 `completed`,6 个 artifacts 均存在且哈希匹配。
下文保留 attempt 1–4 的失败过程与原始证据;这些失败促成了 scope identity、owner TaxID 和 normalization label 的最小修订,不代表最终状态。最终 9 项只读矩阵也已通过,证明 Os direct、Sv/Ft/第二 unsupported 植物、未知身份、At fallback 以及 PPI/KaKs 数据依赖隔离均符合计划。
## 基线
- Scope:`workspace/job_1784552755238_b8762f/final/Sv.HKL.HKL.target-Sv.target_only.scope.json`
- Scope SHA256:`31d8f69ef697c9c802cc929cd2383aca8e700a6c7fc52a57db408156384ed711`
- Target config:`Sv / Setaria_viridis`;显式树 TaxID `4556`
- 提交前没有 Ortholog/PPI 文件,五条 `plantai_4090_9010.*` 队列均为 0。
- 9010 PIDs:Web `2523340`;workers `2523309, 2523315, 2523323, 2523330, 2523341`。
- STRING snapshot:v12.0,ID `ede47d546d853d0ec30ee75066976a35c08fd2412e6e5fc7866bbd205fc2eeb3`,source-manifest SHA `46fd3d72d7e2086682d7cb3723c668b6bb629087ad4c8ce1e1aac9480131c6e7`。
## 1. 未确认与确认 preflight
真实请求:`POST /api/ppi/species-resolution`。核心请求体:
```json
{
"job_id": "job_1784552755238_b8762f",
"prefix": "Sv.HKL",
"scopeFile": "workspace/job_1784552755238_b8762f/final/Sv.HKL.HKL.target-Sv.target_only.scope.json",
"ppiSpecies": "auto",
"targetSpecies": ["Sv"],
"geneFamily": "HKL",
"targetScientificName": "Setaria viridis",
"ppiTargetTreeTaxonId": "4556",
"ppiReferenceTaxonId": "4555",
"ppiReferenceStorageKey": "string_taxon_4555",
"ppiReferenceSelectionMode": "tree_nearest",
"ppiReferenceUserConfirmed": false,
"dependencyOwner": "ppi",
"requestedStages": ["ppi"]
}
```
未确认结果为 `confirmation_required / ppi_reference_confirmation_required`,provenance 为 `required=true, confirmed=false`。把唯一确认字段改为 `true` 后,HTTP 200 返回:
```text
status=needs_reference_data
issue_code=ppi_reference_data_missing
selected_taxon_id=4555
reference_species=string_taxon_4555
required_files=[pep]
missing_required=[pep]
```
没有 CDS 或 Ka/Ks 要求,确认后的 provenance 为 `required=true, confirmed=true`。
## 2. 真实 reference bundle 下载
请求:`POST /api/reference-bundle/download`
```json
{
"job_id": "job_1784552755238_b8762f",
"speciesCode": "string_taxon_4555",
"speciesName": "Setaria italica",
"taxonId": "4555",
"requestedStages": ["ppi"],
"includeRecommended": false,
"timeoutSec": 600,
"asyncMode": true
}
```
- Task ID:`d9cdbb88-1eb0-4109-947d-f6e14f7f5eb4`
- `/api/task/{id}`:`success`,progress 100
- Assembly:`GCF_000263155.2`
- 下载:9,242,771 bytes
- `requested_file_types=[pep]`
- PEP records:35,844;CDS records:0
- PEP:[string_taxon_4555.pep.fasta](../../input/job_1784552755238_b8762f/string_taxon_4555/string_taxon_4555.pep.fasta),SHA `2c037fe5e3e17e6afe9dd7134c7a5ed4a6eb5e12c54c1cc1b29978b2f90bd926`
- Manifest:`input/job_1784552755238_b8762f/string_taxon_4555/string_taxon_4555.reference_bundle_download.manifest.json`
## 3. 真实 PPI-owned Ortholog
第一次 direct request 错误地额外携带了普通 `referenceSpecies/refSpeciesList=[string_taxon_4555]`,入口按 config 物种校验并返回 HTTP 400,没有 task_id、队列或文件副作用。修正请求仅保留 owner 字段:
```json
{
"stage": "ortholog",
"job_id": "job_1784552755238_b8762f",
"prefix": "Sv.HKL",
"cpu": 4,
"blastEvalue": 0.00001,
"scopeFile": "workspace/job_1784552755238_b8762f/final/Sv.HKL.HKL.target-Sv.target_only.scope.json",
"scopeMode": "target_only",
"analysisRoute": "target_only",
"geneFamily": "HKL",
"targetSpecies": ["Sv"],
"ppiReferenceTaxonId": "4555",
"ppiReferenceStorageKey": "string_taxon_4555",
"ppiReferenceSelectionMode": "tree_nearest",
"ppiReferenceUserConfirmed": true,
"dependencyOwner": "ppi"
}
```
- Task ID:`0a20a621-ca10-47fe-a4c3-da1d334303d2`
- Queue:`plantai_4090_9010.medium`,CPU 4
- 结果:success,6 pairs
- Log:`workspace/job_1784552755238_b8762f/logs/20260721_082842_ortholog.log`
- Mapping:`workspace/job_1784552755238_b8762f/final/Sv.HKL.orthologs.txt`,SHA `cdce241cfa9217549ec3a940cd22bf69ca610e647d3b8f3cc204eef12a9aa677`
- Sidecar:`workspace/job_1784552755238_b8762f/final/Sv.HKL.orthologs.txt.identity.json`
- Manifest:`workspace/job_1784552755238_b8762f/final/Sv.HKL.ortholog.manifest.json`
- Manifest/sidecar 均记录 reference TaxID `4555`、storage key `string_taxon_4555`、PEP SHA、target/member/mapping identity 与 mapping path。
## 4. 阻断:post-Ortholog preflight
再次发送已确认的真实 preflight,HTTP 200 返回:
```text
status=needs_ortholog
decision=needs_reference_ortholog
issue_code=stale_ortholog_identity_conflict
message=Existing Ortholog mapping identity is stale or unverifiable:
ppi_owner_mapping_sidecar_identity_mismatch.
```
逐字段重算结果:
| 字段 | Expected | Actual | 结果 |
|---|---|---|---|
| reference TaxID | `4555` | `4555` | 相同 |
| storage key | `string_taxon_4555` | `string_taxon_4555` | 相同 |
| reference PEP SHA | `2c037f…bd926` | `2c037f…bd926` | 相同 |
| query path | `Target.Sv.HKL.curated_members.pep.fa` | 同左 | 相同 |
| query SHA | `5da2e0…bc3a1` | 同左 | 相同 |
| target identity | `c59de0…6f847` | 同左 | 相同 |
| mapping path/SHA | `Sv.HKL.orthologs.txt` / `cdce24…677` | 同左 | 相同 |
| member-set input | 空字符串 | 空字符串 | 相同 |
| scope ID | `…target_only` | `…target_plus_reference` | **不同** |
| member identity | `d29df1…d49e` | `6ba954…bb1f` | **不同** |
| mapping identity | `a8f853…b060` | `f288bd…0568` | **不同** |
复算 `target_plus_reference` scope 精确得到 sidecar actual 的两项 identity,证明根因是 scope 身份分叉。
调用路径:
- preflight:`_ppi_mapping_identity_matches_current_inputs` → 从传入的原 `target_only` scope 调 `build_scope_id` → `build_ortholog_run_identity`。
- producer:`run_stage(stage="ortholog")` 的 request context 把执行 scope 指向已有 `target_plus_reference` scope;PPI owner override 再替换 reference 为 `string_taxon_4555`,随后写 sidecar/manifest。
## 停止边界与安全
按“任一步失败立即报告”的要求,阻断后没有提交 PPI,没有运行 API species matrix,没有构造 Bn backend job。最终没有任何 PPI 文件,default/medium 队列均为 0,也没有删除任何用户结果。
9000 五个 worker PID 保持 `3588799, 3588807, 3588814, 3588821, 3588830`。本任务没有向 9000 或 19000 发送请求/信号。只读终检发现先前的 19000 PID `2483131` 已由外部机制替换为 `2526118`(启动时间 08:28:48);该进程仅被观察,未被本任务操作。
结构化证据见 [JSON](./2026-07-21-string-ppi-task7-live-e2e.json)。
## Attempt 2:scope 修复后的真实 9010 复验
9010 在受控重启后使用的新模块 SHA:
- `apps/web/vue3/main.py`: `72261549d622e70a90a43f8795e3c9cf0eccf499899c62233e1f7c25768fd3e1`
- `tasks.py`: `89b434ccd7e2a4c997efc87cbec954fbfd63857931752b2daa0549279f13fc08`
- `gfa_core/mas/tools/stage_tools.py`: `ffda6ec77256e8ef23c2635210f5624db550c2e657aaaf8b38b0c3b820d5f1a9`
- `apps/web/pipeline_backend.py`: `32b4391ec4d3fda87d78180b923bcb1c5d4066588980bbc61e73d5fe153b5d17`
- `gfa_core/ortholog_materialize.py`: `a0a70088f230eb0560355c7a68cb05a9b4933c72cc626c9ebef6427f46c97913`
### Attempt 2 请求
再次向真实 `POST /api/execute` 提交 owner-only Ortholog 请求:
```json
{
"stage": "ortholog",
"job_id": "job_1784552755238_b8762f",
"prefix": "Sv.HKL",
"cpu": 4,
"blastEvalue": 0.00001,
"scopeFile": "workspace/job_1784552755238_b8762f/final/Sv.HKL.HKL.target-Sv.target_only.scope.json",
"scopeMode": "target_only",
"analysisRoute": "target_only",
"geneFamily": "HKL",
"targetSpecies": ["Sv"],
"ppiReferenceTaxonId": "4555",
"ppiReferenceStorageKey": "string_taxon_4555",
"ppiReferenceSelectionMode": "tree_nearest",
"ppiReferenceUserConfirmed": true,
"dependencyOwner": "ppi"
}
```
请求没有发送 `forceRerun` 或 `forceRerunStages`,所以 API 模型/参数构造中的有效值为 `forceRerun=false`、`forceRerunStages=[]`。请求模型没有 `use_existing` 字段,本次也未发送任何 `use_existing` 参数。
- API task ID:`cb4515ba-117f-4749-9b72-a5a083ad04dd`
- Celery task ID:`66463b47-abe9-49f4-82a3-87263e11fad6`
- Queue:`plantai_4090_9010.medium`
- `/api/task/{id}`:`success`,6 pairs,Celery 用时 `0.5197922608349472s`
### Attempt 2 实际行为
worker 日志明确记录:
```text
09:00:12.554 WARN Effective member FASTA resolution failed for Target.string_taxon_4555.HKL
09:00:12.591 INFO Reusing identity-matched ortholog pairs for Sv -> string_taxon_4555:
workspace/job_1784552755238_b8762f/ortholog/Sv.HKL.Sv_to_string_taxon_4555_pairs.txt
09:00:12.596 Direct single-stage result: success, 6 pairs
09:00:12.672 Celery task succeeded in 0.5197922608349472s
```
API/Celery success 消息声称日志为 `workspace/job_1784552755238_b8762f/logs/20260721_090012_ortholog.log`,但该文件不存在。`/api/task` 返回的 `log` 字段实际仍是 attempt 1 的 `20260721_082842_ortholog.log` 内容。这与 worker 的 reuse 行一致:attempt 2 没有执行新的 `run_ortholog.py` 命令。
中间产物没有变化:
| 文件 | mtime | SHA256 |
|---|---|---|
| `ortholog/Sv.HKL.Sv_to_string_taxon_4555_pairs.txt` | `08:28:47.682668677` | `4c5e1c3b…d35f29` |
| `ortholog/Sv.HKL.Sv_to_string_taxon_4555_pairs.txt.identity.json` | `08:28:47.714255320` | `f97a7774…6201` |
final 物化产物在 attempt 2 被重写:
| 文件 | mtime | SHA256 |
|---|---|---|
| `final/Sv.HKL.orthologs.txt` | `09:00:12.591883154` | `cdce241c…a677` |
| `final/Sv.HKL.orthologs.txt.identity.json` | `09:00:12.592846398` | `f0a96652…14bca` |
| `final/Sv.HKL.ortholog.manifest.json` | `09:00:12.593582705` | `3236e7ed…8f60` |
| scoped Ortholog manifest | `09:00:12.594018966` | `dcccb1b7…1420` |
intermediate sidecar 的核心 identity 仍为:TaxID `4555`、storage key `string_taxon_4555`、target identity `c59de0…6f847`、member identity `6ba954…bb1f`、mapping identity `00c273…6a0a`。物化后的 final sidecar 保留相同 target/member identity,final mapping identity 为 `f288bd…0568`。
### Attempt 2 根因
新的 producer 修复位于 `pipeline_backend.py:9477-9506`:只有传入的 `ortholog_scope_data.scope_mode == "target_only"` 时,才设置 `preserve_target_only_scope=true`;随后 `build_ortholog_run_identity` 和 `ortholog_run_identity_matches` 决定是否复用中间结果。
但请求在到达该修复前已被 `/api/execute` 改写:
1. owner-only 请求只带 `ppiReferenceStorageKey=string_taxon_4555`,未带普通 `refSpecies/ppiReferenceSpecies/referenceBundleSpecies`。
2. `main.py:8898-8913` 构造 `technical_reference_species` 时不读取 `ppiReferenceStorageKey`,因此列表为空。
3. Ortholog 在 `main.py:8914-8937` 进入通用 target-reference fallback,恢复 job 默认参考 `At` 和 `target_plus_reference`。
4. `_ensure_gene_family_scope_file` 在 `main.py:9002-9013` 判定原 `target_only` scope 与新 expected scope 不同,生成 `Sv.HKL.HKL.target-Sv.ref-At.target_plus_reference.scope.json` 并替换请求中的 `scopeFile`。
5. Celery 经 `tasks.py::execute_single_stage_task` → `StageToolRegistry.execute` → `StageToolExecutor.execute` → `pipeline_backend.run_stage` 收到的是已经改写的 scope。
6. producer 看到 `source_scope_mode=target_plus_reference`,因此 `preserve_target_only_scope=false`;expected identity 与旧 intermediate sidecar 相同,`ortholog_run_identity_matches` 返回 true,并复用旧 pairs。
因此,attempt 2 证明当前修复点太晚:它能保留收到的 `target_only` scope,却无法纠正 API 入队前已经发生的 scope 改写。
### Attempt 2 停止点
post-Ortholog 真实 preflight 在 `09:00:54` 再次返回 `needs_ortholog / stale_ortholog_identity_conflict`。按失败即停规则,没有提交 PPI,也没有运行 species matrix 或独立 Bn job;本轮没有代码修改或结果删除。
## Attempt 3:target-only producer 修复后的真实主链
### Gate 与 9010 重启
真实 job scope:
- 绝对路径:`/home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev/workspace/job_1784552755238_b8762f/final/Sv.HKL.HKL.target-Sv.target_only.scope.json`
- SHA256:`31d8f69ef697c9c802cc929cd2383aca8e700a6c7fc52a57db408156384ed711`
- `scope_id=HKL.target-Sv.target_only`,`scope_mode=target_only`,target=`[Sv]`,reference=`[]`
重启前确认 9010 Web/worker 全部位于目标目录,使用 `BBAV5_QUEUE_PREFIX=plantai_4090_9010`、`BBAV5_REDIS_URL=redis://localhost:6379/11`,DB11 PONG。只停止旧 9010 Web PID `2544115` 和五个 worker master `2544081/2544089/2544096/2544103/2544116`。
重启后:
- Web:`2586056`
- default/heavy/medium/light/rnaseq:`2586051/2586052/2586053/2586054/2586055`
- 5/5 worker pong;`/docs` 与 `/openapi.json` 均 HTTP 200
- 9000 worker master `3588799/3588807/3588814/3588821/3588830` 与 19000 Web `2529914` 未变
- 当前 `apps/web/vue3/main.py` SHA:`90240498d608c8182afb10ad79e81a0213b20e428c3a20f69a7c63c9458266a4`
### 真实 preflight 与 Ortholog
confirmed owner preflight 使用原 target-only scope、TaxID `4555`、storage key `string_taxon_4555`,先返回预期的 `needs_ortholog / stale_ortholog_identity_conflict`。随后提交:
```json
{
"stage": "ortholog",
"job_id": "job_1784552755238_b8762f",
"prefix": "Sv.HKL",
"cpu": 4,
"blastEvalue": 0.00001,
"scopeFile": "/home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev/workspace/job_1784552755238_b8762f/final/Sv.HKL.HKL.target-Sv.target_only.scope.json",
"scopeMode": "target_only",
"analysisRoute": "target_only",
"geneFamily": "HKL",
"targetSpecies": ["Sv"],
"ppiReferenceTaxonId": "4555",
"ppiReferenceStorageKey": "string_taxon_4555",
"ppiReferenceSelectionMode": "tree_nearest",
"ppiReferenceUserConfirmed": true,
"dependencyOwner": "ppi"
}
```
- API task:`eaf45f36-d86e-4887-ae2d-d799d3ccaaef`
- Celery task:`6ad681e3-e7d5-49fd-b78c-0d8c999b3df6`
- 真实新命令已执行,Celery 用时 `5.773302449146286s`;没有 reuse 行
- 新日志:`logs/20260721_100750_ortholog.log`,SHA `902d3998e3c3098ff62b67817867d89dfb3aa7d690877dee292627118b4215f5`
- intermediate pair/sidecar mtime 均更新为 `10:07:56`;sidecar SHA `21d61a72…00fe6`
- final sidecar SHA `ffd3c39b…90358`
- scoped manifest:`Sv.HKL.HKL.target-Sv.target_only.ortholog.manifest.json`,SHA `95e74562…1ce07`
- manifest/sidecar 均记录 TaxID `4555`、storage key `string_taxon_4555`、PEP SHA `2c037f…bd926`、target identity `c59de0…6f847`、member identity `dc9fbb…094a`
- manifest `scope_id=HKL.target-Sv.target_only`、`scope_mode=target_only`、`analysis_route=target_only`,scopeFile 保持原绝对路径
post-Ortholog preflight 返回 HTTP 200:`status=ready`、`decision=ready_reference_mapping`、issue code 为空,provenance `required=true, confirmed=true`。
### 真实 PPI 请求与失败
在 ready gate 后提交的完整请求:
```json
{
"stage": "ppi",
"job_id": "job_1784552755238_b8762f",
"prefix": "Sv.HKL",
"cpu": 4,
"scopeFile": "/home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev/workspace/job_1784552755238_b8762f/final/Sv.HKL.HKL.target-Sv.target_only.scope.json",
"scopeMode": "target_only",
"analysisRoute": "target_only",
"geneFamily": "HKL",
"targetSpecies": ["Sv"],
"ppiSpecies": "auto",
"ppiScore": 200,
"ppiReferenceTaxonId": "4555",
"ppiReferenceStorageKey": "string_taxon_4555",
"ppiReferenceSelectionMode": "tree_nearest",
"ppiReferenceUserConfirmed": true,
"dependencyOwner": "ppi"
}
```
- API task:`1f2a89c4-5042-4b93-a50f-923cd8925bfa`
- Celery task:`a25e255e-6d14-4c8f-98ac-151b90aa682c`
- Queue:`plantai_4090_9010.light`,CPU 4
- Celery task wrapper 用时 `11.837375451112166s`,业务结果为 failed
- 错误:`PPI 无法从 Ortholog 映射推断 STRING 参考物种`
- issue code:`ppi_invalid_ortholog_mapping`
Celery 的原始 kwargs 未写入 task 状态或 worker 日志,不能事后逐字恢复;可验证的有效参数链为:`main.py` 将请求的 `ppiSpecies/ppiReferenceTaxonId/StorageKey/SelectionMode/UserConfirmed` 放入 params,`StageToolExecutor` 将同名字段传入 `run_stage`。失败 provenance 保留 `selection_mode=tree_nearest`、`confirmed=true`、mapping reference=`string_taxon_4555` 和 mapping path,证明 owner 状态已到达执行层。
PPI 在调用 `skills/ppi/run.py` 之前失败,所以:
- 没有新的 PPI stage log
- worker 没有 `[CMD] ... skills/ppi/run.py`
- 没有 network/report/url/id-resolution 等 PPI 成功 artifacts
- 仅生成中间 source ID 文件 `ppi/analysis/Sv.HKL.HKL.target-Sv.target_only.ppi_source_ids.txt`,6 IDs,SHA `1e0cc6…df2ef`
- failed manifest:`final/Sv.HKL.ppi.manifest.json`,SHA `ce6e65ec…f885a`,`artifacts={}`
- 精确 scope 的 `/api/stage-status` 为 `not_found/completed=false`,因为 scoped PPI manifest 未生成
failed manifest resolution 为:`ppiSpecies=auto`、selected taxon/reference 为空、fallback=`invalid_mapping`、reason=`ortholog_mapping_target_species_not_supported_by_string`。失败 provenance 的 selected taxon 也为空,但仍保留确认信息与 `string_taxon_4555` mapping。
### Attempt 3 根因判定
这不是验证请求遗漏字段,也不是 API→Celery 传输丢字段。当前前端真实请求构造同样保持 `ppiSpecies=auto`:`executeStageDirect` 从 stage/confirm 取值,否则为 `auto`;`applyPpiOwnerFieldsToRequest` 只追加 owner TaxID/storage/mode/confirmed,不把 `ppiSpecies` 改成 selected TaxID。因此本次请求与真实前端路径一致。
执行层的分叉为:
1. `run_stage` 对 `ppiSpecies=auto` 将 execution species 初始化为空。
2. target-only scope 的 reference list 为空,所以不能从 scope 得到 execution species。
3. 读取 mapping 第五列得到 `string_taxon_4555`,但 `infer_string_species_from_ortholog_mapping` 仅调用 legacy `species_to_string_code`;storage key 不在该别名表中,因此返回空。
4. `run_stage` 虽已收到 `ppiReferenceTaxonId=4555` 与 storage key,却没有在该解析分支用 owner TaxID 作为 STRING execution identity,于 CLI 前失败。
5. 失败 provenance 的 selected taxon 为空是次生记录问题:`fail_ppi_execution` 仅从空的 `ppi_species` 计算 TaxID,也没有使用 `ppi_reference_taxon_id`。
按失败即停规则,没有重试、没有改请求、没有修改代码、没有运行物种矩阵或 Bn job。终检五个 9010 队列均为 0;9000/19000 PID 保持不变。
## Attempt 4:复用 ready Ortholog 后的单次真实 PPI 重试
### Gate、重启与请求
本轮没有重跑 Ortholog。重启前、重启后分别用真实 `/api/ppi/species-resolution` 确认已有映射为 `ready / ready_reference_mapping`:TaxID `4555`、storage key `string_taxon_4555`,provenance confirmation 为 `required=true, confirmed=true`。复用的 final mapping 为 `final/Sv.HKL.orthologs.txt`,SHA256 `cdce241c…a677`;final sidecar SHA256 `ffd3c39b…90358`;scoped Ortholog manifest SHA256 `95e74562…1ce07`。
只重启了 9010:Web PID `2595459`,default/heavy/medium/light/rnaseq worker master 为 `2595454/2595455/2595456/2595457/2595458`,5/5 pong,`/docs` 与 `/openapi.json` 均 HTTP 200。9000 worker master `3588799/3588807/3588814/3588821/3588830` 和 19000 Web PID `2529914` 未变化。
生效代码 SHA256:
| 文件 | SHA256 |
|---|---|
| `apps/web/vue3/main.py` | `90240498d608c8182afb10ad79e81a0213b20e428c3a20f69a7c63c9458266a4` |
| `tasks.py` | `89b434ccd7e2a4c997efc87cbec954fbfd63857931752b2daa0549279f13fc08` |
| `gfa_core/mas/tools/stage_tools.py` | `ffda6ec77256e8ef23c2635210f5624db550c2e657aaaf8b38b0c3b820d5f1a9` |
| `apps/web/pipeline_backend.py` | `57b35484a89cb096211ac18032a34ad220a33dbc5bc98a455724713ce3303d05` |
| `gfa_core/ortholog_materialize.py` | `a0a70088f230eb0560355c7a68cb05a9b4933c72cc626c9ebef6427f46c97913` |
| `gfa_core/ppi_provenance.py` | `b4d947d5…c3031` |
| `gfa_core/mas/tools/stage_status.py` | `a3fc7012…d473` |
| `skills/ppi/run.py` | `8518de8c…36afe` |
提交的完整 PPI 请求与 attempt 3 相同:
```json
{
"stage": "ppi",
"job_id": "job_1784552755238_b8762f",
"prefix": "Sv.HKL",
"cpu": 4,
"scopeFile": "/home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev/workspace/job_1784552755238_b8762f/final/Sv.HKL.HKL.target-Sv.target_only.scope.json",
"scopeMode": "target_only",
"analysisRoute": "target_only",
"geneFamily": "HKL",
"targetSpecies": ["Sv"],
"ppiSpecies": "auto",
"ppiScore": 200,
"ppiReferenceTaxonId": "4555",
"ppiReferenceStorageKey": "string_taxon_4555",
"ppiReferenceSelectionMode": "tree_nearest",
"ppiReferenceUserConfirmed": true,
"dependencyOwner": "ppi"
}
```
- API task ID:`fd77c17d-0387-477c-a294-747f41277529`
- Celery task ID:`f401575e-43ac-43dd-84ac-26d1b20a392e`
- Queue:`plantai_4090_9010.light`,CPU 4
- wrapper 用时:`29.942377381026745s`
- 业务状态:`failed`
### 完整执行身份与失败证据
本轮通过了 attempt 3 的 execution-species 阻塞,真实 CLI 已执行:
```text
/home/xzq/miniconda3/envs/test4py311/bin/python skills/ppi/run.py --gene-ids /home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev/workspace/job_1784552755238_b8762f/ppi/analysis/Sv.HKL.HKL.target-Sv.target_only.ppi_source_ids.txt --species 4555 --normalization-species-label 4555 --prefix Sv.HKL --output /home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev/workspace/job_1784552755238_b8762f/ppi --score 200 --provenance-json /home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev/workspace/job_1784552755238_b8762f/ppi/Sv.HKL.ppi_provenance.json --mapping /home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev/workspace/job_1784552755238_b8762f/final/Sv.HKL.orthologs.txt --id-map /home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev/input/job_1784552755238_b8762f/string_taxon_4555/string_taxon_4555.pep_cds_idmap.tsv
```
ID map 的 header 与首个证据行是:
```text
species_code protein_id pep_id cds_id gene_id ncbi_gene_id pep_present cds_present pep_header cds_header
string_taxon_4555 NP_001267731.1 NP_001267731.1 ...
```
skill 在载入 6 个 source IDs 和 6 条 Ortholog mapping 后停止,精确错误为:
```text
Alias evidence species mismatch at row 2: declared '4555', observed 'string_taxon_4555'
```
因此 attempt 4 的单一直接阻塞点是两个不同层级的身份被当成同一个字段:
- STRING 远程查询 execution identity:TaxID `4555`,`--species 4555` 正确;
- 本地 reference bundle / ID-map normalization identity:storage key `string_taxon_4555`;
- 实际错误参数:`--normalization-species-label 4555`,与 ID map 的 `species_code=string_taxon_4555` 冲突。
也就是说,Ortholog mapping、owner TaxID、STRING 查询物种和确认 provenance 都已正确到达执行层;本次失败只由 normalization label 未使用 storage identity 触发。
### Manifest、provenance 与停止点
| 文件 | SHA256 | 结果 |
|---|---|---|
| `logs/20260721_102510_ppi.log` | `07f7cb3a…d650` | 完整 CLI 与 mismatch 错误 |
| `final/Sv.HKL.ppi.manifest.json` | `987b929b…886f` | failed,`artifacts={}` |
| `ppi/Sv.HKL.manifest.json` | `71250422…6463e` | failed,精确 mismatch message |
| `ppi/Sv.HKL.ppi_provenance.json` | `94875cbf…4242` | selected TaxID `4555`、mapping reference `string_taxon_4555`、normalization label `4555` |
| scoped source IDs | `1e0cc6e5…df2ef` | 6 IDs |
`final/Sv.HKL.ppi.manifest.json` 是 stale/merge 的 legacy failed manifest:顶层 error 已更新为 attempt 4 的 exit-code/log,但 timestamp 和 `parameters.ppi_species_resolution` 仍保留 attempt 3 的 `10:09:28 / invalid_mapping`;其 provenance 则已更新为 selected TaxID `4555` 和 normalization label `4555`。因此不能把旧 resolution 块当作本轮根因。
精确 scoped `/api/stage-status` 返回 `not_found/completed=false`,期望 manifest 为 `final/Sv.HKL.HKL.target-Sv.target_only.ppi.manifest.json`;legacy task stage status 为 `failed/completed=false`、`artifacts_checked=0`。没有生成 network/report/url/id-resolution 等成功产物。
按失败即停规则,本轮没有 PPI 重试、没有 Ortholog 重跑、没有物种矩阵、没有独立 Bn job、没有代码修改或文件删除。终检五个 9010 队列均为 0,9000/19000 进程保持不变。
## Attempt 5:normalization identity 修复后的真实 PPI 成功
### Gate 与 9010 重启
本轮仍只执行 PPI,没有重跑 Ortholog。重启前和重启后两次真实 `/api/ppi/species-resolution` 均返回:
```text
status=ready
decision=ready_reference_mapping
selected_taxon_id=4555
reference_species=string_taxon_4555
mapping_reference_species=string_taxon_4555
confirmation required=true, confirmed=true
```
既有 Ortholog 身份未变化:mapping SHA256 `cdce241c…a677`,final sidecar `ffd3c39b…90358`,target-only scoped Ortholog manifest `95e74562…1ce07`。生效代码 SHA256 为:
| 文件 | SHA256 |
|---|---|
| `apps/web/vue3/main.py` | `90240498d608c8182afb10ad79e81a0213b20e428c3a20f69a7c63c9458266a4` |
| `tasks.py` | `89b434ccd7e2a4c997efc87cbec954fbfd63857931752b2daa0549279f13fc08` |
| `gfa_core/mas/tools/stage_tools.py` | `ffda6ec77256e8ef23c2635210f5624db550c2e657aaaf8b38b0c3b820d5f1a9` |
| `apps/web/pipeline_backend.py` | `9834917f36c9b400b22b7a8a50b7e047a57a3cf3e01ee83184f5e3b5aa9a629a` |
| `gfa_core/ortholog_materialize.py` | `a0a70088f230eb0560355c7a68cb05a9b4933c72cc626c9ebef6427f46c97913` |
| `gfa_core/ppi_provenance.py` | `b4d947d5ffa05db776039ffdec0c6f713e247a706994673dff1d92e4733c3031` |
| `gfa_core/mas/tools/stage_status.py` | `a3fc701271bbfca599324eeac721f027dd67752a1e640977b9ffef76cb21d473` |
| `skills/ppi/run.py` | `2f592370b3c0c97d8f5e0500f348099fb85e581ad29219e2143b629011327a12` |
仅重启 9010:Web PID `2608735`,default/heavy/medium/light/rnaseq worker master 为 `2608731/2608635/2608732/2608607/2608636`;5/5 pong,`/docs` 与 `/openapi.json` HTTP 200。9000 worker master `3588799/3588807/3588814/3588821/3588830` 与 19000 Web PID `2529914` 未变化。
### 唯一真实 PPI 请求
```json
{
"stage": "ppi",
"job_id": "job_1784552755238_b8762f",
"prefix": "Sv.HKL",
"cpu": 4,
"scopeFile": "/home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev/workspace/job_1784552755238_b8762f/final/Sv.HKL.HKL.target-Sv.target_only.scope.json",
"scopeMode": "target_only",
"analysisRoute": "target_only",
"geneFamily": "HKL",
"targetSpecies": ["Sv"],
"ppiSpecies": "auto",
"ppiScore": 200,
"ppiReferenceTaxonId": "4555",
"ppiReferenceStorageKey": "string_taxon_4555",
"ppiReferenceSelectionMode": "tree_nearest",
"ppiReferenceUserConfirmed": true,
"dependencyOwner": "ppi"
}
```
- API task ID:`72ddcc69-fa90-4514-bd78-3a931e8054c9`
- Celery task ID:`44f60fe5-ffcc-4def-b9fd-48d531a085a2`
- Queue:`plantai_4090_9010.light`,CPU 4
- Celery wrapper:`32.72843774687499s`
- 最终业务状态:`success`
真实 CLI 中两个身份已正确分离:
```text
... skills/ppi/run.py ... --species 4555 --normalization-species-label string_taxon_4555 ...
```
其中 `4555` 仅用于 STRING 远程查询,`string_taxon_4555` 用于本地 reference bundle / ID-map 归一化校验。attempt 4 的 alias-evidence mismatch 不再出现。
### STRING 真实请求与生物结果
stage log `logs/20260721_104344_ppi.log`(SHA256 `eb3cfcb8…dc5f`)记录:载入 6 个目标 ID、6 条 Ortholog mapping;向 STRING TaxID `4555` 查询 6 个已解析 ID:
```text
4555.K3Z5J1, 4555.K3Z625, 4555.K3ZDE9,
4555.A0A368R4B9, 4555.K3XGZ3, 4555.K3XGV8
```
真实 STRING URL 明确包含 `species=4555&required_score=200&network_type=functional`。结果:6/6 genes、15 interactions,平均 score `0.904`,15 条均为 high-confidence;ID resolution 的 member/query mapping rate 均为 `1.0`,0 unresolved、0 ambiguous。STRING network image API 另生成有效 PNG,`3253 × 793`、RGBA、161,819 bytes。
### Manifest、artifacts 与 scoped status
target-only scoped success manifest:`final/Sv.HKL.HKL.target-Sv.target_only.ppi.manifest.json`,SHA256 `118ddf51…0359`。其 `scope_id=HKL.target-Sv.target_only`、`scope_mode=target_only`、`analysis_route=target_only`、`member_set_id=HKL.target-Sv.target_only:target_only:all_members`。
| Artifact | SHA256 | 大小 |
|---|---|---:|
| `final/Sv.HKL.ppi_network.tsv` | `9fe9e10c…c52a` | 492 |
| `final/Sv.HKL.ppi_report.md` | `866e63d6…d60f` | 717 |
| `final/Sv.HKL.ppi_id_resolution.tsv` | `488f0a2a…5399` | 1,845 |
| `final/Sv.HKL.ppi_url.txt` | `3c26395f…dbdf` | 304 |
| `final/Sv.HKL.ppi_network.string.png` | `fe7891cf…b862` | 161,819 |
| `final/Sv.HKL.ppi_alphafold2_links.tsv` | `dde7bdba…1598` | 1,748 |
精确 scoped `/api/stage-status` 返回 `status=completed, completed=true, manifest_status=success, artifacts_checked=6`,missing artifacts 与 errors 均为空。provenance 一致记录:selected STRING TaxID `4555`、mapping reference `string_taxon_4555`、normalization label `string_taxon_4555`、selection mode `tree_nearest`、user confirmation `required=true, confirmed=true`,STRING snapshot ID 仍为 `ede47d…eeb3`。
本轮没有 Ortholog 重跑、PPI 重试、物种矩阵、独立 Bn job、代码修改或文件删除。终检五个 9010 队列均为 0;9000/19000 进程保持不变。
## Final read-only matrix:当前 9010 + 已部署 snapshot
验证方式:仅调用既有 job `job_1784552755238_b8762f` 的 `POST /api/ppi/species-resolution`,并读取 attempt 5、Task 4 的既有证据。没有调用 `/api/execute`、没有新建 job、没有触发 PPI/Ortholog/KaKs、没有重启或修改代码。所有预检请求 HTTP 均为 `200`。
| # | 场景 | 关键请求 | 关键响应/证据 | 等级 | 结果 |
|---:|---|---|---|---|---|
| 1 | Os direct,无 Ortholog | `Os / Oryza sativa Japonica Group / TaxID 39947 / requestedStages=[ppi]` | `ready / ready_target_string / exact_string / selected=39947 / candidates=[]`。未传 scope/mapping。父种 TaxID `4530` 另返回 Oryza Top3,未被错误当作 exact。 | real API | PASS |
| 2 | Sv tree-nearest Top3 与确认 | `Sv / Setaria viridis / 4556`;确认时 owner=`4555,string_taxon_4555,tree_nearest,true` | 未确认:`confirmation_required`,Top3 `4555(d2),4540(d6),888268(d6)`;确认:`ready_reference_mapping`,mapping=`final/Sv.HKL.orthologs.txt`,provenance confirmed=true。 | real API + real job | PASS |
| 3 | Ft 动态近源 | `Ft / Fagopyrum tataricum / 62330` | Top3 `3562(d10),3476(d12),3775(d12)`;`candidate_source=string_species_tree`、`resolution_source=explicit_tree_taxon_id`、policy=`string_species_tree_v12_topology_v1`。响应没有静态 Ft 标记。 | real API | PASS |
| 4 | 旧 map 外、registry 内 | `Bn / Brassica napus / 3708` | 当前 API:`ready_target_string / exact_string / selected=3708`。真实 STRING 证据:`docs/validation/2026-07-21-string-ppi-task4-real-network.{md,json}`,TaxID 3708 alias/network 均成功。 | real API + prior real STRING | PASS |
| 5 | 第二 unsupported 植物稳定 Top3 | `Cs / Camellia sinensis / 4442`,相同请求两次 | 两次均为 `542762(d1),1590841(d7),4155(d9)`,`candidate_source=string_species_tree`;非 Ft。 | real API ×2 | PASS |
| 6 | unknown 补身份,不猜 At | 第一次 `Xx` 无 scientific name/TaxID;第二次补 `Camellia sinensis / 4442` | 第一次 `unresolved / target_string_tree_unresolved`、空 candidates/reference;补身份后返回 Camellia Top3,第一候选 `542762`,不是 At。 | real API | PASS |
| 7 | 自然 At fallback 的确认门 | `Aa / Arabidopsis arenosa / 38785`,候选 Top1 `3702 At`;owner storage=`At`、mode=`model_fallback` | 未确认:`confirmation_required`;确认:`needs_ortholog`(未执行),selected=`3702`、reference=`At`、PEP complete;provenance required=true/confirmed=true,species_resolution.reference_selection_mode=`model_fallback`。 | real API | PASS |
| 8 | nearest 主链成功 | 读取 attempt 5 | scoped manifest SHA `118ddf51…0359` 与当前文件一致;network SHA `9fe9e10c…c52a`;6/6 genes、15 interactions、mapping rate 1.0;TaxID 4555、storage normalization `string_taxon_4555`。 | prior real job + current file verification | VERIFIED |
| 9 | PPI 与 KaKs/CDS 独立 | PPI-only 使用已确认 Sv owner;KaKs-only 使用同一 storage/reference | PPI-only 保持 `ready_reference_mapping`;KaKs-only 返回 `needs_reference_data / kaks_reference_cds_missing`,bundle=`pep_only`、missing=`[cds]`、`kaks_ready=false`。没有触发任何 stage。 | real API | PASS |
### 请求/响应身份摘要
- API:`http://127.0.0.1:9010/api/ppi/species-resolution`
- Snapshot:STRING `12.0`,ID `ede47d546d853d0ec30ee75066976a35c08fd2412e6e5fc7866bbd205fc2eeb3`
- 所有 tree-nearest 候选均携带 LCA、两侧 edge 数和 `tree_distance`。
- Item 7 特意使用 snapshot 中 At 自然为 Top1 的 `Arabidopsis arenosa`;对 Ft 强塞 At 的试探被 API 继续阻断为 `confirmation_required`,没有把非候选伪装成 fallback。
- Item 9 的 PPI 与 KaKs 是两个独立预检请求;KaKs 缺 CDS 没有覆盖或中断 PPI 的 ready 状态。
- 终检五个 `plantai_4090_9010.*` Redis 队列长度均为 `0`。
结构化字段已追加到同名 JSON 的 `final_read_only_matrix`。