Phase 80: API & Frontend Sync¶
Status: Complete Date: 2026-03-24
Goal¶
Bring API schemas and frontend components current with engine state. Fix scenario data issues. Add enable_all_modern convenience meta-flag and calibration exercise scenarios.
Changes¶
80a: API Schema Updates¶
api/schemas.py: Addedhas_space: bool = Falseandhas_dew: bool = FalsetoScenarioSummary. Added docstring toRunSubmitRequest.config_overridesdocumenting CalibrationSchema fields.api/routers/scenarios.py: Wiredhas_spaceandhas_dewdetection in_extract_summary()using same"space_config" in cfgpattern as existing flags.
80b: CalibrationSliders Overhaul¶
frontend/src/pages/editor/CalibrationSliders.tsx: Complete rewrite — replaced 4 hardcoded sliders with 29enable_*toggles in 7 collapsible groups + ~40 numeric sliders in 7 groups. Added "Enable All Modern" master toggle that sets 21 non-deferred flags. Uses native<details>/<summary>for accessibility.frontend/src/types/api.ts: Addedhas_space,has_dewtoScenarioSummaryinterface.frontend/src/types/editor.ts: WidenedSET_CALIBRATIONvalue type fromnumbertonumber | boolean.
80c: Scenario Data Fixes¶
stochastic_warfare/simulation/calibration.py: Addedenable_all_modern: bool = Falsemeta-flag withmodel_post_initvalidator that sets 21 validatedenable_*flags viaobject.__setattr__(). 7 deferred flags (enable_fuel_consumption,enable_ammo_gate,enable_command_hierarchy,enable_carrier_ops,enable_ice_crossing,enable_bridge_capacity,enable_environmental_fatigue) intentionally excluded.data/scenarios/eastern_front_1943/scenario.yaml: Replaced WW1 weapon IDs (lee_enfield,gewehr_98,mills_bomb) with new WW2 equivalents (mosin_nagant,kar98k,ppsh41,stielhandgranate,rgd33).data/scenarios/golan_heights/scenario.yaml: Added explicitvictory_conditionssection (force_destroyed, morale_collapsed, time_expired at 18h).
80d: WW2 Small Arms Data¶
Created 10 new YAML files:
- Weapons (5): kar98k.yaml, mosin_nagant.yaml, ppsh41.yaml (guns); stielhandgranate.yaml, rgd33.yaml (explosives — new explosives/ subdir)
- Ammo (5): 792x57mm_mauser.yaml, 762x54r.yaml, 762x25mm_tokarev.yaml, stielhandgranate_charge.yaml, rgd33_charge.yaml
80e: Calibration Exercise Scenarios¶
Created 3 scenarios exercising 16 CalibrationSchema fields never set to non-default values:
- calibration_arctic: Arctic infantry patrol — exercises cold_casualty_base_rate, night_thermal_floor, wind_accuracy_penalty_scale, rain_attenuation_factor, dig_in_ticks, observation_decay_rate
- calibration_urban_cbrn: Urban CBRN response — exercises gas_casualty_floor, gas_protection_scaling, heat_casualty_base_rate, c2_min_effectiveness, engagement_concealment_threshold, fire_damage_per_tick
- calibration_air_ground: Air-ground combined arms — exercises cloud_ceiling_min_attack_m, icing_maneuver_penalty, planning_available_time_s, disable_threshold, wave_interval_s, target_selection_mode
Test Summary¶
| Test File | Tests | Verifies |
|---|---|---|
tests/unit/test_phase80_api_frontend_sync.py |
18 | Schema fields, enable_all_modern, scenario data, weapon YAML |
frontend/src/__tests__/pages/CalibrationSliders.test.tsx |
8 | Component rendering, toggle dispatch, slider dispatch, reducer |
| Total | 26 |
Files Changed¶
New files (15): - 5 weapon YAML + 5 ammo YAML + 3 scenario YAML + 1 Python test + 1 frontend test
Modified files (20):
- stochastic_warfare/simulation/calibration.py — enable_all_modern meta-flag
- api/schemas.py — has_space, has_dew, config_overrides docstring
- api/routers/scenarios.py — has_space, has_dew wiring
- frontend/src/types/api.ts — has_space, has_dew
- frontend/src/types/editor.ts — SET_CALIBRATION boolean value
- frontend/src/pages/editor/CalibrationSliders.tsx — full overhaul
- data/scenarios/eastern_front_1943/scenario.yaml — WW2 weapon IDs
- data/scenarios/golan_heights/scenario.yaml — victory_conditions
- frontend/src/__tests__/pages/ScenarioListPage.test.tsx — has_space/has_dew in mocks
- frontend/src/__tests__/api/scenarios.test.ts — has_space/has_dew in mocks
- frontend/src/__tests__/hooks/useScenarios.test.ts — has_space/has_dew in mocks
- frontend/src/__tests__/pages/BatchPanel.test.tsx — has_space/has_dew in mocks
- tests/validation/test_historical_accuracy.py — 3 calibration scenarios in DRAW_SCENARIOS
- tests/validation/test_phase_67_structural.py — enable_all_modern in deferred flags + calibration.py in consumer search
- CLAUDE.md, README.md, docs/index.md, docs/devlog/index.md, docs/development-phases-block8.md, mkdocs.yml — lockstep
Lessons Learned¶
- Duplicate group names in toggle+slider sections cause test failures: "Environment" appeared in both toggle and slider groups —
getByTextthrows on duplicates. UsegetAllByTextor rename one group. - Pydantic frozen models need
object.__setattr__:model_post_initruns after validation, but the model is frozen — direct attribute assignment raises.object.__setattr__bypasses the descriptor. - AmmoType enum doesn't have BALL: Existing small arms ammo uses
APtype. Non-enum ammo types cause silent failures in some code paths. - WW2 ammunition lives in
ammunition/notammo/: Directory naming inconsistency vs the plan spec. Always check existing structure before creating files.
Known Limitations¶
- Nested morale calibration fields (
morale.base_degrade_rate, etc.) not exposed in CalibrationSliders UI — top-levelmorale_degrade_rate_modifiercovers 90% of use cases subsystem_weibull_shapes,posture_*_protection,target_value_weights,victory_weights,side_overridesrequire specialized dict-editor UI — deferred- Calibration exercise scenarios are for field coverage, not validation — correct winner is less important than exercising non-default parameter paths
Postmortem¶
1. Delivered vs Planned¶
Plan (from development-phases-block8.md):
- 80a: API schema updates (has_space, has_dew) — Delivered
- 80b: CalibrationSliders overhaul (29 toggles + ~40 sliders) — Delivered
- 80c: Scenario data fixes (eastern_front_1943, golan_heights, enable_all_modern, 3 exercise scenarios) — Delivered
- Plan expected ~18 tests — Delivered 26 (18 Python + 8 frontend)
Unplanned additions: - 10 WW2 weapon/ammo YAML (plan mentioned creating WW2 weapon data but didn't enumerate all 10 files individually) - 6 regression fixes to pre-existing test mocks (ScenarioListPage, BatchPanel, scenarios.test.ts, useScenarios.test.ts, test_historical_accuracy, test_phase_67_structural)
Descoped: Per-side override sliders (dict-editor UI) — correctly deferred per plan.
Verdict: Scope well-calibrated. Minor regression fixes expected when adding fields to shared types.
2. Integration Audit¶
| Item | Wired? | Evidence |
|---|---|---|
enable_all_modern meta-flag |
Yes | Consumed by model_post_init in calibration.py, tested in 3 unit tests |
has_space / has_dew |
Yes | Schema → router → frontend types, 4 test files updated |
| CalibrationSliders component | Yes | Imported by ScenarioEditorPage, 8 component tests |
| WW2 weapon YAML | Yes | Referenced in eastern_front_1943/scenario.yaml weapon_assignments |
| WW2 ammo YAML | Yes | Referenced by weapon compatible_ammo fields |
| Calibration exercise scenarios | Yes | Validated by test_phase_30_scenarios, tracked in DRAW_SCENARIOS |
No dead modules. All new files are imported/referenced by at least one consumer.
3. Test Quality Review¶
- Integration tests:
test_phase80_api_frontend_sync.pycovers cross-layer paths (API schema → router wiring, CalibrationSchema → enable_all_modern, scenario YAML → weapon data) - Realistic data: Tests use actual scenario YAML files and real pydantic models, not trivial mocks
- Edge cases: Deferred flag exclusion tested (7 flags verified as False), empty calibration_overrides handled
- Frontend tests: Cover both reducer-level (unit) and component-level (integration) paths
- No slow tests — all run in <2s
4. API Surface Check¶
enable_all_modernfield: type-hinted, default=False,model_post_initis a standard pydantic methodhas_space/has_dew: type-hinted asbool = FalseonScenarioSummary- No new public functions — only new pydantic fields and a
model_post_initoverride - No bare
print()— all logging via existing patterns
5. Deficit Discovery¶
No new deficits. Known limitations (nested morale UI, dict-editor types) are already documented and deferred to Phase 82+ if needed.
6. Documentation Freshness¶
| Doc | Accurate? | Notes |
|---|---|---|
| CLAUDE.md phase summary | Yes | Phase 80 row with correct test count and deliverables |
| devlog/index.md | Yes | Phase 80 row added |
| development-phases-block8.md | Yes | Status → Complete |
| README.md | Yes | Badge updated to 10,167 tests, phase 80, phases 75-80 added to table |
| docs/index.md | Yes | Test count updated to ~10,490, scenario count to 44 |
| mkdocs.yml | Yes | Phase 80 devlog nav entry added |
| MEMORY.md | Yes | Status and phase summary table updated |
| User-facing docs | N/A | No new modules/engines/eras — scenarios guide, API ref, units ref unchanged |
7. Performance Sanity¶
Full test suite: 9,853 passed in ~31 min (1,878s). This is consistent with previous phases — no performance regression. New tests add <1s total.
8. Summary¶
- Scope: On target — all planned items delivered + expected regression fixes
- Quality: High — 26 tests, no TODOs, no dead code
- Integration: Fully wired — every new artifact consumed by at least one path
- Deficits: 0 new items
- Action items: None — ready for commit