Phase 7 — Godot Headless Calibration
Goal: The Rust abstract sim is a high-throughput lab, not ground truth for complex physics/AI. Calibrate a few golden cells against headless Godot before full-matrix sign-off.
Skill Chain: godot-testing-patterns (seeded RNG, N-frame gameplay sim) → godot-builder (GODOT_PATH, headless CLI).
When required
- Any Godot project where threat/agency resolution depends on physics, navigation, AnimationTree, or non-trivial AI.
- After large extract/sim refactors.
- Optional skip only if Phase 0 declared the game fully formulaic (pure Resource math, no physics) — document the waiver in
BALANCE_PLAN.md.
Procedure
- Pick 3–5 golden cells (session × style × loadout) spanning easy/mid/hard and weak/strong styles.
- Implement a headless Godot runner (GUT test or
--script) that:- Seeds RNG the same way the game does in shipping builds.
- Drives a bot approximating the cell's
PlayStyle(reaction delay / miss rates as best-effort). - Emits win/grade/time JSON compatible with json-schema.md cell fields.
- Run the abstract sim on the same cells with the same
--seedand ≥300 runs (1000 preferred). - Compare win rates (and key texture metrics if available).
Pass criteria
| Check | Default tolerance |
|---|---|
| |p̂_sim − p̂_godot| | ≤ 5–10 percentage points (lock in Phase 0) |
| Grade mean / fail-kind ranking | Same ordinal story (not bit-identical) |
| Systematic bias all cells same direction | FAIL — model bug, not noise |
If outside tolerance: fix extract (missed coeff) or sim fidelity before trusting matrix-wide verdicts.
CLI shape
balance-lab calibrate --cells tools/balance_lab/golden_cells.json --runs 500
# Internally: rust matrix subset + invokes Godot headless; prints delta table + PASS/FAILNEVER
- NEVER claim “mathematically balanced” from an uncalibrated abstract model of physics-heavy combat.
- NEVER require bit-identical Godot vs Rust — require decision-same (bands/tolerance).
- NEVER calibrate only the pro style — include a weak style cell.