pipelines/MINT_DESIGN_A_BUILD_SPACE_2026-07-27.md
Read-only schema design for the rank-14 mint of docs/COMBAT_PROGRAM_ADDENDUM.md §§7-12 as
integrated at T1_Combat_System_Spec §§12-15, T1_Ability_Tree §5H/§5I/§14A,
T1_Integrity_Paths §8.11, T1_Tier_C_MMO_Spec §8.7-.9. Tree read at HEAD ab5d32c.
Nothing in the repo is edited by this pass; this file is the only write.
Binding lens inputs (all SURVIVES verdicts honoured, all KILLED findings left dead):
p1a_dqpm_badge_budget.md — F1 SURVIVES (title corrected), F2 SURVIVES (MISSING→WEAKER),
F3 SURVIVES (defect roster 4→5); F4/F5/F6 KILLED and not resurrected (no option_source
enum, no parallel magnitude_class ladder, no bespoke second allocation ledger).
p1a_combinatorial_build_space.md — F2/F3/F4/F5/F6/F7/F8/F9 SURVIVE with the refuters'
corrections applied verbatim; F1 KILLED — "extension rail" already means child tables
(T1_Integrity_Paths §8.11.5 calls the deferred bond_abilities child table "the
T0_Familiar_Registry extension registered per docs/registry_extensions.json"), so **no tier-doc
amendment is proposed and no "wrong rail" is claimed.**
---
T1_Ability_Tree §5H.4 rules it directly: bonus rows land on the extension rail **"rather than
as new columns on the base row."** The gate-safe vector for that, matched to the existing idiom:
1. Pre-mint address — each table below is declared in docs/registry_extensions.json
_deferred with owner_registry / shape / source / target / status /
referenced_by, exactly as familiar-bond-ladder is today. The _deferred block is
informational (check_registry_extensions.py reads only extensions), so this costs no gate
movement and gives every placeholder cell a real future home.
2. At mint — each lands as a new registry under registries/<name> [DRAFT v0.1]/Sheet1.csv
and is declared in docs/fidelity_baseline.json added_registries. That list already carries
12 registries with no frozen _source counterpart (Rune, Flora, Mineral, Element_Effectiveness,
Environment_Grammar, Dwelling, Festival, Gather_Node, Hollow_Codex, Minigame, Reputation_Ladder,
Vehicle) — this is a well-exercised, gate-clean path.
3. At first data — registered in docs/fk_spec.json with registry / tab / primary_key /
id_formats (pattern + min_values floor at the verified live count) / foreign_keys — the
sequencing the _deferred.target note itself prescribes ("to be registered in docs/fk_spec.json
once minted"). This TIGHTENS the house convention rather than departing from it (n3): the
live precedent registers a new table at DRAFT time with a low anchor —
T0_Rune_Registry carries "min_values": 2 against 19 live rows with an explicit _note
("PK/id-format validated; FK enforcement DEFERRED until populated (fk_spec convention)") — and
Family A keeps that convention's shape while landing the entry in the SAME commit as the seed
rows with the floor at the seed count, so a min_values: 0 floor (a rule that cannot fail)
never exists even briefly.
4. registry_extensions.json.extensions is NOT used by this family. That manifest owns
*columns on existing registries*, and Family A adds zero columns to any existing registry.
Its only touch on a live registry is two new rows in T0_Worldstate_Variables
(added_rows 17 → 19 for this family; 17 → 21 jointly with Family B — §6.0), plus one
domain-cell declaration on the live WS_035 row (m6). That is the row idiom, not the
column idiom.
Polymorphic parent refs. fk_spec.json keys a foreign key on one column → one target
table.column, so a ref whose target varies by kind cannot be declared there. The house precedent
is T0_RNG_Drop_Table.linked_entity_id + linked_entity_type. Family A mirrors it
(capability_ref + capability_kind + scope_kind) and follows the range_id documentation
precedent: an explicit _note in fk_spec.json recording that the column is validated as an
id-format only and resolved per-kind by the new gate, so it is never mistaken for a dangling
FK. The per-kind resolution map is §1.3 below and is enforced by tooth T-A3.
*(Reconciled M8. This block is verbatim-identical in mint_design_B_item_ally.md. If the two ever
diverge, they are not two firewalls — they are one broken one.)*
1. A tuning MAGNITUDE is never a literal in a canon row. It is a ref into
T0_Balance_Constant_Registry.constant_id — the _deferred address this mint declares
(balance-constant-table; constant_id PK; owner Phase-5M; declared, not minted). The ref
columns are magnitude_ref, threshold_ref, breadth_floor_ref, expected_pick_band_ref
(Family A) and magnitude_ref (Family B, on T0_Imprint_Affix and T0_Status_Table):
one column name, one contract, both families.
2. Ordinals, ratified counts, and indices are LITERALS, and are not magnitudes:
ordinal_rank, ordinal, grade_index, gate_index, pick_budget, pick_cost,
precedence_rank, set_ordinal, imprint_slot_count, roll_window_ordinal, int_tier,
bond_value, bond_threshold, stat_point_budget, priority, phase_index, charges,
stack_cap, and the level / reroll / event counters. They order and count; they do not tune.
T1_Combat_System_Spec §12 fixes "ordinal ordering within a pool" today (hence
ordinal_rank is authored now) and defers "absolute values" to Phase 5M.
3. Deferred magnitudes land BLANK with a TODO_5M note — never as an interim number. Blank at
landing: every ref column above, plus min_tell_ms, answer_window_ms, telegraph_lead_ms,
parry_window_ms, parry_stamina_cost, sigma_window_length.
4. The struct-mirror exception is ENUMERATED and CLOSED. A column that mirrors a shipped engine
struct field keeps that struct's type and units, because the registry becomes the struct's data
source and REGISTRY_ROW_STRUCT_SPEC.md §1 makes a rename or retype a silent column drop. The
complete list is five columns, all on T0_Boss_Attack_Rail (mirroring FHumanityAttackRow):
windup_seconds, active_seconds, recovery_seconds, damage, punish_damage_mult. Their
values stay ILLUSTRATIVE until Phase-5M. Nothing else in either family is exempt — Family A
carries no float magnitude column at all after reconciliation (expected_pick_band_min/max
became the single ref expected_pick_band_ref, M8).
Player-facing strings. Two columns per table carry player-facing text and BOTH are marked for
the natural-voice pipeline, never authored as system voice here. docs/NATURAL_VOICE_DOCTRINE.md
"binds every player-facing word" and §5 assigns the P5 factory checklist as the owner.
docs/REGISTRY_ROW_STRUCT_SPEC.md §2 rule 2 auto-routes *_name / *_text to FText, so the
localization path already exists. The marking mechanism is the string_status enum
(placeholder → authored → voice_passed), which doubles as the pipeline's worklist query.
The internal-vocabulary firewall. role_axis_token, purpose_token, bonus_kind,
power_source, lane, and stack_op are **internal routing vocabulary and never render to a
player** — the same rule that keeps the verb taxonomy off player surfaces (Josh 2026-07-24,
no-mode-taxonomy-on-player-surfaces). Those columns are deliberately *_token / *_class
names, and they stay out of the FText flow by two different mechanisms — worth stating
precisely (n1), because the next author will reason from the stated rule. Verified
docs/REGISTRY_ROW_STRUCT_SPEC.md §2 rule 2: the match set is
(^|_)(title|name|description|summary|prose|caption|label|display|line|text|blurb)$ and the
exclusion set is _id|_ref|_tag|_tags|_status|_class|_type|_key. So ***_class is explicitly
EXCLUDED; *_token is never MATCHED at all** and falls through to rule 7 (FString). Same
outcome, two mechanisms — the earlier "rule 2's exclusion list covers both" reading was wrong on
the token half. Tooth T-A9 enforces the separation.
---
T0_Bonus_Pool_Registry (25 columns)What it is. The pool header, which is also the tier/gate grant row. One row per
(capability scope × tier key × lane). Serves §5I.1's "each tier presents a pool", §5H.4's "keyed
on ability plus tier plus lane", and §12's "tier or gate identifier, pool membership … and grade
ceiling".
Parent registry. Polymorphic per capability_kind (§1.3 map). Declared in
registry_extensions.json _deferred under owner_registry: T0_Ability_Tree_Registry (the
largest consumer and the doc that rules the mechanism at §5H.4), with the per-kind targets listed
in the shape field.
id format. pool_id = POOL_\d{4} (e.g. POOL_0001). Immutable and never reused, on the
beat_id PERMANENCE precedent already gate-enforced at docs/SPINE_SCHEMA_v3.md rule (v) —
cited, not re-minted (F9 refuter).
| # | column | type | enum / FK target | required | ||||
|---|---|---|---|---|---|---|---|---|
| 1 | pool_id | id | PK, POOL_\d{4} | yes | ||||
| 2 | capability_kind | enum | capability_kind_enum (§1.2) | yes | ||||
| 3 | scope_kind | enum | scope_kind_enum: class \ | instance | yes | |||
| 4 | capability_ref | polymorphic ref | resolves per (capability_kind,scope_kind) — §1.3 map | yes | ||||
| 5 | pick_class | enum | pick_class_enum: minor \ | major | yes | |||
| 6 | lane | enum | lane_enum: A \ | B | yes | |||
| 7 | grade_index | int | 1-10 (§2 GRADE index) | one-of w/ 8 | ||||
| 8 | gate_index | int | 1-12 (§2 GATE index) | one-of w/ 8 | ||||
| 9 | unlock_gate_quest_ref | FK | T0_Quest_Definition_Registry.quest_id | major only | ||||
| 10 | grade_ceiling | token FK | T0_Rarity_Grade.rarity_token @ axis=pool_option (§1.2, Family B owns the table) | yes | ||||
| 11 | pick_budget | int | DEFAULT 1 | yes | ||||
| 12 | budget_scope | enum | budget_scope_enum: tier (DEFAULT) \ | capability \ | global | yes | ||
| 13 | respec_class | enum | respec_class_enum: deferred (DEFAULT) \ | free \ | costed \ | gate_locked \ | new_run_only | yes |
| 14 | spec_purpose_refs | multi-FK ; | T0_Spec_Purpose_Registry.purpose_id | no | ||||
| 15 | pool_display_name | FText | player-facing pool header | no | ||||
| 16 | string_status | enum | string_status_enum: placeholder (DEFAULT) \ | authored \ | voice_passed | yes | ||
| 17 | lifecycle | enum | lifecycle_enum: active (DEFAULT) \ | deprecated \ | retired | yes | ||
| 18 | superseded_by | self-FK | T0_Bonus_Pool_Registry.pool_id | no | ||||
| 19-25 | *the house tail* | — | pipeline_consumer, source_ref, populated_from, notes, extensions, version, last_updated | — |
pick_class AND lane both exist. They are 1:1 today (minor↔A, major↔B) and toothT-A1 asserts it. Both are carried because the two consumer vocabularies are both canonical:
§5H.4 keys rows on lane, §5I.1 grants minor/major picks, and the UI renders the pick
class. This is the documented two-encoding idiom fk_spec.json already uses for thread ids
(canonical T\d{2} / grid THREAD_\d{2} / packed T\d{2}:SUFFIX, bridged and documented
rather than canonicalised), not accidental duplication.
grade_index and gate_index are separate nullable columns. §2's two-index reading isload-bearing: the ten grade-gates are both a grade reached and a gate crossed (minor + major
pick together), and **the Portal at Gate 6 and the Crossing of the Abyss at Gate 10 confer no
grade** and grant a major pick alone. A single tier_index column cannot express the two rows
that have a gate index and no grade index. Tooth T-A2.
scope_kind exists. §5H.1: "Bonus kinds are drawn per ability class so the poolsuits the ability" — and the dqpm F2 refuter's scale correction says pools author per ability
CLASS, not per ability. But §5H.2 is per-ability by construction: "Every ability in the §11
catalog carries a transformative set appropriate to its own identity", and Josh's Lane-B
seeds are ability-specific (Fire Bolt → three projectiles; Tremor Stomp → the wall ring).
scope_kind expresses both without a second table: Lane A pools default to class, Lane B
pools to instance. Combat §12's "Per-weapon major-pool identity authors during Phase 6"
rides the same column.
pick_budget / budget_scope defaults reproduce §5I.1 exactly (1 pick, scoped to thetier). §5A itself asked for this to be revisited *at the schema pass* — "That bonus picks cost
no Mastery Points is an applied reading of the ruling rather than a stated term of it,
revisitable at the schema pass" — so carrying a defaulted dial executes the doc's own
deferral and re-litigates no ruling. Phase-5M sets the value; the mint sets only the shape.
respec_class DEFAULT deferred. §5I.1 defers the bonus respec model outright and §5Ascopes §5B.1 to point reallocation only. There is therefore no ruled default to reproduce,
and the honest default is the deferral itself: deferred means *no consumer may assume a
respec model for this pick class*. This mirrors §8.11.6's existing discipline ("until that pass
lands, no consumer may read a loadout field on WS_027, because the field does not yet exist").
Ratification flips a value, never a migration. The two ruled respecs — §5B.1 Mastery Point
respec sited at trade compounds with reagent, multi-day ritual, and faction cost, and §5B.2
Device Bonding respec — are untouched by this column. **The combinatorial-F8 refuter's
correction is honoured: re-selection is NOT relocated to the vril well.** The vril site stays
the §14 quick-change sanctum for already-selected loadout profiles.
grade_ceiling is §12's own named field, on the shared rarity_class ladder. The dqpm F5 kill stands: no parallel magnitude_class worth-enum is minted, because §5I.4 already rules
that "Mythic describes what a pool option is worth" and rarity is that ladder.
capability_kind_enum = ability · weapon · trade · attribute · familiar · companion · imprint · language · inscription · intuition · astral_projection
— the §5I.3 §3 roster plus two additions named as additions, not claimed as verbatim (m5).
§5I.3 verbatim reads: *"the six attributes, the seventy-two weapon proficiencies, the ten trades,
familiar bond, language fluency, inscription, Intuition, and Astral Projection — and gear
imprints carry pools of their own."* The two adds are ability (this doc owns the ability
instance) and companion (§5I.3 assigns the companion layer to T1_Integrity_Paths); both are
justified, neither is in the quoted roster.
The skill/trait translation is RECORDED, not lost (m5). Josh's §10 verbatim seed is *"EVERY
skill, trait, weapon, trade, and any proficiency"*, and neither word is a
capability_kind because §5I.3 already translated them into the §3 roster: a skill is a
proficiency (the weapon / trade / language / inscription kinds) and a trait is an attribute
(the six) or a familiar / companion property. That mapping lands as a notes line on the
registry header so a later reader auditing §10 against the enum finds the two ruled words with a
home rather than no row.
EXAMPLES-NOT-LIMITS: the enum is a ratified vocabulary that grows by adding a value under
critic gate, never by free text.
rarity_class — the SHARED LADDER, not a Family-A enum (reconciled M2). Family A mints **no rarity enum of its own. grade_ceiling (A1) and rarity_class (A2) are token FKs into
T0_Rarity_Grade** — Family B's property table, keyed (axis, rarity_token) — at
axis=pool_option. The single shared ladder, stated once in T0_Rarity_Grade and cited here, is
none · common · uncommon · rare · epic · legendary · mythic · signature: the
UNION of the live vocabularies, so no live cell moves. Verified live distributions:
T0_Rune_Registry {common 8, epic 5, rare 3, legendary 2, none 1} · T0_Flora_Registry
{common 18, uncommon 4, rare 2, signature 1} · T0_Mineral_Registry {common 10, uncommon 6,
rare 3}. mythic is the one token no live cell carries. The earlier draft's closed six-value
enum and its "reuses the live vocabulary (3 registries already carry rarity_class)" claim were
both wrong (m5): only Rune was covered, and 10 live uncommon cells (Flora 4 + Mineral 6)
plus 1 signature cell — 11 in all — had no legal value. *(Re-counted programmatically this
pass: Flora 25 rows, Mineral 19, Rune 19; the critic's "11 uncommon + 1 signature" over-counted
uncommon by one.)* Ordering for grade_ceiling comparisons reads T0_Rarity_Grade.ordinal
within the axis; Family A never re-encodes the ladder.
scope_kind_enum, pick_class_enum, lane_enum, budget_scope_enum, respec_class_enum, string_status_enum, lifecycle_enum as tabled above.
capability_ref per-kind resolution map (tooth T-A3 enforces it)capability_kind | scope_kind=class → | scope_kind=instance → |
|---|---|---|
ability | T0_Ability_Tree_Registry.ability_class (live column, 54 values) | T0_Ability_Tree_Registry.ability_id |
weapon | T0_Weapon_Registry.weapon_class / .weapon_subclass | T0_Weapon_Registry.weapon_id |
trade | *n/a* (ten trades are instances) | T0_Trade_Registry.trade_id |
attribute | *n/a* | attribute_enum literal: STRENGTH · DEXTERITY · CONSTITUTION · AGILITY · ACCURACY · INTELLIGENCE (T1_Ability_Tree §4; no registry owns the six) |
familiar | T0_Familiar_Registry.species_class | T0_Familiar_Registry.familiar_id |
companion | *n/a* | T0_Character_Index.character_id |
imprint | T0_Rune_Registry.operator_family | T0_Rune_Registry.rune_id |
language | *n/a* | T0_Language_Script_Registry.script_id (PK named, n4) |
inscription | *n/a* | T0_Inscription_Spine.spine_id (PK named, n4) |
intuition / astral_projection | *n/a* | literal token (doc-owned capability, no registry) |
Ownership stays exactly where §5I.3 puts it — the ability instance is T1_Ability_Tree's, the
weapon and imprint instances are T1_Combat_System_Spec's, the trade instance is
T1_Trades_Master's, the ally instance is T1_Integrity_Paths's. **One architecture, per-domain
rosters, no duplicated rows** — and no doc's ownership is moved by this schema.
---
T0_Bonus_Option_Registry (32 columns)What it is. One row per selectable option inside a pool. This is where §12's untyped word
"shape" becomes a machine-evaluable type (combinatorial-F5, the strongest surviving finding), and
where the natural-voice string surface lands (dqpm-F2's surviving schema clause).
Parent registry. T0_Bonus_Pool_Registry (1:N).
id format. option_id = BOPT_\d{5}. Immutable, never reused (beat_id precedent).
| # | column | type | enum / FK target | required | |||
|---|---|---|---|---|---|---|---|
| 1 | option_id | id | PK, BOPT_\d{5} | yes | |||
| 2 | pool_id | FK | T0_Bonus_Pool_Registry.pool_id | yes | |||
| 3 | option_name | FText | player-facing name | yes | |||
| 4 | player_text | FText | one natural-voice line the choice UI renders | yes | |||
| 5 | voice_register_ref | FK | T0_Voice_Registry.voice_id | no | |||
| 6 | string_status | enum | string_status_enum, DEFAULT placeholder | yes | |||
| 7 | bonus_kind | enum | bonus_kind_enum (§2.2) | yes | |||
| 8 | effect_attribute | enum | effect_attribute_enum (§2.3) | yes | |||
| 9 | stack_op | enum | stack_op_enum: add \ | mult \ | override \ | enum_set | yes |
| 10 | magnitude_ref | ref | T0_Balance_Constant_Registry.constant_id (DEFERRED address) — blank-tolerant until Phase-5M | no | |||
| 11 | condition_expr | expr | docs/CONDITION_EXPRESSION_GRAMMAR.md v1.0 ACTIVE; blank = unconditional | no | |||
| 12 | ordinal_rank | int | within-pool ordering, 1..N (§12 "fixed here") | yes | |||
| 13 | rarity_class | token FK | T0_Rarity_Grade.rarity_token @ axis=pool_option (the shared ladder, §1.2) | yes | |||
| 14 | unlock_gate_ref | FK | T0_Quest_Definition_Registry.quest_id | mythic only | |||
| 15 | role_tags | multi-FK ; | T0_Role_Axis_Registry.role_axis_id | yes | |||
| 16 | role_affinity | weighted multi ; | <role_axis_id>:<0..1> — PROPOSAL-TIER, blank = uniform over role_tags | no | |||
| 17 | spec_purpose_refs | multi-FK ; | T0_Spec_Purpose_Registry.purpose_id | no | |||
| 18 | power_source | enum | power_source_enum (§2.4), DEFAULT proficiency | yes | |||
| 19 | pick_cost | int | DEFAULT 1 | yes | |||
| 20 | exclusion_group | tag | nullable; two options sharing a tag cannot be held together, across pools as well as within one. DEFAULT blank | no | |||
| 21 | expected_pick_band_ref | ref | T0_Balance_Constant_Registry.constant_id — the authored share band (floor+ceiling in one constant row); blank = gate default. Was two raw floats; ref'd at reconciliation so the shared firewall has no second exception (M8) | no | |||
| 22 | role_scope | multi-FK ; | T0_Role_Axis_Registry.role_axis_id — which axes this option is *allowed* to dominate; blank = its own role_tags | no | |||
| 23 | build_defining | bool | DEFAULT false — does taking this change what the build IS, or only its numbers? | yes | |||
| 24 | lifecycle | enum | lifecycle_enum, DEFAULT active | yes | |||
| 25 | superseded_by | self-FK | T0_Bonus_Option_Registry.option_id | no | |||
| 26-32 | *the house tail* | — | pipeline_consumer, source_ref, populated_from, notes, extensions, version, last_updated | — |
§5I.4 and Combat §12: MYTHIC is a rarity grade, never a thirteenth mastery tier; it is
"earned, never dropped"; "the completed final mastery questline for the capability is the only
source"; "No drop table, boss reward, or rarity-tiered roll produces a mythic pool option."
Expressed as a three-clause invariant, not as a new source enum — the dqpm-F4 kill stands and
option_source is not resurrected. The refuter allowed exactly one nullable ref as
belt-and-braces, and that is column 14:
T-A4 (MYTHIC INVARIANT).rarity_class == mythic⇒ (a)unlock_gate_refis non-null and
resolves to a quest row whose twelve_tier_gate marks a final mastery-questline crossing;
(b) the option'spool_idhasgrade_ceiling == mythic; (c) **option_idappears in zero
rows of T0_RNG_Drop_Table** (cross-table, positive-controlled — the check asserts the search
reaches the drop table by confirming it can find a known non-mythic reference before reporting
the zero, per the standing "a search that CANNOT match reports zero" lesson).
Converselygrade_ceiling < mythic⇒ no option in that pool carriesrarity_class == mythic,
where<readsT0_Rarity_Grade.ordinalwithinaxis=pool_option(the shared ladder supplies
the ordering; Family A does not re-encode it).
Family B carries the affix-side twin (m9): check_rarity_firewall.py class (e) fails any
T0_Imprint_Affix row whose rarity_token_min names a grade with obtainable_by_roll = FALSE
without hand_authored_override = TRUE — an affix reachable only through a roll that can never
produce it is a dead row that reads as authored content. T-A4 clause (b) and that class are the
same guard on the two sides of the same ladder.
The D-MYTHIC-GATE decision in docs/spine/DECISIONS_PENDING_JOSH.md (which crossing the
questline rides) is a row value, not a schema question: whichever crossing Josh rules,
unlock_gate_ref points at it. The schema is ruling-agnostic by construction.
bonus_kind_enum — the closed, growable vocabularyJosh's verbatim seeds first, then the class-appropriate expansions §5H.1 and Combat §12 name.
The rule stated in the schema doc: **this enum is the authoring baseline, not the roster ceiling
— it grows by adding ratified values under critic gate, never by free text** (the
EXAMPLES-NOT-LIMITS rule as a schema property).
cast_time_reduction · resistance_pierce · elemental_superiority · raw_damage · crit_chance
range_extend · duration_extend · recovery_reduction · directional_control · construct_persistence · structural_integrity ·
reinforce_cost_reduction · charge_window_forgiveness · detection_range ·
signal_resolution · registration_latency · channel_efficiency · hot_depth ·
target_count
windup_reduction · guard_break_pressure · reach_economy · reload_spread · catch_window · rage_build_rate · stamina_economy
projectile_multiply · aoe_on_impact · cast_while_moving · stun_add · construct_ring · mobility_surge
second_construct · shape_change · sustained_mode · party_share_mode · midflight_redirect · chained_burst · legendary_form
effect_attribute_enum — the §12 shape TYPING (the F5 clean survivor)This is the column that closes the foundry's own confessed hole:
HumanityAbilityFoundry.cpp — *"DT_AbilityTree has no magnitude column — TODO_CANON / 5M
firewall"*, with DamageMagnitude = 12.0f; // ILLUSTRATIVE. The vocabulary is deliberately drawn
from two existing surfaces so the foundry binds a bonus row to a GameplayEffect **with no
translation layer**:
Source/Humanity/Public/Combat/HumanityAttributeSet.h: Health · MaxHealth · Vril ·
MaxVril · Stamina · MaxStamina · Rage · MaxRage · Composure · MaxComposure ·
MaxComposureNode · the eight Composure_* node channels.
STEP-0 CO-LANDING DEPENDENCY — the UHumanityAttributeSet extension (M7). Seven of the
twelve authored seed values in §9.2/§9.3 name neither a live GAS attribute nor a live
registry enum column:cast_time,target_elemental_resistance,elemental_superiority,
damage_magnitude,crit_chance,movement_speed,projectile_count. Left as-is they turn
tooth T-A5 RED on the landing commit — the family's own gate failing its own seeds. Both halves
of the fix apply, and neither is optional:
(i) the UHumanityAttributeSet extension adding the damage / crit / resist / cast-time /
movement / projectile channels is named as step 0 of §10's landing order — the Lane-A and
Lane-B seed rows do not land before it; and
(ii) T-A5 carries a declared pending_attribute_channels list holding exactly those seven
names and emits WARN for a value on that list, FAIL for anything else — so the gate is
armed and honest on day one, the list empties when the AttributeSet extension lands, and a
silent red never happens. *Positive control (standing rule):ComposureandRageDO resolve
against the header andcast_pattern/persistence_class/status_effectsDO resolve against
the registry, so the check discriminates and the seven-name zero is real.*
The pipeline_consumer promise that the foundry binds "with no translation layer" is true only
after step 0; until then it binds the resolving subset.
cast_pattern · persistence_class · physical_properties_array · cooldown_class · vril_cost_class ·
range_class · duration_class · status_effects.
stack_op mirrors UE EGameplayModOp (Add / Multiply / Override) plus one house value,
enum_set, for the §5H.2 override discipline: *"a gate bonus states its enum override on the
bonus row rather than mutating the base ability row."* Cast-while-moving is
effect_attribute=cast_pattern + stack_op=enum_set; the Tremor Stomp wall ring is two rows,
persistence_class enum_set and physical_properties_array add. **The base ability row is never
mutated** — which is why Family A adds zero columns to T0_Ability_Tree_Registry.
condition_expr reuses docs/CONDITION_EXPRESSION_GRAMMAR.md (ACTIVE v1.0; reference evaluator
harness/condition_expr.py; in-engine at Source/Humanity/Public/Quest/ConditionExpr.h) — one
grammar, one more surface. docs/proposals/STATE_DELTA_GRAMMAR.md is proposal-tier and is
deliberately not stretched to cover magnitudes.
power_source_enum — the shared vocabulary (combinatorial-F6)proficiency · gear_imprint · ally_spread · familiar_bond · consumable · merge.
This enum is a CROSS-FAMILY CONTRACT. The load-bearing part is not the metric but the *one
shared vocabulary across every effect-bearing §§7-12 row* — bonus options (Family A, DEFAULT
proficiency), imprint affixes (Family B, gear_imprint), ally-spread rows
(ally_spread/familiar_bond). Divergent per-table vocabularies are unrecoverable once five
tables land. The dominance *band* is correctly Phase-5M's and is not invented here.
RECONCILED (M4). The contract was declared here and absent from Family B's tables — a
lens-survivor failure, not a style difference: combinatorial F6 rules ONE shared
power_source enum across every effect-bearing §§7-12 row, and without the column on B's
rows defect D8 source_dominance cannot compute, so the gear-eclipses-build collapse stays
invisible — the exact failure F6 exists to catch. Family B now carries power_source,
lifecycle (+ superseded_by), and string_status on its four effect- / string-bearing tables
(T0_Imprint_Affix, T0_Ally_Behavior_Policy, T0_Rarity_Grade, T0_Status_Table), plus
string_status on every other table with an FText column. Four columns, all defaulted, all
vacuous on day one.
---
T0_Role_Axis_Registry (15 columns)What it is. The role taxonomy as rows: §14A.1's six seed axes, Combat §14's identical six,
and Tier_C §8.7's group-scale reading — one taxonomy, two arenas, so the Tier-C echo reads
the same rows rather than a second roster ("where it and the owning docs differ, the owning docs
govern").
Parent registry. Standalone root (referenced by A2, A4, A5 and by the sweep scorecard).
id format. role_axis_id = ROLE_[A-Z0-9_]+ (e.g. ROLE_GROUP_HEAL).
| # | column | type | enum / FK | required | ||||
|---|---|---|---|---|---|---|---|---|
| 1 | role_axis_id | id | PK, ROLE_[A-Z0-9_]+ | yes | ||||
| 2 | role_axis_token | token | internal label — never player-facing | yes | ||||
| 3 | scope_class | enum | scope_class_enum: single \ | group | yes | |||
| 4 | function_class | enum | function_class_enum: damage \ | heal \ | support \ | terrain \ | resource | yes |
| 5 | arena | enum | arena_enum: solo_party \ | tier_c_raid \ | both, DEFAULT both | yes | ||
| 6 | taxonomy_status | enum | taxonomy_status_enum: seed \ | emergent \ | ratified | yes | ||
| 7 | tier_c_team_ref | token | §8.8 operational team the axis staffs; nullable | no | ||||
| 8 | breadth_floor_ref | ref | T0_Balance_Constant_Registry.constant_id — the "too few viable builds" threshold, Phase-5M | no | ||||
| 9 | lifecycle | enum | lifecycle_enum | yes | ||||
| 10-15 | *house tail* | — | source_ref, populated_from, notes, extensions, version, last_updated | — |
taxonomy_status=emergent is the canon hook, not a violation report. §14A.1: *"A role that
emerges from play and is not named here is an addition to the taxonomy, not a violation of it."*
The sweep's tag↔measure mismatch defect (§5, D9) resolves either to a mis-tagged pool (authoring
defect) or to a new row with taxonomy_status=emergent — which is why the mismatch is a legal
finding rather than an error.
---
T0_Spec_Purpose_Registry (14 columns)What it is. §5I.2 / Combat §14's spec purposes as rows, with the purpose→role derivation made
DATA instead of prose. §5I.2 states the derivation exactly: *"A vril-healing personal-scope
specification is a single-target heal role; the same healing purpose at area scope is a group heal
role."* That is function_class × scope_class → role_axis_ref, so the table stores all three and
tooth T-A6 asserts the derivation is consistent.
Parent registry. Standalone; referenced by A1.14 and A2.17.
id format. purpose_id = SPEC_[A-Z0-9_]+.
| # | column | type | enum / FK | required |
|---|---|---|---|---|
| 1 | purpose_id | id | PK, SPEC_[A-Z0-9_]+ | yes |
| 2 | purpose_token | token | internal, never player-facing | yes |
| 3 | function_class | enum | function_class_enum | yes |
| 4 | scope_class | enum | scope_class_enum | yes |
| 5 | role_axis_ref | FK | T0_Role_Axis_Registry.role_axis_id | yes |
| 6 | capability_kind_scope | multi-enum ; | capability_kind_enum — which capability kinds may carry it; blank = all | no |
| 7 | taxonomy_status | enum | taxonomy_status_enum | yes |
| 8 | lifecycle | enum | lifecycle_enum | yes |
| 9-14 | *house tail* | — | source_ref, populated_from, notes, extensions, version, last_updated | — |
---
T0_Role_Composition_Rule (14 columns)What it is. The combinatorial-F4 survivor #1, the hole nothing else covers: *"Nothing maps a
build's set of option-tags onto one of the six axes. A build with four damage picks and two heal
picks has no defined axis, which means 'builds per role axis' — the headline output — has no
well-defined denominator."* Canon supplies purpose→role (§5I.2) but never *set-of-options*→role.
This is schema shape, not magnitude, so it is not absorbed by the Phase-5M deferral; the
thresholds inside it are magnitudes and ARE deferred, as threshold_ref.
Parent registry. T0_Role_Axis_Registry (1:N).
id format. rule_id = RCR_\d{3}.
| # | column | type | enum / FK | required | |||
|---|---|---|---|---|---|---|---|
| 1 | rule_id | id | PK, RCR_\d{3} | yes | |||
| 2 | role_axis_ref | FK | T0_Role_Axis_Registry.role_axis_id | yes | |||
| 3 | input_kind | enum | input_kind_enum: spec_purpose_share \ | role_tag_share \ | measured_role_vector \ | ally_role_fill | yes |
| 4 | comparator | enum | comparator_enum: max_share \ | share_above_threshold \ | vector_dominant | yes | |
| 5 | threshold_ref | ref | T0_Balance_Constant_Registry.constant_id; blank-tolerant until Phase-5M | no | |||
| 6 | precedence_rank | int | deterministic tie-break order — a build's axis assignment must be reproducible run to run | yes | |||
| 7 | multi_axis_policy | enum | multi_axis_policy_enum: primary_only \ | primary_plus_secondary (DEFAULT) | yes | ||
| 8 | lifecycle | enum | lifecycle_enum | yes | |||
| 9-14 | *house tail* | — | source_ref, populated_from, notes, extensions, version, last_updated | — |
multi_axis_policy DEFAULT primary_plus_secondary is an applied, reversible reading: §14A.5
counts builds per role axis and never says a build belongs to exactly one. Flagged in the row
notes as the applied reading, flippable at ratification by a value change, never a migration —
the §8.11.6 "reversible at ratification" idiom.
---
T0_Worldstate_Variables rows)§5I.1: *"Selection state is per capability, per ability, per tier. Selection-state schema and the
bonus respec model defer to the schema pass."* Selection state is **per-player runtime state, not
canon**, so it does not become a T0 registry. It follows the ruled precedent: T1_Integrity_Paths
§8.11.7 rides the per-companion roster object at WS_027 and the familiar bond state at
WS_012, "extended with the spread and its level-up choice state at the schema pass."
*(Reconciled M1. This block is verbatim-identical in mint_design_B_item_ally.md. Both designs
independently and correctly read the registry's max as WS_042 — and both then took 043. The
collision is resolved by allocating the WS_043+ number space ONCE, in contiguous per-family
blocks, with one owner per concept.)*
Verified: registries/T0_Worldstate_Variables [ACTIVE v0.1]/Sheet1.csv = 42 rows, last id
WS_042; docs/fidelity_baseline.json → added_rows["T0_Worldstate_Variables/Sheet1"] = 17.
| id | variable_name | owner | append-legal (CG-25) | shape | ||
|---|---|---|---|---|---|---|
WS_043 | bonus_selection_state | Family A | no (keyed replace) | key (capability_kind, capability_ref, tier_key, lane, loadout_set_id) → {option_id, selected_at_beat_ref, pick_cost_charged, exclusion_groups_held[]} | ||
WS_044 | bonus_respec_ledger | Family A | yes | `{event_id, respec_kind (bonus \ | mastery_point \ | device_bonding), pool_id, from_option_id, to_option_id, cost_paid_ref, site_ref, refundable (bool)}` |
WS_045 | loadout_set_state | Family B | no (keyed replace) | {owner_kind, owner_ref, set_id → T0_Loadout_Set_Definition.set_id, gear_instance_refs[] → WS_046.instance_id, ability_selection_refs[] → T0_Ability_Tree_Registry.ability_id, is_active} | ||
WS_046 | item_instance_ledger | Family B | yes | the 14 sub-fields of B §1.6 (+ sigma_seq, m3) |
Superseded draft ids — do not read them anywhere: Family A's draft WS_044 loadout_set_state
is withdrawn (the concept moved wholly to Family B, see below) and Family A's draft `WS_045
bonus_respec_ledger moved to WS_044; Family B's draft WS_043 item_instance_ledger` moved to
WS_046 and its draft WS_044 loadout_set_state moved to WS_045. The old numbers appear in no
landed artifact — this allocation is the only one.
ONE OWNER FOR LOADOUT STATE: Family B. B's home carries the unlock gates, the venue class, and
the departs_with_companion = FALSE investment-protection invariant, so it is the better home;
A's draft unlocked_count (ceiling 3) / active_set_index collapse into B's set_id +
is_active, and **the ceiling is the row count of T0_Loadout_Set_Definition, not a number
restated in a second place** (m1). Family A keeps loadout_set_id only as a KEY INTO that row —
which is all its reachability classing needs.
ONE OWNER FOR SELECTION STATE: Family A. B's WS_045 does not store bonus_pick_refs[];
it declares them as a DERIVED read over WS_043 filtered on loadout_set_id = set_id. §14's
"its own gear, its own ability selection, and its own bonus picks" is preserved in
T0_Loadout_Set_Definition.composition_kinds; what is removed is the second copy. One writer, one
home — the double-owned selection shape the critic caught is closed by construction.
Cross-family coupling after reconciliation is exactly two declared pointers, both structural
and unavoidable: A's WS_043 key field loadout_set_id → B's T0_Loadout_Set_Definition.set_id,
and B's derived bonus_pick_refs[] read → A's T0_Bonus_Option_Registry.option_id.
loadout_set_id is the reachability key. Combat §14 rules the second and third sets andtheir vril-site quick-change; §5I.1 says the sets "let one protagonist carry more than one
selection profile." Keying selection state on the set id is what makes the sweep's
reachability classing (in_run / loadout_swap / respec_costed / fresh_run) measurable
against the ruled loadout switch rather than against a relocated respec venue.
refundable DEFAULT false on the respec ledger (WS_044) — the dqpm-F1 verdict residue,encoding §8.11.6's interim non-refund reading ("the player's spent choice budget is not
refunded") as reversible data. Ratification flips a flag.
respec_kind unifies the ruled dual respec (§5B.1 Mastery Point respec, §5B.2 DeviceBonding respec) with the deferred bonus respec in ONE ledger shape — the dqpm-F1 "mint one
allocation-ledger shape" residue, applied without minting a second allocation model. The ally
spread's level-up choice state (Family B) rides the same shape on WS_027/WS_012.
WS_043-WS_044 while respec_class == deferred for the pool inquestion, per the §8.11.6 discipline.
check_ws_value_form.py is a co-landing dependency (m4)The mint's own gate list omitted it; Family B named it correctly and Family A did not. Both rows'
domain declarations land in the same commit as the rows, or every ws.bonus_selection_state
/ ws.bonus_respec_ledger write resolves as an unresolved-head finding.
WS_044 is an append/accumulate ledger, so it needs the CG-25 +-prefix legal-set edit — a
ruled-list edit, recorded here as a required companion change, never assumed. WS_043 is a
keyed-replace object and needs no +.
Correction to the live constant, verified this pass (both the design drafts and the critic's
sub-note were wrong, and this is the number the edit must extend):
harness/check_ws_value_form.py L116-118 —
APPEND_LEGAL_IDS = frozenset({"WS_008","WS_010","WS_012","WS_018","WS_019","WS_020","WS_021","WS_026","WS_027","WS_028","WS_031","WS_034"})
— twelve ids, not six (B's draft) and not seven (the critic's read of a truncated first line).
The comment at L112-115 records why: *"EXTENDED 6->12 by Josh's ruling D-CG25-APPEND-SET
(2026-07-24)"*, with the contract's CG-25 enumeration reconciled to the data in the same commit.
So the landing edit is 12 → 14 (adding WS_044 and WS_046), and the L20 docstring's "six"
is stale text to fix in the same pass. Standing lesson applied: read the constant, not the label.
§11 rules *"the merge combinatorics are DISCOVERY CONTENT: exploring what fuses is itself the
endgame play."* A's build_fingerprint consumes a merge_set and power_source_enum carries
merge, so the sweeps already assume the axis exists — but nothing recorded **which merges a
player has discovered**, and B's not-owned list did not claim it either. An §§7-12 ruling must not
fall through the gap between two families.
Resolved by declaration on a LIVE row, not a new keyspace: WS_035 spellcraft_authored_spells
(live, type object) gains a declared sub-field discovered_merges[] =
{merge_key, component_refs[], discovered_at_beat_ref} — a domain-cell declaration on an
existing row, the same idiom Family B uses for WS_036. The merge *rules* (what fuses with what)
stay with the Rune Forge / §2b lane and are not minted here; this records only the player's
discovery state, which is what the sweeps and the §11 ruling need. WS_035 is not in
APPEND_LEGAL_IDS; whether the discovery list needs + semantics is settled by the same CG-25
ruled-list edit above and is flagged, not assumed.
---
build_space_scorecard.json / .mdNot a registry: a harness artifact on the proven scorecard-gate pattern
(check_boss_axes.py → boss_axes_scorecard.json/.md; check_build_readiness.py →
build_readiness_scorecard.json/.md), emitted by a new harness/check_build_space.py with
--out harness/build_space_scorecard.
gate · balance_version (F9 — the cross-run comparability anchor; **no existing scorecard
carries any run stamp today**) · run_stamp_utc · sweep_config_ref · encounter_class_set[]
(sourced from T0_Boss_Encounter_Registry's encounter classes — not the X9.5 asset-pipeline
benchmark set, which is terrain/PCG and has nothing to do with combat viability) ·
bar_ref · variant_distance_threshold_ref · registry_snapshot_hashes{} · status.
Row immutability is NOT re-specified here. option_id permanence cites
docs/SPINE_SCHEMA_v3.md rule (v) beat_id PERMANENCE, which is already gate-enforced. Only
lifecycle + balance_version are new, per the F9 refuter's narrowing.
build_fingerprint — the build-identity key spec (7 components)§14A.5 and Combat §15 both output "how many distinct builds clear the bar" and neither defines
the unit; §14A.5 claims to establish "the measured quantity" while deferring only magnitudes — and
the unit is not a magnitude. The declared key, an ordered tuple of identity-bearing axes:
build_fingerprint = `(primary_capability_ref, measured_role_vector, weapon_class_set,
element_set, merge_set, familiar_slot_ref, party_composition_key, build_defining_pick_set)`
— collapsed by variant_distance so near-duplicates count once.
Naming collision avoided, per the F3 refuter: the identity flag is build_defining, not
load_bearing — T0_Character_Index already carries a live is_load_bearing column owned by the
attackability vertical in registry_extensions.json, and reusing the token would muddy that
manifest's one-column-one-system rule (checker invariant I2).
build_fingerprint · reachability (reachability_enum: in_run \| loadout_swap \|
respec_costed \| fresh_run) · role_vector_measured (the {single|group} × {damage|heal|
support|terrain} contribution shares, read from the same UHumanityAttributeSet deltas the combat
tests already read) · role_vector_prior (composed from role_affinity via A5's rules) ·
power_source_share{} (fraction of effective power per power_source_enum value) ·
clears_bar (bool). *"1,400 builds, 900 reachable in-run" is an honest number; "1,400 builds" is
not.*
axis_id · breadth_contribution (leave-one-out: the drop in viable-build count when that axis
is pinned to its modal value — the same simulation re-run with one axis frozen, so cost is linear
in the ~6 axes, not combinatorial) · conditional_pick_distribution (pick spread within a pool
conditioned on role axis, not pooled across the population) · viable_build_count.
subject_ref (the attribution key — a sweep cannot attribute variety to options it cannot key) ·
subject_kind (pool_option \| imprint_affix) · pick_share_overall · pick_share_by_role{} ·
pool_diversity_stat (normalised entropy or Gini, so a pool's health is one number) ·
band_verdict (below \| in_band \| above) · keep_rate.
Reconciled m3. The key was option_id alone, which silently excluded the rolled layer;
combinatorial F7's NET names keep-rate as *"the rolled-layer analogue of pick share"* and it
appeared in neither design. subject_ref now resolves to T0_Bonus_Option_Registry.option_id
(subject_kind = pool_option) or T0_Imprint_Affix.affix_id (subject_kind = imprint_affix),
and keep_rate — the fraction of rolled instances carrying that affix the player KEEPS rather
than re-rolls away or discards — populates on rolled subjects only and is blank on pool options.
Family B's T0_Imprint_Affix records the sweeps as a consumer for exactly this. The polymorphic
key follows the same _note-documented idiom as capability_ref (§8.1).
defect_class_enumRow: defect_id · defect_class · subject_ref · evidence · citation.
THE FIVE RATIFIED DEFECT DEFINITIONS (every one a population statistic; the roster is five
across four docs, per the dqpm-F3 refuter's correction of 4 → 5):
| # | defect_class | definition | citation |
|---|---|---|---|
| D1 | dead_pool_option | a pool option the sweep never picks | §14A.5 · §5I.1 · Combat §15 · addendum §10 |
| D2 | thin_role_axis | a role axis with too few viable builds | §14A.1 · §14A.5 |
| D3 | dead_kit_ability | an ability appearing in no viable late-game build | §5H.3 · §14A.5 |
| D4 | single_composition_path | a path whose surviving bench collapses the player into one workable composition | T1_Integrity_Paths §8.11.9 |
| D5 | single_build_raid_role | a raid role only one build can serve | T1_Tier_C_MMO_Spec §8.9 |
THE ATTRIBUTION DEFECT — the sixth, and the one this wave adds:
| # | defect_class | definition | why it is needed |
|---|---|---|---|
| D6 | zero_breadth_axis | an axis whose breadth_contribution is at or near zero — the layer exists and does no work | With no cross-pool cost, a build's spec purpose determines the best pick in each pool independently: every damage build takes option A, every heal build takes option B. D1-D5 all report green (zero never-picked options, roles populated) while the pool layer is decoration. That is meta-collapse hiding inside a passing metric. Partial cover recorded honestly: §14A.5's per-role reporting + D2 detect the collapse in aggregate and cannot attribute it — which is exactly why breadth_contribution is a leave-one-out re-run of the mandated simulation rather than a new instrument. |
THREE FURTHER ARMING ROWS — each computes an already-ruled doctrine that today has no
statistic, threshold, or column. None needs a Josh ruling; each arms a rule already in force:
| # | defect_class | arms | citation |
|---|---|---|---|
| D7 | mandatory_tax_option | pick share above band across role axes (ubiquity *within* one axis is legitimate and role-defining; ubiquity *across* axes is the tax) | Combat §Balance Doctrine — *"A peak that every build must reach to be viable is a defect"*; §5I.1 *"one real choice with filler beside it is not a pool… the sweeps will report it as such"* |
| D8 | source_dominance | one power_source exceeds its Phase-5M band across the viable set — options everybody takes that change nothing. Disjoint from D1/D7: pick shares can be perfectly even while one source supplies most effective power | Combat §Balance Doctrine (same sentence, gear side) |
| D9 | tag_measure_mismatch | composed role_vector_prior vs role_vector_measured disagree — breadth is otherwise manufacturable by tagging (fill the group-heal axis by tagging options group-heal, with no build in it that heals a group). Resolves to a mis-tagged pool OR a new taxonomy_status=emergent axis row | §14A.1 *"a role that emerges from play… is an addition to the taxonomy, not a violation of it"* |
The doctrine's own fix rule applies in both directions and unchanged: *"it is fixed by
widening the option rather than by removing it."*
---
docs/fk_spec.json — five new registry entriesRegistered at first data, not at empty-table creation (a min_values: 0 floor is a rule that
cannot fail) — the tightening of the live draft-time convention recorded at §0 point 3.
The entry shape is the verified live one (n2) — under-specified in both designs' first drafts.
Checked across all 21 live entries: every entry carries registry + tab + primary_key
(a LIST; composite keys are live — T0_Thread_Grid keys ["thread_id","chapter_id"]) +
id_formats (FULLMATCH-anchored pattern + min_values) + foreign_keys; and every FK object
carries column / references_registry / references_tab / references_column /
min_tokens, plus optional token_pattern, target_token_pattern, multi_value_separator,
_note. Family A's five entries below carry all of them; multi_value_separator (verified real
and correctly used) appears on every delimited column.
| registry | primary_key | id_formats | declared FKs |
|---|---|---|---|
T0_Bonus_Pool_Registry | pool_id | POOL_\d{4} | unlock_gate_quest_ref → T0_Quest_Definition_Registry.quest_id; spec_purpose_refs (;) → T0_Spec_Purpose_Registry.purpose_id; superseded_by → self |
T0_Bonus_Option_Registry | option_id | BOPT_\d{5} | pool_id → A1; voice_register_ref → T0_Voice_Registry.voice_id; unlock_gate_ref → T0_Quest_Definition_Registry.quest_id; role_tags (;), role_scope (;) → T0_Role_Axis_Registry.role_axis_id; spec_purpose_refs (;) → A4; superseded_by → self |
T0_Role_Axis_Registry | role_axis_id | ROLE_[A-Z0-9_]+ | — |
T0_Spec_Purpose_Registry | purpose_id | SPEC_[A-Z0-9_]+ | role_axis_ref → A3 |
T0_Role_Composition_Rule | rule_id | RCR_\d{3} | role_axis_ref → A3 |
Plus one documented non-FK _note on T0_Bonus_Pool_Registry.capability_ref, on the
range_id precedent: validated as an id-format only, resolved per-kind by tooth T-A3, and
explicitly not declared under foreign_keys by design, so it is never mistaken for a
dangling FK. Same _note treatment for magnitude_ref / threshold_ref / breadth_floor_ref
while T0_Balance_Constant_Registry remains a _deferred address.
build_space (JOINT roster 25 → 29; Family A owns gate 26)One arithmetic for both families (n5). harness/gates_config.json holds 25 gates today.
Each design was internally right and jointly wrong ("25 → 26" here, "25 gates + the 2 new ones"
there — landed together that is 28, and Family B's reconciliation adds a third). The joint roster
is: 25 today · 26 build_space (Family A) · 27 rarity_firewall (B) · 28
counter_class_coverage (B) · 29 ally_build (B, the M9 host). Same discipline on the
registry counts: added_registries 12 → 25 jointly (A +5, B +8), and
added_rows["T0_Worldstate_Variables/Sheet1"] 17 → 21 jointly (A +2, B +2).
harness/check_build_space.py → harness/build_space_scorecard.json + .md, enrolled in
harness/gates_config.json as gate 26. Lands PASS-on-empty and loudly declared, exactly like
the no_dead_end scaffold — a pre-data gate that certifies structure and arms the moment rows
land, never a vacuous green. Per the combinatorial residue, the gate roster has **no balance gate
today**; this is the arming step behind the AAAAA doctrine.
The gate SELF-TESTS its own classifier on canned rows and exits non-zero if the classifier
rotted — the standing convention harness/check_weave_lifecycle.py already documents and
exercises ("the WARN is honest only if the ruler works"). Concretely: inject a synthetic pool with
one deliberately dominant option and assert the scorecard reports RED on D7. **A breadth number
that has never been shown to fail is not evidence.**
| id | tooth | fails when |
|---|---|---|
| T-A1 | lane/pick-class invariant | pick_class=minor without lane=A, or major without lane=B |
| T-A2 | two-index integrity | neither grade_index nor gate_index set; a minor pool with no grade_index; a major pool with no gate_index; gate_index in {6,10} carrying a grade_index (the two crossings confer no grade); indices outside 1-10 / 1-12 |
| T-A3 | polymorphic ref resolution | capability_ref fails to resolve against the §1.3 target for its (capability_kind,scope_kind) pair. Positive-controlled: the check proves it CAN resolve a known-good ref per kind before reporting any failure |
| T-A4 | MYTHIC invariant | the three clauses of §2.1 — including the cross-table, positive-controlled zero against T0_RNG_Drop_Table |
| T-A5 | effect typing resolves | effect_attribute names no live GAS attribute and no live registry enum column; stack_op=enum_set with an effect_attribute that is not an enum column; condition_expr fails harness/condition_expr.py parse. SCOPED (M7): a value on the declared pending_attribute_channels list (cast_time, target_elemental_resistance, elemental_superiority, damage_magnitude, crit_chance, movement_speed, projectile_count) emits WARN, anything else FAILs; the list empties when the §10 step-0 UHumanityAttributeSet extension lands, and the tooth is FAIL-only from then on |
| T-A6 | purpose→role derivation | a T0_Spec_Purpose_Registry row whose (function_class,scope_class) contradicts its role_axis_ref's own two columns (§5I.2's stated derivation) |
| T-A7 | pool breadth | a pool with fewer than two lifecycle=active options (§5I.1 "a pool offering one real choice with filler beside it is not a pool"). Threshold is a gate constant, per-pool waiver via the standard notes waiver idiom |
| T-A8 | lifecycle / id reuse | an option_id or pool_id present in a prior committed snapshot and absent now without lifecycle=retired; any id reuse. A bare deletion trips the min_values floor by count; a delete-and-reuse keeps the count and passes every existing check silently — this is the hole T-A8 closes |
| T-A9 | internal-vocabulary firewall | a *_token / *_class / bonus_kind / power_source value appearing in a player_text or option_name cell (no mode taxonomy on player surfaces) |
| T-A10 | string pipeline | an option row reaching a build pack with string_status=placeholder; a non-blank option_name with string_status=voice_passed but no voice_register_ref |
| T-A11 | exclusion coherence | an exclusion_group tag held by exactly one option corpus-wide (an exclusion of one is not an exclusion — a rule that cannot fire) |
| T-A12 | budget coherence | sum(pick_cost of held options) > pick_budget within budget_scope; budget_scope=global without a declared global budget row |
check_registry_extensions.py is untouched — it correctly owns columns only, and this family
adds none.
| table / artifact | consumers |
|---|---|
T0_Bonus_Pool_Registry | the ability foundry (addendum §1, applies at cast); the mastery presentation ladder (addendum §5, reads the same tier key, carries no power); W10 build/loadout book screens; check_build_space.py; the P5 factory per chapter |
T0_Bonus_Option_Registry | the foundry → GameplayEffect binding (effect_attribute+stack_op+magnitude_ref, no translation layer); T1_Combat_System_Spec at Phase 5H for damage-formula integration; the natural-voice pipeline (string_status=placeholder is its worklist); the build/loadout UI; the sweeps |
T0_Role_Axis_Registry | the sweeps (per-axis reporting); T1_Tier_C_MMO_Spec §8.7 at group scale; the factory when a new axis emerges |
T0_Spec_Purpose_Registry | the sweeps (role attribution prior); pool authoring; the UI's spec framing |
T0_Role_Composition_Rule | check_build_space.py only — it is the sweep's denominator definition |
WS_043-WS_044 | the runtime save layer; the loadout UI (via B's WS_045 set rows); the sweep's reachability classing |
build_space_scorecard.* | run_gates.py; Phase-5M/5H tuning; the director's balance read |
---
EXAMPLES-NOT-LIMITS is recorded per pool as data, not just prose: every seed pool below
carries `notes = "seed set per addendum §7/§9/§10/§11 (Josh 2026-07-26) — the authoring baseline,
not the roster ceiling; the factory expands per chapter", and populated_from` cites the ruling.
Every option_name / player_text cell below is a PLACEHOLDER carrying
string_status=placeholder — the natural-voice pass authors the real words; none is invented as
system voice here.
pool_id | kind / scope | capability_ref | pick_class / lane | index | grade_ceiling | source |
|---|---|---|---|---|---|---|
POOL_0001 | ability / class | combat | minor / A | grade 1 | rare | §5H.1 (Lane A authors per ability class) |
POOL_0002 | ability / instance | A_F_002 (Fire Bolt) | major / B | gate 1 | epic | §5H.2 (Lane B is per-ability by identity) |
POOL_0003 | ability / instance | A_E_002 (Tremor Stomp) | major / B | gate 1 | epic | §5H.2 |
POOL_0004 | ability / class | mobility | minor / A | grade 1 | rare | §5H.1 class-appropriate rule |
POOL_0005 | ability / class | healing | minor / A | grade 1 | rare | §5H.1 |
POOL_0006 | weapon / class | BRUTE | minor / A | grade 1 | rare | Combat §12 Lane A |
POOL_0007 | weapon / class | BRUTE | major / B | gate 12 | mythic | Combat §12 — the canonical Lane B instance, Legendary form transformation at Proficiency 99, with the mythic ceiling at the final mastery questline |
POOL_0002 and POOL_0003 both carry gate_index=1 as the **authoring placement pending the
per-ability gate assignment the factory makes** (Combat §12: "which gate carries it authors with
the per-weapon detail"); the value is a row edit, not a schema question.
POOL_0001)option_id | bonus_kind | effect_attribute | stack_op | ordinal_rank | role_tags | Josh's words |
|---|---|---|---|---|---|---|
BOPT_00001 | cast_time_reduction | cast_time | mult | 1 | ROLE_SINGLE_DAMAGE | "reduce cast time" |
BOPT_00002 | resistance_pierce | target_elemental_resistance | add | 2 | ROLE_SINGLE_DAMAGE | "decrease the target's elemental resistance" |
BOPT_00003 | elemental_superiority | elemental_superiority | add | 3 | ROLE_SINGLE_DAMAGE | "increase elemental superiority (the matrix edge amplified)" |
BOPT_00004 | raw_damage | damage_magnitude | add | 4 | ROLE_SINGLE_DAMAGE | "raw damage" |
BOPT_00005 | crit_chance | crit_chance | add | 5 | ROLE_SINGLE_DAMAGE | "crit chance" |
All five: rarity_class=common, power_source=proficiency, pick_cost=1, exclusion_group
blank, build_defining=false, magnitude_ref blank (Phase-5M), condition_expr blank,
lifecycle=active, string_status=placeholder. BOPT_00005 additionally routes through
T1_RNG_Sigma_Constraint_System per §5H.1's probabilistic-bonus rule — recorded in notes.
Pool-breadth honesty (T-A7 is armed against this exact seed set): these five are Josh's
verbatim seeds and four of the five are raw-throughput sharpeners, so POOL_0001 as seeded is
close to the "ranked versions of one bonus" shape §5I.1 bans. The factory's expansion per §5H.1
(mobility → range/duration/recovery/directional-control; healing → channel efficiency/HoT
depth/target count) is what makes it a real pool. Recording that here so the seed is never
mistaken for a finished pool.
POOL_0002 — Fire Bolt ("Fireball → three fireballs instead of one · AOE explosion on hit ·
cast while moving"):
option_id | bonus_kind | effect_attribute | stack_op | build_defining | Josh's words |
|---|---|---|---|---|---|
BOPT_00010 | projectile_multiply | projectile_count | override | true | "three fireballs instead of one" |
BOPT_00011 | aoe_on_impact | range_class | enum_set | true | "AOE explosion on hit" |
BOPT_00012 | cast_while_moving | cast_pattern | enum_set | true | "cast while moving" |
POOL_0003 — Tremor Stomp ("Earth Tremor → brief stun · randomized earthen-wall segments
circling the player · brief mobility surge"):
option_id | bonus_kind | effect_attribute | stack_op | build_defining | Josh's words |
|---|---|---|---|---|---|
BOPT_00013 | stun_add | status_effects | add | true | "brief stun" |
BOPT_00014 | construct_ring | persistence_class | enum_set | true | "randomized earthen-wall segments circling the player" |
BOPT_00014b | construct_ring | physical_properties_array | add | true | the same wall-ring's §5G.2 Earth-construct properties — two rows, one option group |
BOPT_00015 | mobility_surge | movement_speed | mult | true | "brief mobility surge" |
BOPT_00014 + BOPT_00014b are the concrete demonstration of §5H.2's override discipline: the
wall ring adds a persistence_class value and a physical_properties_array entry so the
segments enter the §5G.4 physics chains as an authored construct does — **stated on the bonus
rows, with A_E_002's base row untouched.** (Real ids will be sequential; 00014b is written
here only to show the pairing. The mechanism for grouping two rows into one player-facing pick is
a shared exclusion_group + a shared option_name/player_text, which the existing columns
already express — no new column needed.)
role_axis_id | scope_class | function_class | arena | taxonomy_status |
|---|---|---|---|---|
ROLE_GROUP_SUPPORT | group | support | both | seed |
ROLE_GROUP_HEAL | group | heal | both | seed |
ROLE_GROUP_DAMAGE | group | damage | both | seed |
ROLE_SINGLE_SUPPORT | single | support | both | seed |
ROLE_SINGLE_HEAL | single | heal | both | seed |
ROLE_SINGLE_DAMAGE | single | damage | both | seed |
ROLE_GROUP_TERRAIN | group | terrain | tier_c_raid | seed |
ROLE_GROUP_TERRAIN is canon-stated, not invented: Tier_C §8.7 — *"A build whose group role is
terrain rather than damage is a first-class raid role, not a support afterthought"* — with
tier_c_team_ref = Environmental Manipulation per §8.8's four operational teams. The other three
teams (Combat Core, Spawnling Management, Enhancement and Protection) are staffed from the six
shared axes, so they need no axis rows of their own.
purpose_id | function_class | scope_class | role_axis_ref | source |
|---|---|---|---|---|
SPEC_VRIL_HEAL_PERSONAL | heal | single | ROLE_SINGLE_HEAL | §5I.2 verbatim derivation |
SPEC_VRIL_HEAL_AREA | heal | group | ROLE_GROUP_HEAL | §5I.2 verbatim derivation |
SPEC_VRIL_DAMAGE_PERSONAL | damage | single | ROLE_SINGLE_DAMAGE | "vril-HEALING focus vs vril-DAMAGE focus" |
SPEC_VRIL_DAMAGE_AREA | damage | group | ROLE_GROUP_DAMAGE | "PERSONAL vs AREA-OF-EFFECT scopes" |
SPEC_VRIL_REGEN_RATE | resource | single | ROLE_SINGLE_SUPPORT | "vril regeneration per second" |
SPEC_HEAL_OVER_TIME | heal | single | ROLE_SINGLE_HEAL | "healing over time" |
rule_id | role_axis_ref | input_kind | comparator | precedence_rank |
|---|---|---|---|---|
RCR_001 | *(all)* | measured_role_vector | vector_dominant | 1 |
RCR_002 | *(all)* | spec_purpose_share | max_share | 2 |
RCR_003 | *(all)* | role_tag_share | max_share | 3 |
RCR_004 | group axes only | ally_role_fill | share_above_threshold | 4 |
Precedence encodes the F4 survivor's core: the measured vector wins over the authored prior.
Breadth must not be manufacturable by tagging. RCR_003 is the fallback for pre-simulation
authoring passes, and any disagreement between RCR_001 and RCR_002/RCR_003 emits a D9 row.
---
Zero base-row edits. No existing registry gains a column. T0_Ability_Tree_Registry's 185×35
rows are untouched, which is §5H.4's own ruling ("rather than as new columns on the base row") and
is why the fidelity gate's expected_cell_diffs (4,215 entries) and extension_hashes (19
registries) do not move at all.
Baseline deltas, in the same commit as the rows (registry_fidelity.py --emit-baseline, run
UNPIPED per the standing gate-verification lesson):
added_registries: 12 → 17 for Family A alone (the five new tables; the twelve-registry precedent path) — 12 → 25 jointly with Family B's eight (n5; one arithmetic, §8.2).
added_rows: T0_Worldstate_Variables/Sheet1 17 → 19 for Family A's two rows (WS_043, WS_044) — 17 → 21 jointly with Family B's WS_045, WS_046.
expected_cell_diffs, added_columns, added_tabs, overwide_rows, extension_hashes, stub_superseded: unchanged.
Every default reproduces the ruled economy exactly:
| default | reproduces |
|---|---|
pick_cost = 1, pick_budget = 1, budget_scope = tier | §5I.1's free one-pick-per-tier grant, with §5A's distinct-grants severance intact. The dial exists; today's value IS today's canon |
exclusion_group = NULL | no pick-level exclusion exists anywhere in canon (positive-controlled to zero across six T1 docs) |
respec_class = deferred | §5I.1's explicit deferral of the bonus respec model; no consumer may assume one |
refundable = false (WS_044) | §8.11.6's interim non-refund reading, as reversible data |
power_source = proficiency | pool bonuses are proficiency-sourced by construction |
role_affinity = NULL (uniform over role_tags) | tags-plural is the docs' own wording; weighting is a PROPOSAL offered on its merits, never a repair, and is off by default |
expected_pick_band_ref = NULL | no band exists today; the gate falls back to the ratified count == 0 floor test alone, so the gate's day-one behaviour is exactly D1 |
build_defining = false | no build-identity concept exists today; nothing changes until authored |
lifecycle = active, superseded_by = NULL | today's implicit state |
string_status = placeholder | correct on day one — no natural-voice pass has run on these strings, and the doctrine owns them |
multi_axis_policy = primary_plus_secondary | §14A.5 never says a build has exactly one axis; flagged as the applied reading, flippable at ratification |
grade_ceiling per pool tier | §5I.4's "higher-rarity options appear in later-tier pools", now data |
arena = both | §14A.1 + §8.7's "one taxonomy, two arenas" |
Vocabulary extension, not mutation: the shared ladder in T0_Rarity_Grade gains mythic as
its one never-before-used token and covers uncommon + signature so all 11 live cells that
Family A's first-draft enum could not express keep their values. No existing cell in any of the
three registries carrying rarity_class changes value.
Ordering of the mint (each step green before the next): **step 0 — the
UHumanityAttributeSet extension (damage / crit / resist / cast-time / movement / projectile
channels), which the Lane-A and Lane-B seed rows depend on (M7)** → _deferred addresses → empty
registries + added_registries → seed rows → fk_spec.json registration with min_values at the
seed counts → check_ws_value_form.py domain declarations for WS_043/WS_044 + the CG-25
+-prefix ruled-list edit for WS_044 (m4) → --emit-baseline → check_build_space.py enrolled
as a declared PASS-on-empty gate → teeth armed as their inputs populate. Registry/canon edits are never "trivial mechanical": the
content still takes a fresh-context critic and the full run_gates.py suite.
Doc wiring the mint owes (so nothing lands orphaned): a docs/DOC_MAP.md row for the schema
doc and the scorecard; a docs/registry_extensions.json _deferred entry per table (plus
balance-constant-table); docs/fk_spec.json entries; harness/gates_config.json gate 26. **No
tier-doc amendment is proposed by this family** — the combinatorial-F1 kill stands, and §5H.4 /
§12 already point at the right rail.
*(Reconciled M1/M2/M3/M4/M8. The first draft DECLARED this contract and Family B did not carry it;
that is what made the pair unlandable. Every line below now names one owner and one consumer.)*
| shared thing | OWNER (authoritative) | CONSUMER |
|---|---|---|
power_source_enum (§2.4) | Family A | B's T0_Imprint_Affix, T0_Ally_Behavior_Policy, T0_Rarity_Grade, T0_Status_Table carry the column (M4) |
lifecycle_enum + superseded_by | Family A | the same four B tables (M4) |
string_status_enum (+ voice_register_ref → T0_Voice_Registry.voice_id) | Family A | every B table with an FText column; B's voice_status = pending_natural_voice marker is retired in favour of it (M4) |
the role_axis_id keyspace (T0_Role_Axis_Registry) | Family A | B's role_tag / role_axis_ref are FK columns, not enums (M3) |
the purpose_id keyspace (T0_Spec_Purpose_Registry) | Family A | B's spec_purpose_ref is an FK column (M3) — which also un-conflates function from scope |
the rarity ladder + per-grade properties (T0_Rarity_Grade, keyed (axis, rarity_token)) | Family B | A's grade_ceiling / rarity_class are token FKs at axis=pool_option (M2) |
loadout SET definition + set state (T0_Loadout_Set_Definition, WS_045) | Family B | A holds loadout_set_id as a key only (M1, m1) |
bonus SELECTION state (WS_043) | Family A | B's bonus_pick_refs[] is a derived read, not a stored copy (M1) |
the WS_043-WS_046 allocation | allocated once, §6.0 | both |
the tuning firewall + T0_Balance_Constant_Registry deferred address | stated identically in both (§0) | both — magnitude_ref / threshold_ref / breadth_floor_ref / expected_pick_band_ref all resolve to constant_id (M8) |
the effect_attribute + stack_op + condition_expr typed quartet | Family A | B's eligibility_expr and condition_expr reuse the same shipped grammar |
| the gate / registry / WS-row arithmetic (29 gates · 12→25 registries · 17→21 WS rows) | one arithmetic, §8.2 | both (n5) |
One shared vocabulary is the load-bearing part; thirteen tables landing with divergent
vocabularies is the unrecoverable outcome.
---
Applied against mint_design_critic.md (verdict: NO-GO as a pair · GO-WITH-FIXES individually).
Read-only on C:/dev/humanity-forgotten @ ab5d32c; the two design files are the only writes.
Where the critic prescribed a fix it is applied verbatim; where it offered options, the choice
minimising cross-family coupling was taken and is recorded below with its reason.
WS_043+ space ONCE, in contiguous per-family blocks: WS_043 bonus_selection_state (A) · WS_044
bonus_respec_ledger (A) · WS_045 loadout_set_state (B) · WS_046 item_instance_ledger
(B). *Choice recorded:* the critic left the middle ids open; contiguous per-family blocks were
chosen over interleaving because each family's rows stay independently reviewable, and B's item
ledger keeps the critic's prescribed WS_046. A's draft WS_044 loadout_set_state is
WITHDRAWN (one owner: Family B); A's draft WS_045 moved to WS_044. §6.0 lists the superseded
draft ids so no reader mis-keys them. Beyond the critic: the double-owned *selection-state
shape* is also closed — B's bonus_pick_refs[] is now a DERIVED read over WS_043, not a stored
copy — leaving exactly two cross-family pointers.
rarity enum**; grade_ceiling and rarity_class are token FKs into B's T0_Rarity_Grade, which
becomes a PROPERTY table keyed (axis, rarity_token) — no RG_ surrogate keyspace, no live cell
moved, both creature-F8 and bl-loot-F5 satisfied. *Owner choice:* B owns the ladder (it owns the
table and the per-grade properties); A owns the role/spec rosters — ownership split by
authorship, not by argument. Verified this pass: composite PKs are a live house shape
(T0_Thread_Grid keys ["thread_id","chapter_id"]), and the live distributions were re-counted
programmatically — 10 live uncommon + 1 signature = 11 cells, correcting the critic.
role_tag / role_axis_ref / spec_purpose_ref become FK columns into A's T0_Role_Axis_Registry and
T0_Spec_Purpose_Registry. Zero authoring cost — the rows exist in §9.4/§9.5 — and it repairs
B's function/scope conflation, restoring §5I.2's two-axis derivation and tooth T-A6.
power_source, lifecycle (+ superseded_by) and string_status land on B's four effect/string-bearing tables;
string_status additionally on every B table with an FText column, and voice_register_ref on
the one whose string is a spoken line. B's voice_status = pending_natural_voice marker (declared
in §0.5, carried in no table) is retired in favour of A's enum. §2.4 records the F6 reasoning:
without the column on B's rows, defect D8 source_dominance cannot compute at all.
survivors with named owners — F8 → the HUD/pip lane, F6 → the SFX consumer lane — and the
hitzone_parts line no longer cites F7).
stub_supersededtargets; the two I3-tripping manifest keys dropped; §6.2 re-columned by vector).
offered (i) name the UHumanityAttributeSet extension as a co-landing dependency or (ii)
scope T-A5 to WARN. Both are applied, because either alone leaves a hole: (i) is now step 0 of
§10's ordering, and (ii) gives T-A5 a declared pending_attribute_channels list (the seven names)
that WARNs on those and FAILs everything else, emptying when step 0 lands. Silent red is
impossible in both directions, and the positive control is recorded with the tooth.
(A §0 / B §0.4): magnitudes are refs into T0_Balance_Constant_Registry.constant_id; ordinals and
ratified counts are literals; deferred magnitudes land blank; the struct-mirror exception is
ENUMERATED and CLOSED at five T0_Boss_Attack_Rail columns. *Choice recorded:* the critic allowed
either ref-ing expected_pick_band_* or listing it as a second exception — the ref was chosen
(expected_pick_band_min/max → single expected_pick_band_ref) because it leaves the exception
register at exactly one entry instead of two. A2 is 33 → 32 columns.
(stat_point_budget on WS_027 and WS_012, plus tooth T-B1 in A's T-A12 class, hosted by
the new harness/check_ally_build.py).
bonus_axis onto A — APPLIED as "B drops the claim" — the minimum-coupling option; A mints no such column, and the axis is derivable sweep-side from bonus_kind /
effect_attribute if it is ever wanted.
sigma_seq + keep-rate — APPLIED. sigma_seq added to B's instance ledger; keep-rate given a home here: §7.5's per-option rows are re-keyed subject_ref +
subject_kind (pool_option | imprint_affix) with keep_rate on rolled subjects, 5 → 7 fields.
check_ws_value_form.py — APPLIED (new §6.2; the gate and the CG-25 +-prefix ruled-list edit are in §10's ordering). **Both the design AND the critic were wrong on
the constant: it holds twelve** ids (extended 6→12 by Josh's ruling D-CG25-APPEND-SET,
2026-07-24), not six and not seven — the critic read a truncated first line. The landing edit is
12 → 14, and the stale "six" in the docstring is fixed in the same pass.
capability_kind_enumadditions named as additions; the skill/trait → attribute+proficiency translation recorded as a
notes line so Josh's §10 words stay traceable to a row; the rarity claim corrected under M2).
discovered_merges[] declared on the LIVE WS_035 spellcraft_authored_spells — a domain declaration rather than a new
keyspace; the merge RULES stay with the Rune Forge / §2b lane and are not minted here).
acquisition_source vocabulary + case convention; theEquipment column arithmetic and the 7-vs-8 assetgen form; the affix-side mythic firewall twin,
cross-referenced from §2.1 here).
*_class excluded; *_token unmatched → rule 7).tab and min_tokens.T0_Rune_Registry draft-time convention it tightens.T0_Language_Script_Registry.script_id / T0_Inscription_Spine.spine_id named.added_registries 12 → 25, added_rows[T0_Worldstate_Variables/Sheet1] 17 → 21.
None. Every finding was reconcilable without contradicting a ruled canon point or a lens
SURVIVES verdict. The four OPEN items (rarity ladder 4-vs-5 + ability_count axis; the three
unnamed stat slots; familiar element affinity; the player→ally order channel) and the two
system-canon routings (sekiro F2, D-MYTHIC-GATE) remain Josh's and are untouched — and the M2
reconciliation explicitly does not pre-empt OPEN-1 (the uncommon token exists because live
cells already carry it; its imprint_slot_count stays blank).
Status: the pair is landable together. The four cross-design collisions are closed with one
owner each, both self-defeating teeth are fixed, and every MODERATE and MINOR is applied in place.