Summary
Provide a minimal, dependency-free adapter for CI, deterministic tests, and server/headless runs.
Objective
Implement HeadlessAdapter that records render commands (no GPU), simulates input via scripted events, and provides deterministic execution for reproducible integration tests.
Implementation Status
| Component |
Status |
Notes |
HeadlessAdapter |
✅ Complete |
Implements all Phase 1 contracts |
HeadlessRenderProvider |
✅ Complete |
Records sprites, texts, and meshes in separate typed lists |
HeadlessInputProvider |
✅ Complete |
Stateful, scriptable input (HashSet-based) |
HeadlessUserInterfaceProvider |
✅ Complete (stub) |
Empty pending UI contract finalisation |
HeadlessAssetProvider + HeadlessAssetLoader |
✅ Complete |
In-memory cache; stub loader |
HeadlessAudioPlayer |
✅ Complete |
Records calls with correct method names (StartPlayback/StopPlayback) |
RecordedCall DTO |
✅ Complete |
|
TestAdapter |
✅ Complete |
Records both lifecycle and all provider calls via wrapper providers |
DeterministicEngineRunner |
✅ Complete |
Frame loop runs; SimulationTime exposed; RNG accessible; onTick callback provided |
| Integration test suite |
✅ Complete |
AI, combat, and map-generation scenario tests all passing (132 tests total) |
Technical Details
HeadlessAdapter implements IEngineAdapter and composes all headless providers. No native platform dependencies.
HeadlessRenderProvider records SubmitSprite, SubmitText, and SubmitMesh calls to separate typed lists (RecordedSprites, RecordedTexts, RecordedMeshes).
HeadlessInputProvider maintains scriptable key and mouse button state via sets of strings and integers.
HeadlessAudioPlayer records calls as (Method, AudioAssetId, Arg) tuples with correct method name strings.
TestAdapter wraps HeadlessAdapter and records both adapter lifecycle calls (InitializeAsync, ShutdownAsync) and all provider method calls via recording wrapper providers (RecordingRenderProvider, RecordingInputProvider, RecordingAssetProvider, RecordingAudioPlayer).
DeterministicEngineRunner stores a fixed timestep and seeded RNG. Exposes SimulationTime (incrementing after each frame), Random (seeded RNG for caller access), and accepts optional per-step onTick callback receiving DeterministicTickContext with time, RNG, and adapter.
- Integration Tests:
AiIntegrationTests.NpcScenario_IsDeterministic: Verifies deterministic sprite generation with seeded RNG
CombatIntegrationTests.CombatScenario_IsDeterministic: Verifies deterministic call ordering via TestAdapter
CombatIntegrationTests.CombatScenario_AudioOnEvenStepsOnly: Verifies audio call recording and filtering
MapGenerationIntegrationTests.MapScenario_Produces1000Meshes: Verifies mesh recording and count stability
MapGenerationIntegrationTests.MapScenario_IsDeterministic: Verifies deterministic mesh generation with seeded RNG
Requirements
- ✅ Headless adapter passes integration scenarios for AI, combat and map generation.
- GIVEN deterministic seeds and scenario scripts
- WHEN CI runs integration suite
- THEN results are stable and asserted by tests.
- All integration tests pass; results are verified as deterministic across multiple runs.
Outstanding Tasks
None. Phase 2 is complete.
Acceptance Criteria
Dependencies
Parent: #2
Phase 1 interfaces: complete (#1)
Summary
Provide a minimal, dependency-free adapter for CI, deterministic tests, and server/headless runs.
Objective
Implement
HeadlessAdapterthat records render commands (no GPU), simulates input via scripted events, and provides deterministic execution for reproducible integration tests.Implementation Status
HeadlessAdapterHeadlessRenderProviderHeadlessInputProviderHeadlessUserInterfaceProviderHeadlessAssetProvider+HeadlessAssetLoaderHeadlessAudioPlayerStartPlayback/StopPlayback)RecordedCallDTOTestAdapterDeterministicEngineRunnerSimulationTimeexposed; RNG accessible;onTickcallback providedTechnical Details
HeadlessAdapterimplementsIEngineAdapterand composes all headless providers. No native platform dependencies.HeadlessRenderProviderrecordsSubmitSprite,SubmitText, andSubmitMeshcalls to separate typed lists (RecordedSprites,RecordedTexts,RecordedMeshes).HeadlessInputProvidermaintains scriptable key and mouse button state via sets of strings and integers.HeadlessAudioPlayerrecords calls as(Method, AudioAssetId, Arg)tuples with correct method name strings.TestAdapterwrapsHeadlessAdapterand records both adapter lifecycle calls (InitializeAsync,ShutdownAsync) and all provider method calls via recording wrapper providers (RecordingRenderProvider,RecordingInputProvider,RecordingAssetProvider,RecordingAudioPlayer).DeterministicEngineRunnerstores a fixed timestep and seeded RNG. ExposesSimulationTime(incrementing after each frame),Random(seeded RNG for caller access), and accepts optional per-steponTickcallback receivingDeterministicTickContextwith time, RNG, and adapter.AiIntegrationTests.NpcScenario_IsDeterministic: Verifies deterministic sprite generation with seeded RNGCombatIntegrationTests.CombatScenario_IsDeterministic: Verifies deterministic call ordering viaTestAdapterCombatIntegrationTests.CombatScenario_AudioOnEvenStepsOnly: Verifies audio call recording and filteringMapGenerationIntegrationTests.MapScenario_Produces1000Meshes: Verifies mesh recording and count stabilityMapGenerationIntegrationTests.MapScenario_IsDeterministic: Verifies deterministic mesh generation with seeded RNGRequirements
Outstanding Tasks
None. Phase 2 is complete.
Acceptance Criteria
HeadlessAdapterimplements all Phase 1 contracts.TestAdapteravailable for recording and asserting adapter calls.Dependencies
Parent: #2
Phase 1 interfaces: complete (#1)