Spaces:
Running
Running
docs: per-scenario closer-look checklist distilled from #1 and #2
Browse filesReproducible solvency/stability/capability methodology + the defect
patterns already seen, so per-scenario review agents look for and
test the same things.
- SCENARIO_REVIEW_CHECKLIST.md +138 -0
SCENARIO_REVIEW_CHECKLIST.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Per-Scenario Closer-Look Checklist
|
| 2 |
+
|
| 3 |
+
The reproducible methodology applied to #1 (action-multiunit-coordination)
|
| 4 |
+
and #2 (action-sequenced-execution). Every remaining active pack gets
|
| 5 |
+
the same treatment: **closer look โ fix defects โ re-verify โ run each
|
| 6 |
+
difficulty easyโmediumโhard on the model โ inspect the playback โ
|
| 7 |
+
commit/push**. Read this fully before touching a pack.
|
| 8 |
+
|
| 9 |
+
Guiding principle: **the benchmark must validly test its stated
|
| 10 |
+
capability; do NOT compensate for model weakness, and do NOT
|
| 11 |
+
over-engineer.** A model failing a correctly-designed scenario is a
|
| 12 |
+
*good* result (real discrimination). Only fix genuine scenario defects.
|
| 13 |
+
|
| 14 |
+
---
|
| 15 |
+
|
| 16 |
+
## A. SOLVENCY โ can the intended strategy actually win, in budget?
|
| 17 |
+
|
| 18 |
+
1. **The win predicate must enforce the advertised capability โ and
|
| 19 |
+
only that.** The classic defect: the prose claims X but the win
|
| 20 |
+
condition is satisfiable without doing X.
|
| 21 |
+
- #1: "split the force" but `reach_region` (โฅ1 unit) let one
|
| 22 |
+
touring unit win โ switched to `units_in_region_gte` (โฅ2 in EACH
|
| 23 |
+
region).
|
| 24 |
+
- #2: "ordered route" but only the *final* region was a predicate โ
|
| 25 |
+
a beeline that skipped every waypoint won โ added the stateful
|
| 26 |
+
`waypoint_sequence` latch (Wk+1 only counts after Wk; skip /
|
| 27 |
+
out-of-order / idle โ never satisfied).
|
| 28 |
+
- Ask: "what is the laziest play that satisfies this win condition?"
|
| 29 |
+
If it isn't the intended capability, the predicate is wrong.
|
| 30 |
+
2. **Is the optimal/intended play winnable within the tick budget?**
|
| 31 |
+
Estimate path length; engine advances **~90 ticks per decision
|
| 32 |
+
turn** (`tick โ 93 + 90ยท(turn-1)`). The intended strategy must
|
| 33 |
+
finish comfortably under `within_ticks`; the *inefficient* strategy
|
| 34 |
+
must NOT (that gap is the discrimination).
|
| 35 |
+
3. **Coordinate-blind objectives must be solvable.** If
|
| 36 |
+
`objective_coords: relative`, the model can't cell-count โ it needs
|
| 37 |
+
a feedback loop (an `enemy_building_spotted` interrupt revealing the
|
| 38 |
+
marker, a landmark building at each region) and a forgiving enough
|
| 39 |
+
radius. A "search band" beats a bare compass word.
|
| 40 |
+
4. **Map fits the actors.** Every actor/region coordinate must be
|
| 41 |
+
inside the map's playable bounds. Actors at scout-arena coords on a
|
| 42 |
+
rush-hour map โ engine panic. Confirm `compiled.map_supported` and
|
| 43 |
+
that `base_map` resolves to the *intended* map.
|
| 44 |
+
|
| 45 |
+
## B. STABILITY โ deterministic, no crashes, fail is reachable
|
| 46 |
+
|
| 47 |
+
5. **Non-win must be a real LOSS, not a draw.** Every level needs a
|
| 48 |
+
`fail_condition`. Idiom: `any_of[ {after_ticks: BUDGET+1},
|
| 49 |
+
{not:{units_lost_lte: N}}, {not:{own_units_gte: 1}} ]`.
|
| 50 |
+
6. **Tick/turn alignment (critical, easy to get wrong).** A
|
| 51 |
+
`fail after_ticks: K` only bites if K is reachable within
|
| 52 |
+
`max_turns`: require `K โค 93 + 90ยท(max_turns-1)`. Likewise the
|
| 53 |
+
episode must be able to reach `within_ticks` before `max_turns`
|
| 54 |
+
ends, or a staller draws instead of losing. Re-derive this for
|
| 55 |
+
every level after any budget/turn change.
|
| 56 |
+
7. **`base_map` override goes INSIDE `overrides:`** โ a Level-level
|
| 57 |
+
`base_map` key is silently ignored (it's not a `Level` field).
|
| 58 |
+
8. **Smoke the engine path before a full run**: compile the level,
|
| 59 |
+
`_scenario_to_tmp_yaml`, `RustEnvPool` reset(seed) + a few
|
| 60 |
+
`env.step`; if the pack enables interrupts, also drive
|
| 61 |
+
`raw_env.step_until_event([...],None,5,[sig])` ~30 steps โ catches
|
| 62 |
+
panics/oob without burning a model run.
|
| 63 |
+
9. **Hard-tier spawn contract**: if the pack is in
|
| 64 |
+
`tests/test_hard_tier.py::UPGRADED`, `hard` must keep โฅ2
|
| 65 |
+
`spawn_point` groups (seed-varied start). A deliberate exception is
|
| 66 |
+
allowed only with a stated reason added to `NOT_APPLICABLE`.
|
| 67 |
+
|
| 68 |
+
## C. CAPABILITY โ clean difficulty axis, faithful framing
|
| 69 |
+
|
| 70 |
+
10. **One new controlled variable per tier** so a tier failure
|
| 71 |
+
attributes to a single capability. easy = the bare skill; medium =
|
| 72 |
+
+1 axis (a third region / parallel split / contest / attrition);
|
| 73 |
+
hard = +1 more (relative coords + scouting, larger map, strict
|
| 74 |
+
budget). Avoid stacking uncontrolled variables.
|
| 75 |
+
11. **Keep established idioms** (e.g. the single-final-region +
|
| 76 |
+
`[after_ticks, within_ticks]` band for "execute, don't stall";
|
| 77 |
+
fact+proc key-building destruction for adversarial). Don't invent a
|
| 78 |
+
new mechanism when one exists โ but DO add a reusable predicate /
|
| 79 |
+
engine feature when the capability genuinely can't be expressed
|
| 80 |
+
(`units_in_region_gte`, `waypoint_sequence`, `enemy_building_
|
| 81 |
+
spotted` interrupt, scripted `enemy.bot`).
|
| 82 |
+
12. **Title/description are plain and self-explanatory**; the
|
| 83 |
+
objective brief the model sees (`game_knowledge.objective_brief`)
|
| 84 |
+
must state the exact machine win/fail in plain language with no
|
| 85 |
+
degenerate lines.
|
| 86 |
+
|
| 87 |
+
## D. RUN & INSPECT (one difficulty at a time)
|
| 88 |
+
|
| 89 |
+
13. Run on **`qwen/qwen3.6-flash`** via OpenRouter (key in `./.env`,
|
| 90 |
+
git-ignored): `python3 -m openra_bench.run_eval --packs
|
| 91 |
+
openra_bench/scenarios/packs/<pack>.yaml --levels <lvl> --seeds 1
|
| 92 |
+
--provider openrouter --model qwen/qwen3.6-flash --playback
|
| 93 |
+
playback/run1`. easy, then medium, then hard.
|
| 94 |
+
14. **Inspect the playback** (`playback/run1/*/<pack>:<lvl>:public/
|
| 95 |
+
seed1/`): `manifest.json` (outcome/turns), `score.json`
|
| 96 |
+
(composite/weakest_link/speed), `turns.jsonl` (per-turn `units`,
|
| 97 |
+
`enemies`, `signals`, `interrupt`, `goal`), `messages.json` (model
|
| 98 |
+
text is in the **`reasoning`** field, not `content`). Reconstruct:
|
| 99 |
+
did the intended mechanism fire? final positions vs win regions?
|
| 100 |
+
`units_lost`? terminal "episode end" frame present?
|
| 101 |
+
15. **Classify the outcome**: scenario defect (โ fix, re-verify, re-run)
|
| 102 |
+
vs legitimate model failure (โ record as valid discrimination, no
|
| 103 |
+
change). Cite evidence from the playback.
|
| 104 |
+
|
| 105 |
+
## E. RE-VERIFY & SHIP
|
| 106 |
+
|
| 107 |
+
16. `python3 -m pytest tests/ -q` fully green (add/extend focused
|
| 108 |
+
tests for any new predicate/knob/scenario behaviour).
|
| 109 |
+
17. `python3 scripts/gen_scenario_docs.py` (regenerate the HTML
|
| 110 |
+
catalog) when prose/objectives change.
|
| 111 |
+
18. Commit per fixed scenario, **no Claude co-author line**, using
|
| 112 |
+
`git -c commit.gpgsign=false commit`. Then
|
| 113 |
+
`git fetch -q origin && git rebase -q origin/main && git push -q
|
| 114 |
+
origin HEAD`. Engine changes (OpenRA-Rust) commit+push separately;
|
| 115 |
+
rebuild the wheel (`maturin develop --release`) if the engine
|
| 116 |
+
changed and re-run the affected scenario.
|
| 117 |
+
19. Record a "Per-scenario closer look โ #N" note in
|
| 118 |
+
`SCENARIO_QUALITY.md` (the defect found, the fix, the
|
| 119 |
+
easy/medium/hard outcomes + verdict).
|
| 120 |
+
|
| 121 |
+
## Reference: defect patterns already seen
|
| 122 |
+
|
| 123 |
+
- Win condition doesn't enforce the stated capability (laziest play
|
| 124 |
+
wins). โ #1, #2
|
| 125 |
+
- `reach_region`/single-region where a *split* or *ordered* visit is
|
| 126 |
+
intended. โ #1, #2
|
| 127 |
+
- Missing `fail_condition` โ non-win == draw. โ #1, #2
|
| 128 |
+
- `after_ticks` fail unreachable within `max_turns` (tick/turn
|
| 129 |
+
misalignment). โ #2
|
| 130 |
+
- Relative objective too literal ("NE corner" โ map extreme), region
|
| 131 |
+
inset & unreachable blind, landmark fogged โ unfair. โ #1 hard
|
| 132 |
+
- `base_map` at Level level silently ignored. โ #2 hard
|
| 133 |
+
- Actors placed off the resolved map โ engine panic in the interrupt
|
| 134 |
+
path. โ #2 hard
|
| 135 |
+
- Bench advertises a tool the engine can't execute (1:1 parity). โ
|
| 136 |
+
capture_actor / S8
|
| 137 |
+
- Inert deadline (`within_ticks` โซ optimal) โ no anti-stall teeth. โ
|
| 138 |
+
#1 easy, #2 easy (acceptable for *easy* only).
|