Layer 4 — the walkable quarter: a quarter now generates complete building +
street geometry. Implements D-220/D-229/D-233/D-234 (and the D-213 water bearing), absorbing #976 (footprint + street geometry) into #957 as one coherent
deliverable. All integer-deterministic (D-010).
What a generated quarter now contains
Buildings — subdivide_block_footprints: density-scaled BSP of each
128×128-tile block into variable axis-aligned TileRect plots (D-229 fast-path),
with the D-233 BulkClass roofed-coverage fraction deciding building-vs-open.
Each footprint → a BuildingPropertyTag (zone-type, entry-class, era, floors,
condition, flavor) in QuarterWorldState.block_tags, built in the plan phase.
Building tag derivation (D-229) — the authored (ZoningType × economic_role × setting) → ZoneTypeId selection table (D-229 amendment; planetary variants,
setting tweaker, station ids excluded → Q-109), entry-class (D-217 U-curve +
Grid/Organic fork), era (founding_age + prosperity + seed), FloorExtent (D-220),
initial condition (D-217).
Terrain orientation — Layer-1 TerrainAnalysis::water_bearing (8-octant
integer, no atan2) on each attractor → real coastal/river founding orientations
(#956's 0 stub gone for water settlements).
Waterfront rule (D-234b) — the water-facing quarter edge drops its setback
to 0 so buildings present flush to the quay.
Removed the write-only BlockSkeleton.era stub (era lives on the tag).
Pending cross-layer dependency (flagged, not a stub)
The waterfront rule + #956's bearings are correct and tested, but their real
per-settlement input only reaches quarter generation once the Layer-3 placement
→ Layer-4 GenerateSkeleton dispatch is wired — today city_context_reader
stubs founding_orientation: Cardinal and nothing dispatches quarter generation
from placements. That dispatch (with its trigger-timing design call, D-206) is the
next integration; the geometry here is complete and ready to consume it.
1323 lib tests + all integration tests pass. ~35 new tests across the
selection table, tag derivations, footprint packing, street network, water
bearing, and the waterfront rule (incl. the no-station-ids invariant).
Closes#957. Subsumes #976 (footprint + street geometry); only #976's open-water
edge-adjacency refinement rides with the pending dispatch.
## Summary
Layer 4 — the **walkable quarter**: a quarter now generates complete building +
street geometry. Implements D-220/D-229/D-233/D-234 (and the D-213 water bearing),
**absorbing #976** (footprint + street geometry) into #957 as one coherent
deliverable. All integer-deterministic (D-010).
## What a generated quarter now contains
- **Buildings** — `subdivide_block_footprints`: density-scaled BSP of each
128×128-tile block into variable axis-aligned `TileRect` plots (D-229 fast-path),
with the D-233 BulkClass roofed-coverage fraction deciding building-vs-open.
Each footprint → a `BuildingPropertyTag` (zone-type, entry-class, era, floors,
condition, flavor) in `QuarterWorldState.block_tags`, built in the plan phase.
- **Building tag derivation** (D-229) — the authored `(ZoningType × economic_role
× setting) → ZoneTypeId` selection table (D-229 amendment; planetary variants,
setting tweaker, station ids excluded → Q-109), entry-class (D-217 U-curve +
Grid/Organic fork), era (founding_age + prosperity + seed), FloorExtent (D-220),
initial condition (D-217).
- **Streets** (D-234) — typed `AccessPoint`/`CorridorSpine`/`ChunkLayout` (were
`String` stubs): access nodes from road-entry octants + reservation gates;
morphology-gated arterials (Ribbon / HubSpoke / Prim-MST mesh), ±45°-snapped;
per-block local lattice modulated by D-096 Grid/Organic.
- **Terrain orientation** — Layer-1 `TerrainAnalysis::water_bearing` (8-octant
integer, no `atan2`) on each attractor → real coastal/river founding orientations
(#956's `0` stub gone for water settlements).
- **Waterfront rule** (D-234b) — the water-facing quarter edge drops its setback
to 0 so buildings present flush to the quay.
- Removed the write-only `BlockSkeleton.era` stub (era lives on the tag).
## Decisions
D-229 amended (zone-selection table), D-234 amended (implementation note),
**Q-109 filed** (cascade generation-source dispatch — the planetary/station/mod/
save-only seam surfaced here).
## Pending cross-layer dependency (flagged, not a stub)
The waterfront rule + #956's bearings are correct and tested, but their *real*
per-settlement input only reaches quarter generation once the **Layer-3 placement
→ Layer-4 `GenerateSkeleton` dispatch** is wired — today `city_context_reader`
stubs `founding_orientation: Cardinal` and nothing dispatches quarter generation
from placements. That dispatch (with its trigger-timing design call, D-206) is the
next integration; the geometry here is complete and ready to consume it.
## Test plan
- `cargo fmt --check` clean; `cargo clippy --all-targets -- -D warnings` clean.
- **1323 lib tests + all integration tests pass.** ~35 new tests across the
selection table, tag derivations, footprint packing, street network, water
bearing, and the waterfront rule (incl. the no-station-ids invariant).
- Golden (`cascade_layer1.json`) + `atlas_response_ready.msgpack` rebaked —
additive (`water_bearing` field) / representational only; selection unchanged.
Closes #957. Subsumes #976 (footprint + street geometry); only #976's open-water
edge-adjacency refinement rides with the pending dispatch.
Surfaced during #957 zone-selection authoring: a body's setting/mode should
dispatch the cascade entry to planetary / station / mod-DLC-forked /
save-only(player_base) sources, distinct from setting's in-path tweaker role.
Captured as an open question so #957 stays scoped to the planetary path; this is
why #957's zone table excludes station-only zone ids.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The pure per-footprint tag derivations for Layer-4 quarter generation (D-229),
ahead of the footprint-subdivision + assembly step:
- zone_type_for: the authored (ZoningType × economic_role × setting) → ZoneTypeId
selection (D-229 amendment) — planetary variants only, setting as a tweaker,
station-only ids never selected (Q-109); deterministic seed-pick, no empty slice.
- building_entry_class: zone × layout_mode × prosperity, with the D-217 Broken-band
U-curve degrade (Commercial→BreachOnly) and the Grid/Organic credential fork.
- construction_era: founding_age + prosperity + seed (D-229); old+Broken → Derelict.
- floor_extent: D-220 density-class floor ranges from density_pct + seed-jitter.
- initial_condition: D-217 frozen-amber condition from prosperity + era cause.
All integer-deterministic (D-010). 9 unit tests incl. the no-station-ids invariant.
Footprint subdivision + assign_building_tags assembly + block_tags wiring follow
(needs the footprint-packing model decided).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Record the (ZoningType × economic_role × setting) → ZoneTypeId selection table
for the planetary cascade: base candidate slices per ZoningType refined by
economic_role, a setting tweaker (Maritime/Agricultural/Wilderness — planetary
variants only), and the gap-fill rules (entry-class U-curve at the D-217 Broken
band <2300bps; era per founding_age+prosperity+seed; FloorExtent from D-220
density midpoints; doors deferred to #979). Station-only zone ids are excluded —
they belong to a separate cascade (Q-109).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Build the per-quarter building geometry + tags (absorbs #976's footprint
subdivision into #957 — one coherent walkable-quarter deliverable):
- subdivide_block_footprints: deterministic BSP of each 128x128-tile block into
variable axis-aligned building plots (D-229 fast-path). Lot size + setback
scale with D-220 density (Frontier -> few big lots/wide gaps; Compressed ->
many small lots/shared walls); the D-233 BulkClass roofed-coverage fraction
decides building-vs-interstitial. morphology is wired in for the D-234
waterfront/street layer (needs Layer-1 terrain water-adjacency threaded up).
- assign_all_block_tags: subdivides + tags every non-reserved block's footprints
via the #957 derivation helpers, populating QuarterWorldState.block_tags in the
GenerateSkeleton plan-phase (D-230). Reserved blocks get no standard fill.
- Remove the write-only BlockSkeleton.era String stub - construction era now
lives per-footprint on BuildingPropertyTag.era (typed ConstructionEra).
All integer-deterministic (D-010). 5 new tests. Doors stay Vec::new() (#979).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Complete the Layer-4 quarter geometry with the street layer (D-234), replacing
the ChunkLayout/CorridorSpine/AccessPoint String stubs with real types:
- AccessPoint{position,kind} + AccessKind (QuarterEdge/ReservationGate/
BlockJunction): the quarter's road nodes (from road_entry_directions octants +
reservation gates), the node set the D-097 audit reads.
- CorridorSpine{from,to,path}: arterial trunk edges, ±45°-snapped polylines
(D-096 cap). Topology gated by morphology (D-234a): Ribbon (fjord/canyon/
mountain-pass), HubSpoke (delta/island/enclosed water), Mesh/Prim-MST
(plains/meander/coastal). A spanning tree over the access nodes.
- ChunkLayout{spacing,offset,rotation_steps}: per-block local ±45° lattice,
spacing from density, offset/rotation modulated by the D-096 Grid/Organic mode.
Wired into generate_quarter_skeleton (access_points + corridors + per-block
chunk_layout). All integer-deterministic (D-010). 7 new tests.
Remaining D-234 piece: the per-edge waterfront pier/quay rule needs Layer-1
terrain water-adjacency threaded to the skeleton (cross-layer plumbing).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Close the last D-234 piece — terrain water-direction extraction wired through
to founding orientation and the quarter waterfront rule:
- Layer 1: TerrainAnalysis::water_bearing — 8-octant integer bearing toward the
nearest water from the water_dist gradient (D-010, no atan2). Stored on
GeographicAttractor.water_bearing (360 = none).
- #956 founding orientation: coastal/river settlements now get a real
water-facing bearing (the anchoring attractor's), replacing the 0 stub.
- #957 waterfront rule (D-234b): the water-facing quarter edge (from the
settlement's Coastal founding orientation) drops its block setback to 0 so
buildings present flush to the quay (dock-orthogonal). Typed Edge + coastal_edge
+ per-block gating.
Golden + atlas_response fixture rebaked (additive water_bearing field only).
8 new tests. All integer-deterministic (D-010).
Pending: the waterfront rule reads context.founding_orientation, which
city_context_reader still stubs to Cardinal — real per-settlement orientation
reaches quarter generation once the Layer-3 placement -> Layer-4 GenerateSkeleton
dispatch is wired (the remaining cross-layer integration).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Note the #957 implementation on D-234: typed AccessPoint/CorridorSpine/
ChunkLayout, morphology-gated arterials + per-block lattice, BSP footprint
subdivision with D-233 coverage, and the waterfront rule. Flag the remaining
cross-layer dependency: the waterfront rule's real input (per-settlement Coastal
orientation) needs the Layer-3 placement -> Layer-4 GenerateSkeleton dispatch,
since city_context_reader still stubs founding_orientation to Cardinal.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PR #153 review (Hoshe H1): zone_type/era/floors/flavor all shared one fp_chain
and each took splitmix64(seed) of the same value, correlating the fields (era
tracking floor height across a city). Derive a distinct sub-chain per field so
they draw independent entropy. Block_tags aren't serialized, so no fixture
change; behavior stays deterministic.
Also (review): n=1 corridor test (empty, no panic), Frontier-density waterfront
test, and a comment on the reserved `_morphology` param (Tyre).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Determinism, BSP bounds (len - min_lot can't underflow — guarded by min_lot*2),
street net (prim_mst/snap45_path/coastal_edge boundaries), water-bearing
gradient + 360 sentinel, and the BlockSkeleton.era removal all verified clean.
One behavioral issue + two test gaps, now fixed:
#
File
Issue
Status
H1
skeleton_gen.rsassign_block_tags
zone/era/floors/flavor shared one fp_chain → each splitmix64(seed) of the same value → correlated fields (era tracking floor height citywide)
Fixedf880635b2 — distinct per-field sub-chains
H2
skeleton_gen.rs tests
no n=1 corridor test (empty/no-panic path)
Fixed — added
H3
skeleton_gen.rs tests
waterfront test only at density 70
Fixed — added Frontier-density test
Tyre (architecture): APPROVE
Scope collapse (#976 → #957) is the right call — street geometry + footprint
subdivision aren't separable at the Quarter level; the module is large but coherent (one transform: context → walkable quarter). D-234 fidelity confirmed
(morphology→topology gating, arterial-MST/local-lattice split, Voronoi rejected,
waterfront rule). The flagged dispatch dependency is documented honestly across
D-234 note + PR + Q-109; implementing the waterfront rule now (correct, dormant,
safe Cardinal fallback) is the right call. Typed structs well-shaped; String→struct
change is generation-internal (not on the IPC wire). D-229/D-234 inline amendments
Q-109 are correct decision hygiene. One non-blocking polish: comment the
reserved _morphology param — done in the fix commit.
Verdict: APPROVED
(Hoshe's H1 fix + both test gaps + Tyre's polish landed in f880635b2.)
## Review: layer4-quarter-skeleton → main (type: code)
Reviewers: Hoshe (QA) + Tyre (architecture). Gate: clippy `--all-targets -D
warnings` clean; 1325 lib + integration tests pass.
### Hoshe (QA / correctness): APPROVE (after fix)
Determinism, BSP bounds (`len - min_lot` can't underflow — guarded by `min_lot*2`),
street net (`prim_mst`/`snap45_path`/`coastal_edge` boundaries), water-bearing
gradient + 360 sentinel, and the `BlockSkeleton.era` removal all verified clean.
One behavioral issue + two test gaps, now fixed:
| # | File | Issue | Status |
|---|------|-------|--------|
| H1 | `skeleton_gen.rs` `assign_block_tags` | zone/era/floors/flavor shared one `fp_chain` → each `splitmix64(seed)` of the same value → correlated fields (era tracking floor height citywide) | **Fixed** `f880635b2` — distinct per-field sub-chains |
| H2 | `skeleton_gen.rs` tests | no n=1 corridor test (empty/no-panic path) | **Fixed** — added |
| H3 | `skeleton_gen.rs` tests | waterfront test only at density 70 | **Fixed** — added Frontier-density test |
### Tyre (architecture): APPROVE
Scope collapse (#976 → #957) is the right call — street geometry + footprint
subdivision aren't separable at the Quarter level; the module is large but
*coherent* (one transform: context → walkable quarter). D-234 fidelity confirmed
(morphology→topology gating, arterial-MST/local-lattice split, Voronoi rejected,
waterfront rule). The flagged dispatch dependency is documented honestly across
D-234 note + PR + Q-109; implementing the waterfront rule now (correct, dormant,
safe Cardinal fallback) is the right call. Typed structs well-shaped; String→struct
change is generation-internal (not on the IPC wire). D-229/D-234 inline amendments
+ Q-109 are correct decision hygiene. One non-blocking polish: comment the
reserved `_morphology` param — **done** in the fix commit.
### Verdict: APPROVED
(Hoshe's H1 fix + both test gaps + Tyre's polish landed in `f880635b2`.)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Layer 4 — the walkable quarter: a quarter now generates complete building +
street geometry. Implements D-220/D-229/D-233/D-234 (and the D-213 water bearing),
absorbing #976 (footprint + street geometry) into #957 as one coherent
deliverable. All integer-deterministic (D-010).
What a generated quarter now contains
subdivide_block_footprints: density-scaled BSP of each128×128-tile block into variable axis-aligned
TileRectplots (D-229 fast-path),with the D-233 BulkClass roofed-coverage fraction deciding building-vs-open.
Each footprint → a
BuildingPropertyTag(zone-type, entry-class, era, floors,condition, flavor) in
QuarterWorldState.block_tags, built in the plan phase.(ZoningType × economic_role × setting) → ZoneTypeIdselection table (D-229 amendment; planetary variants,setting tweaker, station ids excluded → Q-109), entry-class (D-217 U-curve +
Grid/Organic fork), era (founding_age + prosperity + seed), FloorExtent (D-220),
initial condition (D-217).
AccessPoint/CorridorSpine/ChunkLayout(wereStringstubs): access nodes from road-entry octants + reservation gates;morphology-gated arterials (Ribbon / HubSpoke / Prim-MST mesh), ±45°-snapped;
per-block local lattice modulated by D-096 Grid/Organic.
TerrainAnalysis::water_bearing(8-octantinteger, no
atan2) on each attractor → real coastal/river founding orientations(#956's
0stub gone for water settlements).to 0 so buildings present flush to the quay.
BlockSkeleton.erastub (era lives on the tag).Decisions
D-229 amended (zone-selection table), D-234 amended (implementation note),
Q-109 filed (cascade generation-source dispatch — the planetary/station/mod/
save-only seam surfaced here).
Pending cross-layer dependency (flagged, not a stub)
The waterfront rule + #956's bearings are correct and tested, but their real
per-settlement input only reaches quarter generation once the Layer-3 placement
→ Layer-4
GenerateSkeletondispatch is wired — todaycity_context_readerstubs
founding_orientation: Cardinaland nothing dispatches quarter generationfrom placements. That dispatch (with its trigger-timing design call, D-206) is the
next integration; the geometry here is complete and ready to consume it.
Test plan
cargo fmt --checkclean;cargo clippy --all-targets -- -D warningsclean.selection table, tag derivations, footprint packing, street network, water
bearing, and the waterfront rule (incl. the no-station-ids invariant).
cascade_layer1.json) +atlas_response_ready.msgpackrebaked —additive (
water_bearingfield) / representational only; selection unchanged.Closes #957. Subsumes #976 (footprint + street geometry); only #976's open-water
edge-adjacency refinement rides with the pending dispatch.
Complete the Layer-4 quarter geometry with the street layer (D-234), replacing the ChunkLayout/CorridorSpine/AccessPoint String stubs with real types: - AccessPoint{position,kind} + AccessKind (QuarterEdge/ReservationGate/ BlockJunction): the quarter's road nodes (from road_entry_directions octants + reservation gates), the node set the D-097 audit reads. - CorridorSpine{from,to,path}: arterial trunk edges, ±45°-snapped polylines (D-096 cap). Topology gated by morphology (D-234a): Ribbon (fjord/canyon/ mountain-pass), HubSpoke (delta/island/enclosed water), Mesh/Prim-MST (plains/meander/coastal). A spanning tree over the access nodes. - ChunkLayout{spacing,offset,rotation_steps}: per-block local ±45° lattice, spacing from density, offset/rotation modulated by the D-096 Grid/Organic mode. Wired into generate_quarter_skeleton (access_points + corridors + per-block chunk_layout). All integer-deterministic (D-010). 7 new tests. Remaining D-234 piece: the per-edge waterfront pier/quay rule needs Layer-1 terrain water-adjacency threaded to the skeleton (cross-layer plumbing). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>Review: layer4-quarter-skeleton → main (type: code)
Reviewers: Hoshe (QA) + Tyre (architecture). Gate: clippy
--all-targets -D warningsclean; 1325 lib + integration tests pass.Hoshe (QA / correctness): APPROVE (after fix)
Determinism, BSP bounds (
len - min_lotcan't underflow — guarded bymin_lot*2),street net (
prim_mst/snap45_path/coastal_edgeboundaries), water-bearinggradient + 360 sentinel, and the
BlockSkeleton.eraremoval all verified clean.One behavioral issue + two test gaps, now fixed:
skeleton_gen.rsassign_block_tagsfp_chain→ eachsplitmix64(seed)of the same value → correlated fields (era tracking floor height citywide)f880635b2— distinct per-field sub-chainsskeleton_gen.rstestsskeleton_gen.rstestsTyre (architecture): APPROVE
Scope collapse (#976 → #957) is the right call — street geometry + footprint
subdivision aren't separable at the Quarter level; the module is large but
coherent (one transform: context → walkable quarter). D-234 fidelity confirmed
(morphology→topology gating, arterial-MST/local-lattice split, Voronoi rejected,
waterfront rule). The flagged dispatch dependency is documented honestly across
D-234 note + PR + Q-109; implementing the waterfront rule now (correct, dormant,
safe Cardinal fallback) is the right call. Typed structs well-shaped; String→struct
change is generation-internal (not on the IPC wire). D-229/D-234 inline amendments
reserved
_morphologyparam — done in the fix commit.Verdict: APPROVED
(Hoshe's H1 fix + both test gaps + Tyre's polish landed in
f880635b2.)Pull request closed