feat(simulation): FillChunk shell derivation — Void/Wall/FloorSlab/Roof from cached tags (T-987)

Implement the D-230 on-demand derive phase (data-production half). New
atlas/shell.rs derives a sparse building shell for one 64 m chunk from the
plan-phase BuildingPropertyTags: rectangle-containment (footprint ∩ chunk) ×
z-range (per-floor voxel bands from FloorExtent), in a quarter-ground z frame
(D-110). Walls on the footprint perimeter, FloorSlab on interior floor bases,
Roof above the top floor; interior air is Void and never stored.

- gen_queue.rs: GenWorkItem::FillChunk carries pre-resolved block_tags +
  block_pos + sub_chunk (run_work_item stays cache-free, mirroring
  GenerateSkeleton); GenCompletion::ChunkFilled carries Box<FilledChunk>; the
  arm calls shell::fill_chunk; pure build_fill_chunk_item(&QuarterWorldState,..)
  added.
- plugin.rs: ChunkFilled handler accepts the shell (trace-only — the Phase-5
  rendering consumer and the on-demand streaming dispatch trigger are deferred;
  do not build on legacy chunk_streaming.rs before Phase 5, gated by T-962).

Tests: determinism, sparsity-vs-dense-volume, wall/floor/roof correctness,
basement z-origin, sub-chunk clipping, full submit→drain→ChunkFilled round-trip.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-27 23:34:46 +02:00
co-authored by Claude Opus 4.8
parent 85311f716c
commit 5f85dc55d5
6 changed files with 630 additions and 13 deletions
+16 -1
View File
@@ -175,7 +175,22 @@ fn drain_generation_completions(
}
// body_id empty = stub result from GenerateSkeleton stub; silently ignore.
}
GenCompletion::ChunkFilled { .. } => {}
GenCompletion::ChunkFilled { filled } => {
// The shell is derived (D-230, T-987). There is no consumer on the
// main thread yet: in-world rendering of generated tiles is Phase 5
// (gated by T-962), and the on-demand *dispatch* trigger — enqueueing
// FillChunk as the player's load radius enters a chunk — lives in the
// Phase-5 streaming path, which must not be built on the legacy
// `chunk_streaming.rs` rendering code before then (CLAUDE.md cascade
// rule). FillChunk is re-derivable on demand (D-227), so dropping the
// result here costs nothing structural; we only trace it for now.
tracing::trace!(
quarter_id = filled.quarter_id,
chunk = ?filled.chunk_in_quarter(),
voxels = filled.voxel_count(),
"FillChunk derived (no Phase-5 consumer yet)"
);
}
}
}
}