feat(simulation): Layer 5 exterior grammar + material fill + D-253 (T-988/959/1097/1057) #174

Closed
jpmschweitzer wants to merge 0 commits from layer5-tile-fill into main
Owner

Summary

The Layer-5 batch — building-exterior visual grammar, material fill onto the shell, ops-surface tagging, and the region transient-state D-record. Advances T-750 (Phase 4) toward the T-962 walkable-world gate.

  • T-988 — BuildingExteriorTag grammar (authored-depth v1). New trait_exterior.rs: 3-step era-free derivation (visual_bundle filter → zone-bias weighted pick → density→setback), color seed-sampled within the template's register band. Resolved at GenerateSkeleton (T-994 precedent), frozen on BuildingPropertyTag; FillChunk only reads it. Four append-only integer-discriminant material enums; trait_catalog_reader now parses visual_bundle + two new tables (OnceLock-cached); new SeedDomain::TraitExterior with per-axis sub-chains (no cross-field correlation). Content authored by Miri (zone-bias, 57 sparse entries) + Araminta (28 color bands), baked into systems.db with V-TT-06/07 importer validation (token-in-bundle, coverage + integer HSV bounds).
  • T-959 — Layer-5 material fill. FillChunk reads the frozen exterior tag → wall/roof materials onto Wall/Roof shell voxels (FilledChunk.surface_material), purely additive. Interstitial-fill-from-setback split to T-1098 (needs a FillChunk block-metadata + geometry design pass; nothing consumes FillChunk until Phase 5).
  • T-1097 — ops-surface. BlockSkeleton.interstitial_character (OpenSpace | OperationsSurface), D-233 bulk-driven: bulk-industry blocks' non-roofed remainder tags as built economic infrastructure.
  • T-1057 — D-253 (resolves Q-105): region transient state model — four clock terms (diurnal/tidal/weather/seasonal), memoized-by-bucket absolute-clock evaluation, edge-fuzzed per-tile inheritance, integer-deterministic, state-model-only. Q-102 resolved-in-practice; Q-103/Q-109 deferred to Phase 5+.

Verification

Full pre-push gate green: cargo fmt --check, cargo clippy --all-targets -D warnings, 1666 lib tests, make test-tooling (incl. new V-TT-05/06/07 failure-branch units), cargo deny, fresh systems.db stamp. No golden impact (harnesses top out at CascadeLayer::RoadGraph — Layer 4/5 is structurally unreachable).

🤖 Generated with Claude Code

## Summary The Layer-5 batch — building-exterior visual grammar, material fill onto the shell, ops-surface tagging, and the region transient-state D-record. Advances T-750 (Phase 4) toward the T-962 walkable-world gate. - **T-988 — BuildingExteriorTag grammar** (authored-depth v1). New `trait_exterior.rs`: 3-step era-free derivation (visual_bundle filter → zone-bias weighted pick → density→setback), color seed-sampled within the template's register band. Resolved at GenerateSkeleton (T-994 precedent), frozen on `BuildingPropertyTag`; FillChunk only reads it. Four append-only integer-discriminant material enums; `trait_catalog_reader` now parses `visual_bundle` + two new tables (OnceLock-cached); new `SeedDomain::TraitExterior` with per-axis sub-chains (no cross-field correlation). Content authored by Miri (zone-bias, 57 sparse entries) + Araminta (28 color bands), baked into `systems.db` with **V-TT-06/07** importer validation (token-in-bundle, coverage + integer HSV bounds). - **T-959 — Layer-5 material fill.** FillChunk reads the frozen exterior tag → wall/roof materials onto Wall/Roof shell voxels (`FilledChunk.surface_material`), purely additive. Interstitial-fill-from-setback split to **T-1098** (needs a FillChunk block-metadata + geometry design pass; nothing consumes FillChunk until Phase 5). - **T-1097 — ops-surface.** `BlockSkeleton.interstitial_character` (OpenSpace | OperationsSurface), D-233 bulk-driven: bulk-industry blocks' non-roofed remainder tags as built economic infrastructure. - **T-1057 — D-253** (resolves Q-105): region transient state model — four clock terms (diurnal/tidal/weather/seasonal), memoized-by-bucket absolute-clock evaluation, edge-fuzzed per-tile inheritance, integer-deterministic, state-model-only. Q-102 resolved-in-practice; Q-103/Q-109 deferred to Phase 5+. ## Verification Full pre-push gate green: `cargo fmt --check`, `cargo clippy --all-targets -D warnings`, **1666 lib tests**, `make test-tooling` (incl. new V-TT-05/06/07 failure-branch units), `cargo deny`, fresh systems.db stamp. No golden impact (harnesses top out at CascadeLayer::RoadGraph — Layer 4/5 is structurally unreachable). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jpmschweitzer added 4 commits 2026-07-11 10:34:16 +02:00
T-959 rescoped (objects descoped, title updated); T-1097 (ops-surface
fill, D-233) split out as a new child; T-1057 gates T-959 (blocker edge);
recovered T-1057's lost description + triage dispositions. README index
regen reflects Q-049 resolution (PR #173).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
D-253 (resolves Q-105): the region owns transient clock-bound surface
state — four phase terms (diurnal/tidal/weather/seasonal), memoized-by-
bucket absolute-clock evaluation, edge-fuzzed per-tile inheritance,
integer-deterministic (D-010), state-model-only (no gameplay/rendering).
Discharges the T-1030/T-1078/T-1082 forward-contracts. Diurnal promoted to
a first-class term (user-confirmed).

Q-102 resolved-in-practice (D-246 voxel_mosaic + D-228 override stack);
Q-103 + Q-109 deferred to Phase 5+ with dated triage notes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Ratified content baked into systems.db as two new tables:
- architecture_zone_bias (57 rows): sparse per-template, per-zone_type
  token-weight overrides (integer bps), Miri-authored — the D-235 step-2
  zone bias. V-TT-06: every token must exist in that template's own
  visual_bundle axis.
- color_register_bands (28 rows): per color_register integer HSV bands
  (hue centidegrees, sat/val bps), Araminta-authored. V-TT-07: full
  catalog coverage + valid integer bounds (min<max, in range).

Both TOMLs registered in generator_sources (stamp coverage); DDL in
systems-schema.sql + migration.py; validation wired into import_economics
steps 18/19 and test_traits.py failure-branch units (make test-tooling).
systems.db regenerated + re-stamped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
T-988 — BuildingExteriorTag {wall_material, roof_form, facade_rhythm,
setback_tier, color:HsvColor, street_surface}. New trait_exterior.rs:
3-step era-free derivation (visual_bundle filter -> zone-bias weighted
pick -> density->setback), color seed-sampled within the register band.
Resolved at GenerateSkeleton plan time (T-994 precedent), frozen on
BuildingPropertyTag; FillChunk only reads it. Four append-only
integer-discriminant enums (WallMaterial/RoofForm/FacadeRhythm/
StreetSurface), unknown token -> axis Generic + warn. trait_catalog_reader
now parses visual_bundle + the two new tables (OnceLock-cached).
New SeedDomain::TraitExterior (per-axis sub-chains — no cross-field
correlation).

T-959 — FillChunk reads the frozen exterior tag: wall_material/roof_form
onto Wall/Roof shell voxels (FilledChunk.surface_material). Additive,
ShellVoxel untouched, all shell tests pass. (Interstitial-fill-from-setback
split to T-1098 — needs a FillChunk block-metadata + geometry design pass;
nothing consumes FillChunk until Phase 5.)

T-1097 — BlockSkeleton.interstitial_character (OpenSpace|OperationsSurface),
D-233 bulk-driven: bulk-industry blocks' non-roofed remainder tags as built
economic infrastructure, not generic open space.

cargo check --all-targets clean; 1666 lib tests pass; no golden impact
(harnesses top out at CascadeLayer::RoadGraph, unreachable by Layer 4/5).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Author
Owner

Review: layer5-tile-fill → main (type: code)

Reviewers: Hoshe (code quality), Tyre (architecture) — both read the branch worktree at 204359927.

Hoshe (Code Quality): REQUEST_CHANGES

The trait_exterior.rs derivation is careful, integer-only, correctly domain-separates its seven per-axis RNG sub-chains, and every content-gap path degrades to Generic/neutral (all tested). shell.rs surface_material is cleanly additive (ShellVoxel untouched). Two robustness gaps in the new importer validation block approval.

# File Issue
H1 tooling/economy-db/economy_import/traits.py:313 populate_architecture_zone_bias: a non-dict axis value (wall = 15000, or the array-shaped wall = ["steel_frame"] copy-paste from the sibling catalog's visual_bundle) hits (weights or {}).items() → bare AttributeError, not the clean V-TT-06 error every other malformed shape produces. The function guards zone_map (line 294) and axes (line 300) are dicts but never the per-axis weights. import_economics rolls back so no DB corruption, but the user gets a traceback instead of an actionable stanza pointer. Untested branch. Fix: isinstance(weights, dict) guard mirroring the two above it.
H2 tooling/economy-db/economy_import/traits.py:319 if not isinstance(weight, int) or weight <= 0 doesn't exclude bool (an int subclass) — weight = true passes as 1. populate_color_register_bands explicitly guards this same footgun for its own values; match it.

Tyre (Architecture): APPROVE

No comments. Independently verified: D-253 is internally consistent and correctly scoped (adds the time dimension over T-1078's spatial baseline, does not touch the D-243 spatial stack; scope boundary explicitly excludes gameplay/passability/rendering); Q-102/103/109 citations check out against D-246/D-228 and shipped shell.rs; determinism clean (no HashMap, no floats, integer-only draws); SeedDomain::TraitExterior = 16 appended + pinned; seven independent seed sub-axes off fp_chain, zero shared rolls; schema/migration/generator_sources all paired; ExteriorCatalog clone is launch-bounded in the no-budget plan phase; zero bare unwrap/expect/panic in new production paths; the T-1097 BlockSkeleton relocation and the T-1098 deferred-interstitial seam are both architecturally clean.

Verdict: CHANGES REQUESTED

H1 + H2 are isolated Python hardening (+ their missing tests) in one importer function. Fixing now.

Process notes: no client/merge-path touched (server + tooling + governance only). Runtime verification = the full pre-push gate (clippy -D warnings, 1666 lib tests, make test-tooling incl. V-TT failure-branch units, cargo deny, fresh stamp). No golden impact.

## Review: layer5-tile-fill → main (type: code) Reviewers: Hoshe (code quality), Tyre (architecture) — both read the branch worktree at `204359927`. ### Hoshe (Code Quality): REQUEST_CHANGES The `trait_exterior.rs` derivation is careful, integer-only, correctly domain-separates its seven per-axis RNG sub-chains, and every content-gap path degrades to Generic/neutral (all tested). `shell.rs` surface_material is cleanly additive (ShellVoxel untouched). Two robustness gaps in the new importer validation block approval. | # | File | Issue | |---|------|-------| | H1 | `tooling/economy-db/economy_import/traits.py:313` | `populate_architecture_zone_bias`: a non-dict axis value (`wall = 15000`, or the array-shaped `wall = ["steel_frame"]` copy-paste from the sibling catalog's `visual_bundle`) hits `(weights or {}).items()` → bare `AttributeError`, not the clean `V-TT-06` error every other malformed shape produces. The function guards `zone_map` (line 294) and `axes` (line 300) are dicts but never the per-axis `weights`. `import_economics` rolls back so no DB corruption, but the user gets a traceback instead of an actionable stanza pointer. Untested branch. Fix: `isinstance(weights, dict)` guard mirroring the two above it. | | H2 | `tooling/economy-db/economy_import/traits.py:319` | `if not isinstance(weight, int) or weight <= 0` doesn't exclude `bool` (an int subclass) — `weight = true` passes as 1. `populate_color_register_bands` explicitly guards this same footgun for its own values; match it. | ### Tyre (Architecture): APPROVE No comments. Independently verified: D-253 is internally consistent and correctly scoped (adds the *time* dimension over T-1078's spatial baseline, does not touch the D-243 spatial stack; scope boundary explicitly excludes gameplay/passability/rendering); Q-102/103/109 citations check out against D-246/D-228 and shipped `shell.rs`; determinism clean (no HashMap, no floats, integer-only draws); `SeedDomain::TraitExterior = 16` appended + pinned; seven independent seed sub-axes off `fp_chain`, zero shared rolls; schema/migration/generator_sources all paired; `ExteriorCatalog` clone is launch-bounded in the no-budget plan phase; zero bare unwrap/expect/panic in new production paths; the T-1097 `BlockSkeleton` relocation and the T-1098 deferred-interstitial seam are both architecturally clean. ### Verdict: CHANGES REQUESTED H1 + H2 are isolated Python hardening (+ their missing tests) in one importer function. Fixing now. Process notes: no client/merge-path touched (server + tooling + governance only). Runtime verification = the full pre-push gate (clippy -D warnings, 1666 lib tests, make test-tooling incl. V-TT failure-branch units, cargo deny, fresh stamp). No golden impact.
jpmschweitzer added 1 commit 2026-07-11 13:24:26 +02:00
H1: guard that each axis value is a {token=weight} table before .items() —
a scalar (wall = 15000) or the array shape (wall = ["steel_frame"], a
plausible copy-paste from the sibling catalog's visual_bundle) now yields a
clean V-TT-06 error instead of a bare AttributeError. Mirrors the isinstance
guards already on zone_map and axes.
H2: exclude bool from the positive-integer weight check (weight = true is an
int subclass, previously slipped through as 1) — matches the guard
populate_color_register_bands already applies to its own values.
Two new ZoneBiasValidationTests cover both branches.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Author
Owner

Review response — both findings fixed in b8e0b1b66

No pushbacks; both verified against the branch and fixed.

# Resolution
H1 populate_architecture_zone_bias now guards that each axis value is a {token = weight_bps} table before iterating — a scalar (wall = 15000) or the array shape (wall = ["steel_frame"], the copy-paste-from-visual_bundle case Hoshe named) yields a clean V-TT-06 error naming the stanza + the wrong type, instead of a bare AttributeError. Mirrors the isinstance guards already on zone_map and axes.
H2 The positive-integer weight check now excludes bool (isinstance(weight, bool) or not isinstance(weight, int) or weight <= 0) — weight = true is rejected instead of slipping through as 1. Matches the guard populate_color_register_bands already applies to its own values.

Two new ZoneBiasValidationTests cover both branches (test_non_dict_axis_value_reports_vtt06_not_a_traceback asserts the clean error for both the scalar and array shapes; test_bool_weight_is_rejected). make test-tooling now runs 26 traits units, all green.

systems.db regenerated + re-stamped (traits.py is a stamped generator source, so the stamp had to flip). Full pre-push gate re-run green.

Tyre's review was APPROVE with no comments. With H1/H2 addressed, the batch is review-clean.

## Review response — both findings fixed in `b8e0b1b66` No pushbacks; both verified against the branch and fixed. | # | Resolution | |---|-----------| | H1 | `populate_architecture_zone_bias` now guards that each axis value is a `{token = weight_bps}` table before iterating — a scalar (`wall = 15000`) or the array shape (`wall = ["steel_frame"]`, the copy-paste-from-`visual_bundle` case Hoshe named) yields a clean **V-TT-06** error naming the stanza + the wrong type, instead of a bare `AttributeError`. Mirrors the `isinstance` guards already on `zone_map` and `axes`. | | H2 | The positive-integer weight check now excludes `bool` (`isinstance(weight, bool) or not isinstance(weight, int) or weight <= 0`) — `weight = true` is rejected instead of slipping through as `1`. Matches the guard `populate_color_register_bands` already applies to its own values. | Two new `ZoneBiasValidationTests` cover both branches (`test_non_dict_axis_value_reports_vtt06_not_a_traceback` asserts the clean error for both the scalar and array shapes; `test_bool_weight_is_rejected`). `make test-tooling` now runs 26 traits units, all green. `systems.db` regenerated + re-stamped (traits.py is a stamped generator source, so the stamp had to flip). Full pre-push gate re-run green. Tyre's review was APPROVE with no comments. With H1/H2 addressed, the batch is review-clean.
jpmschweitzer closed this pull request 2026-07-11 15:02:20 +02:00

Pull request closed

This pull request cannot be reopened because the branch was deleted.
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jpmschweitzer/settled-reach#174