# Why Stage 02 is never won — the escort sinks at ~11 minutes (2026-08-10) **Status: ✅ measured, one 500 s run.** The standing open item since 2026-07-29 was "no mission completed". This is the first session whose deliverable was the *ending* rather than a measurement, and it settles why: **the mission is lost before it can be won, and the pilot's survival policy is what guarantees it.** Run: `tools/re-capture/mission_run.sh 500 mission01` — boot → Stage 02 in flight → `pilot.py` (escort-weighted targeting, target commitment, guided missiles) for 500 s, with every entity's hull sampled at 2 Hz and a screenshot every 30 s. Artifacts at `/sylph-home/re/mission01/` (9 MB `mission.jsonl`, not committed). ## The escort's decay is linear, and it ends the mission | t (s) | ACROPOLIS hull | % | |---|---|---| | 0–160 | 25000 | 100 % | | 180 | 24510 | 98.0 | | 280 | 20279 | 81.1 | | 380 | 13799 | 55.2 | | 480 | 8541 | 34.2 | | 485 (end) | 8182 | 32.7 | Untouched until **t ≈ 170 s**, then **≈53 HP/s** with no let-up — so the asset reaches zero at **t ≈ 640 s**, and the whole-run average rate puts it at 722 s. Either way the escort is dead at **10–12 minutes**, and "the ACROPOLIS is sunk" is a defeat condition ([mission-escort-state](mission-escort-state.md)). This also retires a suspicion: the 240 s time-box of earlier runs was *not* hiding a win, and the ~500 s ceiling of a single blocking tool call is **not** the binding constraint. A longer session would simply watch the loss arrive. ## What is actually killing it — and the conflict that follows Attributing damage by co-presence (which hostiles are within 3000 units of the asset in the sample where its hull drops, damage split evenly among the classes present — suggestive, not per-shot proof), only **two** classes are ever near it: | class | samples present | attributed damage | |---|---|---| | `UN_e007_ADAN_Turret` | 200 | 8483 | | `UN_e010_ADAN_Attacker_S` | 194 | 8334 | Roughly half the damage comes from **turrets** — and `pilot.py` treats turrets as **keep-out zones at 2500 units, never as targets**. That rule is not arbitrary: a turret is what shot down every pilot before 2026-07-30, and it is why the craft now survives. But it means **the policy that keeps the pilot alive also guarantees the escort dies.** Survival and the objective are in direct conflict, and the pilot currently resolves it entirely in favour of survival. The HUD at t≈485 s says the same thing from the game's side: - `YOU KILLED WARSHIPS` **0000** — not one warship in 500 s, across every run ever; - `YOU KILLED WARPLANES` **0009** — fighters only; - `REMAINING OB` **004 → 008** — objectives are being *added* by waves faster than any are cleared, so the pilot is not touching the objective set at all; - SHIELD and ARMOR bars full, hull **1500/1500**, 120 missiles spent. ![Stage 02 at t≈485 s](captures/mission01-t485.png) ## The conclusion that matters The pilot optimises the wrong thing. It maximises survival and fighter kills; the mission scores **objectives** and **the escort**, and the fighter population (134 → 92) is close to irrelevant to both. An untouched 1500/1500 hull at the moment the escort passes 33 % is not a good run — it is **unspent risk budget**. Concretely, for the next attempt, in priority order: (**Step 1 below was run on 2026-08-11 and did not hold — see the follow-up A/B at the end of this file before acting on it.**) 1. **Turrets near the asset must become targets**, not keep-out zones — accepting hull damage is the only way to cut ~50 % of the incoming escort damage. The keep-out rule should be scoped to turrets that are *not* threatening the asset, rather than applied globally. 2. **Engage warships.** `WARSHIPS 0000` forever means the objective class has never been attacked; `REMAINING OB` rising is the scoreboard saying so. 3. Re-check whether the escort damage rate actually falls once turrets die — that is the experiment that tells us whether (1) is sufficient or whether the bombers need dedicated intercept too. ## Method note, learned the hard way A harness-tracked **background** task does *not* protect the display: the same run launched in the background lost Xvfb 11 s in, at the turn boundary (`skip_intro` exit 3, "DISPLAY LOST"). The comment in `launch_mission.sh` saying the script may be run as a tracked background task is **wrong**; the one-blocking-foreground-call rule still stands, which caps a single attempt at the tool's 600 s timeout. And do not pipe a long run through `tail` — the first attempt printed nothing because `timeout` killed the pipeline before it flushed; the on-disk artifacts are what survived. --- # Follow-up A/B (2026-08-11): making turrets targets does **not** save the escort **Status: ✅ measured (3 runs), and it falsifies the causal claim above.** The section above ends by naming step 1 — "turrets near the asset must become targets" — as the fix worth ~50 % of the escort damage. That was an *inference from an attribution*, never a measurement. It has now been run, and it does not hold. ## First, a correction to the run labelling `pilot.py` gained the `SYLPH_KILL_TURRETS` gate at 21:20:28 on 2026-08-10; `/sylph-home/re/mission02` started at **21:22:25**, i.e. *after* it, with the gate **on**. So `mission02` was never a second baseline — it is a treatment run that the previous session produced but never reported. The arms are: | run | turret rule | evidence (`pilot.log`) | |---|---|---| | `mission01` | **off** (baseline) | `tgt=e007` on **0** of 3968 lines | | `mission02` | **on** | `tgt=e007` on 1588 of 3844 lines | | `mission03` | **on** (this session) | `tgt=e007` on 1218 of 3514 lines | `mission01` predates the edit, so the *only* difference between the arms is the gate. Everything else — build, save slot, nav route, loadout — is identical. ## The result, all three runs truncated to a common t = 428 s | run | rule | ACROPOLIS @428 s | % | decay rate | turrets seen | turrets killed | attack onset | |---|---|---|---|---|---|---|---| | `mission01` | off | 11735 | 46.9 % | 50.3 HP/s | 92 | 30 | 166 s | | `mission02` | on | 11127 | 44.5 % | 52.7 HP/s | 98 | 34 | 167 s | | `mission03` | on | 13257 | 53.0 % | 44.4 HP/s | 88 | 41 | 166 s | **The two runs of the *same* arm differ by 8.5 percentage points (2130 HP) — more than either differs from the baseline.** The baseline sits *between* the two treatment runs on escort hull and on decay rate. So the effect of the turret rule is **not resolvable at n=1 per arm**, and the honest statement is: it was not demonstrated. Extrapolating each run's own rate, the escort still reaches zero at **t ≈ 590–670 s** in every arm — the mission is lost in all three. The rule does do the mechanical thing it was written to do (turret kills 30 → 34, 41; 1218–1588 frames spent with a turret as the committed target). It just does not convert into escort hull. ![Stage 02 at t≈430 s with the turret rule on — WARSHIPS 0000, REMAINING OB 008](captures/mission03-turretrule-t430.png) ## What *is* reproducible across all three runs These are the numbers to build on, because they repeat to within a percent: - **The assault on the ACROPOLIS is scripted, not emergent.** Onset at **166 / 167 / 166 s** — ±1 s across three runs with completely different pilot behaviour in between. Nothing the pilot does moves it. - **The damage split is a property of the scenario, not of our targeting.** `e007` turrets vs `e010` bombers is **50.6/49.4, 50.0/50.0, 51.0/49.0** — and the baseline, in which we never fired at a turret at all, splits the same way. A co-presence attribution that is invariant to whether we attack one of the two classes is measuring the wave script, not our contribution. - **Turrets die anyway**: 30 of 92 are already dead by t=428 s in the baseline, from friendly fire. The turret rule adds ~4–11 kills on top of that, which is why its escort-hull effect is small enough to be buried in run-to-run noise. - `WARSHIPS 0000` and `REMAINING OB` rising (004 → 008) in **every** run, including this one. Per-run series: [`captures/escort-decay-ab.csv`](captures/escort-decay-ab.csv) (10 s grid, hull + turret alive/killed counts for all three runs). ## The methodological finding, which is the transferable one **A single 430 s flight cannot resolve an escort-hull effect smaller than ~9 percentage points.** Every pilot conclusion drawn from one run — including step 1 above, and including anything drawn from `mission03` alone — is inside the noise. Each run costs ~10 minutes of wall clock and one blocking foreground call, so a properly powered A/B is ~6 runs ≈ 1 hour. **Any future pilot tuning must budget that, or not be believed.** ## What this means for the reason we wanted a win Story progress was wanted only because unit definitions instantiate per stage, so unit-field coverage is stuck at 21/110 ([unit struct](structures/unit-struct-runtime.md)). This result says the pilot route to that coverage is expensive and unproven: the escort dies on a script at ~10–11 minutes, our best lever moved it by less than the noise, and the objective class (`WARSHIPS`) has never been touched in any run ever. **Before spending another hour on pilot tuning, the cheaper lever to price is the save file** — if the profile's save data can be read and understood, stage unlock state is a much shorter path to the same coverage, and the save format is itself something the reimplementation needs. Marked `NEEDS-HUMAN` as a direction choice; no save-file modification has been attempted.