Files
PlantAI-dev/docs/validation/2026-07-21-string-ppi-task4-real-network.md
2026-08-03 18:42:47 +08:00

174 lines
6.2 KiB
Markdown

# Task 4 validation — numeric TaxID to real STRING network
Date: 2026-07-21
Target: `planai5090:/home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev`
Gate result: **PASS**
## Read-only implementation review
The reviewed Task 4 implementation keeps the execution TaxID separate from the
local gene-ID normalization label. Numeric execution taxa must be members of
the fixed STRING snapshot; legacy species codes remain compatible. The TaxID
survives preflight, API request normalization, worker parameters, backend CLI
construction, skill execution, and manifest generation.
`skills/ppi/run.py::StringAPI` discovers the official stable API address,
rejects untrusted redirects, maps inputs through `get_string_ids`, attributes
rows by `queryIndex`, validates TaxID and full STRING identifiers, and submits
only validated IDs to `network` with `add_nodes=0`. Network rows are checked for
TaxID, submitted endpoints, score range, and threshold. No Task 5 scheduling or
UI behavior was changed during this Gate.
CodeGraph was unavailable on the real target (`codegraph: command not found`,
exit 127), so the review used targeted source reads after recording the
limitation.
## Regression evidence
The first test command referenced a nonexistent
`tests/unit/test_string_rate_gate.py` and exited before collection. The corrected
focused command ran only files present in the repository:
```text
tests/unit/test_ppi_numeric_taxon_task4.py
tests/unit/test_ppi_id_resolution.py
tests/unit/test_string_ppi_production_wiring_red.py
tests/unit/test_ppi_string_policy.py
43 passed in 13.90s
```
## Official identifier discovery
Initial official `get_string_ids` probes for TaxID 3708 were `FLC`, `FT`,
`SOC1`, `AP1`, and `CO`. STRING mapped `FT` to `3708.D0QX04`. It also mapped
`CO`, but the returned annotation described a magnesium transporter; this
homonym was rejected as biologically unsuitable. `FLC`, `SOC1`, and `AP1` did
not map. A second symbol-only probe (`LFY`, `AG`, `SVP`, `GI`, `LHY`, `TOC1`,
`TFL1`, `FUL`, `SEP1`, `SPL3`, `SPL9`) returned zero mappings.
The official species-specific STRING v12 aliases file was then downloaded from:
```text
https://stringdb-downloads.org/download/protein.aliases.v12.0/3708.protein.aliases.v12.0.txt.gz
```
It records `3708.A0A078GRX0` with the product description
`MADS-box protein SOC1`. The protein ID was not submitted directly to the
network. The current `StringAPI.get_string_ids` first resolved the aliases-file
token `A0A078GRX0`, together with `FT`, producing two validated mappings:
| Query | STRING ID | TaxID | Preferred name |
|---|---|---:|---|
| `FT` | `3708.D0QX04` | 3708 | `FT` |
| `A0A078GRX0` | `3708.A0A078GRX0` | 3708 | `BnaC04g50370D` |
## Real StringAPI Gate
The Gate imported and executed the current
`skills.ppi.run.StringAPI`; the HTTP recorder only observed the requests and
did not bypass or replace its validation.
| Step | Method and endpoint | HTTP |
|---|---|---:|
| version | `GET https://string-db.org/api/json/version` | 200 |
| mapping | `POST https://version-12-0.string-db.org/api/json/get_string_ids` | 200 |
| network | `POST https://version-12-0.string-db.org/api/json/network` | 200 |
Version response:
```json
{
"string_version": "12.0",
"stable_address": "https://version-12-0.string-db.org"
}
```
Validated request summary:
- TaxID: `3708`
- Mapping input: `FT`, `A0A078GRX0`
- Mapping result: `2/2`
- Network input: `3708.D0QX04`, `3708.A0A078GRX0`
- `required_score=200`
- `network_type=functional`
- `add_nodes=0`
- `caller_identity=PlantAI`
The real network request returned one validated edge:
```text
3708.A0A078GRX0 (BnaC04g50370D)
-- score 0.467 -->
3708.D0QX04 (FT)
```
The response TaxID was 3708 and both endpoints were members of the submitted
validated ID set. Therefore Task 4 passes the real STRING stable-v12 Gate.
No service was restarted during the real-network Gate above, and no Task 5
work was performed.
## Deployment Gate on port 9010
Deployment Gate completed at `2026-07-21 06:04:42 CST`. Only the 9010 Web
process and the five `plantai_4090_9010` worker parents were restarted after a
directed `inspect active` reported all five workers empty.
| Process | Old PID | New PID | Queue |
|---|---:|---:|---|
| Web 9010 | 2470234 | 2479563 | — |
| default worker | 2470133 | 2479460 | `plantai_4090_9010.default` |
| heavy worker | 2470139 | 2479470 | `plantai_4090_9010.heavy` |
| medium worker | 2470146 | 2479477 | `plantai_4090_9010.medium` |
| light worker | 2470155 | 2479484 | `plantai_4090_9010.light` |
| rnaseq worker | 2470163 | 2479492 | `plantai_4090_9010.rnaseq` |
The Web process and every worker reported cwd
`/home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev`. Every worker reported
`BBAV5_QUEUE_PREFIX=plantai_4090_9010` and
`BBAV5_REDIS_URL=redis://localhost:6379/11`. Redis DB11 returned `PONG`; a
directed Celery ping returned `pong` from all five nodes; and
`/api/celery/health` returned `ok=true`, the expected five queues, and all five
project workers online.
Port 19000 retained PID `2466042`; port 9000 had no listener before or after.
Neither was signalled or restarted. The final socket check showed exactly one
9010 listener, PID `2479563`.
### Deployed request contract
The live `GET /openapi.json` schema for `ExecuteRequest` exposes both
`ppiSpecies` and `normalizationSpeciesLabel` as strings. A fresh deployed
Pydantic model probe constructed:
```json
{
"ppiSpecies": "3708",
"ppiSpecies_type": "str",
"normalizationSpeciesLabel": "Bn"
}
```
`model_dump()` retained both values exactly, so numeric-looking TaxID `3708`
is not converted, truncated, or discarded by Pydantic.
### Fresh worker-environment import probe
A separate fresh Python process used the same target cwd, test4py311
interpreter, queue prefix, and DB11 environment as the workers. It imported:
```text
skills.ppi.run:
/home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev/skills/ppi/run.py
gfa_core.mas.tools.stage_tools:
/home/xzq/5090/PlantAI-dev4090-7/PlantAI-dev/gfa_core/mas/tools/stage_tools.py
```
`StringAPI.resolve_species_id("3708")` returned `"3708"`. A separate fresh
process rejected `999999999` with `ValueError: STRING TaxID 999999999 is not
in the fixed STRING snapshot registry` and exit code 1.
No formal PPI task was submitted; end-to-end task submission remains reserved
for Task 7. No Task 5 work was performed.