5.4 KiB
Progress Ledger — reikhelm procgen core
Orchestrator's external memory. One entry per task as it completes.
Environment notes
- Rust 1.96.0 stable.
~/.cargo/binNOT on PATH — prependexport PATH="$HOME/.cargo/bin:$PATH"in every cargo shell call. - Resolved dep versions: rand 0.10.1, rand_chacha 0.10.0, rand_core 0.10.1, serde 1.0.228 (derive), macroquad 0.4.15. rand 0.10 line — RNG task must target 0.10 API (prefer building helpers on RngCore::next_u64).
Execution schedule
- Phase 0: Task 1 (scaffold) — direct dispatch, de-risk toolchain/version resolution.
- Phase 1: Tasks 2→3→5 chain + Task 4 (RNG) — core library layer.
- Phase 2: Task 6 (engine) — keystone Pass/Pipeline contract + validator.
- Phase 2.5: orchestrator pre-stubs 5 pass files + wires passes/mod.rs.
- Phase 3: Tasks 7–11 (passes) — parallel, worktree-isolated; then adversarial verify.
- Phase 4: Task 12 (recipe + integration) — heavy determinism/connectivity verification.
- Phase 5: Task 13 (viz) — build + boundary check.
Task log
Task 1 — Workspace scaffold ✅ (commit 08e99e3)
- Two-crate workspace, resolver "2", edition 2021. core deps: rand/rand_chacha/serde(derive); viz deps: macroquad + reikhelm-core (path).
cargo build+cargo testgreen (0 tests). lib.rs has only crate doc; main.rs plainfn main()stub..dev/plan committed into repo root (fine for greenfield). No rendering dep in core ✓.
Tasks 2–5 — core library layer ✅ (commits f707bd1, dbfd44a, 6ffe0cc, 659ef00)
Ran as Phase 1 workflow (sequential 2→3→4→5). All 41 tests green, no warnings. Reviewed all source directly.
- T2 geometry: Point/Rect/Line + extras (OFFSETS4/8, offset, right/bottom/is_empty, sign). Fixed iteration orders for determinism. Point derives Hash. Line::cells handles diagonal as connected staircase (documented).
- T3 grid: bounds-safe Grid, row-major, OOB read=None/write=no-op. iter_rect avoids Rect::iter borrow lifetime. Now also derives PartialEq/Eq (see fix below).
- T4 rng: ChaCha8 wrapper.
forkmix = splitmix64(basis) → FNV-1a over label bytes → splitmix64 finalizer. NO DefaultHasher. fork(&self) order-independent, doesn't mutate parent. range=half-open w/ rejection sampling; shuffle=hand-rolled Fisher–Yates on next_u64; chance clamps + 53-bit. Adversarial RNG verify never ran (worktree error) — I reviewed it manually: contract holds. - T5 data model: Tile{Wall(default),Floor,Door}; RegionId(pub usize) id==index invariant; RegionKind{Room,Corridor}; Region/Edge fields pub; Edge.at=Option; ConnGraph new/add_edge/edges/edges_mut/neighbors; Map all-pub; to_ascii
#/./+.
Orchestrator fix — derive PartialEq/Eq on Grid + Map ✅ (commit 8c4ef2e)
T5 deliberately skipped Eq on Map (Grid wasn't Eq) and used a serde-string compare workaround. Added the derives at the data-model layer so Tasks 6 & 12 determinism tests can use assert_eq!(map_a, map_b) directly. Purely additive, 41 tests still green.
⚠️ Environment constraint discovered
Worktree isolation is UNAVAILABLE (WorktreeIsolationError: not in a git repository and no WorktreeCreate hooks configured) — even though git rev-parse confirms a valid repo. Do NOT use isolation: 'worktree' in workflows or Agent calls. Phase 3 (parallel passes 7–11) must use a different anti-race strategy: orchestrator pre-stubs all 5 pass files + pre-wires passes/mod.rs, commits, then passes are implemented — likely SEQUENTIALLY in the shared tree (or with each agent told to only Write its file + not run concurrent cargo) to avoid build races. Re-decide at Phase 3.
Task 6 — generation engine ✅ (commit e0a20f7)
Direct dispatch + my full code review (skipped separate validator — keystone read line-by-line; Task 12 integration tests are the end-to-end backstop). 53 tests green, clippy-clean.
Pass::apply(&self, ctx, rng)exact.GenContext{tiles,regions,graph,blackboard}+add_region→RegionId(len()).Snapshot{label,tiles,regions,edges}.Pipeline::new(w,h)/then/run/run_with_snapshots.- RNG isolation correct: per-NAME occurrence counter (
HashMap<&str,u32>), key"name#occ",root.fork(key)per pass. Isolation test inserts draw-then-discard X between A,B and proves their streams unchanged. ✓ run/run_with_snapshotsshare privaterun_inner(seed, collect)→ cannot diverge. Snapshots clone-after-apply, RNG-untouched. ✓BlackboardHashMap<String,Box>; wrong-type get→None, take non-destructive. ✓passes/mod.rscreated with contract doc comment, NO pub mod lines (7–11 append).
Phase 3 plan (REVISED — no worktrees)
Run passes 7→8→9→10→11 SEQUENTIALLY in shared tree (forced by no worktree isolation). Each implementer creates its file + appends its own pub mod/pub use to passes/mod.rs (sequential = no race, like Tasks 2-5 did with lib.rs). No pre-stubbing needed. Sequential also lets later passes (e.g. DoorPlacer) read earlier passes' real cell-population conventions. Then a PARALLEL adversarial verify fan-out (read-only, no isolation) over the 5 passes for algorithm/determinism/bounds bugs. Heavy integration verification deferred to Task 12.
Open concerns
- Determinism is the highest-risk surface: RNG fork stability (T4) + pipeline per-pass forking (T6). Both get adversarial verification.
- Parallel batch (7–11) shares passes/mod.rs — handled by orchestrator-owned pre-wiring + worktree isolation.