# Task 12: Dungeon Recipe + Integration Tests

**Depends on:** Task 7, Task 8, Task 9, Task 10, Task 11

## Context Files
- `.dev/2026-05-28-procgen-map-core/spec/design.md` — §4.8 (recipes), §8 (error handling), §9 (testing), §10 (acceptance).
- `.dev/2026-05-28-procgen-map-core/README.md` — inter-pass data contract (the full chain).
- `reikhelm-core/src/pass.rs` — `Pipeline` (Task 6).
- `reikhelm-core/src/passes/mod.rs` — all five passes + their configs (Tasks 7–11).
- `reikhelm-core/src/lib.rs` — append the module declaration here.

## Files
- Create: `reikhelm-core/src/recipes/mod.rs` — recipes module root; append `pub mod dungeon;`.
- Create: `reikhelm-core/src/recipes/dungeon.rs` — `DungeonConfig`, `ConfigError`, `dungeon()`; integration tests.
- Modify: `reikhelm-core/src/lib.rs` — append `pub mod recipes;`.

## What to Build
The dungeon recipe (spec §4.8): a function that validates a config and assembles the full pipeline — `BspPartition` → `RoomCarver` → `MstConnect` → `CorridorCarver` → `DoorPlacer` — sized to the config. `DungeonConfig` composes the per-pass configs and the map dimensions, with sensible `Default`s. Validation (spec §8) runs at recipe construction: dimensions > 0, and the room min size must be able to fit within the smallest possible BSP leaf (`min_leaf`), returning `ConfigError` rather than panicking. This task also carries the cross-pass **integration tests** (spec §9) that prove the whole chain works.

## Interface Dependencies
- **Consumes:** `Pipeline` (Task 6); all five passes + configs (Tasks 7–11).
- **Produces:**
  - `struct DungeonConfig { width: u32, height: u32, bsp: BspConfig, rooms: RoomConfig, connect: ConnectConfig }` (+ `Default`).
  - `enum ConfigError { /* e.g. ZeroDimension, RoomLargerThanLeaf, ... */ }` (impl `std::error::Error`/`Display`).
  - `fn dungeon(cfg: DungeonConfig) -> Result<Pipeline, ConfigError>`.

## Tests (integration — spec §9)
- **Determinism:** `dungeon(cfg)?.run(42)` twice produces equal `Map`s and identical `to_ascii()`.
- **`run` == `run_with_snapshots`:** same seed yields the same `Map`; snapshot count == 5.
- **Connectivity:** flood-fill the `Floor`/`Door` tiles of a generated dungeon; assert every `Room` region's interior is reachable (no orphaned rooms).
- **Bounds:** no non-`Wall` tile lies outside the map; all rooms within bounds.
- **Config validation:** zero dimensions and a room-min-size larger than `min_leaf` both return `Err(ConfigError)`, not a panic.
- **Door reachability sanity:** at least one `Door` tile exists in a multi-room dungeon, and connected edges have `at == Some(_)`.
- (Optional) print one ASCII dungeon in a `#[test]` behind `--nocapture` for eyeball confirmation.

## Success Criteria
- [ ] `dungeon(cfg)` validates config and returns a `Pipeline` (or `ConfigError`) assembling all five passes in order.
- [ ] A generated dungeon is fully connected, in-bounds, deterministic, and has doors.
- [ ] `run` and `run_with_snapshots` agree; snapshot count is 5.
- [ ] Module declarations added to `lib.rs`/`recipes/mod.rs`.
- [ ] All tests pass: `cargo test -p reikhelm-core` (full suite green)

## Commit
`"feat(core): dungeon recipe + end-to-end integration tests"`
