Racing placement: Simulation facet + dogfood composition
Policies that keep the org coherent
name: Racing placement split
overview: Extract the headless racing simulation into Novolis.Simulation.Racing (platform facet, ML-agnostic). Keep neural evolution glue in novolis-dogfooding as app composition code. Do not add MachineLearning.Racing or any domain-specific ML packages.
todos:
- id: sim-racing-project
content: Create Novolis.Simulation.Racing project; move ML-agnostic sim code from dogfood; rename namespaces status: completed
- id: sim-racing-tests
content: Add Novolis.Simulation.Racing.Tests (11 test files); wire slnx, packages.json, registry status: completed
- id: dogfood-slim
content: Remove NeuralRacing.Sim; keep Training + Neural controllers in app; PackageReference sim + neural status: completed
- id: dogfood-tests
content: Reduce NeuralRacing.Tests to 2 trainer test files only status: completed
- id: governance
content: Update library-boundaries, frank docs, migrate-frank-slice; optional wave-12 brief status: completed isProject: false
Problem
MachineLearning.Racing would be reverse leakage: a domain scenario (racing + evolution) packaged under a repo that should stay orthogonal building blocks like novolis-math or novolis-raylib.
- Math / Physics / Simulation = closed stack; Simulation depends only on Math + Physics.
- MachineLearning = orthogonal (not in stack); apps compose it with other repos.
- Apps own cross-repo glue: "Apps may reference any combination; they own cross-repo glue."
Racing today in novolis-dogfooding/apps/NeuralRacing is a hidden library (~55 sim files + 266 tests) with an invalid dependency: NeuralRacing.Sim ProjectReferences Novolis.MachineLearning.Neural — the sim layer should not depend on ML.
flowchart TB
subgraph ml_repo [novolis-machinelearning]
Core[Core]
NeuralAbs[Neural.Abstractions]
Neural[Neural]
AutoMl[AutoMl]
end
subgraph sim_repo [novolis-simulation]
SimRacing[Simulation.Racing]
end
subgraph dogfood [novolis-dogfooding]
App[NeuralRacing app]
Trainer[Training folder]
NeuralCtrl[NeuralRaceCarController]
TrainerTests[Trainer tests only]
end
Neural --> NeuralAbs
SimRacing --> MathBCL[BCL numerics only at first]
App --> SimRacing
App --> Neural
Trainer --> SimRacing
Trainer --> Neural
NeuralCtrl --> SimRacing
NeuralCtrl --> NeuralWhat belongs where
Code (current NeuralRacing.Sim) | Target | Rationale |
|---|---|---|
Tracks/, Race/, Sensors/, Rewards/, Progress/, Cars/* except neural types | `Novolis.Simulation.Racing` | Headless tick-based sim; IRaceCarController is policy-agnostic |
Cars/NeuralRaceCarController.cs, INeuralRaceCarController.cs | `apps/NeuralRacing/` (app source) | Adapts INeuralNetwork → IRaceCarController; ML-specific |
Training/* (4 files) | `apps/NeuralRacing/` | Evolution loop over sim + DenseNetwork; product/demo glue |
Program.cs | `apps/NeuralRacing/` | Demo entry |
| 11 sim test files (~264 tests) | `Novolis.Simulation.Racing.Tests` | Library tests live with the library |
EvolutionaryRacingTrainer*Tests.cs (2 files) | `apps/NeuralRacing.Tests` | Tests composition, not a platform package |
[novolis-machinelearning](d:\novolis\novolis-machinelearning) stays four packable facets only:
Novolis.MachineLearning.CoreNovolis.MachineLearning.Neural.AbstractionsNovolis.MachineLearning.NeuralNovolis.MachineLearning.AutoMl
No new ML packages. README already states racing is not in this repo — keep that.
Why Simulation.Racing fits the stack
- Matches existing facets (World, Kinematics): domain runtime under Simulation, not under ML.
RaceSimulationis orchestration over discrete ticks (like Simulation’s clock/world model), with custom kinematics — does not requireNovolis.Physics.*on day one.- Must not reference
Novolis.MachineLearning.*(enables sim tests without ML on the graph).
Not Simulation.Racing + MachineLearning.Racing: the second package would re-introduce domain naming in the wrong repo and tempt Simulation ↔ ML coupling in platform code.
Phase 1 — Add Novolis.Simulation.Racing (novolis-simulation)
- Create project at
src/Novolis.Simulation.Racing/using the same pattern as Novolis.Simulation.Kinematics.csproj:
- Import Novolis.Simulation.Packaging.props
PackageId=Novolis.Simulation.Racing- No project references to MachineLearning
- No project reference to Physics required initially (racing is self-contained); optional
Novolis.Math.Geometrylater if shared ray/grid helpers appear
- Move + rename from NeuralRacing.Sim:
- Namespace:
NeuralRacing.*→Novolis.Simulation.Racing.*(folder layout unchanged:Tracks,Race,Cars, etc.) - Exclude:
Training/,NeuralRaceCarController.cs,INeuralRaceCarController.cs
- Add tests
tests/Novolis.Simulation.Racing.Tests/:
- Port 11 files from NeuralRacing.Tests/Sim (all except the two
EvolutionaryRacingTrainer*files) - Namespace:
Novolis.Simulation.Racing.Tests - TUnit exe pattern like Novolis.Simulation.World.Tests
- Small local
TestInfrastructure(copyBaseTest/StructuredTestOutputfrom dogfood or ML test support — do not reference ML test projects)
- Wire repo:
- Novolis.Simulation.slnx
- .novolis/packages.json
- novolis-registry/packages/novolis-simulation-racing.json (new stub)
dotnet build+ run Racing tests in simulation CI
Phase 2 — Slim dogfooding to composition-only
- Delete
apps/NeuralRacing/NeuralRacing.Sim/after move.
- Restructure apps/NeuralRacing:
apps/NeuralRacing/
NeuralRacing.csproj # Exe, IsPackable=false
Program.cs
Training/ # 4 files from old Sim/Training
Controllers/ # NeuralRaceCarController + INeuralRaceCarControllerPackageReferencetoNovolis.Simulation.RacingandNovolis.MachineLearning.Neural(2026.1.*per Directory.Packages.props)- Remove monorepo
ProjectReferenceintonovolis-machinelearning(aligns with dogfooding design); use local GPR orartifacts/nuget-localduring dev per nuget-setup.md
- Slim tests NeuralRacing.Tests:
- Keep only
EvolutionaryRacingTrainerTests.cs+EvolutionaryRacingTrainerValidationTests.cs - Reference app + packages (not Simulation test internals)
- Update Novolis.Dogfooding.slnx and README apps table:
NeuralRacingexercisesSimulation.Racing+MachineLearning.Neural.
Phase 3 — Governance and migration script
Update docs to codify the rule “no domain packages in ML repo”:
| Document | Change |
|---|---|
| library-boundaries.md | Add row: headless racing sim → Simulation.Racing; NN evolution on racing → apps |
| simulation-layer-policy.md | List Simulation.Racing facet |
| wave-8-machinelearning-neural.md | Racing → Simulation.Racing + dogfood glue (not ML package) |
| frank-naming-and-structure.md | Frank.ML.Domain.Racing → Novolis.Simulation.Racing + dogfood |
| frank-inventory.md | Same mapping |
| migrate-frank-slice.ps1 | Frank.ML.Domain.Racing → Novolis.Simulation.Racing (not NeuralRacing) |
Optional: add extraction-briefs/wave-12-simulation-racing.md for the Frank.ML racing sim slice.
Deferred (explicitly out of scope)
| Item | Reason |
|---|---|
| `Vector2` → XZ `Vector3` | Racing uses System.Numerics.Vector2 throughout; library-boundaries forbids Vector2 in stack — schedule as follow-up, do not block the move |
| Integrate `RaceSimulation` with `SimulationWorld` / `ISimulationSystem` | Future alignment; current code is a standalone loop |
| Frank.ML Avalonia / Spectre UI | Stays private Frank.ML; may consume packages later |
| `MachineLearning.Racing` | Rejected — not a building block |
Success criteria
novolis-simulationbuilds;Novolis.Simulation.Racing.Testspasses (~264 tests).novolis-machinelearningunchanged package set (4 facets); no racing code.novolis-dogfoodingNeuralRacingis a thin exe + ~6 glue files + 2 trainer test files; no embedded sim library.- Dependency graph:
Simulation.Racingdoes not referenceMachineLearning.*.