feat(db): ObjectTag registry ratified + importer validation — resolves Q-049 (T-995)

The shipped 28-tag catalog palette is canonical (user ratification,
/whats-next refinement 2026-07-07). New machine-readable registry
wiki/economics/object_tag_vocabulary.toml (wall/roof/facade/street axes +
4 generic fallback terminals, Miri/Araminta co-owned header). Importer
validation in economy_import/traits.py: V-TT-03 (every catalog
allow/block/visual_bundle tag exists in the registry, axis-checked) and
V-TT-04 (fallback graph: non-generics declare a parent, chains acyclic,
resolve to a generic — absorbs T-1004's Phase-4 slice). Registry added to
generator_sources (stamp coverage); systems.db regenerated + stamped.
Q-049 marked Resolved — divergence is now a loud build failure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-08 09:16:20 +02:00
co-authored by Claude Fable 5
parent a6c2ff4740
commit 766ceb436c
6 changed files with 359 additions and 2 deletions
+209
View File
@@ -0,0 +1,209 @@
# ==========================================================================
# ObjectTag vocabulary registry (T-995, parent T-977; decisions D-232/D-235;
# resolves Q-049).
#
# Machine-readable canonical registry for every material/form tag referenced
# by wiki/economics/architecture_trait_catalog.toml's `allow_tags`,
# `block_tags`, and `visual_bundle` fields (T-1005). This file RATIFIES the
# shipped 4-axis / 32-specific-tag + 4-generic-placeholder palette documented
# informally in that catalog's header comment as the canonical ObjectTag
# vocabulary. D-235's original example WallMaterial/RoofForm/FacadeRhythm/
# StreetSurface token lists are superseded by the tags actually shipped here
# (see the dated amendment on D-235 in governance/decisions/architecture.md).
#
# OWNERSHIP (answers Q-049): co-maintained, split by concern, not by file --
# - Miri owns CULTURAL MEANING: which tag a template's allow_tags/block_tags
# draws on, and why (the `cultural_description` prose lives in the
# catalog, not here).
# - Araminta owns VISUAL EXPRESSION: what a tag looks like as a shipped
# asset, and the fallback parent it degrades to before that asset exists
# (D-235's incremental-content mechanism).
# Additions/deprecations: propose a new [tags.<axis>.<tag>] entry here AND
# wire it into at least one catalog template's allow_tags/visual_bundle in
# the same change -- the two sides move together. Importer validation
# (tooling/economy-db/economy_import/traits.py, V-TT-03/V-TT-04) is the
# mechanical enforcement of that co-maintenance contract: it hard-fails the
# import if the catalog references a tag absent from this registry, or if
# this registry's fallback graph doesn't resolve to a generic placeholder --
# the exact silent-divergence failure mode Q-049 raised.
#
# LOCATION (Q-107): this file is generator-facing -- it is read by the same
# importer, at the same time, for the same purpose as
# architecture_trait_catalog.toml. It is therefore Q-107-invariant: wherever
# the wiki-authored source tree consolidation lands the catalog, this
# registry rides with it unchanged; the generator contract does not depend on
# the answer.
#
# STRUCTURE: one [tags.<axis>.<tag_name>] table per tag, grouped under the
# four axes the catalog's visual_bundle actually keys on (wall / roof /
# facade / street -- no other ObjectTag axis is in use; `color_register` is a
# free-form palette cue, not an ObjectTag). Each entry carries:
# description -- short, plain-language, asset-facing (not cultural prose)
# fallback -- the tag (ultimately a generic) this one degrades to when
# its specific asset hasn't shipped yet (D-235). Chains are
# supported (specific -> specific -> generic) for future
# tags like the D-232 `temple_wall_wood` example; today
# every tag resolves in a single hop.
# generic -- true only for the four always-present placeholders
# (generic_wall/roof/facade/street). Generics are
# fallback-terminal: they never carry a `fallback` key.
# ==========================================================================
# ---- wall (10) -----------------------------------------------------------
[tags.wall.concrete_wall]
description = "Cast or poured concrete -- the corridor-neutral structural default."
fallback = "generic_wall"
[tags.wall.steel_frame]
description = "Exposed structural steel frame, typically infilled -- industrial/heavy-process register."
fallback = "generic_wall"
[tags.wall.brick_wall]
description = "Fired clay brick masonry."
fallback = "generic_wall"
[tags.wall.rendered_wall]
description = "Masonry or block wall under a smooth painted or plastered render finish."
fallback = "generic_wall"
[tags.wall.stone_wall]
description = "Cut or coursed stone masonry."
fallback = "generic_wall"
[tags.wall.timber_wall]
description = "Timber-frame or solid-timber wall construction."
fallback = "generic_wall"
[tags.wall.stucco_wall]
description = "Lime- or cement-based stucco render, typically whitewashed."
fallback = "generic_wall"
[tags.wall.glass_curtain_wall]
description = "Non-structural glass curtain-wall cladding hung on a hidden frame."
fallback = "generic_wall"
[tags.wall.composite_panel]
description = "Prefabricated composite/sandwich cladding panel."
fallback = "generic_wall"
[tags.wall.rammed_earth_wall]
description = "Compacted rammed-earth wall construction."
fallback = "generic_wall"
# ---- roof (7) -------------------------------------------------------------
[tags.roof.flat_roof]
description = "Flat or near-flat roof deck."
fallback = "generic_roof"
[tags.roof.pitched_roof]
description = "Sloped roof of moderate pitch, gabled or hipped."
fallback = "generic_roof"
[tags.roof.corrugated_roof]
description = "Corrugated metal sheet roofing -- utilitarian, fast to erect."
fallback = "generic_roof"
[tags.roof.clay_tile_roof]
description = "Fired clay tile roof covering."
fallback = "generic_roof"
[tags.roof.terraced_roof]
description = "Stepped/terraced roof profile, usable as an outdoor deck."
fallback = "generic_roof"
[tags.roof.vaulted_roof]
description = "Masonry vault or barrel-vault roof form."
fallback = "generic_roof"
[tags.roof.green_roof]
description = "Vegetated roof surface over a waterproofed deck."
fallback = "generic_roof"
# ---- facade (8) ------------------------------------------------------------
[tags.facade.regular_facade]
description = "Even, unornamented punched-window facade rhythm -- the neutral default."
fallback = "generic_facade"
[tags.facade.ornamental_facade]
description = "Decorative masonry or molding detail applied to the facade plane."
fallback = "generic_facade"
[tags.facade.industrial_glazing]
description = "Utilitarian steel-framed multi-pane glazing (factory-sash register)."
fallback = "generic_facade"
[tags.facade.arcade_facade]
description = "Ground-floor arcade -- a colonnaded walkway fronting the street."
fallback = "generic_facade"
[tags.facade.shuttered_facade]
description = "Operable exterior shutters over window/door openings."
fallback = "generic_facade"
[tags.facade.screen_facade]
description = "Perforated or louvred screen layer over the structural facade (solar/privacy control)."
fallback = "generic_facade"
[tags.facade.colonnade]
description = "A row of columns supporting an entablature or roof, freestanding from the wall plane."
fallback = "generic_facade"
[tags.facade.lattice_screen]
description = "Fine timber or metal lattice screening (mashrabiya/jalousie register)."
fallback = "generic_facade"
# ---- street (7) ------------------------------------------------------------
[tags.street.paved]
description = "Poured or laid hard pavement -- the neutral default street surface."
fallback = "generic_street"
[tags.street.cobble]
description = "Cobblestone or sett paving."
fallback = "generic_street"
[tags.street.packed_earth]
description = "Compacted, unpaved earth surface."
fallback = "generic_street"
[tags.street.canal_way]
description = "Water-channel frontage in place of, or alongside, a dry street."
fallback = "generic_street"
[tags.street.elevated_walkway]
description = "Raised pedestrian walkway above street or ground level."
fallback = "generic_street"
[tags.street.heavy_haul]
description = "Reinforced surface engineered for heavy freight/vehicle loads."
fallback = "generic_street"
[tags.street.boardwalk]
description = "Raised timber-plank walking surface, typically coastal or wetland."
fallback = "generic_street"
# ---- generic parents (4, fallback-terminal placeholders) -----------------
[tags.wall.generic_wall]
description = "Placeholder wall material -- renders until the specific wall asset ships (D-235 fallback)."
generic = true
[tags.roof.generic_roof]
description = "Placeholder roof form -- renders until the specific roof asset ships (D-235 fallback)."
generic = true
[tags.facade.generic_facade]
description = "Placeholder facade treatment -- renders until the specific facade asset ships (D-235 fallback)."
generic = true
[tags.street.generic_street]
description = "Placeholder street surface -- renders until the specific street asset ships (D-235 fallback)."
generic = true