216 lines
8.1 KiB
Markdown
Executable File
216 lines
8.1 KiB
Markdown
Executable File
# Task 3 Independent Verification — Typed STRING API and deterministic PPI ID resolution
|
|
|
|
## Verdict
|
|
|
|
**FAIL**
|
|
|
|
Most Task 3 behavior is implemented and passes fresh focused, backend, offline,
|
|
multiprocessing, syntax, and direct production-path checks. One blocking
|
|
protocol-validation defect remains: STRING mapping rows that omit (or provide a
|
|
non-string) `preferredName` are accepted as valid. The approved Task 3 requires
|
|
the mapping boundary to retain `queryItem/queryIndex/stringId/preferredName/
|
|
ncbiTaxonId`, reject malformed rows, and perform explicit JSON-shape validation.
|
|
|
|
## Blocking finding
|
|
|
|
### Mapping validation does not require `preferredName`
|
|
|
|
`skills/ppi/run.py:184-234` validates the payload container, `queryIndex`,
|
|
echoed `queryItem`, `stringId`, and `ncbiTaxonId`, but the malformed-row
|
|
condition at lines 226-232 never checks `preferredName`.
|
|
|
|
Fresh direct reproducer:
|
|
|
|
```python
|
|
payload = [{
|
|
"queryIndex": 0,
|
|
"queryItem": "A",
|
|
"stringId": "3562.A",
|
|
"ncbiTaxonId": 3562,
|
|
}]
|
|
StringAPI.validate_mapping_rows(payload, ["A"], "3562")
|
|
```
|
|
|
|
Exit code: `0`
|
|
|
|
```text
|
|
ACCEPTED_MALFORMED_MAPPING [{'queryIndex': 0, 'queryItem': 'A', 'stringId': '3562.A', 'ncbiTaxonId': 3562}]
|
|
```
|
|
|
|
This row should instead raise `StringApiError(kind="protocol")`. Without that
|
|
check, the typed STRING boundary silently converts absent/invalid preferred-name
|
|
evidence to an empty or stringified value later in resolution rather than
|
|
classifying the response as a protocol/shape failure. The focused malformed-row
|
|
parameterization at `tests/unit/test_ppi_id_resolution.py:507-534` covers a
|
|
missing `stringId` but has no missing/non-string `preferredName` case.
|
|
|
|
Required correction: include a non-empty string `preferredName` in the mapping
|
|
row shape validation and add focused missing/non-string regression cases.
|
|
|
|
## Baseline/current and scope evidence
|
|
|
|
Commands were run from `/data/project_roots/PlantAI-dev`. This workspace has no
|
|
functional Git repository, so the review-package baselines were used exactly as
|
|
directed:
|
|
|
|
```bash
|
|
diff -u /tmp/ppi-id-resolution-task3-baseline/run.py skills/ppi/run.py
|
|
diff -u /tmp/ppi-id-resolution-task3-baseline/pipeline_backend.py apps/web/pipeline_backend.py
|
|
diff -u /tmp/ppi-id-resolution-task3-baseline/test_ppi_string_policy.py tests/unit/test_ppi_string_policy.py
|
|
```
|
|
|
|
The expected exit status for changed pairs was `1`. The policy test pair was
|
|
identical (exit `0`). Complete-file inspection was performed for the new
|
|
`gfa_core/string_rate_gate.py` and `tests/unit/test_ppi_id_resolution.py` files.
|
|
The implementation changes are confined to the Task 3 allowlist:
|
|
|
|
- `skills/ppi/run.py`: typed API, relationship origins, deterministic candidate
|
|
resolution, selected-ID network submission, per-relationship report, and
|
|
empty-network handling.
|
|
- `gfa_core/string_rate_gate.py`: shared flock/timestamp pacing.
|
|
- `apps/web/pipeline_backend.py`: one import and the active optional STRING
|
|
image helper's injected client/gate plus `PlantAI` identity.
|
|
- `tests/unit/test_ppi_id_resolution.py`: new offline protocol, provenance,
|
|
execution, and multiprocessing tests.
|
|
- `.superpowers/sdd/task-3-report.md`: implementation record.
|
|
|
|
No Reset API, frontend labels, contract/diagnosis, broad Ortholog redesign, or
|
|
unrelated backend production change appears in the Task 3 baseline diff.
|
|
|
|
## Fresh required verification
|
|
|
|
### Focused Task 3 suite
|
|
|
|
```bash
|
|
/home/xia-lab/miniconda3/envs/test4py311/bin/python -m pytest \
|
|
tests/unit/test_ppi_id_resolution.py tests/unit/test_ppi_string_policy.py -q
|
|
```
|
|
|
|
Exit code: `0`
|
|
|
|
```text
|
|
collected 43 items
|
|
tests/unit/test_ppi_id_resolution.py ...............................
|
|
tests/unit/test_ppi_string_policy.py ............
|
|
43 passed in 0.62s
|
|
```
|
|
|
|
### Explicit no-live-network rerun
|
|
|
|
I reran the same 43 tests after replacing `socket.socket.connect` with a
|
|
function that raises `AssertionError("live network blocked by verifier")`.
|
|
|
|
Exit code: `0`
|
|
|
|
```text
|
|
43 passed in 0.57s
|
|
```
|
|
|
|
This establishes that the focused unit suite, including its forked-process
|
|
rate-gate checks, does not contact STRING or any other live network service.
|
|
|
|
### Relevant backend PPI/image selection
|
|
|
|
```bash
|
|
/home/xia-lab/miniconda3/envs/test4py311/bin/python -m pytest \
|
|
tests/unit/test_pipeline_backend_execution_env.py \
|
|
-k 'string_network_image or ppi' -q
|
|
```
|
|
|
|
Exit code: `0`
|
|
|
|
```text
|
|
collected 31 items / 5 deselected / 26 selected
|
|
26 passed, 5 deselected in 5.65s
|
|
```
|
|
|
|
### Syntax compilation
|
|
|
|
```bash
|
|
/home/xia-lab/miniconda3/envs/test4py311/bin/python -m py_compile \
|
|
gfa_core/string_rate_gate.py skills/ppi/run.py apps/web/pipeline_backend.py
|
|
```
|
|
|
|
Exit code: `0`; no output.
|
|
|
|
### Combined regression
|
|
|
|
```bash
|
|
/home/xia-lab/miniconda3/envs/test4py311/bin/python -m pytest \
|
|
tests/unit/test_id_resolution.py \
|
|
tests/unit/test_ppi_id_resolution.py \
|
|
tests/unit/test_ppi_string_policy.py \
|
|
tests/unit/test_pipeline_backend_execution_env.py -q
|
|
```
|
|
|
|
Exit code: `0`
|
|
|
|
```text
|
|
collected 86 items
|
|
86 passed in 6.59s
|
|
```
|
|
|
|
Pytest/import startup consistently emitted the pre-existing
|
|
`RequestsDependencyWarning` for the environment's installed urllib3 and
|
|
character-detection package versions. It did not affect any assertion.
|
|
|
|
## Direct production `PpiSkill.run()` probe
|
|
|
|
An independent temporary-file probe invoked the unmodified production
|
|
`PpiSkill.run()` with injected local fake STRING clients. It did not call the
|
|
network and verified all of the following in one run:
|
|
|
|
- 24 canonical-to-reference relationships remain 24 TSV data rows.
|
|
- The 24 origins collapse to 12 unique reference queries.
|
|
- Five reference queries resolve from raw versioned XP evidence and seven only
|
|
from local numeric GeneID fallback.
|
|
- `get_network()` receives exactly 12 deduplicated selected STRING IDs, not raw
|
|
XP IDs, local GeneIDs, or 24 duplicated relationship values.
|
|
- A valid `network -> []` returns stage success with
|
|
`network_status=empty_network` and a header-only
|
|
`protein1/protein2/score` TSV.
|
|
- Zero resolved STRING IDs return `status=error` with
|
|
`ppi_string_id_resolution_failed` and do not call `get_network()`.
|
|
- A network `StringApiError(kind="http", status_code=503)` propagates as that
|
|
typed external API failure and is not converted to empty-network success.
|
|
|
|
Exit code: `0`
|
|
|
|
```text
|
|
DIRECT_PROBE_PASS 24_relationships 12_queries 5_raw 7_geneid; empty_network_success; zero_resolution_short_circuit; api_failure_typed
|
|
```
|
|
|
|
## Other requirement evidence
|
|
|
|
- `PpiSkill.run()` constructs origins from exact versioned Ortholog references,
|
|
calls the integrated resolver, writes one summary row per retained
|
|
relationship, and submits `resolution.selected_string_ids` to the network
|
|
call.
|
|
- Candidate probes and final selected STRING IDs are deduplicated while origin
|
|
rows are not. Conflicting local candidates and conflicting Ortholog
|
|
references remain explicit; converging references remain resolved.
|
|
- Mapping `404` and `200 []` are zero-resolution responses. Other HTTP,
|
|
transport, JSON, and the currently validated protocol failures remain typed.
|
|
- `network -> []` and network HTTP failure follow distinct paths.
|
|
- Version discovery accepts both `stable_address` and
|
|
`string_stable_address`; identifier endpoints use POST, mapping uses
|
|
`echo_query=1`, scientific calls use `caller_identity=PlantAI`, and the
|
|
request timeout is 30 seconds.
|
|
- `StringRateGate` uses the common default/env-selected timestamp path,
|
|
`fcntl.flock`, an atomically replaced timestamp file, a one-second production
|
|
interval, and injectable clock/sleeper. Scientific API calls pass through it
|
|
in `_request_json`; every optional image/SVG attempt calls the same gate type.
|
|
Fresh real multiprocessing tests verified scientific/scientific and
|
|
scientific/image serialization.
|
|
|
|
## Scope and residual validation
|
|
|
|
- No production or test source file was edited during verification. This
|
|
verification document is the only created file.
|
|
- No live STRING call, backend service execution, Celery restart, or full real
|
|
job was performed. Those are explicitly deferred to Task 6; Task 3 uses
|
|
realistic local fakes and temporary data.
|
|
- Task 3 cannot pass until malformed mapping rows lacking a valid
|
|
`preferredName` are rejected with a typed protocol error and covered by a
|
|
regression test.
|