Spaces:
Sleeping
Sleeping
| # Prompt β merge "GP's top programs" + "Coordinated modules" into ONE sortable "Groups the engine explored" table | |
| Replace the two overlapping panels with a single table of the groups the GP explored, sortable by four lenses: **GP fitness** (the engine's own pick order), **Combined AUROC**, **Coherence**, **Synergy**. Drop the separate "GP's top programs" block. This supersedes PROMPT_synergy_lens.md and the top-10 panel from PROMPT_gp_top10_groups.md. Read the named code first; verified line refs below. Airgap unchanged. `pytest` + `tsc` after. | |
| GUIDING IDEA: the groups in this table ARE the GP's explored groups (harvested from the population). "GP fitness" sort = the engine's own preference (its picks); the other three are re-score lenses. One table, same groups, selectable lens β this dissolves the "is this from the GP or not" confusion. | |
| ## Part 1 β API: add GP fitness per module | |
| In `api/app.py` `_compute_module_ranking` (~line 1244): it already harvests distinct gene-sets from the run's population (`run.log` candidates), and each candidate carries `fitness`. While harvesting, record per gene-set the **max GP fitness** among candidates with that set; add `gp_fitness: float | None` to each module dict in the payload. No other endpoint change. (Airgap unchanged β fitness is a number, no gene names.) | |
| - `web/lib/api.ts`: add `gp_fitness?: number | null` to the module type (`ModuleRanking` per-module entry, near `combined_holdout` ~line 295). | |
| ## Part 2 β Frontend: one merged table (enhance `ModuleRankingPanel`, ~3521-4100) | |
| - **Sorts (four).** Extend `SortKey` (currently `"combined" | "coherence"`, ~3940) to add `"gp_fitness"` and `"synergy"`. Wire all four into the sort comparator (~3975-3984) and the sort-button row (~4089-4098). Labels: "GP fitness", "Combined AUROC", "Coherence", "Synergy". **Default sort = `gp_fitness`** (so the default view is the engine's own preference order β what the old top-programs panel showed). | |
| - **Columns.** Add **GP fitness** (from the new field) and **Synergy** columns alongside the existing Combined AUROC / Coherence / Size / Genes / Survives. `synergy = m.combined_holdout β max(g.single_gene_metric over m.per_gene)`; guard nulls β "β" and sort to the bottom (both fields already on the row). | |
| - **Keep everything the panel already does:** winner badge (`isWinnerSet`, ~3596) on the winner's gene-set row; SurvivalChips (preβpost `full β subgroup`); inline gene symbols (auto-revealed per page); expand β per-gene single-gene AUROC + rank; pagination. | |
| - **Retitle + caption (plain English):** title e.g. **"Groups the engine explored"**. Caption: "Every gene group the engine tried during the search. Sort by **GP fitness** (what the engine itself preferred β its picks), **Combined AUROC** (the group's average score on held-out patients), **Coherence** (how tightly the genes move together), or **Synergy** (how much the group beats its best single gene). The winning program is badged. The Survives flags show whether a group still separates HPV under the confound checks." | |
| - **"?" tooltip:** explain the four lenses plainly, and keep the winner's-curse caveat for the re-score lenses: "Combined AUROC / Coherence / Synergy re-score ~2,900 groups on the same small held-out set, so their very top values are optimistically biased β the **GP fitness** order (and the badged winner) is the engine's own, cross-validated pick; trust it as the reliable choice." | |
| ## Part 3 β remove the now-duplicate "GP's top programs" block | |
| In `ResultPanel` (~line 1983): remove the "The GP's top programs" block (the top-10-by-fitness list added previously). Its job is now done by sorting the merged table by GP fitness, with per-gene ranks available on expand and the winner badged. Keep the metric cards (Held-out, Permutation p, Nodes, Genes) as the headline. Add one line under the cards pointing down: "The winning program is badged in **Groups the engine explored** below." Remove any fetches in ResultPanel that existed only to feed the deleted block (the merged table fetches its own data); leave the rest intact. | |
| ## Part 4 β leave the other panels alone | |
| - "Known-marker recovery" (single-gene markers-only diagnostic) is unchanged. | |
| - No engine/GP-search change; this is presentation + one additive API field. | |
| ## CONSTRAINTS | |
| - Airgap absolute: module payload stays opaque-ID + scores + `gp_fitness` + survival; symbols revealed only for displayed rows (bounded, as today). Engine/GP search untouched (detection unaffected). | |
| - Defaults: colorectal + non-HNSC behaviour unchanged; existing tests + airgap tests green. | |
| ## Checkpoint | |
| - One "Groups the engine explored" table with four sorts (GP fitness default), GP-fitness + Synergy columns added, winner badged, survival chips, expand-for-per-gene-ranks, pagination. | |
| - Sorting by GP fitness reproduces the engine's preference order (the old top-programs list); sorting by Synergy sinks ZFR2+passenger groups and surfaces additive ones. | |
| - The separate "GP's top programs" block is gone; Result cards keep the headline + a pointer to the table. | |
| - `pytest` green, `tsc` clean, airgap untouched. | |