# Prompt — raise caps, spell out "GP" as "genetic programming", and add DSL operator-usage Three changes, verified against the code (`web/app/Lab.tsx`, `api/app.py`, `engine_v2/gp.py`). Airgap untouched. `pytest` + `tsc` after. ## 1. Raise the Generations / Population ceilings (web/app/Lab.tsx) The parameter list (~lines 1202-1208) caps `generations` at `max: 100` and `population` at `max: 500`. Raise both: - `generations` → `max: 1000` - `population` → `max: 3000` Keep them BOUNDED (not removed) so an accidental huge value can't hang the backend. Leave min/step and the other params unchanged. (Context, not a code requirement: with the current early convergence, more generations alone won't help much — the useful long run is "Maintain diversity" ON + larger population.) ## 2. Spell out "GP" as "genetic programming" in all USER-FACING copy (web/app/Lab.tsx) Replace the abbreviation everywhere it appears in visible text — captions, tooltips, headings, labels, axis titles, sort buttons, table headers. Use "genetic programming" in prose; for the compact fitness label use **"Genetic-programming fitness"** (hyphenated; wraps fine). Known locations (search for `GP` to catch any others): - Parameters subtitle (~1222): "GP knobs…" → "Genetic-programming knobs…" - Run subtitle (~1374): "Starts a GP run on the backend." → "Starts a genetic-programming run on the backend." - Copy/tooltips at ~197, 227, 244, 2119, 2588-2591, 4012, 4586 → "genetic programming" / "the genetic-programming search". - The **"GP fitness"** label everywhere shown: the sort-key label (~4617 `["gp_fitness", "GP fitness"]`), the table header (~4682 `GP fitness`), the scatter axis title (~4233), the scatter heading (~4008 "Landscape — GP fitness × Synergy"), the median-guide label (~4185), and the tooltip dt (~4407) → **"Genetic-programming fitness"** (scatter heading → "Genetic-programming fitness × Synergy"; axis → "Genetic-programming fitness — what the engine preferred →"). - Code COMMENTS that say "GP" (~286, 2160, 2237, 2435, 3800, 4156) are not user-facing — optional. **Do NOT change the internal field/key name `gp_fitness`** (API contract) — only human-readable labels. ## 3. DSL operator-usage across the whole search (API + frontend) Show, after a run completes, how often each DSL operator (Select, Reduce, Combine, Split, Associate, Effect, Fit/Apply, Search) was used across **every candidate program in every generation** (Generations × population). Airgap-safe — operator names are DSL keywords, no gene names. ### 3a. API — new endpoint `GET /runs/{run_id}/operator-usage` Mirror `_compute_module_ranking` (which already walks `run.log`): - Iterate every candidate in every persisted generation (`run.log[*].candidates`). Each candidate has a `program_repr` string (e.g. `Combine(Reduce(Select(M,[…]),min),Reduce(Select(M,[…]),var),protected_div)`; built in `engine_v2/gp.py` ~line 132). - Per operator, count occurrences of its token `Name(` in `program_repr` — `Select(`, `Reduce(`, `Combine(`, `Split(`, `Associate(`, `Effect(`, `FitApply(`, `Search(`. (Matching `Name(` avoids false hits; `MatrixTerminal`/`M` is not an operator.) Sum across ALL candidates across ALL generations. - Return per operator: `total_uses` (sum of occurrences) and `programs_using` (count of candidate-instances containing it ≥ once); plus run totals (`n_generations`, `n_candidates`). Note that persistent elites are counted once per generation they appear in (the "Generations × population" grid the user asked for). - Opaque/airgap-safe (operator keywords + integer counts only). Cache per run; 425 while running, 404 unknown. ### 3b. Frontend — show it on the "DSL vocabulary" tiles After a run completes, fetch `/runs/{id}/operator-usage` and on each operator tile show its usage: - Under each description: **"used 12,431× — in 38% of programs"** (`total_uses`, and `programs_using / n_candidates`). - A small inline bar per tile (relative to the most-used operator) so the distribution is scannable — Select/Reduce dominate; Effect/Split/Fit-Apply/Search are rare or 0 (Search off by default → 0). - Before a run / while running, tiles show just descriptions (gate the counts to a completed run). - Tile-panel "?" / caption: "Counts every use of each operator across all programs the search tried (generations × population). Select and Reduce are the backbone; Effect, Split, Fit/Apply and Search appear only where the engine reached for them." ## CONSTRAINTS - Airgap: the operator-usage endpoint emits keywords + counts only — no gene IDs/names. Engine/GP search untouched. `gp_fitness` data key unchanged. - Frontend reads the new endpoint; no change to the run flow. ## Checkpoint - Generations accepts up to 1000, Population up to 3000. - No visible "GP" remains in the UI ("genetic programming" / "Genetic-programming fitness"); `gp_fitness` key unchanged. - `GET /runs/{id}/operator-usage` returns per-operator counts over all generations × population, opaque-safe; tiles show count + share + bar after a completed run (Search reads 0 when off). - `pytest` green; airgap untouched; `tsc` clean.