MINT_DESIGN_A_BUILD_SPACE_2026-07-27.md

pipelines/MINT_DESIGN_A_BUILD_SPACE_2026-07-27.md

MINT DESIGN — FAMILY A: THE BUILD-SPACE HOMES

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.**

---

0. THE HOUSE MECHANISM THIS MINT USES (and why)

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.

THE SHARED TUNING FIREWALL — one discipline, stated identically in Family A and Family B

*(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

(placeholderauthoredvoice_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.

---

1. TABLE A1 — 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).

#columntypeenum / FK targetrequired
1pool_ididPK, POOL_\d{4}yes
2capability_kindenumcapability_kind_enum (§1.2)yes
3scope_kindenumscope_kind_enum: class \instanceyes
4capability_refpolymorphic refresolves per (capability_kind,scope_kind) — §1.3 mapyes
5pick_classenumpick_class_enum: minor \majoryes
6laneenumlane_enum: A \Byes
7grade_indexint1-10 (§2 GRADE index)one-of w/ 8
8gate_indexint1-12 (§2 GATE index)one-of w/ 8
9unlock_gate_quest_refFKT0_Quest_Definition_Registry.quest_idmajor only
10grade_ceilingtoken FKT0_Rarity_Grade.rarity_token @ axis=pool_option (§1.2, Family B owns the table)yes
11pick_budgetintDEFAULT 1yes
12budget_scopeenumbudget_scope_enum: tier (DEFAULT) \capability \globalyes
13respec_classenumrespec_class_enum: deferred (DEFAULT) \free \costed \gate_locked \new_run_onlyyes
14spec_purpose_refsmulti-FK ;T0_Spec_Purpose_Registry.purpose_idno
15pool_display_nameFTextplayer-facing pool headerno
16string_statusenumstring_status_enum: placeholder (DEFAULT) \authored \voice_passedyes
17lifecycleenumlifecycle_enum: active (DEFAULT) \deprecated \retiredyes
18superseded_byself-FKT0_Bonus_Pool_Registry.pool_idno
19-25*the house tail*pipeline_consumer, source_ref, populated_from, notes, extensions, version, last_updated

1.1 Design notes that are load-bearing

T-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.

load-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.

suits 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.

tier). §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.

scopes §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.

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.

1.2 Named closed enums introduced by A1

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 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.

string_status_enum, lifecycle_enum as tabled above.

1.3 The capability_ref per-kind resolution map (tooth T-A3 enforces it)

capability_kindscope_kind=classscope_kind=instance
abilityT0_Ability_Tree_Registry.ability_class (live column, 54 values)T0_Ability_Tree_Registry.ability_id
weaponT0_Weapon_Registry.weapon_class / .weapon_subclassT0_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)
familiarT0_Familiar_Registry.species_classT0_Familiar_Registry.familiar_id
companion*n/a*T0_Character_Index.character_id
imprintT0_Rune_Registry.operator_familyT0_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.

---

2. TABLE A2 — 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).

#columntypeenum / FK targetrequired
1option_ididPK, BOPT_\d{5}yes
2pool_idFKT0_Bonus_Pool_Registry.pool_idyes
3option_nameFTextplayer-facing nameyes
4player_textFTextone natural-voice line the choice UI rendersyes
5voice_register_refFKT0_Voice_Registry.voice_idno
6string_statusenumstring_status_enum, DEFAULT placeholderyes
7bonus_kindenumbonus_kind_enum (§2.2)yes
8effect_attributeenumeffect_attribute_enum (§2.3)yes
9stack_openumstack_op_enum: add \mult \override \enum_setyes
10magnitude_refrefT0_Balance_Constant_Registry.constant_id (DEFERRED address) — blank-tolerant until Phase-5Mno
11condition_exprexprdocs/CONDITION_EXPRESSION_GRAMMAR.md v1.0 ACTIVE; blank = unconditionalno
12ordinal_rankintwithin-pool ordering, 1..N (§12 "fixed here")yes
13rarity_classtoken FKT0_Rarity_Grade.rarity_token @ axis=pool_option (the shared ladder, §1.2)yes
14unlock_gate_refFKT0_Quest_Definition_Registry.quest_idmythic only
15role_tagsmulti-FK ;T0_Role_Axis_Registry.role_axis_idyes
16role_affinityweighted multi ;<role_axis_id>:<0..1> — PROPOSAL-TIER, blank = uniform over role_tagsno
17spec_purpose_refsmulti-FK ;T0_Spec_Purpose_Registry.purpose_idno
18power_sourceenumpower_source_enum (§2.4), DEFAULT proficiencyyes
19pick_costintDEFAULT 1yes
20exclusion_grouptagnullable; two options sharing a tag cannot be held together, across pools as well as within one. DEFAULT blankno
21expected_pick_band_refrefT0_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
22role_scopemulti-FK ;T0_Role_Axis_Registry.role_axis_id — which axes this option is *allowed* to dominate; blank = its own role_tagsno
23build_definingboolDEFAULT false — does taking this change what the build IS, or only its numbers?yes
24lifecycleenumlifecycle_enum, DEFAULT activeyes
25superseded_byself-FKT0_Bonus_Option_Registry.option_idno
26-32*the house tail*pipeline_consumer, source_ref, populated_from, notes, extensions, version, last_updated

2.1 The MYTHIC constraint the schema must express

§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_ref is non-null and
resolves to a quest row whose twelve_tier_gate marks a final mastery-questline crossing;
(b) the option's pool_id has grade_ceiling == mythic; (c) **option_id appears 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).
Conversely grade_ceiling < mythic ⇒ no option in that pool carries rarity_class == mythic,
where < reads T0_Rarity_Grade.ordinal within axis=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.

2.2 bonus_kind_enum — the closed, growable vocabulary

Josh'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).

elemental_superiority · raw_damage · crit_chance

directional_control · construct_persistence · structural_integrity ·

reinforce_cost_reduction · charge_window_forgiveness · detection_range ·

signal_resolution · registration_latency · channel_efficiency · hot_depth ·

target_count

reach_economy · reload_spread · catch_window · rage_build_rate · stamina_economy

cast_while_moving · stun_add · construct_ring · mobility_surge

party_share_mode · midflight_redirect · chained_burst · legendary_form

2.3 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): Composure and Rage DO resolve
against the header and cast_pattern / persistence_class / status_effects DO 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.

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.

2.4 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.

---

3. TABLE A3 — 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).

#columntypeenum / FKrequired
1role_axis_ididPK, ROLE_[A-Z0-9_]+yes
2role_axis_tokentokeninternal label — never player-facingyes
3scope_classenumscope_class_enum: single \groupyes
4function_classenumfunction_class_enum: damage \heal \support \terrain \resourceyes
5arenaenumarena_enum: solo_party \tier_c_raid \both, DEFAULT bothyes
6taxonomy_statusenumtaxonomy_status_enum: seed \emergent \ratifiedyes
7tier_c_team_reftoken§8.8 operational team the axis staffs; nullableno
8breadth_floor_refrefT0_Balance_Constant_Registry.constant_id — the "too few viable builds" threshold, Phase-5Mno
9lifecycleenumlifecycle_enumyes
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.

---

4. TABLE A4 — 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_]+.

#columntypeenum / FKrequired
1purpose_ididPK, SPEC_[A-Z0-9_]+yes
2purpose_tokentokeninternal, never player-facingyes
3function_classenumfunction_class_enumyes
4scope_classenumscope_class_enumyes
5role_axis_refFKT0_Role_Axis_Registry.role_axis_idyes
6capability_kind_scopemulti-enum ;capability_kind_enum — which capability kinds may carry it; blank = allno
7taxonomy_statusenumtaxonomy_status_enumyes
8lifecycleenumlifecycle_enumyes
9-14*house tail*source_ref, populated_from, notes, extensions, version, last_updated

---

5. TABLE A5 — 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}.

#columntypeenum / FKrequired
1rule_ididPK, RCR_\d{3}yes
2role_axis_refFKT0_Role_Axis_Registry.role_axis_idyes
3input_kindenuminput_kind_enum: spec_purpose_share \role_tag_share \measured_role_vector \ally_role_fillyes
4comparatorenumcomparator_enum: max_share \share_above_threshold \vector_dominantyes
5threshold_refrefT0_Balance_Constant_Registry.constant_id; blank-tolerant until Phase-5Mno
6precedence_rankintdeterministic tie-break order — a build's axis assignment must be reproducible run to runyes
7multi_axis_policyenummulti_axis_policy_enum: primary_only \primary_plus_secondary (DEFAULT)yes
8lifecycleenumlifecycle_enumyes
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.

---

6. SELECTION STATE — the save-layer record (2 new 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."

6.0 THE WORLDSTATE KEYSPACE ALLOCATION — one table, allocated once (M1)

*(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.jsonadded_rows["T0_Worldstate_Variables/Sheet1"] = 17.

idvariable_nameownerappend-legal (CG-25)shape
WS_043bonus_selection_stateFamily Ano (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_044bonus_respec_ledgerFamily Ayes`{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_045loadout_set_stateFamily Bno (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_046item_instance_ledgerFamily Byesthe 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.

6.1 The Family-A rows

their 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.

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.

Bonding 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.

question, per the §8.11.6 discipline.

6.2 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.

6.3 Merge-combinatorics-as-discovery gets a home (m6)

§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.

---

7. THE SWEEP OUTPUT SCHEMA — build_space_scorecard.json / .md

Not a registry: a harness artifact on the proven scorecard-gate pattern

(check_boss_axes.pyboss_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.

7.1 Run header (9 fields)

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.

7.2 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_bearingT0_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).

7.3 Per-build rows (6 fields)

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.*

7.4 Per-axis rows (4 fields) — the attribution instrument

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.

7.5 Per-option rows (7 fields) — and the ROLLED-LAYER analogue (m3)

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).

7.6 Defect rows (5 fields) and the defect_class_enum

Row: 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_classdefinitioncitation
D1dead_pool_optiona pool option the sweep never picks§14A.5 · §5I.1 · Combat §15 · addendum §10
D2thin_role_axisa role axis with too few viable builds§14A.1 · §14A.5
D3dead_kit_abilityan ability appearing in no viable late-game build§5H.3 · §14A.5
D4single_composition_patha path whose surviving bench collapses the player into one workable compositionT1_Integrity_Paths §8.11.9
D5single_build_raid_rolea raid role only one build can serveT1_Tier_C_MMO_Spec §8.9

THE ATTRIBUTION DEFECT — the sixth, and the one this wave adds:

#defect_classdefinitionwhy it is needed
D6zero_breadth_axisan axis whose breadth_contribution is at or near zero — the layer exists and does no workWith 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_classarmscitation
D7mandatory_tax_optionpick 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"*
D8source_dominanceone 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 powerCombat §Balance Doctrine (same sentence, gear side)
D9tag_measure_mismatchcomposed 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."*

---

8. GATE AND TOOTH ADDITIONS

8.1 docs/fk_spec.json — five new registry entries

Registered 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.

registryprimary_keyid_formatsdeclared FKs
T0_Bonus_Pool_Registrypool_idPOOL_\d{4}unlock_gate_quest_refT0_Quest_Definition_Registry.quest_id; spec_purpose_refs (;) → T0_Spec_Purpose_Registry.purpose_id; superseded_by → self
T0_Bonus_Option_Registryoption_idBOPT_\d{5}pool_id → A1; voice_register_refT0_Voice_Registry.voice_id; unlock_gate_refT0_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_Registryrole_axis_idROLE_[A-Z0-9_]+
T0_Spec_Purpose_Registrypurpose_idSPEC_[A-Z0-9_]+role_axis_ref → A3
T0_Role_Composition_Rulerule_idRCR_\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.

8.2 New gate — 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.pyharness/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.**

8.3 The teeth

idtoothfails when
T-A1lane/pick-class invariantpick_class=minor without lane=A, or major without lane=B
T-A2two-index integrityneither 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-A3polymorphic ref resolutioncapability_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-A4MYTHIC invariantthe three clauses of §2.1 — including the cross-table, positive-controlled zero against T0_RNG_Drop_Table
T-A5effect typing resolveseffect_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-A6purpose→role derivationa 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-A7pool breadtha 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-A8lifecycle / id reusean 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-A9internal-vocabulary firewalla *_token / *_class / bonus_kind / power_source value appearing in a player_text or option_name cell (no mode taxonomy on player surfaces)
T-A10string pipelinean 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-A11exclusion coherencean exclusion_group tag held by exactly one option corpus-wide (an exclusion of one is not an exclusion — a rule that cannot fire)
T-A12budget coherencesum(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.

8.4 Consumers (who reads what)

table / artifactconsumers
T0_Bonus_Pool_Registrythe 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_Registrythe 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_Registrythe sweeps (per-axis reporting); T1_Tier_C_MMO_Spec §8.7 at group scale; the factory when a new axis emerges
T0_Spec_Purpose_Registrythe sweeps (role attribution prior); pool authoring; the UI's spec framing
T0_Role_Composition_Rulecheck_build_space.py only — it is the sweep's denominator definition
WS_043-WS_044the 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

---

9. FIRST AUTHORED ROWS — Josh's verbatim examples mapped on

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.

9.1 Pools

pool_idkind / scopecapability_refpick_class / laneindexgrade_ceilingsource
POOL_0001ability / classcombatminor / Agrade 1rare§5H.1 (Lane A authors per ability class)
POOL_0002ability / instanceA_F_002 (Fire Bolt)major / Bgate 1epic§5H.2 (Lane B is per-ability by identity)
POOL_0003ability / instanceA_E_002 (Tremor Stomp)major / Bgate 1epic§5H.2
POOL_0004ability / classmobilityminor / Agrade 1rare§5H.1 class-appropriate rule
POOL_0005ability / classhealingminor / Agrade 1rare§5H.1
POOL_0006weapon / classBRUTEminor / Agrade 1rareCombat §12 Lane A
POOL_0007weapon / classBRUTEmajor / Bgate 12mythicCombat §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.

9.2 Lane A options — Josh's Fire Bolt seed set, verbatim (POOL_0001)

option_idbonus_kindeffect_attributestack_opordinal_rankrole_tagsJosh's words
BOPT_00001cast_time_reductioncast_timemult1ROLE_SINGLE_DAMAGE"reduce cast time"
BOPT_00002resistance_piercetarget_elemental_resistanceadd2ROLE_SINGLE_DAMAGE"decrease the target's elemental resistance"
BOPT_00003elemental_superiorityelemental_superiorityadd3ROLE_SINGLE_DAMAGE"increase elemental superiority (the matrix edge amplified)"
BOPT_00004raw_damagedamage_magnitudeadd4ROLE_SINGLE_DAMAGE"raw damage"
BOPT_00005crit_chancecrit_chanceadd5ROLE_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.

9.3 Lane B options — Josh's transformative seeds, verbatim

POOL_0002 — Fire Bolt ("Fireball → three fireballs instead of one · AOE explosion on hit ·

cast while moving"):

option_idbonus_kindeffect_attributestack_opbuild_definingJosh's words
BOPT_00010projectile_multiplyprojectile_countoverridetrue"three fireballs instead of one"
BOPT_00011aoe_on_impactrange_classenum_settrue"AOE explosion on hit"
BOPT_00012cast_while_movingcast_patternenum_settrue"cast while moving"

POOL_0003 — Tremor Stomp ("Earth Tremor → brief stun · randomized earthen-wall segments

circling the player · brief mobility surge"):

option_idbonus_kindeffect_attributestack_opbuild_definingJosh's words
BOPT_00013stun_addstatus_effectsaddtrue"brief stun"
BOPT_00014construct_ringpersistence_classenum_settrue"randomized earthen-wall segments circling the player"
BOPT_00014bconstruct_ringphysical_properties_arrayaddtruethe same wall-ring's §5G.2 Earth-construct properties — two rows, one option group
BOPT_00015mobility_surgemovement_speedmulttrue"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.)

9.4 Role axes — §14A.1's six seeds + the Tier-C terrain role

role_axis_idscope_classfunction_classarenataxonomy_status
ROLE_GROUP_SUPPORTgroupsupportbothseed
ROLE_GROUP_HEALgrouphealbothseed
ROLE_GROUP_DAMAGEgroupdamagebothseed
ROLE_SINGLE_SUPPORTsinglesupportbothseed
ROLE_SINGLE_HEALsinglehealbothseed
ROLE_SINGLE_DAMAGEsingledamagebothseed
ROLE_GROUP_TERRAINgroupterraintier_c_raidseed

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.

9.5 Spec purposes — §5I.2 / Combat §14 seeds

purpose_idfunction_classscope_classrole_axis_refsource
SPEC_VRIL_HEAL_PERSONALhealsingleROLE_SINGLE_HEAL§5I.2 verbatim derivation
SPEC_VRIL_HEAL_AREAhealgroupROLE_GROUP_HEAL§5I.2 verbatim derivation
SPEC_VRIL_DAMAGE_PERSONALdamagesingleROLE_SINGLE_DAMAGE"vril-HEALING focus vs vril-DAMAGE focus"
SPEC_VRIL_DAMAGE_AREAdamagegroupROLE_GROUP_DAMAGE"PERSONAL vs AREA-OF-EFFECT scopes"
SPEC_VRIL_REGEN_RATEresourcesingleROLE_SINGLE_SUPPORT"vril regeneration per second"
SPEC_HEAL_OVER_TIMEhealsingleROLE_SINGLE_HEAL"healing over time"

9.6 Composition rules — the seed set

rule_idrole_axis_refinput_kindcomparatorprecedence_rank
RCR_001*(all)*measured_role_vectorvector_dominant1
RCR_002*(all)*spec_purpose_sharemax_share2
RCR_003*(all)*role_tag_sharemax_share3
RCR_004group axes onlyally_role_fillshare_above_threshold4

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.

---

10. MIGRATION NOTE — additive-only; every default reproduces current canon

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):

precedent path) — 12 → 25 jointly with Family B's eight (n5; one arithmetic, §8.2).

(WS_043, WS_044) — 17 → 21 jointly with Family B's WS_045, WS_046.

stub_superseded: unchanged.

Every default reproduces the ruled economy exactly:

defaultreproduces
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 = NULLno 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 = proficiencypool 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 = NULLno 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 = falseno build-identity concept exists today; nothing changes until authored
lifecycle = active, superseded_by = NULLtoday's implicit state
string_status = placeholdercorrect 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-baselinecheck_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.

11. THE CROSS-FAMILY CONTRACT — reconciled, with the owner named for each half

*(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 thingOWNER (authoritative)CONSUMER
power_source_enum (§2.4)Family AB's T0_Imprint_Affix, T0_Ally_Behavior_Policy, T0_Rarity_Grade, T0_Status_Table carry the column (M4)
lifecycle_enum + superseded_byFamily Athe same four B tables (M4)
string_status_enum (+ voice_register_refT0_Voice_Registry.voice_id)Family Aevery 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 AB's role_tag / role_axis_ref are FK columns, not enums (M3)
the purpose_id keyspace (T0_Spec_Purpose_Registry)Family AB'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 BA'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 BA holds loadout_set_id as a key only (M1, m1)
bonus SELECTION state (WS_043)Family AB's bonus_pick_refs[] is a derived read, not a stored copy (M1)
the WS_043-WS_046 allocationallocated once, §6.0both
the tuning firewall + T0_Balance_Constant_Registry deferred addressstated 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 quartetFamily AB'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.2both (n5)

One shared vocabulary is the load-bearing part; thirteen tables landing with divergent

vocabularies is the unrecoverable outcome.

---

RECONCILIATION RECORD (2026-07-27)

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.

MAJOR

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_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.

(+ 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).

targets; 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).

MODERATE

option; A mints no such column, and the axis is derivable sweep-side from bonus_kind /

effect_attribute if it is ever wanted.

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.

+-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.

additions 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).

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).

Equipment column arithmetic and the 7-vs-8 assetgen form; the affix-side mythic firewall twin,

cross-referenced from §2.1 here).

MINOR

12 → 25, added_rows[T0_Worldstate_Variables/Sheet1] 17 → 21.

CONTESTED — director

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.

Generated by harness/site/structure_site.py — the URL path is the repo path. review root