# Build the deterministic simulation foundation for the side scroller shooter This ExecPlan is a living document. The sections `Progress`, `Surprises & Discoveries`, `Decision Log`, and `Outcomes & Retrospective` must be kept up to date as work proceeds. `PLANS.md` is checked into the repository root at `PLANS.md`. This document must be maintained in accordance with `PLANS.md`. ## Purpose / Big Picture After this work, the repository will support a classic 2D side scroller shooter whose gameplay rules live in a pure .NET simulation instead of inside Godot scene logic. A developer will be able to run deterministic simulation tests without starting Godot, record and replay exact input streams, save and reload full simulation state, and use Godot only as the host for rendering, audio, input capture, and authoring tools. The change is visible when `dotnet test` can prove gameplay behavior, and when the Godot host can step, pause, fast-forward, and replay the same simulation state hashes for the same seed and inputs. The user-visible outcome is not merely “new projects were added.” The outcome is that the same content, seed, and action stream produce the same gameplay results in both automated tests and the running Godot host. A novice should be able to follow this plan from an empty understanding of the repository and reach that observable result. ## Progress - [x] (2026-04-16 08:24Z) Reviewed `PLANS.md`, the original `groundwork.md`, `SideScrollerGame.sln`, and `godot/SideScrollerGame.Godot.csproj` to anchor this ExecPlan to the current repository state. - [x] (2026-04-16 08:32Z) Rewrote `groundwork.md` as a self-contained ExecPlan with milestones, repository orientation, exact commands, validation guidance, and living-document bookkeeping. - [x] (2026-04-16 08:49Z) Created `src/SideScrollerGame.Sim/SideScrollerGame.Sim.csproj` and `tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj`, added both to `SideScrollerGame.sln`, and wired the Godot and test projects to reference the simulation assembly. - [x] (2026-04-16 08:53Z) Copied the root `FixPoint/*.cs` files into `src/SideScrollerGame.Sim/FixPoint/`, updated the namespace to `SideScrollerGame.Sim.Math`, and added a smoke test proving the simulation project owns the deterministic math layer. - [x] (2026-04-16 09:11Z) Added bootstrap compatibility math types missing from the copied `FixPoint` subset and validated the scaffold with `dotnet build`, `dotnet test`, and `.\godot.cmd --headless --quit --path .\godot --build-solutions`. - [x] (2026-04-16 09:46Z) Implemented the first runnable simulation spine with `Simulation`, `SimulationState`, `WorldSnapshot`, `TickActionBatch`, deterministic fixed-tick movement, deterministic random advancement, and per-tick state hashes. - [x] (2026-04-16 09:46Z) Implemented versioned save/load, replay recording, replay playback, and the `None`, `RoundTripState`, and `RoundTripAndStepClone` verification modes with deterministic unit coverage. - [x] (2026-04-16 10:34Z) Added the first data-driven level runtime slice: world bounds clamping, hazard damage resolution, one-shot trigger activation, and serialization coverage for health plus activated triggers. - [ ] Implement deterministic movement, collision, damage resolution, triggers, and the fixed tick pipeline with exhaustive simulation tests. - [ ] Implement data-driven definitions for heroes, enemies, weapons, projectiles, pickups, modifiers, squads, encounters, and level runtime data. - [ ] Implement Godot host adapters for input translation, fixed-step execution, interpolation, presentation mapping, sound playback, music transitions, and debug transport controls. - [ ] Add compile-time authoring flow from Godot scenes into engine-agnostic runtime content under `content/compiled/`. - [ ] Run the full validation set, update this plan with final outcomes, and keep the plan aligned with the implementation state at every stopping point. ## Surprises & Discoveries - Observation: the repository has already moved the Godot project under `godot/`, so the restructuring work should preserve that host location instead of planning another move. Evidence: `SideScrollerGame.sln` currently references `godot/SideScrollerGame.Godot.csproj`. - Observation: the only deterministic math code in the repository today is the root `FixPoint/` directory, and there is no simulation project yet. Evidence: `rg --files` lists `FixPoint/*.cs`, `godot/SideScrollerGame.Godot.csproj`, `SideScrollerGame.sln`, `PLANS.md`, and `groundwork.md`, but no `src/` or `tests/` projects. - Observation: the repository root contains `godot.cmd`, so all Godot commands in this plan should call that wrapper with `--path .\godot`. Evidence: `rg --files` lists both `godot.cmd` and `godot/project.godot`. - Observation: copied `FixPoint` sources inherit the root files' read-only attribute, so the migration step must clear that attribute before applying namespace edits. Evidence: `Get-Item src/SideScrollerGame.Sim/FixPoint/FixPoint16.cs` reported `Attributes : ReadOnly, Archive` immediately after the copy. - Observation: the root `FixPoint` subset is not self-contained; it references compatibility types such as `IntVector2`, `SInt32Vector2`, `SFixPointQuaternion`, `SFixPointQuaternionTransform`, and `IntMath` that are not present in this repository snapshot. Evidence: the first `dotnet build SideScrollerGame.sln` attempt after the copy failed with CS0246 and CS0103 errors pointing at those missing identifiers inside `FixPointVector2.cs`, `FixPointVector3.cs`, `FixPoint16.cs`, and `FixPoint16Long.cs`. - Observation: `.\godot.cmd --headless --path .\godot --build-solutions` does not terminate on its own in this checkout, but adding `--quit` produces the expected build and exit behavior. Evidence: the plain command timed out after five minutes, while `.\godot.cmd --headless --quit --path .\godot --build-solutions` completed successfully in roughly three seconds. - Observation: the replay and state persistence layer can stay engine-agnostic by serializing fixed-point raw values and action documents through `System.Text.Json`; no Godot serialization hooks were needed for the initial deterministic spine. Evidence: the simulation tests replay hashes successfully after round-tripping `ReplayRecordSerializer` and `Simulation.SaveState` payloads. - Observation: the first meaningful gameplay slice can stay fully data-driven by modeling the level as world bounds plus axis-aligned hazards and triggers, while still preserving deterministic hashes and save/load behavior. Evidence: the latest simulation tests clamp movement to authored bounds, apply hazard damage, and persist activated trigger ids through `Simulation.SaveState`. ## Decision Log - Decision: preserve the original seven-phase technical direction and translate it into milestone-based execution rather than replacing the architecture outright. Rationale: the original groundwork already captured the correct constraints and domain boundaries; rewriting it as an ExecPlan reduces design drift while making the work executable. Date/Author: 2026-04-16 / Codex - Decision: migrate deterministic math into the simulation project by copying `FixPoint/*.cs` into `src/SideScrollerGame.Sim/FixPoint/` first, then retire the root copies only when safe. Rationale: additive migration is safer and more idempotent in this Windows environment, where deletion is restricted and recovery should not depend on rollback commands. Date/Author: 2026-04-16 / Codex - Decision: keep all authoritative gameplay logic and gameplay definitions inside one pure project named `SideScrollerGame.Sim` until a concrete dependency problem appears. Rationale: one simulation assembly is the clearest way to guarantee deterministic tests, shared replay behavior, and a thin Godot host. Date/Author: 2026-04-16 / Codex - Decision: use `godot.cmd` in all concrete steps instead of the shorthand `.\godot`. Rationale: `godot.cmd` is the wrapper that actually exists in this checkout, so the plan must describe commands that a novice can run without guessing aliases. Date/Author: 2026-04-16 / Codex - Decision: keep the migration moving by introducing local compatibility shims for the missing fixed-point support types instead of blocking Milestone 1 on a broader math-library archaeology pass. Rationale: the copied `FixPoint` subset already compiles and is enough for the upcoming deterministic simulation spine, while the shim types can be replaced later if fuller upstream math primitives become necessary. Date/Author: 2026-04-16 / Codex - Decision: use deterministic JSON documents for the first state and replay formats instead of building a custom binary serializer immediately. Rationale: explicit versioned JSON documents are easy to diff, easy to round-trip in tests, and good enough for proving deterministic save/load behavior before optimization work begins. Date/Author: 2026-04-16 / Codex - Decision: start Milestone 4 with axis-aligned world bounds, hazards, and one-shot triggers before tackling richer collision geometry or combat systems. Rationale: this delivers the first data-driven fixed-step gameplay rules with low implementation risk and keeps the deterministic test surface small enough to maintain 100 percent coverage. Date/Author: 2026-04-16 / Codex ## Outcomes & Retrospective At the moment, the outcome is a corrected planning artifact rather than finished gameplay infrastructure. The original groundwork note has been converted into a proper ExecPlan that a future contributor can execute step by step. No simulation code, tests, or host adapters have been implemented yet, so the gap between purpose and delivered software remains the actual implementation work described below. The main lesson from this rewrite is that the repository already contains enough concrete structure to support a precise plan. The plan therefore names real files, current commands, and migration-safe steps instead of speaking in abstract architecture terms. ## Context and Orientation This repository is currently a small Godot 4 .NET project with one solution file, one Godot C# project, and a root folder of fixed-point math helpers. `SideScrollerGame.sln` exists at the repository root and currently includes only `godot/SideScrollerGame.Godot.csproj`. `godot/project.godot` is the Godot project entry point. `godot/SideScrollerGame.Godot.csproj` targets .NET 8 and uses `Godot.NET.Sdk/4.5.1`. The root `FixPoint/` directory contains deterministic numeric helper types such as `FixPoint16.cs`, `FixPointVector2.cs`, and `IntRandom.cs`, but those files are not yet owned by a simulation project. There is no `src/` directory, no `tests/` directory, and no pure gameplay assembly. Several terms matter in this plan and are defined here in plain language. “Authoritative gameplay simulation” means the code that decides what is true in the game world: positions, collisions, damage, enemy behavior, triggers, checkpoints, and progression. “Deterministic” means that if the simulation receives the same content, starting state, random seed, and input actions, it must produce the same results every time, including the same debug hash. A “fixed step” is a simulation update that always advances exactly one sixtieth of a second of game time, regardless of render frame rate. A “replay” is a saved stream of input actions, plus enough metadata to rebuild the same simulation run later. “Compiled runtime content” means engine-agnostic data files produced from Godot-authored scenes so that tests and the Godot host load the same content without depending on live scene trees. The desired end state is a repository where `src/SideScrollerGame.Sim/` contains the pure gameplay assembly, `tests/SideScrollerGame.Sim.Tests/` contains xUnit tests for engine-light gameplay behavior, `godot/` remains the presentation and authoring host, and `content/compiled/` holds deterministic runtime data produced from Godot-authored scenes. The dependency direction must be one-way: the Godot host references the simulation project, the tests reference the simulation project, and the simulation project references no Godot packages or Godot namespaces. ## Milestones ### Milestone 1: Create the simulation and test projects This milestone establishes the repository shape needed for every later change. At the end of the milestone, the solution contains a pure gameplay project and a test project, the Godot host references the simulation assembly, and the deterministic math code lives under the simulation project path. Run the following commands from `D:\Code\SideScrollerGame` as the milestone is implemented: dotnet new classlib --language C# --framework net8.0 --name SideScrollerGame.Sim --output src/SideScrollerGame.Sim dotnet new xunit --language C# --framework net8.0 --name SideScrollerGame.Sim.Tests --output tests/SideScrollerGame.Sim.Tests dotnet sln SideScrollerGame.sln add src/SideScrollerGame.Sim/SideScrollerGame.Sim.csproj dotnet sln SideScrollerGame.sln add tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj dotnet add godot/SideScrollerGame.Godot.csproj reference src/SideScrollerGame.Sim/SideScrollerGame.Sim.csproj dotnet add tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj reference src/SideScrollerGame.Sim/SideScrollerGame.Sim.csproj dotnet build SideScrollerGame.sln Acceptance for this milestone is that the solution builds, the test project runs, and the Godot project still builds after it references the new simulation assembly. A novice should be able to inspect the solution and immediately see where pure gameplay code belongs. ### Milestone 2: Build the deterministic simulation spine This milestone creates the smallest useful simulation loop. At the end of it, a caller can construct a `Simulation`, feed a `TickActionBatch`, advance exactly one tick, and receive a `TickResult` containing events and a deterministic hash. Run the tests and host build from `D:\Code\SideScrollerGame`: dotnet test tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj .\godot.cmd --headless --quit --path .\godot --build-solutions Acceptance for this milestone is behavioral. Two fresh `Simulation` instances created with the same game definition, configuration, seed, and empty action stream must produce the same tick numbers, the same state hash, and the same serialized state bytes for a sequence of no-op ticks. ### Milestone 3: Add save/load, replay, and verification This milestone makes deterministic behavior provable instead of assumed. At the end of it, the simulation can serialize all runtime state, replay saved action batches, and optionally clone itself every tick to verify that save/load and re-stepping reproduce the same state. Run this milestone’s proof commands from `D:\Code\SideScrollerGame`: dotnet test tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj --filter Replay dotnet test tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj --filter Verification Acceptance for this milestone is that a replay generated from a test scenario reproduces the same per-tick hashes on a second run, and that `RoundTripState` plus `RoundTripAndStepClone` fail loudly when a serialization bug is introduced and pass when the state is complete. ### Milestone 4: Implement movement, collision, and the fixed tick pipeline This milestone makes the simulation look like a game instead of a timer. At the end of it, the simulation owns movement, collision, weapon intent resolution, damage resolution, triggers, and snapshot generation in a stable per-tick order. Run the verification commands from `D:\Code\SideScrollerGame`: dotnet test tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj --filter Movement dotnet test tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj --filter Collision dotnet test tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj --filter Trigger Acceptance for this milestone is that deterministic tests cover grounded movement, jump buffering, coyote time, one-way platforms, hazards, projectile sweeps, and trigger ordering, and that those tests fail when system order changes incorrectly. ### Milestone 5: Implement combat systems, enemies, and coordinated behaviors This milestone fills out the genre’s core gameplay. At the end of it, the simulation supports heroes, enemies, weapons, projectiles, pickups, modifiers, squads, flocking, scripted encounters, and boss phase data using engine-agnostic definitions. Run the proof commands from `D:\Code\SideScrollerGame`: dotnet test tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj --filter Combat dotnet test tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj --filter Behavior dotnet test tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj --filter Encounter Acceptance for this milestone is that tests can demonstrate reusable enemy behaviors, squad coordination, damage and drop resolution, and deterministic boss phase transitions without running Godot. ### Milestone 6: Compile authored levels into runtime content This milestone connects Godot authoring to simulation-safe content. At the end of it, a designer can author level markers in Godot, run a compile step, and produce deterministic runtime data under `content/compiled/` that both tests and the host can consume. Run the milestone commands from `D:\Code\SideScrollerGame`: .\godot.cmd --headless --quit --path .\godot --build-solutions dotnet test tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj --filter Content Acceptance for this milestone is that a level scene with spawn markers, checkpoints, trigger zones, encounter data, and music zones compiles into engine-agnostic definitions, and tests can load that compiled data without touching a live Godot scene tree. ### Milestone 7: Finish the Godot host and debugging tools This milestone exposes the simulation to humans. At the end of it, the Godot host translates live input into `TickActionBatch` objects, runs the fixed-step simulation, interpolates between snapshots for rendering, plays overlapping sound effects and cross-faded music, and offers debug transport controls for play, pause, restart, single-step, and fast-forward. Run the proof commands from `D:\Code\SideScrollerGame`: .\godot.cmd --editor --path .\godot .\godot.cmd --headless --quit --path .\godot --build-solutions dotnet test tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj Acceptance for this milestone is that a developer can start the Godot project, load a test level, pause the simulation, advance one step at a time, jump forward to a later tick using saved checkpoints, and observe the same state hash sequence that the automated replay tests produce. ## Plan of Work Start by extending the repository structure instead of altering the Godot host in place. Create `src/SideScrollerGame.Sim/SideScrollerGame.Sim.csproj` and `tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj`, then add both projects to `SideScrollerGame.sln`. Update `godot/SideScrollerGame.Godot.csproj` to reference `src/SideScrollerGame.Sim/SideScrollerGame.Sim.csproj`, and update the test project to reference the same simulation project. If common compiler settings are needed for nullable reference types or analyzers, add them through a shared file such as `Directory.Build.props` at the repository root so the Godot host, simulation project, and tests stay aligned. Next, migrate deterministic math into the new simulation project. Copy the existing files from `FixPoint/` into `src/SideScrollerGame.Sim/FixPoint/` and change namespaces so they read as simulation infrastructure rather than host helpers. Do not make the Godot project authoritative for any gameplay behavior. If the root `FixPoint/` directory remains temporarily, ensure that only the simulation project compiles the copied files and treat the root copies as legacy bootstrap artifacts until a safe cleanup step is possible. After the math layer is inside the simulation project, build the minimal runtime model under `src/SideScrollerGame.Sim/`. Create folders and namespaces that match the long-term architecture: `Definitions/`, `Runtime/`, `Systems/`, `Serialization/`, `Replay/`, and `Verification/`. Define immutable configuration and content types under `Definitions/`. Define mutable world state under `Runtime/`. Define the fixed tick pipeline under `Systems/`. Define deterministic serialization under `Serialization/`. Define replay records under `Replay/`. Define clone-step verification and debug hashes under `Verification/`. Implement the first useful public API immediately instead of waiting for all systems to exist. `src/SideScrollerGame.Sim/Simulation.cs` should expose the constructor and methods described in the original groundwork: a constructor that takes `GameDefinition`, `SimulationConfig`, and a seed; `CurrentTick`; `CurrentState`; `PreviousSnapshot`; `CurrentSnapshot`; `Step(in TickActionBatch actions)`; `SaveState()`; and `LoadState(...)`. The early implementation can return empty event lists and minimal snapshots, but it must already be deterministic, serializable, and testable. Once the simulation spine exists, implement replay and verification before building rich gameplay systems. Add explicit versioned serialization for `SimulationState` and replay files. Introduce `VerificationMode.None`, `VerificationMode.RoundTripState`, and `VerificationMode.RoundTripAndStepClone`. Write tests that intentionally prove determinism: same seed plus same actions equals same hashes, while different seeds or different actions change hashes. Keep test fixtures engine-light and executable from `dotnet test` alone. With deterministic scaffolding proven, implement gameplay in stable layers. Add movement and collision first because every other system depends on positions and contacts. Then add damage, projectiles, pickups, and modifiers. Then add AI behaviors, squads, flocking, and scripted encounters. Keep all semantic animation and audio requests as plain simulation events, not Godot-specific clip names or audio player calls. When a new subsystem is added, add tests that prove its behavior in isolation and in scenario form. In parallel with later gameplay systems, build the host-side adapters under `godot/scripts/host/`. Add a run controller that owns real-time accumulation and fixed-step execution. Add an input translator that converts keyboard and gamepad input into serializable simulation actions. Add presenter code that maps `EntityId` values to visual nodes and interpolates only between simulation snapshots. Add an audio layer that consumes logical sound and music requests. Add debug controls that operate on the simulation runner rather than on Godot timers or animation state. Finally, add the authoring and content compile path. Godot scenes remain the editing surface, but the implementation must compile those scenes into deterministic runtime definitions under `content/compiled/`. Add validation tools for broken references, overlapping markers, and invalid encounters before those authored assets reach the simulation. The tests and the host must both load the compiled content so that authoring and gameplay are verified against the same data. ## Concrete Steps Run all commands from `D:\Code\SideScrollerGame` unless a step states otherwise. 1. Create the new projects and add them to the solution. dotnet new classlib --language C# --framework net8.0 --name SideScrollerGame.Sim --output src/SideScrollerGame.Sim dotnet new xunit --language C# --framework net8.0 --name SideScrollerGame.Sim.Tests --output tests/SideScrollerGame.Sim.Tests dotnet sln SideScrollerGame.sln add src/SideScrollerGame.Sim/SideScrollerGame.Sim.csproj dotnet sln SideScrollerGame.sln add tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj dotnet add godot/SideScrollerGame.Godot.csproj reference src/SideScrollerGame.Sim/SideScrollerGame.Sim.csproj dotnet add tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj reference src/SideScrollerGame.Sim/SideScrollerGame.Sim.csproj Expect `dotnet sln` to report that both projects were added, and expect the `dotnet add ... reference ...` commands to report a new project reference. 2. Copy the root `FixPoint/*.cs` files into `src/SideScrollerGame.Sim/FixPoint/`, then update the namespaces inside those files so the simulation project owns the deterministic numeric layer. After the copy, build the solution: dotnet build SideScrollerGame.sln Expect build output to mention all three projects and to finish without duplicate type definitions. If duplicate types appear, the wrong project is compiling both copies of the math files. 3. Add the simulation spine and test it immediately. Create `src/SideScrollerGame.Sim/Simulation.cs`, `src/SideScrollerGame.Sim/Runtime/SimulationState.cs`, `src/SideScrollerGame.Sim/Runtime/WorldSnapshot.cs`, `src/SideScrollerGame.Sim/Input/SimulationAction.cs`, `src/SideScrollerGame.Sim/Input/TickActionBatch.cs`, `src/SideScrollerGame.Sim/Verification/VerificationMode.cs`, and matching tests under `tests/SideScrollerGame.Sim.Tests/`. Run: dotnet test tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj Expect early tests to prove that stepping the simulation increments the tick and yields stable hashes for identical inputs. 4. Add serialization, replay, and verification. Create files under `src/SideScrollerGame.Sim/Serialization/`, `src/SideScrollerGame.Sim/Replay/`, and `src/SideScrollerGame.Sim/Verification/`, then add tests for replay determinism and state round-tripping. Run: dotnet test tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj --filter Replay dotnet test tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj --filter Verification Expect replay tests to pass with the same hash sequence on repeated runs. 5. Implement movement, collision, combat, triggers, and scenario tests in the simulation project. Keep adding tests before wiring presentation details in Godot. Run: dotnet test tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:Threshold=100 /p:ThresholdType=line,branch /p:ThresholdStat=total Expect the command to fail if gameplay logic coverage drops below 100 percent. 6. Wire the Godot host to the simulation project by adding host-side runner, presenter, audio, and debug transport code under `godot/scripts/host/`, then confirm the host still compiles. Run: .\godot.cmd --headless --quit --path .\godot --build-solutions Expect Godot to regenerate and build C# project artifacts successfully. 7. Build the content compile path and manual host verification flow. Run: .\godot.cmd --editor --path .\godot In the editor, validate that authored level scenes can be compiled into `content/compiled/`, then run the game and observe that pausing, single-stepping, and replaying preserve deterministic state hashes. ## Validation and Acceptance The implementation is acceptable only when a human can see deterministic behavior, not merely when the code compiles. Start with automated proof. `dotnet test tests/SideScrollerGame.Sim.Tests/SideScrollerGame.Sim.Tests.csproj` must pass, and replay-oriented tests must demonstrate that the same seed and action stream yield the same per-tick debug hash sequence. The coverage command in `Concrete Steps` must enforce 100 percent line and branch coverage for gameplay logic inside `SideScrollerGame.Sim`, with only narrow exclusions for non-logic infrastructure such as generated serializers or lookup tables. Then verify the host integration. `.\godot.cmd --headless --quit --path .\godot --build-solutions` must succeed, proving that the Godot project can consume the simulation assembly. After that, start the editor with `.\godot.cmd --editor --path .\godot`, load a level built from compiled runtime content, and verify the following behaviors manually: play starts the simulation, pause freezes the simulation while leaving the editor responsive, advance-one-step increments the tick exactly once, fast-forward resumes from the nearest saved checkpoint and reaches the requested tick, and replaying the same recorded input reproduces the same state hash display. The final acceptance scenario is simple and observable. Record a short run in which the player moves, fires, triggers an encounter, collects a pickup, and reaches a checkpoint. Save the replay. Restart the host with the same compiled content and seed, play the replay, and confirm that the tick count, key gameplay events, and final state hash all match the original run. If any of those differ, the implementation is incomplete. ## Idempotence and Recovery Most steps in this plan are additive and safe to repeat. Re-running `dotnet build`, `dotnet test`, or `.\godot.cmd --headless --quit --path .\godot --build-solutions` is safe and should produce the same result when the repository state has not changed. Re-running the host replay validation is also safe because replays and checkpoints are meant to be reproducible. Project creation commands such as `dotnet new classlib` and `dotnet new xunit` are not naturally idempotent once the destination directories already exist. If those directories have already been created, do not delete them to start over. Instead, inspect the generated files, patch them into the required shape, and continue. The same rule applies to content compilation in this Windows environment: prefer overwriting generated runtime content in place instead of deleting directories. When migrating the `FixPoint/` sources, do not remove the root copies until the simulation project is compiling and all references are proven correct. If a migration step goes wrong, recover by fixing project includes and namespaces rather than by using rollback commands such as `git restore` or `git reset`. The plan is intentionally written so that each milestone can be resumed from the current working tree without assuming a clean slate. ## Artifacts and Notes Current repository snapshot, captured while writing this plan: PS D:\Code\SideScrollerGame> rg --files SideScrollerGame.sln PLANS.md groundwork.md godot.cmd godot\SideScrollerGame.Godot.csproj godot\project.godot FixPoint\IntRandom.cs FixPoint\FixPoint16.cs ... Current solution shape, which this plan will extend: Project(...) = "SideScrollerGame.Godot", "godot/SideScrollerGame.Godot.csproj", "{75DE3F78-FF5C-4E58-8315-8AEF5BF95BBA}" Current Godot project target framework: net8.0 Use those facts as the starting point when implementing this plan. If the repository changes later, update this section and every other affected section of the plan so the document remains self-contained. ## Interfaces and Dependencies Use .NET 8 for the simulation and test projects so they align with the existing Godot project target. Keep the Godot host on `Godot.NET.Sdk/4.5.1` unless a later, repository-wide upgrade is performed deliberately and documented in this plan. The simulation project may use built-in .NET libraries and deterministic-support libraries that do not pull in Godot. Avoid floating-point math, wall-clock time, thread scheduling, asynchronous gameplay work, or any API that can vary results between runs. At the end of Milestone 2, the simulation project must define these public interfaces and types with stable names and repository-relative locations: In `src/SideScrollerGame.Sim/Simulation.cs`, define: public sealed class Simulation { public Simulation(GameDefinition gameDefinition, SimulationConfig config, int seed); public int CurrentTick { get; } public SimulationState CurrentState { get; } public WorldSnapshot PreviousSnapshot { get; } public WorldSnapshot CurrentSnapshot { get; } public TickResult Step(in TickActionBatch actions); public byte[] SaveState(); public static Simulation LoadState(byte[] data, GameDefinition gameDefinition, SimulationConfig config); } In `src/SideScrollerGame.Sim/Input/SimulationAction.cs`, define the serializable action hierarchy: public abstract record SimulationAction; public sealed record MoveAxisChanged(PlayerId PlayerId, sbyte X, sbyte Y) : SimulationAction; public sealed record AimAxisChanged(PlayerId PlayerId, short X, short Y) : SimulationAction; public sealed record ButtonChanged(PlayerId PlayerId, InputButton Button, bool IsPressed) : SimulationAction; public sealed record WeaponSlotSelected(PlayerId PlayerId, int SlotIndex) : SimulationAction; In `src/SideScrollerGame.Sim/Input/TickActionBatch.cs`, define: public sealed record TickActionBatch(int Tick, ImmutableArray Actions); In `src/SideScrollerGame.Sim/Verification/VerificationMode.cs`, define: public enum VerificationMode { None, RoundTripState, RoundTripAndStepClone } In `src/SideScrollerGame.Sim/Runtime/`, define `SimulationState`, `WorldSnapshot`, `TickResult`, entity identifiers, runtime state groups such as `PlayerState`, `EnemyState`, `ProjectileState`, `PickupState`, `HazardState`, `PlatformState`, `TriggerState`, `CameraState`, `LevelRuntimeState`, and `SquadState`, and a stable per-tick pipeline that applies actions, advances timers, updates AI, resolves weapons, integrates movement, resolves collisions, applies damage, processes triggers, and then produces events, snapshots, and hashes. In `src/SideScrollerGame.Sim/Definitions/`, define immutable content types including `GameDefinition`, `LevelDefinition`, `HeroDefinition`, `EnemyDefinition`, `WeaponDefinition`, `ProjectileDefinition`, `PowerUpDefinition`, `SquadDefinition`, and related modifier and behavior definitions. These types must remain engine-agnostic and serializable. In `src/SideScrollerGame.Sim/Replay/` and `src/SideScrollerGame.Sim/Serialization/`, define versioned replay and state persistence types that can serialize the full simulation state, recorded action batches, content hash, seed, and optional checkpoints without relying on Godot serialization. In `godot/scripts/host/`, define host-side adapters with clear responsibilities: a `RunController` that owns real-time accumulation and fixed-step stepping, an input translator that turns Godot input into simulation actions, a presentation registry keyed by `EntityId`, interpolation code that renders between `PreviousSnapshot` and `CurrentSnapshot`, and audio services that consume simulation sound and music requests without becoming gameplay authorities. Revision Note: 2026-04-16, Codex. Replaced the original groundwork note with an ExecPlan that follows `PLANS.md`, because the old document captured architectural intent but did not give a novice enough concrete guidance to implement, validate, and maintain the work.