re: making turrets targets does not save the escort — the effect is inside the noise
The Stage-02 outcome write-up ended by naming "turrets near the asset must become targets" as the fix worth ~50% of the escort damage. That was an inference from a co-presence attribution, not a measurement. Run it and it does not hold. Also corrects the run labelling: pilot.py gained the SYLPH_KILL_TURRETS gate two minutes before mission02 started, so mission02 was already a treatment run, not a second baseline. Only mission01 (0 of 3968 pilot frames targeting a turret) is the baseline. At a common t=428s: baseline 46.9% escort hull, treatment 44.5% and 53.0%. The two runs of the same arm differ by more than either differs from the baseline, and the escort still reaches zero at t~590-670s in all three. So the transferable finding is the power limit: one 430s flight cannot resolve an effect below ~9 percentage points, and every single-run pilot conclusion, including this one's, is inside it. What does reproduce: the assault is scripted (onset 166/167/166s), and the e007/e010 damage split is 50/50 in all three arms including the one that never fires at a turret -- so that attribution measures the wave script, not us. Also records that the viewer's include_external hypothesis in BACKLOG is dead (it defaults true and is threaded through unchanged).
This commit is contained in:
@@ -58,3 +58,26 @@ class cannot hide behind `e106` passing.
|
||||
handedness, node-instance recursion) is not re-breaking a correct assembly — compare
|
||||
the viewer's placement against `assemble_ship`'s output directly before blaming the
|
||||
format layer.
|
||||
|
||||
---
|
||||
|
||||
## Viewer: `include_external` is already on — that hypothesis is dead
|
||||
|
||||
**Checked 2026-08-11.** The item above names "first that it passes
|
||||
`include_external = true` (`iso_loader.rs:4012`)" as the cheap first step. It
|
||||
does: `ShipBrowser::show_external` defaults to `true`
|
||||
(`iso_loader.rs:643`), the checkbox reads it (`ui.rs:1593`) and it is threaded
|
||||
through `RequestShipRender` → `build_ship_model` → `assemble_ship` unchanged
|
||||
(`ui.rs:1689`, `iso_loader.rs:4012`). So a ship rendered by the viewer is the
|
||||
full external assembly, not the bare hull.
|
||||
|
||||
The viewer also does not have a transform stack of its own to blame: it bakes
|
||||
`ScenePart::apply` straight into the vertices and rotates normals by the same
|
||||
`p.m` (`iso_loader.rs:4030-4062`), so its placement is `assemble_ship`'s output
|
||||
by construction. What remains unexcluded, in order of cheapness: the mirror
|
||||
handling (`det < 0` reverses triangle winding only — a reflected part keeps its
|
||||
reflected geometry), `Xbg7Model::models_named` resolving the wrong sub-model when
|
||||
a resource name repeats, and the exhaust cones. **Next step is a visual**: the
|
||||
diagnosis has run out of things it can settle by reading, so the viewer needs to
|
||||
be run against a known-good class (`e106`) and its render compared with
|
||||
`ship_render`'s.
|
||||
|
||||
161
docs/re/captures/escort-decay-ab.csv
Normal file
161
docs/re/captures/escort-decay-ab.csv
Normal file
@@ -0,0 +1,161 @@
|
||||
run,turret_rule,t_s,acropolis_hull,e007_alive,e007_killed_cum
|
||||
mission01,off,0,25000.0,0,0
|
||||
mission01,off,10,25000.0,5,0
|
||||
mission01,off,20,25000.0,6,0
|
||||
mission01,off,30,25000.0,6,0
|
||||
mission01,off,40,25000.0,6,0
|
||||
mission01,off,50,25000.0,8,0
|
||||
mission01,off,60,25000.0,11,0
|
||||
mission01,off,70,25000.0,11,3
|
||||
mission01,off,80,25000.0,8,3
|
||||
mission01,off,90,25000.0,8,3
|
||||
mission01,off,100,25000.0,10,3
|
||||
mission01,off,110,25000.0,14,3
|
||||
mission01,off,120,25000.0,16,3
|
||||
mission01,off,130,25000.0,17,3
|
||||
mission01,off,140,25000.0,20,3
|
||||
mission01,off,150,25000.0,23,3
|
||||
mission01,off,160,25000.0,26,4
|
||||
mission01,off,170,24509.5,33,4
|
||||
mission01,off,180,24509.5,37,4
|
||||
mission01,off,190,24419.5,38,5
|
||||
mission01,off,200,24212.5,41,5
|
||||
mission01,off,210,23447.5,40,5
|
||||
mission01,off,220,23447.5,40,5
|
||||
mission01,off,220,23447.5,40,5
|
||||
mission01,off,230,23447.5,41,5
|
||||
mission01,off,230,23447.5,41,5
|
||||
mission01,off,240,22912.0,43,5
|
||||
mission01,off,240,22867.0,43,5
|
||||
mission01,off,250,22667.0,42,6
|
||||
mission01,off,250,22647.0,42,6
|
||||
mission01,off,260,22334.5,44,6
|
||||
mission01,off,260,22177.9,44,6
|
||||
mission01,off,270,21101.2,46,6
|
||||
mission01,off,270,21101.2,45,6
|
||||
mission01,off,280,20292.6,46,6
|
||||
mission01,off,280,20279.1,46,6
|
||||
mission01,off,290,19598.5,58,6
|
||||
mission01,off,290,19598.5,58,6
|
||||
mission01,off,300,18725.2,58,6
|
||||
mission01,off,300,18658.5,47,6
|
||||
mission01,off,310,18231.9,47,6
|
||||
mission01,off,310,18231.9,47,6
|
||||
mission01,off,320,17425.2,47,6
|
||||
mission01,off,330,17046.9,49,6
|
||||
mission01,off,340,16044.8,49,7
|
||||
mission01,off,350,15461.5,50,7
|
||||
mission01,off,360,14956.3,51,7
|
||||
mission01,off,370,14425.5,51,8
|
||||
mission01,off,380,13910.5,51,8
|
||||
mission01,off,390,13418.9,49,11
|
||||
mission01,off,400,13218.9,45,12
|
||||
mission01,off,410,12517.9,44,12
|
||||
mission01,off,420,12161.3,44,13
|
||||
mission01,off,430,11601.3,44,13
|
||||
mission02,on,0,25000.0,0,0
|
||||
mission02,on,10,25000.0,5,0
|
||||
mission02,on,20,25000.0,6,0
|
||||
mission02,on,30,25000.0,5,0
|
||||
mission02,on,40,25000.0,5,1
|
||||
mission02,on,50,25000.0,7,1
|
||||
mission02,on,60,25000.0,10,1
|
||||
mission02,on,70,25000.0,7,4
|
||||
mission02,on,80,25000.0,7,4
|
||||
mission02,on,90,25000.0,7,4
|
||||
mission02,on,100,25000.0,7,4
|
||||
mission02,on,110,25000.0,9,4
|
||||
mission02,on,120,25000.0,14,4
|
||||
mission02,on,130,25000.0,16,4
|
||||
mission02,on,140,25000.0,19,4
|
||||
mission02,on,150,25000.0,19,4
|
||||
mission02,on,160,25000.0,23,5
|
||||
mission02,on,170,24730.0,28,5
|
||||
mission02,on,180,24730.0,32,5
|
||||
mission02,on,190,24730.0,36,5
|
||||
mission02,on,200,24640.0,43,6
|
||||
mission02,on,210,24190.0,46,6
|
||||
mission02,on,220,24055.0,47,6
|
||||
mission02,on,220,24055.0,47,6
|
||||
mission02,on,230,24055.0,49,6
|
||||
mission02,on,230,24055.0,49,6
|
||||
mission02,on,240,23474.5,52,6
|
||||
mission02,on,240,23474.5,52,6
|
||||
mission02,on,250,23474.5,53,6
|
||||
mission02,on,250,23474.5,53,6
|
||||
mission02,on,260,23474.5,54,6
|
||||
mission02,on,260,23474.5,54,6
|
||||
mission02,on,270,22697.0,54,6
|
||||
mission02,on,270,22697.0,54,6
|
||||
mission02,on,280,22091.2,56,6
|
||||
mission02,on,280,22091.2,55,7
|
||||
mission02,on,290,21577.9,55,7
|
||||
mission02,on,290,21555.4,55,7
|
||||
mission02,on,300,20799.1,56,7
|
||||
mission02,on,310,19781.1,55,7
|
||||
mission02,on,320,18925.8,56,8
|
||||
mission02,on,330,18592.5,56,8
|
||||
mission02,on,340,17432.5,57,8
|
||||
mission02,on,350,16932.6,59,8
|
||||
mission02,on,360,16171.6,58,9
|
||||
mission02,on,370,15017.6,58,11
|
||||
mission02,on,380,14217.2,59,11
|
||||
mission02,on,390,13322.2,59,12
|
||||
mission02,on,400,12808.9,58,13
|
||||
mission02,on,410,12090.6,61,16
|
||||
mission02,on,420,11440.6,66,19
|
||||
mission02,on,430,11127.3,55,19
|
||||
mission03,on,0,25000.0,0,0
|
||||
mission03,on,10,25000.0,3,0
|
||||
mission03,on,20,25000.0,8,0
|
||||
mission03,on,30,25000.0,5,0
|
||||
mission03,on,40,25000.0,6,0
|
||||
mission03,on,50,25000.0,8,0
|
||||
mission03,on,60,25000.0,9,0
|
||||
mission03,on,70,25000.0,16,0
|
||||
mission03,on,80,25000.0,10,0
|
||||
mission03,on,90,25000.0,11,0
|
||||
mission03,on,100,25000.0,10,2
|
||||
mission03,on,110,25000.0,15,2
|
||||
mission03,on,120,25000.0,12,2
|
||||
mission03,on,130,25000.0,10,4
|
||||
mission03,on,140,25000.0,11,6
|
||||
mission03,on,150,25000.0,14,6
|
||||
mission03,on,160,25000.0,17,7
|
||||
mission03,on,170,24685.0,24,7
|
||||
mission03,on,180,24640.0,23,7
|
||||
mission03,on,190,24640.0,27,7
|
||||
mission03,on,200,24460.0,26,8
|
||||
mission03,on,210,24100.0,28,8
|
||||
mission03,on,220,24100.0,29,9
|
||||
mission03,on,230,24100.0,28,11
|
||||
mission03,on,230,24100.0,28,11
|
||||
mission03,on,240,23810.0,35,11
|
||||
mission03,on,240,23810.0,36,11
|
||||
mission03,on,250,23630.0,36,12
|
||||
mission03,on,250,23630.0,36,12
|
||||
mission03,on,260,23630.0,38,13
|
||||
mission03,on,260,23630.0,38,13
|
||||
mission03,on,270,22998.0,39,13
|
||||
mission03,on,270,22908.0,39,13
|
||||
mission03,on,280,22197.5,40,13
|
||||
mission03,on,280,22188.5,40,13
|
||||
mission03,on,290,21602.4,38,13
|
||||
mission03,on,290,21602.4,38,13
|
||||
mission03,on,300,21042.4,39,13
|
||||
mission03,on,300,20975.8,39,13
|
||||
mission03,on,310,20529.1,41,15
|
||||
mission03,on,310,20529.1,41,15
|
||||
mission03,on,320,19812.5,38,17
|
||||
mission03,on,320,19767.5,38,17
|
||||
mission03,on,330,19434.2,39,18
|
||||
mission03,on,340,18785.9,37,19
|
||||
mission03,on,350,18339.2,37,19
|
||||
mission03,on,360,17528.1,38,19
|
||||
mission03,on,370,16901.5,37,19
|
||||
mission03,on,380,16260.7,35,19
|
||||
mission03,on,390,15708.2,37,19
|
||||
mission03,on,400,15346.2,37,19
|
||||
mission03,on,410,14412.1,36,20
|
||||
mission03,on,420,13951.9,37,22
|
||||
mission03,on,430,13211.9,35,23
|
||||
|
BIN
docs/re/captures/mission03-turretrule-t430.png
Normal file
BIN
docs/re/captures/mission03-turretrule-t430.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
@@ -66,6 +66,8 @@ the mission scores **objectives** and **the escort**, and the fighter population
|
||||
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
|
||||
@@ -87,3 +89,93 @@ 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.
|
||||
|
||||

|
||||
|
||||
## 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.
|
||||
|
||||
@@ -47,7 +47,7 @@ python3 "$SD/mission_state.py" watch "$OUT/cfg.json" "$SECS" 2 "$OUT/mission.jso
|
||||
> "$OUT/mission.log" 2>&1 &
|
||||
WATCHER=$!
|
||||
|
||||
python3 "$SD/pilot.py" "$OUT/cfg.json" "$SECS" > "$OUT/pilot.log" 2>&1
|
||||
SYLPH_KILL_TURRETS="${SYLPH_KILL_TURRETS:-0}" python3 "$SD/pilot.py" "$OUT/cfg.json" "$SECS" > "$OUT/pilot.log" 2>&1
|
||||
PILOT_RC=$?
|
||||
wait $WATCHER 2>/dev/null
|
||||
kill $SHOTTER 2>/dev/null
|
||||
|
||||
@@ -100,6 +100,18 @@ MISSILE_PERIOD = 2.0 # s between launches; 300 rounds is not unlimited
|
||||
# configuration here — override with $SYLPH_ASSET for another stage.
|
||||
ASSET_NAME = os.environ.get("SYLPH_ASSET", "Acropolis")
|
||||
|
||||
# Turrets are keep-out zones everywhere else in this file, and that rule is what
|
||||
# stopped the pilot being shot down. But the 2026-08-10 outcome run measured the
|
||||
# cost of it: of the damage that sinks the ACROPOLIS, roughly half comes from
|
||||
# e007 turrets sitting 1.5-3 km off it (the other half from e010 bombers), and a
|
||||
# turret is 100 HP -- one missile, or ~7 nose-gun hits. Several were already at
|
||||
# 45-95 HP from stray fire and were never finished off, because nothing ever
|
||||
# targets them. So the rule that keeps us alive is also what loses the escort.
|
||||
# Gated rather than simply changed, so the measured baseline stays reproducible:
|
||||
# SYLPH_KILL_TURRETS=1 lets DEFEND -- and only DEFEND -- treat a turret that is
|
||||
# near the asset as a target. ENGAGE still avoids them.
|
||||
KILL_TURRETS = os.environ.get("SYLPH_KILL_TURRETS") == "1"
|
||||
|
||||
|
||||
class Pilot:
|
||||
KP, KD = 2.2, 0.45
|
||||
@@ -230,7 +242,9 @@ class Pilot:
|
||||
"""
|
||||
out = []
|
||||
for off, nm, p, v, r, hard in hos:
|
||||
if hard:
|
||||
# A turret near the asset IS a killable objective (100 HP) when
|
||||
# SYLPH_KILL_TURRETS is set; a capital hull never is.
|
||||
if hard and not (KILL_TURRETS and "Turret" in nm):
|
||||
continue
|
||||
rel = a_p - p
|
||||
d = float(np.linalg.norm(rel))
|
||||
@@ -520,9 +534,12 @@ class Pilot:
|
||||
self.set_throttle(0)
|
||||
fire = True
|
||||
|
||||
# a turret inside its keep-out radius outranks the target
|
||||
# A turret inside its keep-out radius outranks the target -- except the
|
||||
# one we are deliberately attacking, or the keep-out would steer us off
|
||||
# the very thing we chose to kill and neither goal would be served.
|
||||
tgt_off = tgt[0] if tgt else None
|
||||
for off, nm, p, v, r, hard in hos:
|
||||
if not hard:
|
||||
if not hard or (KILL_TURRETS and off == tgt_off):
|
||||
continue
|
||||
d = float(np.linalg.norm(p - me_p))
|
||||
if d < self.TURRET_KEEPOUT:
|
||||
|
||||
Reference in New Issue
Block a user