reikhelm/.dev/conventions.md
Parley Hatch 068df27c7d chore: orchestration bookkeeping through Task 6 (progress, ledger, conventions)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 21:22:42 -06:00

3.6 KiB
Raw Blame History

Project Conventions — reikhelm

Ground truth every dispatched agent reads. Plan lives at .dev/2026-05-28-procgen-map-core/.

Toolchain & environment (CRITICAL)

  • Rust 1.96.0 stable, aarch64-apple-darwin, via rustup.
  • ~/.cargo/bin is NOT on the non-interactive shell PATH. Every shell command that runs cargo, rustc, or rustup MUST first export it:
    export PATH="$HOME/.cargo/bin:$PATH"
    
    Put this at the front of the same Bash invocation as your cargo command. If you forget it you'll get command not found: cargo.
  • Run all cargo commands from the workspace root /Users/caspar/Projects/reikhelm.

Dependency versions (RESOLVED by Task 1)

  • rand 0.10.1, rand_chacha 0.10.0, rand_core 0.10.1, serde 1.0.228 (derive), macroquad 0.4.15.
  • This is the rand 0.10 line — newer than 0.8/0.9. Verify exact API paths against the compiler: ChaCha8Rng implements SeedableRng (seed_from_u64(u64) / from_seed([u8;32])); rand_core::RngCore gives next_u32/next_u64. To minimize exposure to rand's churning trait paths (SliceRandomIndexedRandom/IndexedMutRandom across 0.8→0.9), prefer building range/chance/choose/shuffle directly on RngCore::next_u64 (e.g. FisherYates shuffle from our own range) — also more transparent for determinism. cargo build is the arbiter.

Git

  • Repo is initialized in Task 1; work happens on the default branch (no feature branch — greenfield bring-up, explicitly authorized by the session goal).
  • Each task commits with the exact message given in its task file's ## Commit section.
  • End every commit message body with this trailer (on its own line, preceded by a blank line):
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    
  • Commit only the files your task created/modified. Do not commit /target (gitignored).

Module wiring ownership

  • A task that CREATES a module file also appends its own pub mod <name>; to the parent (lib.rs or passes/mod.rs or recipes/mod.rs) — EXCEPT the parallel pass batch (Tasks 711): for those, the orchestrator pre-wires passes/mod.rs and pre-creates empty stub files, so pass implementers ONLY edit their own pass file and never touch mod.rs.

Determinism rules (load-bearing — spec §7)

  • All generation randomness flows through reikhelm_core::rng::Rng (ChaCha8). Never thread_rng/rand::random().
  • Never std::collections::hash_map::DefaultHasher for anything that affects generation — it's version-unstable. RNG fork uses an explicit integer mix (splitmix64 / FNV-style).
  • No HashMap/HashSet iteration order may influence generated output (use sorted/BTreeMap or index order where order matters).
  • Same seed → byte-identical Map, every run, every machine.

Rust style

  • Derive traits rather than hand-impl where possible (Clone, Copy, Debug, PartialEq, Eq, serde).
  • Public items get a /// doc comment. Keep functions small and total — no panics on valid input.
  • Grid writes go through bounds-safe accessors; OOB is a no-op, never a panic (spec §8).
  • Prefer iterators/combinators over index loops where it reads cleanly. This is a learning-Rust project: favor clear, idiomatic code over clever code.
  • Tests live in an inline #[cfg(test)] mod tests { use super::*; ... } at the bottom of the module file.

Reporting (for dispatched implementers)

End your report with a STATUS line: DONE, DONE_WITH_CORRECTIONS, NEEDS_CONTEXT, or BLOCKED. Paste the actual cargo test output (not "tests pass"). List every file you created/modified. If you deviated from the task spec, say why.