Something went wrong. Try again.
HEXWORK - A Lantern in the Deep: 3D ASCII terminal roguelike RPG in Rust.
Entirely designed and built by Muse Spark 1.3 to evaluate if I like the model.
Something went wrong. Try again.
Phase 2 Wiring Plan (parent integration, executes when A–D return) #
Workstreams own their files; parent owns everything else. This doc is the exact merge contract so integration is mechanical.
1. lib.rs additions (parent edits) #
pub mod air;
pub mod fire;
pub mod fluids;
pub mod gravity;
pub mod laws;
pub mod light;
pub mod materials;
pub mod rope;
pub mod rot;
pub mod scent;
pub mod signal;
pub mod sound;
pub mod structure;
2. State additions (parent edits state.rs only) #
pub laws: LawLog— first-time law registry; consulted before pushing any hazard CauseLink (§4.10.5 "no silent rules").pub fall_odo: BTreeMap<u64, f32>— per-actor metres descended, passed&muttogravity::step_falling_with_massevery Move tick (total-height damage; fix-C odometer). Clear an actor's entry on teleport; entries for grounded/embedded/dead actors self-reset each call.pub sounds: Vec<SoundEvent>— Sound phase drains this queue.pub lights: Vec<LightSource>— lantern + carried glow + flora; Light phase consumes.pub corpses: BTreeMap<(i32,i32,i32), CorpseClock>— Rot phase owns.pub spillover: Vec<Spill>— remainder queue when a phase exceeds its 4k update cap; drained first next tick. ExactSpillshape TBD from workstream return signatures — keep per-system spillover INSIDE each module if they already queue it; parent only wires what exists.
3. Phase wiring (parent edits run_phase only) #
| Phase | Call | Region scope |
|---|---|---|
| Move | gravity::step_falling(&mut actors, &grid, ...) replaces settle stub |
actors |
| Fluids | fluids::step_fluids(grid, region, rng, causes, tick) |
active ±72 vox |
| Gas | air::advect_markers(grid, &self.drafts(), ...) |
active ±72 vox |
| Fire | fire::step_fire(grid, region, rng, causes, tick) |
active ±72 vox |
| Signal | signal::step_signal(grid, &sources, region, ...) (sources: worldgen live cable; test arena stubs) |
active ±72 vox |
| Light | light::propagate_light_capped(grid, &self.lights, dirty_only=true); on lamp remove/move/douse call clear_light_box(old box) FIRST, then propagate; re-queue when spillover > 0 |
dirty cells |
| Sound | drain self.sounds → sound::propagate_sound(...); AI investigate stub stays (Phase 9/10) |
edges+nodes |
| Structure | structure::step_structure(grid, region, ...) |
dirty supports |
| Rot | rot::step_rot(...) + scent::step_scent(...) |
region + corpse map |
Region = active 3×3×3 chunks around player actor (±72 voxels each axis). Hymns stays stubbed (Phase 8); AETHER_MIST cookoff links already emitted by fire.rs.
4. Conflict resolution rules (parent judges by these) #
- Design docs beat implementation: docs/03 §3.3 > subagent API choices.
- Determinism law is absolute: any HashMap/Instant/threading found at wiring time is rejected back to the workstream, not patched by parent.
- API mismatches between workstreams (e.g. scent emission paths assumed
by fluids vs. scent's real signature) are fixed at the CALLER side in
state.rs, never by editing a workstream's file without its consent — if the callee's shape is wrong per spec, send it back with the exact diff required. hash_state()MUST extend to voxel contents + new maps once phases mutate them (determinism contract). Parent adds: grid contents hash (bounded: hash only loaded chunks, BTreeMap order), corpses, lights.
5. Phase 2 gate tests (parent writes tests/phase2_laws.rs AFTER wiring) #
20 rule-chain integration tests. Canonical list (each asserts the causal story, not just the end state). Reviewer-ordered adjustments folded in (review-audit C/A, xhigh):
sledge_opens_shortcut_loudasserts the cause LINK text ("everything hears"-class line), not aState.soundsqueue entry — no such queue exists yet; the Sound phase translates link→event at wiring.supported_lintel_standsusesextra == 0stone (weakened rusted/cracked collapse is design-grounded law 11 and stays: rusted iron andextra != 0cracked stone collapse even with support).- Bowling tests place the victim ≤ 0.8 m HORIZONTALLY, expect a single victim with lander-takes-ceil split; damage-0 landings never bowl.
- Mid-fall ticks assert empty events + reduced
pos.z(still-airborne = cross-strata arrival hook, not grounded). boulder_down_shaft/thrown_potionexpectations use TOTAL-height damage (fix-workstream-c odometer), not final-tick remainder.- Gas-phase tests build
Vec<(u64, u64, f32)>flow triples viapack_cellfrom edges + drafts + cell→volume map (NOTdrafts()magnitudes passed raw —drafts()returns edge-indexed magnitudes; see MAJOR-4), call the 4-argadvect_markers, and re-queueflows[budget..]tails. step_structureregion args are tight ≤ 64-span dirty bounds, never the whole ±72 active volume (MAX_REGION_SPAN truncation is documented).
Canonical list (each asserts the causal story, not just the end state):
oil_under_door_grate_chokes_actor(the mimic kill, generic actor)smoke_rises_through_shaftchlorine_pools_upward_from_floor(levitate counter demo hook)thrown_potion_arcs_and_shatters_belowboulder_down_shaft_arrives_below(cross-strata arrival)coin_throw_lures_loudest_node(voice-throw)rope_snaps_when_overloaded(CHECK GRATES link present)cut_rope_drops_actor_with_fall_damageunsupported_lintel_collapses/ 10.supported_lintel_standssledge_opens_shortcut_loud(sound event emitted)water_douses_fire_to_steamoil_ignites_and_spreadsacid_blood_pits_iron_grate(cable-rat story beat)verdigris_eats_copper_wireshock_chains_through_water(tragedy path link)corpse_bloats_bursts_spawns(Rustmother link)wet_iron_rusts_over_timeflour_reveals_hidden_vent(SECRET_REVEALED + link)first_time_law_logged_once(laws.rs deduplication)
Plus proptest material×hazard matrix (tests/phase2_matrix.rs, needs
proptest dev-dep — parent adds AFTER workstreams land to avoid breaking
their builds with a lockfile change mid-flight).
6. Gate acceptance (checklist Phase 2 gate) #
- All 12 laws demoable in test arena (
hexwork --arenalands Phase 5; until then the 20 integration tests ARE the demo, run headless). - Every hazard emits a first-time law log line (assert via LawLog in tests).
cargo fmt --check,clippy -D warnings, 24+ pre-existing tests still green, 10k-tick soak stable with NEW hash (hash WILL change — voxel contents join it; record new canonical hash in soak test comment).- Tick ≤ 8ms p99 narrative: criterion bench extended to a populated arena
(parent adds
benches/arena.rsin Phase 13 perf harness; for now assert 10k-tick soak wall time < 80s headless as a smoke bound).