Advisor: turn the Rust simulation-kernel design into an implementation plan #12

Closed
opened 2026-07-09 18:23:32 +00:00 by coilyco-ops · 1 comment
Owner

Use #11 as the source design brief, but parse it against the current factory-game-v3 state. This is an advisor/design task, not an implementation task.

Current repo state to account for:

  • main is green.
  • Unity project scaffolding has been removed.
  • Assets are tracked through Git LFS and verified.
  • The repo is in the aos baseline with AGENTS.md, .ward/ward.yaml, docs/FEATURES.md, and Forgejo CI.
  • The old tests.csproj / NuGet path is retained as reference-only and is not active validation.
  • There is no Rust or Bevy code yet: no Cargo.toml, no .rs files.

Design direction from #11 to preserve:

  • Rust simulation kernel first, viewer later.
  • Treat the project as simulation core -> observability/tests -> optional visual frontend, not as an engine-first rewrite.
  • Start with a pure Rust deterministic simulation crate, not Bevy.
  • Preserve the interesting design axis: autonomous logistics/dispatch protocols, resources, production, movement, deterministic ticks, and testable systems.
  • Do not spend effort on Unity cleanup, NuGet tests, or visualization for the first slice.

Advisor deliverable:

  • Propose the first 3-5 implementation issues that should follow this design.
  • Define the first Rust workspace/crate shape, likely crates/factory_sim, crates/factory_content, and crates/factory_cli.
  • Identify the smallest closed-loop sim slice to implement first: item/content IDs, resource/capacity model, tiny GameState, deterministic tick tests, and CLI runner skeleton.
  • State which current C# files/classes should be read as source material for that first slice.
  • Define acceptance criteria for the first implementation issue, including cargo test and a headless CLI output shape.
  • Call out what must remain explicitly out of scope: Bevy viewer, Unity cleanup, NuGet/C# test repair, full gameplay parity.

Expected outcome: a concise issue comment with the recommended issue breakdown and first implementation brief, so a follow-up engineer can start without re-reading the whole #11 essay.

Use #11 as the source design brief, but parse it against the current `factory-game-v3` state. This is an advisor/design task, not an implementation task. Current repo state to account for: * `main` is green. * Unity project scaffolding has been removed. * Assets are tracked through Git LFS and verified. * The repo is in the aos baseline with `AGENTS.md`, `.ward/ward.yaml`, `docs/FEATURES.md`, and Forgejo CI. * The old `tests.csproj` / NuGet path is retained as reference-only and is not active validation. * There is no Rust or Bevy code yet: no `Cargo.toml`, no `.rs` files. Design direction from #11 to preserve: * Rust simulation kernel first, viewer later. * Treat the project as `simulation core -> observability/tests -> optional visual frontend`, not as an engine-first rewrite. * Start with a pure Rust deterministic simulation crate, not Bevy. * Preserve the interesting design axis: autonomous logistics/dispatch protocols, resources, production, movement, deterministic ticks, and testable systems. * Do not spend effort on Unity cleanup, NuGet tests, or visualization for the first slice. Advisor deliverable: * Propose the first 3-5 implementation issues that should follow this design. * Define the first Rust workspace/crate shape, likely `crates/factory_sim`, `crates/factory_content`, and `crates/factory_cli`. * Identify the smallest closed-loop sim slice to implement first: item/content IDs, resource/capacity model, tiny `GameState`, deterministic tick tests, and CLI runner skeleton. * State which current C# files/classes should be read as source material for that first slice. * Define acceptance criteria for the first implementation issue, including `cargo test` and a headless CLI output shape. * Call out what must remain explicitly out of scope: Bevy viewer, Unity cleanup, NuGet/C# test repair, full gameplay parity. Expected outcome: a concise issue comment with the recommended issue breakdown and first implementation brief, so a follow-up engineer can start without re-reading the whole #11 essay.
Author
Owner

🔎 ward agent advisor

ward agent advisor --harness codex ran a one-shot standard research pass on this question:

Read the issue title, body, and comment thread below as the research brief. Identify the decisions, options, open questions, and risks, then give a clear advisory recommendation that can be posted back on the issue.


Recommendation

Treat this as a single-repo planning answer. The next work should start a pure Rust deterministic simulation workspace and deliberately avoid Bevy, Unity cleanup, or parity-chasing. I could not pull the full text of #11 anonymously from Forgejo, so this recommendation preserves the design bullets quoted in this issue body as the source brief.

The key planning decision is to port behavior, not architecture. The Unity reference is useful for domain semantics, but the Rust kernel should not mimic MonoBehaviours or the current world-object/component wiring literally. The first slice should be a state-oriented kernel shaped as:

  • simulation core -> deterministic tests/observability -> optional viewer later
  • content definitions separate from simulation state
  • typed IDs and enums, not stringly-typed command/state plumbing
  • tick(state) -> events + next_state, with stable output suitable for golden tests
  1. Bootstrap Rust workspace and deterministic kernel skeleton

    • Add a Cargo workspace at the repo root.
    • Create crates/factory_sim, crates/factory_content, and crates/factory_cli.
    • factory_sim owns GameState, tick stepping, entity/resource state, and deterministic event emission.
    • factory_content owns typed item/content IDs and the first hard-coded content catalog.
    • factory_cli owns a headless runner that prints stable per-tick snapshots.
    • Do not add Bevy or any rendering dependency.
  2. Port the minimal content and inventory model

    • Implement typed IDs for the first slice: IronOre, IronBars, and the minimum actor/building IDs needed for the loop.
    • Port item properties that actually matter to the kernel first: weight, volume, stack_size, craft_time, craft_output_multiplier, ingredients, and finite/manifest source semantics.
    • Implement a deterministic inventory/resource container with capacity checks and reserved-capacity behavior.
  3. Implement the first closed-loop production slice

    • Recommended loop: ore source -> hauler -> factory -> iron bars.
    • Keep topology minimal. Use node IDs plus adjacency or explicit route edges. Do not pull in full grid pathfinding yet.
    • Include one autonomous haul protocol with typed states equivalent to the current Collect/Deliver flow.
    • Include one production rule equivalent to IronOre -> IronBars.
  4. Add deterministic scenario tests and CLI golden output

    • Add fixture scenarios that run for N ticks and assert exact snapshots/events.
    • Prove repeatability by running the same scenario twice and asserting byte-for-byte identical output.
    • Use the CLI output as the first observability surface before any viewer exists.
  5. Only after that, widen the kernel surface

    • Next expansions should be additional recipes, more dispatch verbs, or richer movement.
    • Power, batteries, deployment, and viewer work should wait until the minimal haul/produce loop is stable.

First Workspace Shape

Recommended initial layout:

Cargo.toml
crates/
  factory_sim/
    src/
      lib.rs
      ids.rs
      state.rs
      inventory.rs
      tick.rs
      events.rs
      entities/
  factory_content/
    src/
      lib.rs
      items.rs
      recipes.rs
      scenarios.rs
  factory_cli/
    src/
      main.rs

Recommended ownership split:

  • factory_sim - pure deterministic kernel. No file IO requirement, no renderer assumptions.
  • factory_content - the first content registry and starter scenarios. Hard-code content first. Data-driven loading can come later.
  • factory_cli - scenario selection, tick count input, stable text or JSON-lines output.

Smallest Closed-Loop Slice To Build First

The smallest slice that still respects the design brief is:

  • ItemId and minimal content catalog for IronOre and IronBars
  • Inventory with weight/volume/capacity accounting and reserved-capacity support
  • Tiny GameState containing:
    • one source node with finite ore
    • one hauler with cargo and a typed dispatch state
    • one factory with input inventory, output inventory, and craft progress
    • a simple topology representation
    • global tick counter
  • Deterministic tick stepping for:
    • source extraction or source availability
    • hauler collect/deliver transition
    • factory craft progress and output creation
  • CLI runner skeleton that advances ticks and prints stable snapshots

The important scope cut is this: include autonomous logistics state, but not full movement/pathfinding complexity. A one-edge-per-tick route or fixed adjacency is enough for the first loop. That preserves the interesting logistics axis without letting pathfinding swallow the milestone.

C# Source Material To Read First

These are the reference files that matter for the first Rust slice:

  • Assets/Scripts/GameContent.cs - base item schema and recipe shape.
  • Assets/Scripts/FactoryGame/FactoryGameContent.cs - canonical item set, recipe data, and spawnable distinctions.
  • Assets/Scripts/Components/ResourcesComponent.cs - capacity accounting, transfer semantics, and reserved-capacity behavior.
  • Assets/Scripts/Components/ProductionComponent.cs - deterministic craft progress, input consumption, and output creation semantics.
  • Assets/Scripts/Components/MiningComponent.cs - extraction behavior and finite-vs-manifest source semantics.
  • Assets/Scripts/WorldObjects/WorldObjectFactory.cs - how production, inserters, and dispatch intents are composed around a factory.
  • Assets/Scripts/Components/DispatchComponent.cs - dispatch intent generation and target-selection concepts.
  • Assets/Scripts/Components/DispatchReceiverComponent.cs - haul-state transitions like Collect <-> Deliver and Retrieve <-> Deploy.
  • Assets/Scripts/Components/ResourceRetrieverComponent.cs - when a mobile unit actually pulls cargo.
  • Assets/Scripts/Components/ResourceInserterComponent.cs - adjacency-based local transfer semantics.
  • Assets/Scripts/WorldObjects/WorldObjectTruck.cs - the current mobile logistics composition.
  • Assets/Scripts/WorldObject.cs - useful only as a reference for what state exists on an actor, not as a structural template to port.

The most important semantic references for issue 1 are:

Acceptance Criteria For The First Implementation Issue

Suggested first issue title:

Bootstrap the Rust simulation workspace and first deterministic closed-loop slice

Suggested acceptance criteria:

  • A root Cargo.toml defines a workspace containing crates/factory_sim, crates/factory_content, and crates/factory_cli.
  • factory_sim exposes a pure-Rust tick API that can advance a tiny GameState without any Bevy dependency.
  • factory_content defines typed IDs and at least the first recipe/content needed for IronOre -> IronBars.
  • The kernel implements inventory capacity checks and deterministic craft progress for the first slice.
  • The kernel implements one minimal autonomous haul loop with typed state transitions equivalent to Collect and Deliver.
  • cargo test --workspace passes.
  • At least one test proves determinism by asserting that the same scenario produces the same tick snapshots on repeated runs.
  • factory_cli can run a tiny scenario headlessly and print stable output per tick.

Recommended CLI contract for the first slice:

cargo run -p factory_cli -- run --scenario iron-bars --ticks 6

Recommended output shape: JSON lines, one object per tick, for example:

{"tick":0,"source":{"iron_ore":20},"hauler":{"mode":"collect","cargo":{}},"factory":{"input":{},"progress":0,"output":{}}}
{"tick":1,"source":{"iron_ore":10},"hauler":{"mode":"deliver","cargo":{"iron_ore":10}},"factory":{"input":{},"progress":0,"output":{}}}
{"tick":2,"source":{"iron_ore":10},"hauler":{"mode":"collect","cargo":{}},"factory":{"input":{"iron_ore":10},"progress":1,"output":{}}}

That output shape is intentionally plain. It is for testability and diffability, not presentation.

Decisions, Options, Open Questions, Risks

Decisions to make now

  • Use a Rust workspace immediately, not a single crate that gets split later.
  • Keep factory_sim free of Bevy and Unity-shaped abstractions.
  • Use typed Rust enums/newtypes for IDs and dispatch verbs instead of porting C# strings.
  • Use stable scenario output as the first observability surface.

Options considered

  • Hard-coded content vs external data files:
    • Recommendation: hard-code the first content catalog in factory_content. External content loading is premature before the kernel semantics settle.
  • Grid/pathfinding now vs later:
    • Recommendation: later. Start with a minimal topology model so the first logistics slice stays small and deterministic.
  • Full dispatch verb set now vs minimal haul verbs now:
    • Recommendation: implement only the minimal haul loop first. Retrieve/Deploy can follow after the first closed loop is solid.

Open questions for the follow-up engineer

  • Should the first source node be an explicit OrePatch + MiningDrill pair, or a simplified extractor/source actor with equivalent output semantics?
    • Recommendation: keep the actor count minimal, but preserve the difference between finite resource sources and recipe-based production.
  • Should the CLI snapshot schema be human text or JSON lines?
    • Recommendation: JSON lines, because deterministic golden tests are easier to maintain.
  • Should batteries/power be part of the first slice?
    • Recommendation: no. They are interesting, but not necessary to validate kernel direction.

Main risks

  • Porting the Unity component graph too literally will create a Rust codebase that is hard to test and easy to over-couple.
  • Pulling in pathfinding or Bevy too early will bury the kernel milestone under engine work.
  • Leaving IDs and commands as strings will recreate avoidable correctness problems in the new code.
  • Chasing gameplay parity before the first deterministic loop exists will slow the migration and blur acceptance criteria.

Explicitly Out Of Scope

Keep these out of the first slice and out of the first issue:

  • Bevy viewer or any rendering/frontend work
  • Unity project cleanup beyond using the existing C# as reference material
  • NuGet or tests.csproj repair
  • Full gameplay parity with the Unity version
  • Power grid, batteries, deployment verbs, or pathfinding beyond the minimum topology needed for the first haul loop

That scope cut is the main recommendation. The first milestone should prove that the repo can host a deterministic Rust factory kernel with a testable autonomous logistics loop, not that the whole game has been ported.


Researched and posted automatically by ward agent advisor --harness codex (ward#179). This is one-shot research, not a carried change - verify before acting on it.

— Codex, via ward agent

### 🔎 ward agent advisor `ward agent advisor --harness codex` ran a one-shot **standard** research pass on this question: > Read the issue title, body, and comment thread below as the research brief. Identify the decisions, options, open questions, and risks, then give a clear advisory recommendation that can be posted back on the issue. --- ## Recommendation Treat this as a **single-repo planning answer**. The next work should start a **pure Rust deterministic simulation workspace** and deliberately avoid Bevy, Unity cleanup, or parity-chasing. I could not pull the full text of `#11` anonymously from Forgejo, so this recommendation preserves the design bullets quoted in this issue body as the source brief. The key planning decision is to **port behavior, not architecture**. The Unity reference is useful for domain semantics, but the Rust kernel should not mimic MonoBehaviours or the current world-object/component wiring literally. The first slice should be a state-oriented kernel shaped as: - `simulation core -> deterministic tests/observability -> optional viewer later` - `content definitions` separate from `simulation state` - `typed IDs and enums`, not stringly-typed command/state plumbing - `tick(state) -> events + next_state`, with stable output suitable for golden tests ## Recommended First Issue Sequence 1. **Bootstrap Rust workspace and deterministic kernel skeleton** - Add a Cargo workspace at the repo root. - Create `crates/factory_sim`, `crates/factory_content`, and `crates/factory_cli`. - `factory_sim` owns `GameState`, tick stepping, entity/resource state, and deterministic event emission. - `factory_content` owns typed item/content IDs and the first hard-coded content catalog. - `factory_cli` owns a headless runner that prints stable per-tick snapshots. - Do **not** add Bevy or any rendering dependency. 2. **Port the minimal content and inventory model** - Implement typed IDs for the first slice: `IronOre`, `IronBars`, and the minimum actor/building IDs needed for the loop. - Port item properties that actually matter to the kernel first: `weight`, `volume`, `stack_size`, `craft_time`, `craft_output_multiplier`, `ingredients`, and finite/manifest source semantics. - Implement a deterministic inventory/resource container with capacity checks and reserved-capacity behavior. 3. **Implement the first closed-loop production slice** - Recommended loop: `ore source -> hauler -> factory -> iron bars`. - Keep topology minimal. Use node IDs plus adjacency or explicit route edges. Do **not** pull in full grid pathfinding yet. - Include one autonomous haul protocol with typed states equivalent to the current `Collect`/`Deliver` flow. - Include one production rule equivalent to `IronOre -> IronBars`. 4. **Add deterministic scenario tests and CLI golden output** - Add fixture scenarios that run for N ticks and assert exact snapshots/events. - Prove repeatability by running the same scenario twice and asserting byte-for-byte identical output. - Use the CLI output as the first observability surface before any viewer exists. 5. **Only after that, widen the kernel surface** - Next expansions should be additional recipes, more dispatch verbs, or richer movement. - Power, batteries, deployment, and viewer work should wait until the minimal haul/produce loop is stable. ## First Workspace Shape Recommended initial layout: ```text Cargo.toml crates/ factory_sim/ src/ lib.rs ids.rs state.rs inventory.rs tick.rs events.rs entities/ factory_content/ src/ lib.rs items.rs recipes.rs scenarios.rs factory_cli/ src/ main.rs ``` Recommended ownership split: - `factory_sim` - pure deterministic kernel. No file IO requirement, no renderer assumptions. - `factory_content` - the first content registry and starter scenarios. Hard-code content first. Data-driven loading can come later. - `factory_cli` - scenario selection, tick count input, stable text or JSON-lines output. ## Smallest Closed-Loop Slice To Build First The smallest slice that still respects the design brief is: - `ItemId` and minimal content catalog for `IronOre` and `IronBars` - `Inventory` with weight/volume/capacity accounting and reserved-capacity support - Tiny `GameState` containing: - one source node with finite ore - one hauler with cargo and a typed dispatch state - one factory with input inventory, output inventory, and craft progress - a simple topology representation - global tick counter - Deterministic tick stepping for: - source extraction or source availability - hauler collect/deliver transition - factory craft progress and output creation - CLI runner skeleton that advances ticks and prints stable snapshots The important scope cut is this: **include autonomous logistics state, but not full movement/pathfinding complexity**. A one-edge-per-tick route or fixed adjacency is enough for the first loop. That preserves the interesting logistics axis without letting pathfinding swallow the milestone. ## C# Source Material To Read First These are the reference files that matter for the first Rust slice: - `Assets/Scripts/GameContent.cs` - base item schema and recipe shape. - `Assets/Scripts/FactoryGame/FactoryGameContent.cs` - canonical item set, recipe data, and spawnable distinctions. - `Assets/Scripts/Components/ResourcesComponent.cs` - capacity accounting, transfer semantics, and reserved-capacity behavior. - `Assets/Scripts/Components/ProductionComponent.cs` - deterministic craft progress, input consumption, and output creation semantics. - `Assets/Scripts/Components/MiningComponent.cs` - extraction behavior and finite-vs-manifest source semantics. - `Assets/Scripts/WorldObjects/WorldObjectFactory.cs` - how production, inserters, and dispatch intents are composed around a factory. - `Assets/Scripts/Components/DispatchComponent.cs` - dispatch intent generation and target-selection concepts. - `Assets/Scripts/Components/DispatchReceiverComponent.cs` - haul-state transitions like `Collect <-> Deliver` and `Retrieve <-> Deploy`. - `Assets/Scripts/Components/ResourceRetrieverComponent.cs` - when a mobile unit actually pulls cargo. - `Assets/Scripts/Components/ResourceInserterComponent.cs` - adjacency-based local transfer semantics. - `Assets/Scripts/WorldObjects/WorldObjectTruck.cs` - the current mobile logistics composition. - `Assets/Scripts/WorldObject.cs` - useful only as a reference for what state exists on an actor, not as a structural template to port. The most important semantic references for issue 1 are: - `GameContent.Item` in [Assets/Scripts/GameContent.cs](/workspace/factory-game-v3/Assets/Scripts/GameContent.cs:5) - content IDs and recipes in [Assets/Scripts/FactoryGame/FactoryGameContent.cs](/workspace/factory-game-v3/Assets/Scripts/FactoryGame/FactoryGameContent.cs:6) - capacity and transfer rules in [Assets/Scripts/Components/ResourcesComponent.cs](/workspace/factory-game-v3/Assets/Scripts/Components/ResourcesComponent.cs:8) - craft progression in [Assets/Scripts/Components/ProductionComponent.cs](/workspace/factory-game-v3/Assets/Scripts/Components/ProductionComponent.cs:11) - haul-state transitions in [Assets/Scripts/Components/DispatchReceiverComponent.cs](/workspace/factory-game-v3/Assets/Scripts/Components/DispatchReceiverComponent.cs:10) - factory composition in [Assets/Scripts/WorldObjects/WorldObjectFactory.cs](/workspace/factory-game-v3/Assets/Scripts/WorldObjects/WorldObjectFactory.cs:11) - truck composition in [Assets/Scripts/WorldObjects/WorldObjectTruck.cs](/workspace/factory-game-v3/Assets/Scripts/WorldObjects/WorldObjectTruck.cs:9) ## Acceptance Criteria For The First Implementation Issue Suggested first issue title: **Bootstrap the Rust simulation workspace and first deterministic closed-loop slice** Suggested acceptance criteria: - A root `Cargo.toml` defines a workspace containing `crates/factory_sim`, `crates/factory_content`, and `crates/factory_cli`. - `factory_sim` exposes a pure-Rust tick API that can advance a tiny `GameState` without any Bevy dependency. - `factory_content` defines typed IDs and at least the first recipe/content needed for `IronOre -> IronBars`. - The kernel implements inventory capacity checks and deterministic craft progress for the first slice. - The kernel implements one minimal autonomous haul loop with typed state transitions equivalent to `Collect` and `Deliver`. - `cargo test --workspace` passes. - At least one test proves determinism by asserting that the same scenario produces the same tick snapshots on repeated runs. - `factory_cli` can run a tiny scenario headlessly and print stable output per tick. Recommended CLI contract for the first slice: ```text cargo run -p factory_cli -- run --scenario iron-bars --ticks 6 ``` Recommended output shape: **JSON lines**, one object per tick, for example: ```json {"tick":0,"source":{"iron_ore":20},"hauler":{"mode":"collect","cargo":{}},"factory":{"input":{},"progress":0,"output":{}}} {"tick":1,"source":{"iron_ore":10},"hauler":{"mode":"deliver","cargo":{"iron_ore":10}},"factory":{"input":{},"progress":0,"output":{}}} {"tick":2,"source":{"iron_ore":10},"hauler":{"mode":"collect","cargo":{}},"factory":{"input":{"iron_ore":10},"progress":1,"output":{}}} ``` That output shape is intentionally plain. It is for testability and diffability, not presentation. ## Decisions, Options, Open Questions, Risks **Decisions to make now** - Use a Rust workspace immediately, not a single crate that gets split later. - Keep `factory_sim` free of Bevy and Unity-shaped abstractions. - Use typed Rust enums/newtypes for IDs and dispatch verbs instead of porting C# strings. - Use stable scenario output as the first observability surface. **Options considered** - Hard-coded content vs external data files: - Recommendation: hard-code the first content catalog in `factory_content`. External content loading is premature before the kernel semantics settle. - Grid/pathfinding now vs later: - Recommendation: later. Start with a minimal topology model so the first logistics slice stays small and deterministic. - Full dispatch verb set now vs minimal haul verbs now: - Recommendation: implement only the minimal haul loop first. `Retrieve/Deploy` can follow after the first closed loop is solid. **Open questions for the follow-up engineer** - Should the first source node be an explicit `OrePatch + MiningDrill` pair, or a simplified extractor/source actor with equivalent output semantics? - Recommendation: keep the actor count minimal, but preserve the difference between finite resource sources and recipe-based production. - Should the CLI snapshot schema be human text or JSON lines? - Recommendation: JSON lines, because deterministic golden tests are easier to maintain. - Should batteries/power be part of the first slice? - Recommendation: no. They are interesting, but not necessary to validate kernel direction. **Main risks** - Porting the Unity component graph too literally will create a Rust codebase that is hard to test and easy to over-couple. - Pulling in pathfinding or Bevy too early will bury the kernel milestone under engine work. - Leaving IDs and commands as strings will recreate avoidable correctness problems in the new code. - Chasing gameplay parity before the first deterministic loop exists will slow the migration and blur acceptance criteria. ## Explicitly Out Of Scope Keep these out of the first slice and out of the first issue: - Bevy viewer or any rendering/frontend work - Unity project cleanup beyond using the existing C# as reference material - NuGet or `tests.csproj` repair - Full gameplay parity with the Unity version - Power grid, batteries, deployment verbs, or pathfinding beyond the minimum topology needed for the first haul loop That scope cut is the main recommendation. The first milestone should prove that the repo can host a **deterministic Rust factory kernel with a testable autonomous logistics loop**, not that the whole game has been ported. --- Researched and posted automatically by `ward agent advisor --harness codex` (ward#179). This is one-shot research, not a carried change - verify before acting on it. <!-- ward-agent-reply --> <!-- ward-agent-signature --> — Codex, via `ward agent`
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/factory-game-v3#12
No description provided.