feat(db): architecture zone-bias + color-register-band tables + V-TT-06/07 (T-988)

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>
This commit is contained in:
2026-07-11 09:03:19 +02:00
co-authored by Claude Fable 5
parent 14b2eb69c5
commit ba781f9324
10 changed files with 1147 additions and 4 deletions
+380
View File
@@ -0,0 +1,380 @@
# ==========================================================================
# Architecture zone-type bias table (T-988, D-235 step 2)
#
# D-235's BuildingExteriorTag derivation is 3 steps: (1) the district's
# dominant trait template (D-232) filters the available token set per axis
# via its own `visual_bundle`; (2) THIS FILE biases which of those
# already-filtered tokens a building is likely to draw, keyed on the
# building's FUNCTION (D-142 zone_type) — "an industrial block stays stone,
# not corrugated metal, if the template's allow-list says so"; (3) density
# sets setback_tier. This table is step 2 only.
#
# SPARSE / FALLBACK MODEL. This is deliberately NOT a full 28-template x
# 31-zone_type x 4-axis matrix (3,472 cells). It authors only the cases
# where cultural or functional logic genuinely demands a lean — a civic
# building reaching for stone and colonnade, a market stall staying in the
# lighter/cheaper register, a fishing quay pulling boardwalk over cobble.
# Every (template, zone_type) pair NOT listed here — and every token within
# a listed entry not given a weight — falls back to a UNIFORM draw across
# the template's visual_bundle for that axis. Absence of an entry is not an
# oversight; it means the template's own visual_bundle already tells the
# whole story for that function, or (rarely, see note at end) the template
# has no per-axis choice left to bias.
#
# OWNERSHIP. Same co-maintenance split as object_tag_vocabulary.toml
# (Q-049's resolution: split by concern, not by file) —
# - Miri owns the CULTURAL/FUNCTIONAL rationale: which zone_type leans
# toward which already-allowed token, and why (the inline comment above
# each entry below).
# - Araminta owns VISUAL-COHERENCE tuning of the bps weights themselves
# (does the resulting draw distribution actually read well against the
# shipped art, does a "boost" ever starve a token to invisibility).
# This pass (T-988 content deliverable) is Miri's cultural-logic
# authoring pass with initial weights; Araminta's visual-coherence review
# of the weights is a expected follow-up, same pattern as her parallel
# `color_register_bands.toml` pass in this same ticket.
#
# SCHEMA. Integer basis points (D-010): 10000 = 1.0x the uniform baseline.
# A weight above 10000 boosts a token above uniform likelihood; a weight
# below 10000 (never authored as 0 — no hard excludes here, that's what
# the template's own allow/block already did) suppresses it toward rare.
# Only tokens already present in the template's own visual_bundle.<axis>
# may appear (importer-validated, V-TT check) — this file never expands a
# template's palette, only re-weights within it. Unlisted tokens/axes/zones
# keep the uniform baseline.
#
# [bias.<template_tag>.<zone_type_id>]
# wall = { <wall_token> = <bps>, ... } # optional per axis
# roof = { <roof_token> = <bps>, ... }
# facade = { <facade_token> = <bps>, ... }
# street = { <street_token> = <bps>, ... }
# ==========================================================================
# ==========================================================================
# A. CROSS-CORRIDOR POOL
# ==========================================================================
# mixed_market_vernacular: brick reads load-bearing/durable shopfront vs.
# rendered's softer domestic finish upstairs.
[bias.mixed_market_vernacular.commercial_market]
wall = { brick_wall = 15000 }
street = { cobble = 14000 }
[bias.mixed_market_vernacular.residential_surface]
wall = { rendered_wall = 14000 }
street = { paved = 13000 }
# speculative_boomtown: freight gets the rawest register (first thing
# thrown up); the market street is the town's "arrived" storefront.
[bias.speculative_boomtown.industrial_freight]
wall = { steel_frame = 16000 }
roof = { corrugated_roof = 16000 }
street = { packed_earth = 15000 }
[bias.speculative_boomtown.commercial_market]
wall = { composite_panel = 14000 }
roof = { flat_roof = 13000 }
street = { paved = 13000 }
# extraction_camp: the works itself is steel; worker housing is poured
# concrete, not rig-grade steel.
[bias.extraction_camp.extraction_platform]
wall = { steel_frame = 18000 }
[bias.extraction_camp.residential_surface]
wall = { concrete_wall = 14000 }
# industrial_utilitarian: the production floor is steel/corrugated/heavy-
# haul; the district's few storefronts keep the older brick frontage.
[bias.industrial_utilitarian.industrial_manufacturing]
wall = { steel_frame = 15000 }
roof = { corrugated_roof = 14000 }
street = { heavy_haul = 15000 }
[bias.industrial_utilitarian.commercial_market]
wall = { brick_wall = 13000 }
roof = { flat_roof = 12000 }
street = { paved = 13000 }
# cold_chain_works: the plant is permanent concrete with truck access; the
# produce-market front is the lighter composite-panel register.
[bias.cold_chain_works.industrial_processing]
wall = { concrete_wall = 14000 }
street = { heavy_haul = 15000 }
[bias.cold_chain_works.commercial_market]
wall = { composite_panel = 13000 }
street = { paved = 13000 }
# precision_arcology: labs get the showcase glass + green roof + clean
# raised walkways; the production floor behind it stays flat/paved/panel.
[bias.precision_arcology.research_station]
roof = { green_roof = 15000 }
street = { elevated_walkway = 14000 }
[bias.precision_arcology.industrial_manufacturing]
wall = { composite_panel = 13000 }
roof = { flat_roof = 14000 }
street = { paved = 13000 }
# information_spire: civic seats keep institutional restraint even at the
# top of the spire; retail/market level gets the reactive screen facade.
[bias.information_spire.administrative_civil]
facade = { regular_facade = 15000 }
street = { elevated_walkway = 13000 }
[bias.information_spire.commercial_market]
facade = { screen_facade = 14000 }
street = { paved = 13000 }
# civic_monumental: the courts get the fullest ceremonial treatment of any
# building in the catalog; a mere checkpoint in an Administrative district
# is NOT a courthouse — utilitarian concrete, ornament suppressed hard.
[bias.civic_monumental.administrative_civil]
wall = { stone_wall = 16000 }
roof = { vaulted_roof = 15000 }
facade = { colonnade = 15000 }
street = { cobble = 14000 }
[bias.civic_monumental.administrative_judicial]
wall = { stone_wall = 16000 }
roof = { vaulted_roof = 16000 }
facade = { colonnade = 16000 }
street = { cobble = 14000 }
[bias.civic_monumental.security_checkpoint]
wall = { concrete_wall = 15000 }
roof = { flat_roof = 15000 }
facade = { ornamental_facade = 6000 }
# foreign_quarter: the transplant that draws a crowd gets the grand vaulted/
# lattice register; the quiet domestic import stays plainer.
[bias.foreign_quarter.entertainment_venue]
roof = { vaulted_roof = 15000 }
facade = { lattice_screen = 14000 }
[bias.foreign_quarter.residential_surface]
roof = { clay_tile_roof = 13000 }
facade = { screen_facade = 13000 }
# ==========================================================================
# B. PER-CORRIDOR BASELINE POOLS
# ==========================================================================
# core_cosmopolitan: the old ministries stay stone/ornamental; modern retail
# layers glass over the old core; ordinary old-town housing stays brick.
[bias.core_cosmopolitan.administrative_civil]
wall = { stone_wall = 15000 }
facade = { ornamental_facade = 14000 }
[bias.core_cosmopolitan.commercial_market]
wall = { glass_curtain_wall = 14000 }
facade = { regular_facade = 13000 }
[bias.core_cosmopolitan.residential_surface]
wall = { brick_wall = 13000 }
roof = { pitched_roof = 13000 }
# north_anglo_frontier: civic restraint in brick vs. timber farm sheds with
# corrugated roofs on packed-earth farm tracks.
[bias.north_anglo_frontier.administrative_civil]
wall = { brick_wall = 14000 }
facade = { regular_facade = 14000 }
street = { paved = 13000 }
[bias.north_anglo_frontier.rural_agricultural]
wall = { timber_wall = 14000 }
roof = { corrugated_roof = 15000 }
street = { packed_earth = 15000 }
# south_lusophone: the praça-facing arcade for the market vs. the shuttered
# private house.
[bias.south_lusophone.commercial_market]
facade = { arcade_facade = 15000 }
street = { cobble = 14000 }
[bias.south_lusophone.residential_surface]
facade = { shuttered_facade = 14000 }
wall = { stucco_wall = 13000 }
# west_germanic_ordered: engineered brick precision for manufacturing vs.
# the plain rendered residential street.
[bias.west_germanic_ordered.industrial_manufacturing]
wall = { brick_wall = 14000 }
street = { paved = 14000 }
[bias.west_germanic_ordered.residential_surface]
wall = { rendered_wall = 13000 }
street = { cobble = 12000 }
# west_compact_cooperative: the civic hall is visibly held in common
# (colonnade + green roof) vs. plain cooperative housing.
[bias.west_compact_cooperative.administrative_civil]
facade = { colonnade = 16000 }
roof = { green_roof = 14000 }
[bias.west_compact_cooperative.residential_surface]
facade = { regular_facade = 13000 }
wall = { rendered_wall = 13000 }
# east_dense_utilitarian: signage-saturated screen facade at the retail/
# transit level vs. lattice-screened concrete housing above.
[bias.east_dense_utilitarian.commercial_market]
facade = { screen_facade = 15000 }
street = { elevated_walkway = 14000 }
[bias.east_dense_utilitarian.residential_surface]
facade = { lattice_screen = 14000 }
wall = { concrete_wall = 13000 }
street = { paved = 13000 }
# frontier_surname_settlement: the founder-family's one formal stone
# building vs. rammed-earth farm outbuildings on packed earth.
[bias.frontier_surname_settlement.administrative_civil]
wall = { stone_wall = 16000 }
facade = { regular_facade = 14000 }
street = { cobble = 15000 }
[bias.frontier_surname_settlement.rural_agricultural]
wall = { rammed_earth_wall = 14000 }
roof = { flat_roof = 13000 }
street = { packed_earth = 15000 }
# frontier_hardscrabble: only the wall axis has any choice here — a
# checkpoint gets the standardized defensive concrete; a frontier outpost
# gets the locally hand-built rammed earth.
[bias.frontier_hardscrabble.security_checkpoint]
wall = { concrete_wall = 15000 }
[bias.frontier_hardscrabble.wilderness_frontier]
wall = { rammed_earth_wall = 14000 }
# ==========================================================================
# C. HERITAGE SUB-POOLS
# ==========================================================================
# scottish_highland_vernacular: scattered crofts (pitched roof, packed
# earth track) vs. the one village market building (tile roof, cobble).
[bias.scottish_highland_vernacular.residential_dispersed]
roof = { pitched_roof = 14000 }
street = { packed_earth = 14000 }
[bias.scottish_highland_vernacular.commercial_market]
roof = { clay_tile_roof = 13000 }
street = { cobble = 13000 }
# west_african_compound: the market-facing arcade vs. the private family
# compound behind its shuttered rammed-earth wall.
[bias.west_african_compound.commercial_market]
facade = { arcade_facade = 15000 }
street = { cobble = 13000 }
[bias.west_african_compound.residential_surface]
facade = { shuttered_facade = 14000 }
wall = { rammed_earth_wall = 13000 }
street = { packed_earth = 14000 }
# iberian_hacienda: the estate-office colonnade reads institutional vs. the
# veranda-fronted domestic hacienda.
[bias.iberian_hacienda.administrative_civil]
facade = { colonnade = 15000 }
wall = { stone_wall = 14000 }
[bias.iberian_hacienda.residential_surface]
facade = { arcade_facade = 14000 }
wall = { stucco_wall = 13000 }
# atlantic_creole_maritime: the working waterfront (timber, boardwalk) vs.
# inland creole housing (render, cobble).
[bias.atlantic_creole_maritime.port_fishing]
wall = { timber_wall = 14000 }
street = { boardwalk = 15000 }
[bias.atlantic_creole_maritime.residential_surface]
wall = { rendered_wall = 13000 }
street = { cobble = 13000 }
# nordic_timber: the coastal fishing quay pulls boardwalk; inland housing
# keeps the turf/green-roof domestic register on cobble.
[bias.nordic_timber.port_fishing]
street = { boardwalk = 15000 }
[bias.nordic_timber.residential_surface]
roof = { green_roof = 13000 }
street = { cobble = 13000 }
# central_european_blok: civic solidity keeps its ornament in reserve (but
# still reaches for it) vs. the plain perimeter-block housing stock.
[bias.central_european_blok.administrative_civil]
facade = { ornamental_facade = 14000 }
wall = { brick_wall = 14000 }
[bias.central_european_blok.residential_surface]
facade = { regular_facade = 13000 }
wall = { rendered_wall = 13000 }
# east_asian_temple_enclave: ceremonial reception gets the full vaulted-
# colonnade register; the ordinary residential quarter around the temple
# stays in the softer timber/lattice domestic register.
[bias.east_asian_temple_enclave.diplomatic_elite]
roof = { vaulted_roof = 16000 }
facade = { colonnade = 15000 }
[bias.east_asian_temple_enclave.residential_surface]
wall = { timber_wall = 14000 }
roof = { clay_tile_roof = 13000 }
facade = { lattice_screen = 13000 }
street = { cobble = 13000 }
# vietnamese_water_village: working water trade backs onto the canal;
# land-fronting tube-houses face the boardwalk instead.
[bias.vietnamese_water_village.port_fishing]
wall = { timber_wall = 14000 }
street = { canal_way = 15000 }
[bias.vietnamese_water_village.rural_aquaculture]
street = { canal_way = 15000 }
[bias.vietnamese_water_village.residential_surface]
wall = { rendered_wall = 13000 }
street = { boardwalk = 13000 }
# afrikaans_kraal: the werf/farmstead register (render, pitched roof, dirt
# track) vs. the more formal Cape civic building (stone, tile, cobble).
[bias.afrikaans_kraal.rural_pastoral]
wall = { rendered_wall = 14000 }
roof = { pitched_roof = 14000 }
street = { packed_earth = 14000 }
[bias.afrikaans_kraal.administrative_civil]
wall = { stone_wall = 14000 }
roof = { clay_tile_roof = 13000 }
street = { cobble = 13000 }
# arab_oasis_qanat: the shaded souk-adjacent market lane vs. the courtyard
# house with its wind-tower privacy screen.
[bias.arab_oasis_qanat.commercial_market]
wall = { stucco_wall = 14000 }
facade = { lattice_screen = 14000 }
street = { cobble = 14000 }
[bias.arab_oasis_qanat.residential_surface]
wall = { rammed_earth_wall = 14000 }
roof = { terraced_roof = 14000 }
facade = { screen_facade = 14000 }
street = { packed_earth = 14000 }
# ==========================================================================
# NOT BIASED — flagged, not an oversight
# ==========================================================================
# generic_baseline is the one template with ZERO degrees of freedom: every
# axis (wall/roof/facade/street) carries exactly one token in its
# visual_bundle. There is nothing left to bias — any zone_type drawing this
# template gets that one token per axis regardless. This is correct: it is
# the corridor-neutral fallback the draw can always reach (catalog line 57),
# and a single-token axis is definitionally already "uniform."
# ==========================================================================
+330
View File
@@ -0,0 +1,330 @@
# ==========================================================================
# Color register bands (T-988, D-235) — numeric HSV bands per D-232
# trait-template `color_register` label. Turns the free-form palette-cue
# string documented in object_tag_vocabulary.toml ("a palette cue, NOT an
# ObjectTag") into an authored, sampleable numeric range.
#
# THE MODEL: each color_register gets ONE integer HSV band. The fill seed
# picks a single (hue, sat, val) point uniformly within the band per
# building — same register, same family feel, different building each time.
# This is the register acting as intended (D-235): "always within the
# template's register," never a fixed single color, never unbounded.
#
# INTEGER UNITS (D-010 — no floats, ever; determinism is save-critical
# under D-227):
# hue 0..36000 centidegrees (degrees x 100; standard 0-360 deg wheel)
# sat 0..10000 basis points (0-100.00%)
# val 0..10000 basis points (0-100.00%)
# All three axes are closed [min, max] integer ranges, min < max, sampled
# uniformly (no wraparound support — no band crosses the hue 0/36000 seam).
#
# SATURATION CEILING (visual-hierarchy discipline, not a hard schema rule):
# every band in this file stays at or below sat = 3600 (36%). This keeps
# building material color — structure, the least important read — clearly
# under the saturation the project reserves for foreground signal (entity /
# relationship color has historically run 40-60% in this project's palette
# work). Buildings should never visually compete with the things standing
# in front of them. Even the two "brightest allowed" cultural-accent
# registers (bright_painted, falu_red_and_pine) stay under this ceiling.
#
# OWNERSHIP (Q-049 split, same as object_tag_vocabulary.toml): Miri owns
# whether a register's cultural placement is right for its template/corridor
# (the WHY); Araminta owns the numeric HSV authoring (the WHAT it looks
# like) and the cross-register visual discipline (distinctness, saturation
# hierarchy, mood). Changes to a band's numbers are Araminta's call; changes
# to which register a template carries are Miri's. Add both together when a
# new template ships a new color_register value.
#
# COVERAGE: every color_register value referenced by
# architecture_trait_catalog.toml's `visual_bundle.color_register` MUST have
# a `[register.<value>]` entry here — the importer validates this (T-988).
# 28 values are banded below, one per current template. Two are flagged in
# the section comments as the most interpretive calls in the set — real
# entries, not placeholders, but worth a cultural sanity-check from Miri.
#
# The fill seed samples (h, s, v) once per building and stores the result as
# three plain integers on BuildingExteriorTag — no re-derivation, no drift.
# ==========================================================================
# ==========================================================================
# I. COOL NEUTRAL / INSTITUTIONAL & TECH — cool-cast hues (~190-220 deg),
# the lowest-saturation family in the file. Differ mainly by value
# (how pale) and a hair of saturation (how "designed" vs "clinical").
# ==========================================================================
[register.neutral_grey]
hue = [20000, 21200] # centidegrees (200-212 deg, cool blue-grey)
sat = [400, 1200] # bps (4-12%)
val = [4800, 6400] # bps (48-64%)
# generic_baseline — corridor-neutral concrete default; the fallback every
# other register is a deviation FROM. Mid-value, barely-there cool tint.
[register.clean_pale]
hue = [19000, 20200] # centidegrees (190-202 deg, near-neutral, faint cool)
sat = [200, 800] # bps (2-8%) -- the lowest sat band in the catalog
val = [7600, 9000] # bps (76-90%)
# cold_chain_works — food/pharma hygiene register. Clinical pale, almost
# no color at all; reads as "clean" through value and absence of tint.
[register.cool_clean]
hue = [20000, 21400] # centidegrees (200-214 deg, cool blue)
sat = [600, 1600] # bps (6-16%)
val = [7000, 8400] # bps (70-84%)
# precision_arcology — cleanroom/fab register. Quiet, controlled, a shade
# more saturated and a shade darker than clean_pale (expensive, not sterile).
[register.glass_and_light]
hue = [20400, 21800] # centidegrees (204-218 deg, cool blue, glazing tint)
sat = [1000, 2200] # bps (10-22%)
val = [7200, 8800] # bps (72-88%)
# information_spire — glass curtain-wall office towers. Brightest, most
# reflective register in the set; the sat bump over cool_clean is the
# tinted-glazing read, not "more colorful," just "more glass."
[register.neon_over_grey]
hue = [19200, 20400] # centidegrees (192-204 deg, cool cyan-grey)
sat = [1200, 2600] # bps (12-26%)
val = [4400, 6000] # bps (44-60%)
# east_dense_utilitarian — cyberpunk-density baseline. The grey base carries
# a restrained cool cast; actual neon is signage/lighting, a different
# system (environmental neutrality) -- this band stays a paint color, not a
# light source, so it never reads as garish.
# ==========================================================================
# II. WARM CIVIC PALE — the warm-hue counterpart to section I. One entry:
# civic authority reads warm and dignified, not cool and clinical.
# ==========================================================================
[register.pale_stone]
hue = [3800, 5000] # centidegrees (38-50 deg, warm stone tan)
sat = [400, 1400] # bps (4-14%)
val = [6800, 8200] # bps (68-82%)
# civic_monumental — colonnades and institutional gravitas. Pale and low-sat
# like section I, but warm instead of cool: authority, not sterility.
# ==========================================================================
# III. INDUSTRIAL OXIDE & RAW — warm rust-to-greige hues, low-mid sat,
# low-mid value. The heavy-process / unfinished / hostile-world family.
# ==========================================================================
[register.oxide_and_dust]
hue = [2000, 3000] # centidegrees (20-30 deg, rust orange)
sat = [1800, 3200] # bps (18-32%)
val = [3200, 4800] # bps (32-48%, dark and dusty)
# extraction_camp — mine/rig/well-is-the-town register. Darkest and
# grittiest of the industrial family; rust-streaked steel, ground dust.
[register.oxide_and_steel]
hue = [1600, 2800] # centidegrees (16-28 deg, rust diluted toward neutral)
sat = [1000, 2200] # bps (10-22%, lower than oxide_and_dust)
val = [3600, 5200] # bps (36-52%)
# industrial_utilitarian — large-span sheds, tank farms. Steel dilutes the
# rust the extraction camp shows raw; less dust, more exposed structure.
[register.raw_provisional]
hue = [3000, 4200] # centidegrees (30-42 deg, warm greige)
sat = [600, 1600] # bps (6-16%)
val = [5200, 6800] # bps (52-68%)
# speculative_boomtown — thrown-up-fast composite/steel. Low commitment
# color for a settlement still deciding what it is; unfinished, provisional.
[register.hardened_earth]
hue = [2800, 3800] # centidegrees (28-38 deg, earth-neutral)
sat = [600, 1600] # bps (6-16%)
val = [3600, 5000] # bps (36-50%, dark)
# frontier_hardscrabble — hardened against a hostile primary. Dense concrete
# and rammed earth, minimal exposed surface; the darkest earth-family band.
# ==========================================================================
# IV. EARTH & MASONRY BASELINES — warm brown-tan mid-tones, the "everyday
# vernacular" family. Six corridor baselines that must read as siblings
# (all timber/brick/render/stone) while staying individually legible.
# ==========================================================================
[register.mixed_warm]
hue = [1600, 3000] # centidegrees (16-30 deg, brick-orange)
sat = [1200, 2400] # bps (12-24%)
val = [4600, 6200] # bps (46-62%)
# mixed_market_vernacular — organic ground-floor-trade townscape. Warmest
# and most saturated of this section; decades of layered commercial signage.
[register.muted_practical]
hue = [2600, 3800] # centidegrees (26-38 deg, muted brown)
sat = [800, 1800] # bps (8-18%)
val = [4600, 6000] # bps (46-60%)
# north_anglo_frontier — Commonwealth-frontier civic restraint. Weatherboard
# and brick, orderly and unshowy; the corridor's practical default.
[register.ordered_earth]
hue = [3000, 4000] # centidegrees (30-40 deg, earth tan)
sat = [900, 1900] # bps (9-19%)
val = [5000, 6400] # bps (50-64%)
# west_germanic_ordered — disciplined massing, engineered tidiness.
# Everything has its place; the color is as restrained as the geometry.
[register.communal_warm]
hue = [2800, 3800] # centidegrees (28-38 deg, warm, same family as ordered_earth)
sat = [1200, 2400] # bps (12-24%)
val = [5600, 7200] # bps (56-72%, brighter than ordered_earth)
# west_compact_cooperative — shared halls, civic infrastructure held in
# common. Brighter and a touch warmer than the Germanic baseline it sits
# beside -- "legible to its members" reads as more open, not more muted.
[register.sober_masonry]
hue = [2600, 3600] # centidegrees (26-36 deg, muted brick-brown)
sat = [900, 1900] # bps (9-19%)
val = [4400, 5800] # bps (44-58%)
# central_european_blok — Polish/Czech masonry perimeter blocks. Ornament
# held in reserve; so is the color -- solid, civic, unornamented.
[register.local_stone]
hue = [3200, 4400] # centidegrees (32-44 deg, warm stone-earth)
sat = [800, 1800] # bps (8-18%)
val = [5200, 6800] # bps (52-68%)
# frontier_surname_settlement — built from whatever the world offered.
# Self-reliant and coherent across centuries; unglamorous by design.
# ==========================================================================
# V. OCHRE / TERRACOTTA / SAND — warm orange-tan, mid-to-high sat and
# value, the sun-baked family. Distinguished from section IV by being
# more saturated (IV's earths are muted; these are declarative).
# ==========================================================================
[register.warm_ochre]
hue = [3200, 4200] # centidegrees (32-42 deg, ochre-orange)
sat = [1800, 3000] # bps (18-30%)
val = [5400, 7000] # bps (54-70%)
# west_african_compound — rendered ochre walls around shared courtyards.
# Warmer and more saturated than the frontier-earth registers in section IV.
[register.terracotta_and_lime]
hue = [1800, 2800] # centidegrees (18-28 deg, terracotta red-orange)
sat = [1600, 2800] # bps (16-28%)
val = [6000, 7600] # bps (60-76%)
# iberian_hacienda — stucco courtyards, clay-tile roofs, arcaded verandas.
# The band carries the terracotta warmth; lime-washed brightness lives at
# the high end of value. (One HSV point can't hold two named materials at
# once -- terracotta is the primary read here, lime is the value lift.)
[register.sand_and_shade]
hue = [3600, 4600] # centidegrees (36-46 deg, sandy tan)
sat = [600, 1600] # bps (6-16%)
val = [6200, 7600] # bps (62-76%)
# arab_oasis_qanat — rammed-earth courtyard houses under harsh dryland
# light. Paler and less saturated than warm_ochre/terracotta -- sun-bleached
# rather than declarative.
# ==========================================================================
# VI. DEEP SATURATED CULTURAL ACCENTS — the most saturated bands in the
# file, still capped well under the entity-color saturation floor.
# Each is a specific, real-world-anchored callback, used sparingly by
# the heritage/import deviation system (D-232), not a corridor default.
# ==========================================================================
[register.falu_red_and_pine]
hue = [600, 1400] # centidegrees (6-14 deg, deep barn red)
sat = [2200, 3400] # bps (22-34%)
val = [3200, 4600] # bps (32-46%, dark and saturated)
# nordic_timber — the iconic Scandinavian falu-red timber callback. Dark,
# saturated, unmistakably itself; pine restraint keeps it from drifting
# toward orange.
[register.lacquer_and_timber]
hue = [200, 1000] # centidegrees (2-10 deg, deep lacquer red)
sat = [2000, 3200] # bps (20-32%)
val = [3000, 4400] # bps (30-44%, dark and lacquered)
# east_asian_temple_enclave — CJK temple-precinct callback. Darker and a
# touch closer to true red than falu_red_and_pine -- the two must not be
# confused for each other despite the shared "deep saturated red" family.
[register.bright_painted]
hue = [1400, 2400] # centidegrees (14-24 deg, warm coral-orange)
sat = [2400, 3600] # bps (24-36%, the highest sat in the file)
val = [6400, 8000] # bps (64-80%)
# atlantic_creole_maritime — Cape-Verdean/Afro-Atlantic bright-painted
# timber and deep porches. Deliberately the boldest register in the whole
# set -- capped at 3600 bps (36%) to stay clear of the entity-color
# saturation range, so it reads as "the brightest building" without ever
# competing with a relationship-colored character standing in front of it.
# ==========================================================================
# VII. PASTEL & WHITEWASH — very low saturation, high value, pale-painted
# feel. Three whitewash-family callbacks that must stay distinct from
# each other at a glance.
# ==========================================================================
[register.whitewash_and_azulejo]
hue = [3400, 4400] # centidegrees (34-44 deg, warm white cast)
sat = [300, 1000] # bps (3-10%)
val = [8000, 9200] # bps (80-92%, very pale)
# south_lusophone — whitewashed render around the praça. The azulejo blue
# tile trim is a facade/accent detail outside a single HSV band's scope;
# this band is the wall's warm-white base.
[register.cape_whitewash]
hue = [3800, 4600] # centidegrees (38-46 deg, warm-neutral white)
sat = [300, 1000] # bps (3-10%)
val = [7800, 9000] # bps (78-90%)
# afrikaans_kraal — Cape gabled werf whitewash. Same mechanism as
# whitewash_and_azulejo; hue nudged a few degrees warmer and value nudged
# down slightly so the two whitewash registers stay tellable apart.
[register.weathered_pastel]
hue = [16000, 18000] # centidegrees (160-180 deg, soft aqua-green pastel)
sat = [800, 1800] # bps (8-18%)
val = [6800, 8200] # bps (68-82%)
# vietnamese_water_village — canalside tube-houses. The one green-family
# register in the set, chosen for canal/water association and to stay
# clearly distinct from the file's several warm-whitewash bands above.
# FLAGGED FOR MIRI: real-world Vietnamese heritage townscapes (Hoi An) skew
# warm ochre/yellow more often than aqua -- this is a legibility trade-off
# (distinctness against 3 other pale-warm registers) over strict real-world
# color-matching. Worth a cultural sanity check; easy to re-hue if wrong.
# ==========================================================================
# VIII. VIOLET-COOL OUTLIER — the only violet-hued band in the file. Used
# once, deliberately, so it stays a signature rather than a habit.
# ==========================================================================
[register.grey_stone_heather]
hue = [26000, 28000] # centidegrees (260-280 deg, violet-grey)
sat = [500, 1400] # bps (5-14%)
val = [4200, 5800] # bps (42-58%)
# scottish_highland_vernacular — drystone and slate against weather. The
# violet lean is a literal read of "heather" over grey stone; low-sat
# enough to stay a grey with a cast, not a purple building.
# FLAGGED FOR MIRI: the most interpretive hue placement in the file (the
# only band outside the neutral/warm-earth/cool-tech families) -- confirm
# it reads as "Highland stone" and not just "purple."
# ==========================================================================
# IX. DELIBERATELY WIDE / PLURAL — the two registers whose whole cultural
# point is variety, not a single tone. Hue bands here are 3-4x the width
# used everywhere else in this file, on purpose.
# ==========================================================================
[register.layered_patina]
hue = [2000, 6000] # centidegrees (20-60 deg, warm brown through olive)
sat = [1000, 2400] # bps (10-24%)
val = [4800, 6800] # bps (48-68%)
# core_cosmopolitan — centuries-deep, no single grammar dominant, old
# infrastructure carrying new uses. The widest hue band in the file is the
# point: a "layered patina" city block should NOT sample as one fixed tone.
[register.imported_accent]
hue = [1000, 5000] # centidegrees (10-50 deg, warm red-orange through tan)
sat = [1600, 3200] # bps (16-32%)
val = [5200, 7200] # bps (52-72%)
# foreign_quarter — the import-swerve template: a coherent transplant
# carried whole from another corridor (the Shinto temple in Amsterdam).
# Wide by design for the same reason as layered_patina -- it can arrive
# from anywhere, so it shouldn't sample as anywhere in particular.