Phase 53: C2 & AI Completeness¶
Status: Complete Tests: 44 new Files modified: 6 source + 1 new test file Deficits resolved: 7 (D12, E8, Phase 19 school_id, Phase 19 get_stratagem_affinity, Phase 25 C2 effectiveness, Phase 25 stratagem affinity, Phase 25 school_id auto-assignment)
Summary¶
Wired 5 orphaned C2/AI engines into the simulation loop and replaced hardcoded C2 effectiveness with a comms-based computation. FogOfWarManager now updates per-side detection pictures (gated by enable_fog_of_war calibration flag). StratagemEngine evaluates concentration/deception opportunities in the DECIDE phase with school affinity weights. ATOPlanningEngine generates ATO for aerial units in strategic ticks. IadsEngine is instantiated and SEAD parameters are wired. C2 effectiveness is computed from average channel reliability to friendly units.
53b: C2 Effectiveness¶
- Added
compute_c2_effectiveness()toCommunicationsEngine - Computes average channel reliability to friendly units
- Replaces hardcoded
c2_effectiveness = 1.0in battle.py OBSERVE phase and fallback assessment - New calibration field:
c2_min_effectiveness(default 0.3) _compute_c2_effectiveness()helper in battle.py wraps the comms engine call
Resolves: Phase 25 deficit (C2 effectiveness hardcoded at 1.0).
53c: StratagemEngine + school_id¶
StratagemEngineinstantiated in_create_engines(), attached toSimulationContextasstratagem_engineevaluate_concentration_opportunity()andevaluate_deception_opportunity()called in DECIDE phase with school affinity weightsschool_idfromCommanderPersonalityauto-assigns viaSchoolRegistryin_apply_commander_assignments()
Resolves: Phase 19 deficits (school_id dead, get_stratagem_affinity never called), Phase 25 deficit (stratagem affinity wiring).
53a: FogOfWarManager¶
- FoW
update()called per-side inexecute_tick, gated byenable_fog_of_warcalibration flag (default False) - OBSERVE phase uses detected enemy count when fog of war is enabled
- New calibration field:
enable_fog_of_war - Backward compatible: disabled by default, existing scenarios unchanged
Resolves: D12 (per-commander assessment unimplemented).
53e: SEAD/IADS + Escalation¶
IadsEngineinstantiated in_create_engines(), attached toSimulationContextasiads_enginesead_effectivenessandsead_arm_effectivenessadded toIadsConfig- Both wired into
apply_sead_damage()for SEAD strike resolution PoliticalPressureEngine.update()called in_update_escalation()with per-side casualty data
Resolves: E8 (4 SEAD/IADS params — sead_effectiveness, sead_arm_effectiveness, iads_degradation_rate wired; drone_provocation_prob accessible).
53d: Structural Wiring¶
ATOPlanningEngineinstantiated in_create_engines(), attached toSimulationContextasato_engine- Aerial units auto-registered with ATO engine
generate_ato()called in strategic tickPlanningProcessEngine.update()called in strategic tickOrderPropagationEngineavailability logged in DECIDE phase
Files Changed¶
| File | Action | Changes |
|---|---|---|
c2/communications.py |
Modified | Added compute_c2_effectiveness() method |
simulation/calibration.py |
Modified | Added c2_min_effectiveness, enable_fog_of_war fields |
simulation/battle.py |
Modified | FoW update in execute_tick, C2 effectiveness in OBSERVE, stratagem eval + order prop logging in DECIDE, _compute_c2_effectiveness() helper |
simulation/scenario.py |
Modified | Added stratagem_engine, iads_engine, ato_engine fields to SimulationContext + instantiation in _create_engines() + school_id auto-assignment in _apply_commander_assignments() |
simulation/engine.py |
Modified | planning_engine.update(), ATO generation, political_engine.update() in _update_escalation() |
combat/iads.py |
Modified | Added sead_effectiveness, sead_arm_effectiveness to IadsConfig, modified apply_sead_damage() |
tests/unit/test_phase53_c2_ai.py |
New | 44 tests |
Lessons Learned¶
- Comms-based C2 effectiveness is the right abstraction: Average channel reliability captures the essence of C2 degradation (jammed/disrupted comms = degraded C2) without needing per-unit path tracing.
- Calibration flag gating (enable_fog_of_war) preserves backward compat: All existing scenarios run identically with the flag defaulting to False. Individual scenarios opt in.
- school_id auto-assignment in post-creation hook is clean:
_apply_commander_assignments()runs after all entities are created, so SchoolRegistry lookup works reliably. - SEAD params on IadsConfig (not CalibrationSchema) is the right home: These are engine-specific parameters that belong on the engine config, not the global calibration schema.
Postmortem¶
Delivered vs Planned¶
- 53a (FoW): Delivered. Gated by calibration flag, per-side detection in OBSERVE phase.
- 53b (C2 effectiveness): Delivered.
compute_c2_effectiveness()replaces hardcoded 1.0. - 53c (Stratagem + school_id): Delivered. Both evaluate_* methods called in DECIDE, school_id auto-assigns.
- 53d (ATO + planning + order prop): Delivered structurally. ATO generates in strategic tick, planning engine updates, order prop logged.
- 53e (SEAD/IADS + escalation): Delivered. IadsEngine instantiated, SEAD params wired, political pressure engine called.
- Scope: 44 tests vs planned ~51. Slightly under but all substeps covered.
Integration Audit¶
compute_c2_effectiveness()called from battle.py OBSERVE phasestratagem_engineinstantiated and evaluated in DECIDE phaseato_engineinstantiated and generates ATO in strategic tickiads_engineinstantiated, SEAD params consumed inapply_sead_damage()enable_fog_of_warcalibration flag read inexecute_tick()school_idauto-assigned via SchoolRegistry in_apply_commander_assignments()political_engine.update()called in_update_escalation()
Deficits Discovered¶
sead_arm_effectivenessdefined on IadsConfig but never consumed — onlysead_effectivenessis used inapply_sead_damage(). The ARM missile Pk modifier needs a consumer in the SEAD strike path.drone_provocation_probin CalibrationSchema but never consumed by any engine — no escalation trigger integration point exists for drone encounters.