# Plan: PPI stage-local STRING ID resolution on a reusable job-local alias core _Locked via discussion — Codex + user_ ## Goal Preserve canonical family-member IDs while making PPI resolve target/reference protein IDs through job-local PEP/CDS evidence and the official STRING `get_string_ids` API before network lookup, with explicit provenance and a correct distinction between ID failure, external API failure, and a successful empty network. ## Approach 1. Add a small reusable `gfa_core.id_resolution` module that reads job-local alias evidence and extracts RefSeq protein accession, LOC symbol, and numeric NCBI GeneID without performing network calls. 2. Extend future reference-bundle ID maps with an explicit `ncbi_gene_id` column while remaining compatible with existing maps by parsing `cds_header`. 3. Add typed STRING API methods for `get_string_ids`, `network`, and `version`; use the returned stable version address, POST identifier lists, include `caller_identity`, respect STRING's request interval, and raise structured errors instead of returning an empty list. 4. Replace lossy query lists with explicit relationship records that retain every `canonical target -> versioned Ortholog reference` path; probe raw and GeneID candidates, then deduplicate only the final STRING network query set. 5. Pass the canonical input, exact scope-matched Ortholog relationship, and species-matched job-local ID map through main PPI and PPI Reset. Reset accepts canonical target IDs only, is bound to an exact source `scope_id`, snapshots verified evidence before launch, and rejects undeclared/mixed namespaces or paths outside the job; direct-target Reset validates against its canonical member snapshot without requiring Ortholog. 6. Replace the old terminal mapping-rate threshold with `complete`, nonterminal `partial`, and terminal `failed` resolution states; exclude ambiguous members from network queries. 7. Synchronize the PPI contract, skill docs, persisted success/failure manifests, diagnosis, status, and frontend labels using denominator-defined nested metrics shared by main, scoped, and Reset outputs. 8. Validate with unit/contract/API tests and the full real `Ft.SPL -> soe` job: 24 canonical provenance paths, 12 unique STRING queries, 12/12 query resolution, and `success + empty_network` for zero edges; repeat the scoped Reset path. ## Key decisions & tradeoffs - Canonical `final_members` IDs are immutable; all external IDs are stage-local aliases. - Ortholog relationships are not aliases. - The first release uses the existing job-local `pep_cds_idmap.tsv` plus a reusable parser, not a global database or SQLite registry. - STRING-specific HTTP probing remains in the PPI adapter; generic local alias extraction lives in `gfa_core`. - STRING returns one best match per submitted candidate. If different local candidates for one biological query resolve to different STRING IDs, the query is conflicting/ambiguous and is not silently selected. - Resolution evidence has one summary row per canonical-to-reference relationship. Many canonical members may share one network query; deduplication never removes their provenance rows. - Query resolution and network deduplication are separate metrics: every reference query may resolve even when several converge on one submitted STRING ID. - Partial nonzero ID resolution proceeds with a warning; zero resolved IDs block PPI. The old minimum-count/rate failure threshold is retired for execution decisions. - A normal zero-edge response is success with `network_status=empty_network`; API failure is a separate failure. - Empty networks still emit a header-only `protein1/protein2/score` TSV and a success manifest. Zero resolution and API failures emit failed manifests and nonzero CLI exits. - STRING mapping/network calls use one stable version and validated `queryIndex`/taxon responses. Optional public web/image links are labeled non-authoritative if they are not version-pinned. ## Risks / open questions - STRING mapping aliases and database versions change; every probe must record taxon, version, and evidence. - Existing ID maps lack `ncbi_gene_id`; legacy header parsing must be covered by tests. - Existing PPI code strips protein versions before resolution; exact versions remain primary and versionless forms are lookup aliases only. - PPI Reset currently selects a generic manifest first, accepts a client path, and loses the Ortholog relationship. Its scope/namespace contract must be corrected with the main path. - Direct-target PPI jobs may not have a reference-bundle ID map and must still work through raw-ID probing. - Every active PPI-path STRING HTTP request—including optional image fallbacks—uses one shared interprocess lock/timestamp gate because the light queue can run multiple workers; unit and multiprocessing tests cover the one-second production rule. - The repository has no usable Git metadata, so commit checkpoints cannot be executed in this workspace. ## Out of scope - Ortholog/KaKs reference-state fixes and immutable scoped Ortholog artifacts. - Migration of expression, enrichment, synteny, or other consumers. - Global cross-job ID databases. - Rewriting `final_members`, Ortholog, or KaKs algorithms. - Treating a valid empty PPI network as failure.