fix: complete PPI and KaKs reference handoff

This commit is contained in:
potaser
2026-08-10 23:13:05 +08:00
parent 39a2c969de
commit 7b7e334213
37 changed files with 4770 additions and 561 deletions
@@ -0,0 +1,308 @@
# PPI First, KaKs Reference Choice Implementation Plan
> **Working repository:** `~/remote-projects/5090/teamWorkspace/sj-2/PlantAI-dev`
>
> **Goal:** In the normal full gene-family workflow, show PPI and KaKs but not their internal Ortholog producers. Run PPI first. After PPI reaches a real terminal outcome, open the normal KaKs confirmation dialog and let the user choose either the PPI technical reference or the configured project reference. Keep the two mappings and manifests isolated.
## Task determination
This is a temporary execution-closure task, not the long-term KaKs reference-quality project.
The user-visible workflow is:
```text
normal gene-family plan
-> PPI (direct STRING or hidden PPI-owned Ortholog)
-> KaKs reference confirmation
-> PPI technical reference
-> configured project reference (for the current Ft case: At)
-> hidden KaKs-owned Ortholog only when an exact reusable mapping is absent
-> KaKs
```
The current failure has three connected causes:
1. The deterministic full-workflow normalizer adds `ortholog` to the visible plan, while KaKs also has a hard `ortholog` dependency.
2. The frontend inserts one visible Ortholog stage and lets PPI and KaKs compete for that stage's owner/reference state.
3. All Ortholog producers materialize the same `final/<prefix>.orthologs.txt` and `<prefix>.ortholog.manifest.json`; PPI-near-reference and KaKs-At runs can overwrite each other.
Fixing only the plan list, only the popup order, or only the mapping filename is insufficient. These three seams must change together.
## First-principles invariants
1. PPI chooses a STRING route for PPI; KaKs chooses a comparative reference for KaKs. One choice must not silently mutate the other.
2. Ortholog remains a supported explicit analysis stage, but is an internal producer when required by PPI or KaKs.
3. KaKs waits for PPI sequencing without declaring a hard PPI dependency. PPI failure, explicit skip, or unavailable PPI reference must still release the KaKs dialog.
4. A PPI-owned mapping and a KaKs-owned mapping may coexist for one prefix and different references.
5. A mapping is reusable only when target/member FASTA identity, reference identity, reference PEP checksum, scope identity, and mapping checksum match.
6. PPI remains PEP-only. Missing KaKs CDS must never prevent PPI submission or completion.
7. The configured reference remains unchanged for unrelated stages. A KaKs selection is written only to KaKs-owned parameters/state.
## Scope and assumptions
### In scope
- The normal/default full gene-family plan no longer contains implicit `ortholog`.
- The normal plan orders PPI before KaKs.
- KaKs has no visible/static hard dependency on Ortholog or PPI; runtime orchestration supplies its internal mapping.
- The existing KaKs stage confirmation dialog gains two reference-source choices.
- PPI-owned and KaKs-owned Ortholog outputs use separate namespaces.
- Same-reference exact mapping reuse is supported.
- PPI completion/failure/explicit skip releases KaKs; a reference download still running does not.
- PPI/KaKs failures remain isolated from unrelated stages.
### Preserved behavior
- An explicit user request for “直系同源基因鉴定/Ortholog” still produces and displays the standalone Ortholog stage and canonical standalone outputs.
- Direct-target STRING PPI remains direct and does not create Ortholog.
- Existing PPI STRING species selection, ID normalization, PPI CLI, KaKs CLI, and scientific algorithms remain unchanged.
- Methodology execution, subfamily workflow, main-Agent handoff, intent Agent, PlanningAgentV2 implementation, and analysis YAML are not redesigned.
### Deferred
- The generic high-quality KaKs reference selector using taxonomy, assembly quality, BUSCO, annotation completeness, and PEP/CDS quality.
- Automatic ranking of multiple non-PPI KaKs candidate species.
- Generic scheduler refactoring or frontend component extraction.
## Reference-choice rules
The KaKs dialog appears only after the PPI stage has settled for this batch.
| PPI outcome | PPI-reference option | Config-reference option | KaKs behavior |
|---|---|---|---|
| PPI direct-target STRING | Hidden; there is no separate comparative PPI reference | Show configured reference | Continue with config choice |
| PPI reference selected and PEP/CDS/mapping exact | Enabled | Show configured reference | Reuse PPI mapping if selected |
| PPI reference selected, CDS missing | Enabled with “需补齐 CDS” | Show configured reference | If selected, download/complete only the KaKs bundle, then continue |
| PPI reference selected, mapping missing/stale | Enabled if PEP/CDS can be prepared | Show configured reference | Run hidden KaKs-owned Ortholog |
| PPI failed or was skipped | Show only if a separate PPI reference and usable files exist | Show configured reference | PPI outcome does not block confirmation |
| Neither choice has PEP+CDS | Disabled with exact missing-file reasons | Disabled with exact missing-file reasons | Pause only KaKs |
The reference choice is explicit. No silent fallback from one option to the other.
## Task 1 — Freeze the visible planning contract
**Files:**
- Modify: `apps/web/vue3/main.py`
- Modify: `gfa_core/mas/stage_catalog.py`
- Modify: `apps/web/vue3/index.html`
- Modify: `tests/unit/test_task_status_attachment.py`
- Modify: `tests/unit/test_subfamily_prediction_plan.py` or add one focused full-workflow plan test
- Modify: `tests/unit/test_ppi_frontend_display_contract.py`
### Steps
1. Add failing tests for the normal “执行基因家族分析” response:
- `ortholog` is absent from `plan.stages` and `stages_detail`;
- `ppi` and `kaks` are present;
- `ppi` appears before `kaks`;
- standalone explicit Ortholog remains supported.
2. Remove implicit Ortholog from `_downstream_gene_family_stages_for_context()` and `FULL_GENE_FAMILY_WORKFLOW_STAGES`.
3. Change the normal static KaKs dependency from `identify + ortholog` to `identify` in the normal planning catalog, plan-detail builder, and frontend dependency table.
4. Keep the standalone Ortholog catalog entry and explicit Ortholog intent unchanged.
5. Do not filter Ortholog out in the rendered frontend. The backend plan itself must be correct.
### Acceptance gate
- A normal full plan displays PPI and KaKs, never implicit Ortholog.
- An explicit Ortholog request still displays Ortholog.
- No frontend-only post-processing is used to disguise a wrong backend plan.
## Task 2 — Give internal mappings owner-specific identities
**Files:**
- Modify: `gfa_core/ortholog_materialize.py`
- Modify: `apps/web/pipeline_backend.py`
- Modify: `apps/web/vue3/main.py` only for the narrow execution-request fields needed to carry mapping ownership
- Modify: `tests/unit/test_ppi_ortholog_owner_identity_task5b.py`
- Modify: `tests/unit/test_pipeline_backend_execution_env.py`
### Output contract
Use one path helper rather than repeating filename construction:
```text
standalone: final/<prefix>.orthologs.txt
PPI owner: final/<prefix>.ppi.orthologs.txt
KaKs owner: final/<prefix>.kaks.orthologs.txt
```
Apply the same owner namespace to pairs, raw pairs, BLAST output, sidecar, and Ortholog manifest. Keep `manifest.stage = "ortholog"`; record `dependency_owner` and the effective mapping identity in parameters/provenance.
### Steps
1. Add failing coexistence tests that materialize PPI-owned Spinacia and KaKs-owned At mappings for the same prefix and assert both remain unchanged.
2. Extend `materialize_ortholog_final_outputs()` with a narrow owner/output namespace. Empty owner preserves every current standalone filename.
3. In `run_stage("ortholog")`, accept only `""`, `"ppi"`, or `"kaks"` as mapping owner and pass it to materialization.
4. Centralize owner-aware candidate paths for preflight and execution. Do not let PPI or KaKs fall through to a different owner's mapping merely because that file exists.
5. Add a narrow KaKs mapping-source owner field to `ExecuteRequest` and backend forwarding. Prefer an owner token over a client-supplied arbitrary filesystem path.
6. Validate reuse against the existing Ortholog identity sidecar:
- selected reference storage/species identity;
- target/query FASTA identity;
- member identity;
- reference PEP checksum;
- scope identity;
- mapping checksum.
7. Preserve canonical filenames and resolution for explicit standalone Ortholog.
### Acceptance gate
- PPI Spinacia and KaKs At mappings coexist.
- Rerunning one owner does not change the other owner's file or Manifest checksum.
- A stale/wrong-reference mapping is rejected rather than silently reused.
- Existing standalone Ortholog tests still pass.
## Task 3 — Sequence KaKs after PPI without a hard dependency
**Files:**
- Modify: `apps/web/vue3/index.html`
- Modify: `tests/unit/test_ppi_owner_scheduling_task5.py`
- Modify: `tests/unit/test_ppi_frontend_display_contract.py`
### Steps
1. Add scheduler tests for a batch containing both PPI and KaKs:
- KaKs is not submitted while PPI is pending, running, or paused for an active reference download;
- PPI completed releases KaKs;
- PPI failed releases KaKs;
- PPI explicitly skipped releases KaKs;
- unrelated stages continue while PPI waits.
2. Add one narrow soft sequencing state to the existing batch state. Do not encode PPI as a KaKs dependency in `stageDependencies`.
3. Release the gate only on a real PPI terminal outcome. Generic `paused` is not sufficient because an active background reference download is resumable.
4. Remove the path that inserts/replaces a visible `ortholog` item in `batchExecuteStages` for PPI/KaKs ownership.
5. Reuse the existing direct internal producer submission helper, but track its result under the owner stage rather than `stageExecutionStatus.ortholog`.
6. Ensure PPI internal-producer failure pauses/fails only PPI and still releases KaKs confirmation when terminal.
### Acceptance gate
- There is no Ortholog row or Ortholog confirmation popup in the normal batch.
- KaKs confirmation cannot race ahead of PPI.
- PPI failure cannot cause KaKs to be dependency-failed.
- Other unrelated stages are not serialized behind PPI.
## Task 4 — Add the KaKs reference choice to the existing dialog
**Files:**
- Modify: `apps/web/vue3/index.html`
- Modify: `apps/web/vue3/main.py` only if a read-only candidate-readiness payload is needed
- Modify: `apps/web/pipeline_backend.py` only to return owner-aware readiness/identity data
- Modify: `tests/unit/test_ppi_frontend_display_contract.py`
- Modify: `tests/unit/test_ppi_snapshot_preflight_task3.py`
### Steps
1. Reuse the existing stage-confirmation dialog and its PPI reference card styles. Do not create a second visual system or a synthetic visible stage.
2. When opening the KaKs confirmation dialog, build two candidates:
- `ppi_reference`: the separate PPI technical reference, only when one exists;
- `project_reference`: the configured reference from the confirmed project scope.
3. For each candidate, show species label/code, source, PEP status, CDS status, mapping status, and the reason when unavailable.
4. Store the confirmed choice only in KaKs stage params, for example `kaksReferenceSource`, `referenceSpecies/refSpeciesList`, and `orthologMappingOwner`. Do not update PPI owner fields or unrelated plan-level reference fields.
5. If the PPI candidate lacks CDS, use the existing reference-bundle endpoint with `requestedStages=["kaks"]` to complete that selected species. PPI remains completed and is never reopened or downgraded.
6. If the selected reference lacks an exact mapping:
- submit a hidden `dependencyOwner="kaks"` Ortholog producer;
- on success, submit KaKs with `orthologMappingOwner="kaks"`;
- if the exact PPI-owned mapping is reusable, submit KaKs with `orthologMappingOwner="ppi"` and do not recompute.
7. If neither candidate can be made ready, pause only KaKs and retain a retryable, explicit reason.
### Acceptance gate
- For the Ft case, the dialog can show the PPI near-reference and configured At as separate choices.
- Selecting At cannot change PPI's reference TaxID, mapping, Manifest, or artifacts.
- Selecting the PPI reference cannot change config/project reference for other stages.
- A missing CDS or mapping produces a KaKs-only action/pause.
## Task 5 — Synchronize the minimum contracts
**Files:**
- Modify: `gfa_core/schemas/stages/ppi_contract_v1.md`
- Modify: `gfa_core/schemas/stages/kaks_contract_v1.md`
- Modify: `gfa_core/schemas/stages/ortholog_contract_v1.md`
### Steps
1. Document PPI-owned and KaKs-owned internal Ortholog identities and standalone Ortholog preservation.
2. Document that PPI and KaKs readiness/reference state are independent.
3. Document the KaKs reference-source choice and exact mapping-reuse rule.
4. Document soft sequencing: PPI terminal outcome releases KaKs, but PPI success is not a KaKs prerequisite.
Do not change CLI inputs or the scientific method contracts beyond these execution/provenance facts.
## Task 6 — Verification without polluting the user's real case
### Automated tests
Run the focused tests first:
```bash
/home/xia-lab/miniconda3/envs/test4py311/bin/python -m pytest -q \
tests/unit/test_task_status_attachment.py \
tests/unit/test_ppi_frontend_display_contract.py \
tests/unit/test_ppi_owner_scheduling_task5.py \
tests/unit/test_ppi_ortholog_owner_identity_task5b.py \
tests/unit/test_ppi_snapshot_preflight_task3.py \
tests/unit/test_pipeline_backend_execution_env.py -k 'ppi or kaks or ortholog or full_workflow'
```
Then run the related gene-family planning/API suite discovered from failures. Do not broaden to unrelated WGS/RNA-seq work unless a shared contract test fails.
### Isolated real-data matrix
Create a dedicated test job ID/folder. Do not write PPI, KaKs, or Ortholog outputs into `job_1786184894919_b7d741/final` or any user acceptance job.
Validate these routes:
1. **Ft + PPI near reference + KaKs same reference**
- visible plan has PPI/KaKs and no Ortholog;
- PPI-owned mapping succeeds;
- KaKs dialog appears after PPI;
- choose PPI reference;
- exact mapping is reused;
- PPI and KaKs succeed.
2. **Ft + PPI near reference + KaKs At**
- choose configured At;
- KaKs-owned At mapping is generated;
- PPI near-reference mapping and Manifest checksums remain unchanged;
- KaKs succeeds with At PEP/CDS.
3. **PPI failure/skip isolation**
- force PPI to fail or explicitly skip it;
- KaKs dialog still appears;
- choose At and complete KaKs;
- unrelated runnable stages keep their own statuses.
4. **PPI active download gate**
- while PPI reference download is running, KaKs dialog does not open;
- after PPI settles, it opens once.
5. **Standalone Ortholog regression**
- explicitly request Ortholog;
- visible standalone stage and canonical outputs remain available.
For each route capture request payloads, task statuses, owner-specific Manifests, mapping checksums, and final stage statuses in the dedicated test folder.
### Live service verification
After unit/API verification, restart only the sj-2 service on port 9016. Verify the served HTML contains the new contract, then exercise one isolated frontend job. Do not restart unrelated workers/services unless backend code loading proves it is necessary.
## Stop rules
Stop and re-diagnose if implementation requires any of the following:
- changing PPI/STRING ID mapping or network analysis logic;
- changing KaKs calculation logic or neutral-rate semantics;
- modifying main-Agent/intent-Agent prompts or analysis YAML;
- making PPI wait for CDS;
- writing PPI reference into shared project reference fields;
- overwriting another owner's mapping/Manifest;
- hiding Ortholog only by frontend display filtering while it remains in the normal backend plan.
## Final acceptance criteria
- Normal full gene-family planning shows PPI and KaKs, not implicit Ortholog.
- PPI is processed before KaKs reference confirmation.
- KaKs offers the PPI technical reference and configured reference when valid.
- PPI success is not required for KaKs to continue.
- PPI and KaKs mappings/manifests are owner-isolated and reproducible.
- At selection for KaKs does not mutate PPI; PPI-near-reference selection does not mutate unrelated stages.
- No original user job is polluted by verification outputs.
@@ -0,0 +1,252 @@
# PPI 专属 Ortholog 参考 PEP 身份一致性修订计划
> **执行约束:** 实施时必须继续遵循 `karpathy-guidelines`:先写可失败的回归测试,只做最小生产改动,每一步都用可观察证据验收;不得顺手重构前端、规划层、下载层或身份校验层。
**目标:** 当 PPI 使用已下载近源物种或用户显式确认的 At 作为技术参考物种时,PPI 专属 Ortholog 的生产端与 PPI 二次预检必须使用同一份全蛋白组 PEP,使 Ortholog → PPI → Ka/Ks 能继续调度,同时保持普通独立 Ortholog 的原有 family PEP 语义不变。
**架构边界:** PPI 的技术参考物种只属于 `dependency_owner=ppi` 的隐藏依赖,不进入公共规划阶段,也不改变 `target_only` 生物学 scope。修复点仅位于后端 Ortholog 输入解析分支;严格的路径、SHA256、taxon、storage key、mapping identity 校验继续保留。
**技术栈:** Python 3.11、FastAPI、Celery、pytest;真实验证使用 sj-2 的 9016 Web/API 和对应 Celery workers。
---
## 1. 已确认的问题
### 1.1 当前真实失败链
真实任务 `job_1786243816439_04955b` 已给出完整证据链:
1. 菠菜参考包下载尝试 3 次后因 `IncompleteRead(488265 bytes read)` 失败;重试机制工作正常。
2. 用户显式选择 At 兜底后,PPI 专属 Ortholog 成功生成 24 对映射。
3. 随后的 PPI 二次预检返回 `stale_ortholog_identity_conflict`,PPI 未提交。
4. Ka/Ks 正确识别同一参考准备链,未再次启动下载,但因 PPI 映射未通过身份校验而暂停。
### 1.2 根因不是“身份校验太严格”,而是生产者与消费者解析了不同文件
| 环节 | 实际解析文件 | 结果 |
|---|---|---|
| PPI 专属 Ortholog 生产端 | `input/.../At.SPL.pep.fasta` | family PEP,9,929 bytes,SHA256 `42dca87b...` |
| PPI 二次预检消费端 | `input/.../At/At.pep.fasta` | whole-proteome PEP,34,646,980 bytes,SHA256 `193f9d45...` |
两者虽然都叫 At,但不是同一个输入身份。Ortholog Manifest 和 sidecar 如实记录了 family PEP;PPI 预检按全蛋白组 PEP 构建期望身份,因此拒绝复用是正确行为。
### 1.3 精确代码位置
生产端位于 `apps/web/pipeline_backend.py` 的 `stage == "ortholog"` 分支:
```python
subject_fasta = first_existing_scope_file(
ortholog_scope_data,
reference_species,
["family_pep", "pep"],
)
if not subject_fasta:
subject_fasta = resolve_species_family_pep(...)
if not subject_fasta:
subject_fasta = resolve_species_sequence_file(..., family_only=False)
```
即使 `ppi_owned_producer=True`,它仍优先选 family PEP。
消费端 `_resolve_ppi_only_snapshot_preflight()` 经 `_ppi_mapping_identity_matches_current_inputs()` 使用 `resolve_species_sequence_file(..., family_only=False)`,解析的是技术参考物种的 whole-proteome PEP。
### 1.4 最近三轮修订与本次失败的关系
| 修订轮次 | 已产生的变化 | 当前结论 |
|---|---|---|
| PPI owner/scope 修订 | 隐藏 Ortholog 归 PPI 所有;公共 scope 保持 `target_only`;增加严格身份校验和二次预检 | 设计正确,必须保留 |
| 下载进度展示修订 | Tip 旁显示下载任务、字节数和终态 | 只增强可见性,没有制造数据链问题 |
| PEP+CDS 一次下载修订 | PPI 阶段一次准备 PEP+CDS;`IncompleteRead` 最多重试 3 次;Ka/Ks 不再重复下载 | 当前日志证明已生效;它暴露了此前项目记录中已暂缓的 PEP 身份不一致 |
因此,本次不能回退上述三轮修订,也不能通过删除严格身份校验“让它通过”。
## 2. 冻结的最小修订方案
### 2.1 唯一生产代码改动
**文件:** `apps/web/pipeline_backend.py`
在 `stage == "ortholog"` 的 subject 解析处,仅对 `ppi_owned_producer` 分流:
```python
if ppi_owned_producer:
subject_fasta = resolve_species_sequence_file(
ws,
final_dir,
in_dir,
ortholog_scope_data,
reference_species,
family,
"pep",
family_only=False,
)
else:
subject_fasta = first_existing_scope_file(
ortholog_scope_data,
reference_species,
["family_pep", "pep"],
)
if not subject_fasta:
subject_fasta = resolve_species_family_pep(
ws, final_dir, in_dir, reference_species, family
)
if not subject_fasta:
subject_fasta = resolve_species_sequence_file(
ws,
final_dir,
in_dir,
ortholog_scope_data,
reference_species,
family,
"pep",
family_only=False,
)
```
该分流保证:
- PPI 专属 Ortholog 与 PPI 预检调用同一个 whole-proteome resolver;
- 菠菜缓存参考和 At 兜底都走同一规则,而不是写死 Ft、菠菜或 At;
- 普通独立 Ortholog 仍优先使用 family PEP,不改变既有科研语义;
- Ka/Ks 继续复用 PPI 已确认的 bundle/mapping owner,不新增第二次 Ortholog。
### 2.2 明确禁止的改动
本次不得修改:
- `apps/web/vue3/index.html` 的规划、调度、弹窗和进度状态机;
- `apps/web/vue3/main.py` 的接口契约和下载任务实现;
- PlanningAgentV2、主 Agent、意图 Agent 或任何 YAML 阶段定义;
- `gfa_core/ortholog_materialize.py` 的严格 identity 计算与比较;
- `stage_context.reference_species`、公共 `scope_id` 或 PPI 的 `target_only` 语义;
- PEP+CDS 一次下载、3 次重试、Ka/Ks 禁止二次下载的现有逻辑;
- 全局调整 `first_existing_scope_file(["family_pep", "pep"])` 的优先级。
## 3. 实施任务
### Task 1:先建立能复现真实冲突的 RED 测试
**文件:** `tests/unit/test_ppi_ortholog_owner_identity_task5b.py`
- [ ] 增加 At 同时存在两套 PEP 的 fixture:
- `input/At.SPL.pep.fasta`:family PEP;
- `input/At/At.pep.fasta`:whole-proteome PEP;
- `input/At/At.cds.fasta`:与 whole PEP 使用相同 transcript ID,如 `AT5G16970.1`。
- [ ] 以 `dependency_owner="ppi"`、`ppi_reference_storage_key="At"`、`ppi_reference_taxon_id="3702"` 执行隐藏 Ortholog。
- [ ] 断言当前代码的 `--subject` 错误指向 `At.SPL.pep.fasta`,并使“必须指向 `At/At.pep.fasta`”的新断言先失败。
- [ ] 断言生成映射后再次调用 `resolve_ppi_species_resolution()`;当前代码应因 reference PEP SHA 不同而不是 `ready`。
运行:
```bash
/home/xia-lab/miniconda3/envs/test4py311/bin/python -m pytest -q \
tests/unit/test_ppi_ortholog_owner_identity_task5b.py \
-k "whole_reference_pep"
```
预期 RED:失败信息明确显示 expected `At/At.pep.fasta`,actual `At.SPL.pep.fasta`;不得用其他异常作为“红灯”。
### Task 2:实施 PPI owner 专属的 resolver 分流
**文件:** `apps/web/pipeline_backend.py`
- [ ] 按 2.1 的代码结构修改 subject 解析。
- [ ] 不改变 `references=[ppi_owner_storage_key]`、`_effective_ppi_owner_scope_id()`、`member_set_id=""`、owner-specific 输出命名。
- [ ] 保留找不到 whole PEP 时的明确失败,不允许静默回退到 family PEP;否则生产端和预检会再次形成双重真相。
- [ ] 运行语法检查:
```bash
/home/xia-lab/miniconda3/envs/test4py311/bin/python -m py_compile \
apps/web/pipeline_backend.py
```
### Task 3:补齐身份与非回归测试
**文件:** `tests/unit/test_ppi_ortholog_owner_identity_task5b.py`
- [ ] GREEN 断言 PPI-owned Ortholog 命令的 `--subject` 精确等于 whole-proteome PEP。
- [ ] 断言 PPI owner sidecar 与 Manifest 的 `reference_pep_sha256`、`reference_storage_key`、`reference_taxon_id`、`mapping_path` 全部对应同一 whole PEP。
- [ ] 断言二次 PPI preflight 返回 `status == "ready"`,不再出现 `stale_ortholog_identity_conflict`。
- [ ] 断言 PPI Manifest 仍为 `scope_mode == "target_only"`,`stage_context.reference_species == []`,`selected_species == ["Ft"]`。
- [ ] 新增普通独立 Ortholog 回归用例:当 family PEP 与 whole PEP 同时存在时,非 PPI owner 仍选择 family PEP。
- [ ] 为直接相关的旧 fixture 补充 CDS,使其进入身份校验分支;不改与本问题无关的前端文本断言或 effective-member fixture。
运行:
```bash
/home/xia-lab/miniconda3/envs/test4py311/bin/python -m pytest -q \
tests/unit/test_ppi_ortholog_owner_identity_task5b.py
/home/xia-lab/miniconda3/envs/test4py311/bin/python -m pytest -q \
tests/unit/test_ppi_ortholog_owner_identity_task5b.py \
tests/unit/test_ppi_owner_scheduling_task5.py \
tests/unit/test_ppi_frontend_display_contract.py
```
验收时必须把修订前基线与修订后结果分开报告。已知旧前端字符串断言、旧 fixture 缺 CDS、effective-member 相关失败不得被伪装为本次新增回归,也不得借机修改生产代码。
### Task 4:在独立验证 job 做真实 API 闭环
**位置:** sj-2 独立创建 `job_codex_ppi_kaks_pep_identity_<timestamp>`,不得把验证产物写入用户当前 job 的 `final/`。
- [ ] 从真实 Ft/At 案例只读复用以下输入:Ft 家族成员 PEP、At family PEP、At whole PEP、At whole CDS、scope/config。
- [ ] 初次调用 `POST /api/ppi/species-resolution`,使用:
```json
{
"job_id": "job_codex_ppi_kaks_pep_identity_<timestamp>",
"prefix": "Ft.SPL",
"targetSpecies": ["Ft"],
"referenceSpecies": [],
"geneFamily": "SPL",
"ppiReferenceTaxonId": "3702",
"ppiReferenceStorageKey": "At",
"ppiReferenceSelectionMode": "explicit_fallback",
"ppiReferenceUserConfirmed": true,
"dependencyOwner": "ppi",
"requestedStages": ["ppi"]
}
```
- [ ] 初次预检必须为 `needs_ortholog`,且不再要求下载完整 At bundle。
- [ ] 调用 `POST /api/execute` 执行隐藏 `ortholog`,请求保留 `dependencyOwner="ppi"`、`targetSpecies=["Ft"]`、`referenceSpecies=[]` 和 PPI owner 字段。
- [ ] 轮询任务直至成功,并检查后端命令日志:`--query` 为 Ft family PEP,`--subject` 为 `At/At.pep.fasta`。
- [ ] 检查 PPI-owned Ortholog 产生有效映射、sidecar、Manifest,映射数量大于 0;所有 reference identity 字段一致。
- [ ] 再次调用 `/api/ppi/species-resolution`,必须返回 `ready`,不得返回 stale identity conflict。
- [ ] 调用 `/api/execute` 执行 PPI,轮询到 terminal success;检查 PPI Manifest 和网络产物,不以“任务已提交”代替成功。
- [ ] 进入 Ka/Ks 确认路径,确认它复用 PPI 选择的参考 bundle 和 `orthologMappingOwner=ppi`;不得出现第二次参考下载或第二个 Ortholog producer。
- [ ] 执行 Ka/Ks 至 terminal success,并核对 Ka/Ks Manifest 的 reference/mapping provenance。
- [ ] 最后确认活动任务数为 0、前端计时漏斗停止、PPI/KaKs 的 terminal 状态能正常显示。
### Task 5:覆盖近源物种路径并区分外部下载故障
- [ ] 若 `string_taxon_3562` 已有完整且非损坏的 PEP+CDS bundle,在独立验证 job 重复 Task 4,要求 PPI-owned Ortholog 的 `--subject` 为 `string_taxon_3562` whole PEP,二次预检为 `ready`。
- [ ] 若菠菜下载仍因远端 `IncompleteRead` 失败,只验收重试次数、字节进度、terminal failure 和 At 手动兜底入口;明确记录为外部下载失败,不得把它误判为本次 identity 修订失败。
- [ ] 不为通过测试而在代码中预设 Ft、菠菜或 At;两条路径必须由同一 storage-key + whole-PEP 解析规则驱动。
### Task 6:部署 sj-2 并做用户前端验收
- [ ] 确认修改发生在 `/home/xzq/5090/teamWorkspace/sj-2/PlantAI-dev`,不是 sj 或主项目。
- [ ] 重启 sj-2 的 9016 Web 服务及该项目全部 Celery workers;启动时显式使用远端 Conda 根 `/home/xzq/miniconda3`。
- [ ] 检查 9016 健康接口、Web PID、Celery PID 和日志所指项目根均为 sj-2。
- [ ] 用户前端验证前,只清理独立验证 job;不得删除用户任务或公共 data。
- [ ] 用户用新 job 验收以下两条路径:
1. 近源参考包可用:一次准备 PEP+CDS → 一个隐藏 PPI-owned Ortholog → PPI → Ka/Ks 确认与复用;
2. 近源下载失败:显示进度和失败 → 用户确认 At → 一个隐藏 PPI-owned Ortholog → PPI → Ka/Ks 确认与复用。
## 4. 完成判据
只有同时满足以下条件,才能宣称修复完成:
- PPI-owned Ortholog 的实际 `--subject` 与 PPI 预检解析出的 whole PEP 是同一路径、同一 SHA256;
- Ortholog Manifest、identity sidecar、PPI preflight 的 taxon/storage/path/hash/mapping identity 完全一致;
- PPI 二次预检为 `ready`,PPI 真实执行成功并生成有效产物;
- Ka/Ks 在 PPI 后出现确认,复用已准备的 PEP+CDS 和 PPI mapping owner,不二次下载、不二次生成 Ortholog;
- 公共规划中不出现 Ortholog,PPI 公共 scope 仍为 Ft `target_only`;
- 独立 Ortholog 保持 family PEP 优先,既有分析语义不变;
- 前端无无限旋转,所有 task 到达 terminal 状态;
- 真实验证产物只存在独立测试目录,不污染用户 job。
## 5. 回滚边界
若新回归测试证明 `resolve_species_sequence_file(..., family_only=False)` 在某种 storage key 下不能稳定解析 whole PEP,只回滚本次单一分流并保留 RED 证据;不得回滚 owner/scope、严格 identity、PEP+CDS 一次下载或前端进度显示。此时应先补清 resolver 输入契约,再重新评估,不得用 family PEP 或禁用 SHA 校验作为临时通行证。
@@ -0,0 +1,43 @@
# PPI/KaKs Integration Commit and Push Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Commit the validated PPI → owner-specific Ortholog → Ka/Ks workflow and push it to the main PlantAI repository without including runtime data.
**Architecture:** Preserve the tested cross-layer change as one functional integration: frontend orchestration, API/backend identity resolution, owner-namespaced Ortholog materialization, contracts, and their tests. Keep input, workspace, downloaded bundles, logs, caches, and shared data outside Git.
**Tech Stack:** Vue 3 single-page frontend, FastAPI, Celery, Python, pytest, Git.
## Global Constraints
- Push must be a normal fast-forward update; never force-push.
- Do not stage `input/`, `workspace/`, `final/`, downloaded reference bundles, logs, PID files, caches, or shared `data` content.
- Preserve standalone, PPI-owner, and KaKs-owner Ortholog namespaces.
- Verify the relevant regression suite before committing and re-check the committed tree before pushing.
---
### Task 1: Clean the commit boundary
**Files:** All currently modified tracked source, contract, and test files; the three PPI/KaKs plan/spec documents.
- [ ] Remove whitespace errors without changing runtime behavior.
- [ ] Update stale source-contract assertions to the current unified dialog and producer variable names.
- [ ] Confirm no runtime outputs are staged.
### Task 2: Verify the integrated workflow
**Files:** `tests/unit/test_ppi*.py`, reference-bundle tests, handoff/snapshot tests, and the affected production files.
- [ ] Run JavaScript syntax validation for `apps/web/vue3/index.html`.
- [ ] Run the focused PPI/KaKs, reference download, owner identity, and context regression tests.
- [ ] Run `git diff --check` and inspect the final staged file list.
### Task 3: Commit and push
**Files:** Only the verified source, contracts, tests, and documentation from Tasks 1–2.
- [ ] Fetch `origin/master` and verify the push remains fast-forward.
- [ ] Commit with a PPI/KaKs integration message.
- [ ] Push the committed branch to `origin/master` without force.
- [ ] Verify the remote master commit ID equals the local committed ID.
@@ -0,0 +1,383 @@
# PPI/KaKs Reference Route Handoff Implementation Plan
**Goal:** 修复 PPI 完成后 Ka/Ks 的两条参考路线,使用户确认的参考物种与 Ortholog owner 原样传递到预检和执行,不发生二次推导、重复下载或错误暂停。
**Architecture:** 保留现有规划、后端 API、CLI 和 owner 专属 Manifest 契约。PlanningAgent 只规划 PPI 与 Ka/Ks;前端收集并传递用户选择;后端 resolver 只验证所选路线;隐藏 Ortholog producer 只在所选 owner 缺少映射时执行。
**Tech Stack:** Vue 3 内嵌脚本、FastAPI、pytest、Node 动态行为测试、Celery、现有 `/api/ppi/species-resolution` 与 `/api/execute`。
## Global Constraints
- 修订项目固定为 `/home/xzq/5090/teamWorkspace/sj-2/PlantAI-dev`,服务端口固定为 `9016`。
- 不修改 MainAgent、PlanningAgent、阶段目录、CLI、分析算法、Manifest Schema 或后端 API 契约。
- 规划继续只显示 PPI 和 Ka/Ks,不显示 Ortholog。
- PPI 技术参考选择只属于 PPI;Ka/Ks 必须在 PPI settled 后单独确认 `reuse PPI` 或 `project reference`。
- 用户确认是路线权威来源;前端不得在确认后从 batch/plan 全局状态重新推导另一条路线。
- 真实验证使用隔离 job 与独立输出目录,不写入用户 job 的 `final/`。
- 不实现跨 owner 哈希复用、页面刷新恢复、统一状态机、断点续传或其它扩展。
- 完成修订和验证后再重启 sj-2 Web 与全部 Celery worker;不自动 commit/push。
---
### Task 1: 用精确行为测试锁定两条路线
**Files:**
- Modify: `tests/unit/test_ppi_owner_scheduling_task5.py`
- Inspect only: `tests/unit/test_ppi_frontend_display_contract.py`
**Interfaces:**
- Consumes: `kaksReferenceChoiceParams`、`buildPpiKaksDependencyRequest`、`ppiNeedsNearReferenceDecision`、`prepareKaksSelectedReference`。
- Produces: 精确复现 PPI 映射复用、At 独立映射、确认参数直传和 PPI-only 近源规则的 RED 测试。
- [ ] **Step 1: 添加 PPI 近源复用路线测试**
构造以下确认结果和 PPI owner 状态:
```javascript
const confirmed = kaksReferenceChoiceParams('ppi', 'string_taxon_3562', 'At');
const ppiOwner = {
ppiReferenceTaxonId: '3562',
ppiReferenceStorageKey: 'string_taxon_3562',
ppiReferenceSelectionMode: 'tree_nearest',
ppiReferenceUserConfirmed: true
};
```
断言 `buildPpiKaksDependencyRequest(['kaks'], confirmed)` 的关键结果为:
```javascript
{
requestedStages: ['kaks'],
dependencyOwner: 'ppi',
referenceSpecies: ['string_taxon_3562'],
ppiReferenceTaxonId: '3562',
ppiReferenceStorageKey: 'string_taxon_3562',
ppiReferenceSelectionMode: 'tree_nearest',
ppiReferenceUserConfirmed: true
}
```
- [ ] **Step 2: 添加项目 At 路线测试**
```javascript
const confirmed = kaksReferenceChoiceParams('project', 'string_taxon_3562', 'At');
```
断言 `dependencyOwner='kaks'`、`referenceSpecies=['At']`,且不携带菠菜 PPI owner 身份。
- [ ] **Step 3: 添加 PPI-only 近源规则测试**
```javascript
const resolution = {
status: 'needs_ortholog',
selected_string_species: 'ath',
diagnostics: {
reference_recommendations: [{species_code: 'string_taxon_3562'}]
}
};
```
断言:
```javascript
ppiNeedsNearReferenceDecision(resolution, ['ppi']) === true;
ppiNeedsNearReferenceDecision(resolution, ['kaks']) === false;
```
- [ ] **Step 4: 添加确认参数直传测试**
Stub `ensurePpiKaksDependencyOwner`,执行 `prepareKaksSelectedReference(confirmed)`,断言精确调用:
```javascript
ensurePpiKaksDependencyOwner('kaks', confirmed);
```
- [ ] **Step 5: 执行 RED 验证**
```bash
/home/xzq/miniconda3/envs/test4py311/bin/python -m pytest -q \
tests/unit/test_ppi_owner_scheduling_task5.py \
-k 'kaks and (reuse or project or confirmed or near_reference)'
```
Expected: 新增测试按预期失败;不得因测试夹具或语法错误失败。
---
### Task 2: 让 Ka/Ks 预检消费用户确认后的唯一参数
**Files:**
- Modify: `apps/web/vue3/index.html:14534-14908`
- Test: `tests/unit/test_ppi_owner_scheduling_task5.py`
**Interfaces:**
- Consumes: `confirmedStageParamsForExecution('kaks', stageParams)` 的返回值。
- Produces: `buildPpiKaksDependencyRequest(stageIds, stageParamsOverride)` 与 `ensurePpiKaksDependencyOwner(ownerStageId, stageParamsOverride)`。
- [ ] **Step 1: 让请求构造器接受确认参数,不新增抽象层**
```javascript
const buildPpiKaksDependencyRequest = (stageIds = [], stageParamsOverride = null) => {
const dependencyStage = (batchExecuteStages.value || [])
.find(stage => getStageId(stage) === stageIds[0]) || {};
const storedStageParams = typeof dependencyStage === 'object'
? (dependencyStage.params || {})
: {};
const stageParams = stageParamsOverride && typeof stageParamsOverride === 'object'
? stageParamsOverride
: storedStageParams;
```
- [ ] **Step 2: 按 mapping owner 决定是否保留 PPI 身份**
```javascript
const mappingOwner = stageParams.orthologMappingOwner || ownerStageId;
const usesPpiOwner = mappingOwner === 'ppi';
```
仅 `usesPpiOwner` 时,从 `stageParams → batchParams → planParams` 读取 `ppiReferenceTaxonId`、`ppiReferenceStorageKey`、`ppiReferenceSelectionMode`、`ppiReferenceUserConfirmed`。项目 At 路线保持这些字段为空。
- [ ] **Step 3: 让 owner 预检接受确认参数**
```javascript
const ensurePpiKaksDependencyOwner = async (ownerStageId, stageParamsOverride = null) => {
const requestedStages = [ownerStageId];
const requestBody = buildPpiKaksDependencyRequest(requestedStages, stageParamsOverride);
```
- [ ] **Step 4: Ka/Ks 准备函数传入确认参数**
```javascript
const prepareKaksSelectedReference = async (stageParams = {}) => {
const ready = await ensurePpiKaksDependencyOwner('kaks', stageParams);
```
后续保持:owner 为 `ppi` 时复用已有映射;owner 为 `kaks` 时只生成一次 Ka/Ks 专属 Ortholog。
- [ ] **Step 5: 执行 GREEN 验证**
```bash
/home/xzq/miniconda3/envs/test4py311/bin/python -m pytest -q tests/unit/test_ppi_owner_scheduling_task5.py
```
Expected: 全文件通过;原有 PPI owner single-flight、running 状态、失败不 resume 行为仍通过。
---
### Task 3: 将近源优先规则限制为 PPI,并隔离 At 兜底
**Files:**
- Modify: `apps/web/vue3/index.html:13804-13927`
- Modify: `apps/web/vue3/index.html:14336-14400`
- Test: `tests/unit/test_ppi_owner_scheduling_task5.py`
**Interfaces:**
- Consumes: `requestedStages` 与 PPI fallback 用户确认结果。
- Produces: PPI-only 近源决策和 fail-closed 的 At fallback。
- [ ] **Step 1: 限制近源规则归属**
```javascript
const ppiNeedsNearReferenceDecision = (resolution = {}, requestedStages = []) => {
if (!requestedStages.includes('ppi')) return false;
const selected = String(resolution.selected_string_species || '').toLowerCase();
return resolution.status === 'needs_ortholog'
&& selected === 'ath'
&& ppiHasNearReferenceBeforeArabidopsis(resolution);
};
```
在 `runPpiSpeciesResolutionPreflight` 和 `ensurePpiKaksDependencyOwner` 中均传入当前 `requestedStages`。
- [ ] **Step 2: PPI下载失败后的At兜底不写Ka/Ks参数**
删除 `applyArabidopsisFallbackForPpiKaks` 中针对 `requestedStages.includes('kaks')` 的参数写入;affected stage 只包含 PPI owner 及其隐藏 Ortholog producer。Ka/Ks 保持原状态,等待 PPI settled 后弹出自己的确认框。
- [ ] **Step 3: fallback orchestration 失败时保持暂停**
```javascript
const orchestrated = await orchestratePpiOwnerAfterReferenceReady({
requestBody,
requestedStages: ['ppi'],
runPreflight: runPpiSpeciesResolutionPreflight,
dependencyStatus: dependencyId => stageExecutionStatus.value[dependencyId],
waitForDependency: waitForPpiProducerDependency,
ensureOrtholog: async (nextResolution, nextRequest) => {
const ready = ensureOrthologStageForPpiKaks(
batchExecuteStages.value || [],
['ppi'],
nextRequest,
nextResolution
);
return {
ready: Boolean(ready),
producerStage: getPpiKaksInternalOrthologProducer('ppi')
};
},
executeProducer: executePpiOwnedOrthologProducer,
resume: async () => resumePpiKaksPausedStages(
['ppi'],
'拟南芥兜底参考已确认'
)
});
if (orchestrated !== true) {
const pauseMessage = '拟南芥兜底参考尚未形成可用的 PPI Ortholog 映射;PPI 保持暂停。';
storePpiKaksReferencePause(['ppi'], {}, pauseMessage);
addAgentMessage('assistant', `⏸️ ${pauseMessage}`);
return false;
}
```
不得在该 handler 中调用 `resumePpiKaksPausedStages(['kaks'])`。
- [ ] **Step 4: 执行调度回归**
```bash
/home/xzq/miniconda3/envs/test4py311/bin/python -m pytest -q \
tests/unit/test_ppi_owner_scheduling_task5.py \
tests/unit/test_ppi_frontend_display_contract.py
```
Expected: 全部通过;规划中无 Ortholog,PPI 先于 Ka/Ks,Ka/Ks 仍受 `ppiSettledForKaks` 门控。
---
### Task 4: 后端 API 路线矩阵验证,不预先修改后端
**Files:**
- Inspect only: `apps/web/vue3/main.py:15185-15225`
- Inspect only: `apps/web/pipeline_backend.py:2795-3177`
- Inspect only: `apps/web/pipeline_backend.py:13398-13421`
**Interfaces:**
- Consumes: 前端最终生成的两个 Ka/Ks preflight payload。
- Produces: 后端现有契约是否足够的证据。
- [ ] **Step 1: 菠菜复用路线 API 验证**
关键 payload:
```json
{
"job_id": "job_codex_ppi_kaks_route_20260810",
"prefix": "Ft.SPL",
"targetSpecies": ["Ft"],
"referenceSpecies": ["string_taxon_3562"],
"ppiReferenceTaxonId": "3562",
"ppiReferenceStorageKey": "string_taxon_3562",
"ppiReferenceSelectionMode": "tree_nearest",
"ppiReferenceUserConfirmed": true,
"dependencyOwner": "ppi",
"requestedStages": ["kaks"]
}
```
Expected: `status=ready`,`ortholog_mapping_source` 指向 PPI owner 映射;不产生下载或新 Ortholog。
- [ ] **Step 2: 项目 At 路线 API 验证**
```json
{
"job_id": "job_codex_ppi_kaks_route_20260810",
"prefix": "Ft.SPL",
"targetSpecies": ["Ft"],
"referenceSpecies": ["At"],
"dependencyOwner": "kaks",
"requestedStages": ["kaks"]
}
```
Expected: At PEP/CDS存在且无Ka/Ks owner映射时返回 `status=needs_ortholog`,不是 `needs_reference_data`,也不受菠菜优先规则阻断。
- [ ] **Step 3: 后端范围门禁**
如果两个 API 结果符合预期,后端保持零改动。如果不符合,只记录确切请求与响应并停止,另行制定后端最小修订,不能顺手扩展。
---
### Task 5: 隔离真实数据闭环验证
**Files:**
- Create at runtime: `input/job_codex_ppi_kaks_route_20260810/`
- Create at runtime: `workspace/job_codex_ppi_kaks_route_20260810/`
- Verify only: `final/*.manifest.json`、logs、`/api/stage-status`
**Interfaces:**
- Consumes: Ft/SPL现有成员输入、At与菠菜参考PEP/CDS。
- Produces: 两条Ka/Ks路线的真实结果,不污染用户job。
- [ ] **Step 1: 创建隔离 job**
逐文件只读复用 Ft/SPL 成员输入和参考 FASTA;不得把整个用户 input 目录软链接为可写目录。运行时缓存和结果全部写入隔离 job。
- [ ] **Step 2: 路线 A:复用 PPI 菠菜映射**
顺序:PPI owner preflight ready → Ka/Ks确认复用 → Ka/Ks preflight ready → `/api/execute` Ka/Ks。
Expected: Ka/Ks确认后不下载、不生成第二个Ortholog,请求携带 `orthologMappingOwner=ppi`,Ka/Ks成功生成结果和manifest。
- [ ] **Step 3: 路线 B:项目 At**
顺序:Ka/Ks确认At → preflight needs_ortholog → 一次 Ka/Ks owner Ortholog → 二次 preflight ready → `/api/execute` Ka/Ks。
Expected: At PEP/CDS已存在时不下载,只生成一次Ka/Ks owner Ortholog,请求携带 `orthologMappingOwner=kaks`,Ka/Ks成功生成结果和manifest。
- [ ] **Step 4: 核对闭环身份**
核对确认参数、preflight请求、Ortholog命令日志、Ortholog manifest、Ka/Ks执行请求、Ka/Ks日志、Ka/Ks manifest、`/api/stage-status` 的参考物种与 owner 全部一致。
- [ ] **Step 5: 确认用户目录未被写入**
比较验证前后用户 job `input/` 与 `final/` 文件清单和 mtime。Expected: 无新增 PPI、Ka/Ks、Ortholog 或缓存文件。
---
### Task 6: 范围审计、重启与前端验收
**Files:**
- Verify: git diff
- Runtime: sj-2 Web 9016 and all sj-2 Celery workers
- [ ] **Step 1: 审计改动范围**
```bash
git diff --name-only
git diff --check
```
Expected code/test changes only:
```text
apps/web/vue3/index.html
tests/unit/test_ppi_owner_scheduling_task5.py
docs/superpowers/plans/2026-08-10-ppi-kaks-reference-route-handoff.md
```
如出现 `planning_v2.py`、`main.py`、`pipeline_backend.py`、CLI、Manifest Schema 或 stage catalog,停止并撤回本轮非必要修改。
- [ ] **Step 2: 确认无运行任务后重启全部sj-2服务**
先检查 `/api/tasks` 和 Celery active;确认空闲后重启 sj-2 Web 与 default/heavy/medium/light/rnaseq workers,不影响其它项目端口或队列。
- [ ] **Step 3: 健康检查**
Expected: 9016首页HTTP 200;`/api/celery/health` 返回sj-2五类worker在线;9016返回的 `index.html` hash 与磁盘文件一致。
- [ ] **Step 4: 前端验收标准**
路线 A:PPI菠菜成功 → Ka/Ks选择复用 → 无下载、无第二次Ortholog → Ka/Ks成功。
路线 B:PPI菠菜成功 → Ka/Ks选择At → 无下载 → 一次Ka/Ks专属Ortholog → Ka/Ks成功。
PPI下载失败路线:确认At → PPI At Ortholog和PPI完成 → Ka/Ks随后独立弹窗;失败时保持PPI暂停,不伪报恢复。
## Completion Gate
只有同时满足以下条件才可声明完成:
1. 新增测试先RED后GREEN。
2. 两条后端预检矩阵与预期一致。
3. 两条真实Ka/Ks路线均执行成功。
4. 用户job没有新增测试产物。
5. 改动范围仅限前端调度、对应测试和本计划文档。
6. 9016 Web与全部sj-2 Celery worker重启并健康。
@@ -0,0 +1,7 @@
# PPI/KaKs Unified Reference Dialogs Implementation Plan
1. Add focused frontend contract tests that require both messages to use `showStageConfirmDialog`, ordered candidate lists, grouped reference fields, and their original accept/cancel semantics.
2. Add two display-only stage IDs and initialize their view model from the existing resolution objects.
3. Add the two panels and dedicated footer actions to the existing stage-confirmation dialog.
4. Replace only the two raw `ElMessageBox` calls with queued stage-confirmation calls.
5. Run the focused tests, related PPI frontend regression tests, syntax/diff checks, then verify the served 9016 page after a safe restart.
@@ -0,0 +1,25 @@
# PPI/KaKs Unified Reference Dialogs Design
## Goal
Render the two PPI/KaKs reference-species messages inside the existing stage-confirmation dialog shell so their information is readable and visually consistent with the rest of the application.
## Scope
- Replace the raw STRING reference confirmation message box with a stage-confirmation dialog.
- Replace the raw reference-data/Ortholog warning alert with a read-only stage-confirmation dialog.
- Show reference candidates as an ordered list.
- Group target species, requested stages, required/missing files, current reference species, and Ortholog mapping into the existing PPI reference panel layout.
- Normalize both topology-candidate and downloaded-reference recommendation field names for display only.
## Non-goals
- No changes to PPI/KaKs download, Ortholog generation, identity, scheduling, API payloads, backend validation, or analysis execution.
- No changes to which candidate is selected: the first ranked candidate remains the confirmed candidate.
- No new automatic confirmation behavior.
## Interaction contract
- STRING candidate dialog: `Cancel PPI` resolves false; `Confirm top candidate` resolves true.
- Reference status dialog: `OK` only acknowledges the message; the preflight remains blocked exactly as before.
- Both dialogs use the existing queue, modal shell, title, progress header, and Element Plus components.