# Task 3 validation — snapshot-driven PPI preflight Date: 2026-07-21 Target: `planai5090:/home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev` ## Scope - PPI-only preflight resolves species exclusively from the fixed STRING v12 snapshot. - Directly supported targets are ready without Ortholog or Ka/Ks reference data. - Unsupported targets return three real tree-nearest STRING candidates and require explicit confirmation. - After confirmation, PPI requires reference PEP first and Ortholog second; CDS is never a PPI dependency. - Reference-bundle download for a PPI-only request downloads `pep` only. - Unknown, conflicting, or unavailable registry identities return structured failures without static or At fallback. Out of scope and unchanged: `skills/ppi` execution, frontend scheduling, and Ka/Ks production behavior. ## TDD evidence Initial focused RED: 8 failed, 1 passed. Failures covered missing snapshot resolver fields, missing confirmation request fields, and CDS leaking into PPI-only downloads. Focused GREEN: ```text pytest -q tests/unit/test_ppi_snapshot_preflight_task3.py \ tests/unit/test_reference_bundle_download_progress.py 9 passed ``` Registry/identity regression: ```text test_ppi_target_identity.py test_ppi_frontend_display_contract.py test_string_species_snapshot.py test_string_species_registry.py 46 passed ``` Backend/reference-state regression on the actual target: ```text /home/xzq/miniconda3/envs/test4py311/bin/python -m pytest -q \ tests/unit/test_pipeline_backend_execution_env.py \ tests/unit/test_reference_bundle_download_progress.py \ tests/unit/test_reference_bundle_download_state.py 43 passed in 18.69s ``` Task 0 boundary checks: Setaria candidate resolution and no-confirmation/no-Ortholog passed. Registry-only numeric STRING execution remains intentionally RED until Task 4, because Task 3 does not modify the PPI execution adapter. ## Operational notes - CodeGraph was unavailable on the target (`codegraph: command not found`, exit 127), so source inspection used targeted file reads after recording the limitation. - No production data or prior Ortholog result was deleted. ## Online Gate on port 9010 Gate completed at `2026-07-21 05:34:20 CST` against the real backend at `http://127.0.0.1:9010`. ### Controlled restart evidence Only the 9010 Web process and the five `plantai_4090_9010` worker parents were restarted. All worker cwd values were `/home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev`. | Process | Old PID | New PID | Queue | |---|---:|---:|---| | Web 9010 | 2455555 | 2470234 | — | | default worker | 2455521 | 2470133 | `plantai_4090_9010.default` | | heavy worker | 2455528 | 2470139 | `plantai_4090_9010.heavy` | | medium worker | 2455537 | 2470146 | `plantai_4090_9010.medium` | | light worker | 2455544 | 2470155 | `plantai_4090_9010.light` | | rnaseq worker | 2455556 | 2470163 | `plantai_4090_9010.rnaseq` | Every new worker reported `BBAV5_QUEUE_PREFIX=plantai_4090_9010` and `BBAV5_REDIS_URL=redis://localhost:6379/11`; `redis-cli -n 11 ping` returned `PONG`. A directed Celery ping returned `pong` from all five expected nodes. `/api/celery/health` returned `ok=true`, the same queue prefix and DB11 URL, and all five expected online workers. Port 19000 retained PID `2466042` before and after this operation. Port 9000 had no listening process before or after; neither port was restarted or signalled. The first Web launch created the correct Web child but its relative PID-file redirection ran from the parent shell's cwd; the transient wrapper was terminated, the healthy child was retained, and the PID file was corrected to `2470234` using an absolute path. No duplicate 9010 listener remained. ### Real API evidence All checks used `POST /api/ppi/species-resolution` with explicit `requestedStages`. 1. Os PPI-only (`job_test`, `Os.HKL`) returned HTTP 200, `status=ready`, `decision=ready_target_string`, `selection_mode=exact_string`, `selected_string_species=osa`, `selected_taxon_id=39947`, and an empty `required_next_stage`. Provenance was `resolution_source=explicit_tree_taxon_id`, STRING version `12.0`, policy `string_species_tree_v12_topology_v1`, and snapshot `ede47d546d853d0ec30ee75066976a35c08fd2412e6e5fc7866bbd205fc2eeb3`. 2. The real job `job_1784552755238_b8762f`, with target scientific name `Setaria viridis` and tree TaxID `4556`, returned `status=confirmation_required`, `selection_mode=tree_nearest`, an empty `required_next_stage`, and candidate TaxIDs `4555`, `4540`, `888268` in that order. Provenance was `candidate_source=string_species_tree` with the same snapshot, policy and STRING version. 3. Unknown target `XxUnknown` returned `status=unresolved`, `issue_code=target_string_tree_unresolved`, empty selected/reference species and TaxID, empty candidates, empty mapping, and empty `required_next_stage`. It did not fall back to At or request Ortholog. Because identity resolution stops before registry lookup, its local `snapshot_id` is intentionally empty. 4. The live PPI-only response returned `reference_bundle_status.required_files=["pep"]` and `diagnostics.required_bundle_files=["pep"]`; CDS was absent. 5. With otherwise identical Os/Spinacia input, `requestedStages=["ppi"]` returned `ready_target_string`, `osa`, TaxID `39947`, empty next stage and required files `["pep"]`. A separate `requestedStages=["kaks"]` request returned `needs_reference_data`, `kaks_reference_cds_missing`, and required files `["pep","cds"]`. The Ka/Ks result did not overwrite or block the independent PPI result.