MINT_DESIGN_B_ITEM_ALLY_2026-07-27.md

pipelines/MINT_DESIGN_B_ITEM_ALLY_2026-07-27.md

MINT DESIGN — FAMILY B: THE ITEM + ALLY HOMES

Schema design only. READ-ONLY run — nothing in C:/dev/humanity-forgotten or C:/dev/Humanity/Humanity

was modified; this file is the sole write. Canon HEAD ab5d32c.

Scope: the concrete data homes for addendum §§7-12 as integrated at T1_Combat_System_Spec §§12-15,

T1_Ability_Tree §5H/§5I/§14A, T1_Integrity_Paths_Worldstates_Master §8.11.5-.9, and

T1_Tier_C_MMO_Spec §8.7-.9 — restricted to FAMILY B: the gear-imprint lane, loadout sets, the ally

homes, boss timing/feedback on the attack rail, and the status grid.

Lens inputs consumed (SURVIVES verdicts + refuter corrections binding; KILLED findings not resurrected):

p1a_bl_loot_engine.md (F1,F2,F4,F5,F6,F7,F8,F9,F10,F11 survive · F3 KILLED — the acquisition-σ

vs roll-quality-σ split is a false premise, §13.2 names acquisition outright; its RESIDUE (quality

windows have no fields) is carried into T0_Rarity_Grade/T0_Imprint_Affix and not as a sigma

disambiguation) · p1a_creature_collection_ally_ai.md (1-9 all survive, 4 corrections applied) ·

p1a_sekiro_timing_defense.md (F1-F8 all survive; F2's i-frame recommendation is a **system-canon

change routed to the rank-18 Josh brief** and is NOT designed here) · p1a_dqpm_turn_readability.md

(F1,F2,F3 survive; F4,F5,F6,F7 killed — the rank-16/20 residue stays out; only F1's status read

columns and F2's read_persistence co-freeze here).

---

0. THE HOUSE MECHANICS THIS DESIGN OBEYS

0.1 THREE landing vectors, all gate-safe, all already precedented (reconciled M6 — the first

draft had two, and three of its five extension targets were on the wrong one).

docs/fidelity_baseline.json added_registries (12 registries already landed this way:

T0_Rune_Registry, T0_Flora_Registry, T0_Minigame_Registry, T0_Gather_Node_Registry, …),

registered in docs/fk_spec.json with a PK, an id_formats pattern + min_values floor, and

its FKs. This is the vector docs/registry_extensions.json _deferred.familiar-bond-ladder

already names for the bond ladder ("a bond_abilities child table … to be registered in

docs/fk_spec.json once minted").

reference width, declared in docs/registry_extensions.json under a named owning system AND in

docs/fidelity_baseline.json added_columns, content pinned by extension_hashes.

harness/check_registry_extensions.py enforces I1/I2/I3 (no phantom column, exactly one owner,

no ownerless manifest key). **Vector B applies only to a registry that HAS a frozen _source

reference width** — verified targets in this design: T0_RNG_Drop_Table, T0_Chapter_Index,

T0_Creature_Roster.

fidelity_baseline.json candidate_header and re-pin it; **no added_columns entry and no

extension_hashes key**. Verified this pass:

`stub_superseded = { T0_Boss_Encounter_Registry/Sheet1, T0_Familiar_Registry/Sheet1,

T0_Questline_Index/Sheet1, T0_School_Registry/Sheet1, T0_Weapon_Registry/Sheet1 }`, none of them

in added_columns and none in the 19 extension_hashes keys.

check_registry_extensions.py L59-69 handles them on a separate path: when a manifest key has no

added_columns, it is satisfied only if every manifest column appears in

stub_superseded[key].candidate_header. So the correct landing edit for defensive-properties

(Weapon, §4.2), ally-build (Familiar, §3.4) and counter-coverage (Boss_Encounter, §4.1) is

the candidate_header + its pin — NOT the added_columns story §6.2 first told.

to exceed, so adding columns to it is free and it declares no manifest key. Verified: not one

of the 12 added_registries carries a manifest key today (the extensions manifest holds 18

keys, none an added registry), and I3 fires immediately on a key with neither added_columns nor

a stub_superseded entry: `{"rule": "I3", "key": key, "detail": "manifest key has no

added_columns and no stub_superseded entry ..."}`. The first draft would have turned the gate RED

on two keys — the imprint-loot group on T0_Rune_Registry (§1.5) and the

assetgen + sfx-pipeline groups on the new T0_Equipment_Registry (§1.4). **Both are dropped:

the columns still land, the manifest keys do not.** (Family A gets this right by construction and

says so — it adds zero columns to any existing registry.)

0.2 §5H.4's ruling, applied. "Per-ability tier-bonus rows land on the T0_Ability_Tree_Registry

extension rail rather than as new columns on the base row." Family B reads that as the general

law: new structured canon is ROWS in a child table, not a widened base row. Vector B is used only

where the fact is genuinely one-per-existing-row (a weapon's defensive_class, a creature's

status_immunity, a drop row's sigma_window_length) — never to hold a one-to-many set.

0.3 Id formats. House patterns are <PREFIX>_\d{3,4}, PK column <thing>_id, uppercase prefix

(WPN_\d{3}, CR_\d{4}, FAM_\d{2}, RN_\d{4}, MG_\d{4}, GN_\d{4}, FL_\d{4}, FR_\d{4}).

Every new table below follows it, and every one is registered with a min_values floor so a silent

mass-emptying fails the gate (the F4/F5 hardening rule already in fk_spec.json).

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

*(Reconciled M8. This block is verbatim-identical to §0 of mint_design_A_build_space.md. If the

two ever diverge, they are not two firewalls — they are one broken one. The first drafts collided

twice: one column name magnitude_ref with two contracts, and each design's stated firewall

stricter than its own tables.)*

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. Family B's magnitude_ref was "string |

Phase-5M placeholder key" with no target; it now takes Family A's target.

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.

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 — this is

the honest statement of what §4.1 already does; the first draft's blanket "every magnitude is

ORDINAL or DEFERRED" and that table disagreed in writing.

Shapes and relation classes freeze now; numbers land at Phase 5M / 5H per

T1_Combat_System_Spec §12's "Schema and Numerical Deferral" and §15's sweep charter.

0.5 Player-facing strings — Family A's treatment ADOPTED (reconciled M4). Every column that

renders to a player carries the suffix _display or _text and is authored BLANK. The marker is

string_status — Family A's enum (placeholder DEFAULT → authoredvoice_passed), which

doubles as the natural-voice pipeline's worklist query — not the `voice_status =

pending_natural_voice` marker this design first declared and then carried in none of its tables.

Every table below with an FText column carries string_status; the tables whose strings are

voiced lines also carry voice_register_refT0_Voice_Registry.voice_id. Per

docs/NATURAL_VOICE_DOCTRINE.md §5 (THE NATURAL-VOICE REWRITE PASS) no system-voice string is

invented in this design. Per docs/REGISTRY_ROW_STRUCT_SPEC.md §2 rule 2 those columns infer to

FText and enter the localization flow; machine tokens (*_id, *_ref, *_class, *_tag) stay

FString and must never carry display text — note the precise mechanism (n1): *_class is in rule

2's EXCLUSION set while *_token is simply never MATCHED and falls through to rule 7 (FString).

0.6 Seeds are FIRST ROWS, never ceilings. Josh's verbatim addendum examples are mapped onto the

first authored rows of each table. Every pool-bearing table carries an examples_not_limits note in

its notes cell and in the DOC_MAP entry, per addendum §12's closing rule and §5I.1's

"a pool offering one real choice with filler beside it is not a pool."

0.7 What Family B does NOT own (stated so the mint does not double-author): tier-bonus pool rows

themselves (§5H.4 rail — Family A); the role-axis and spec-purpose ROSTERS (Family A's

T0_Role_Axis_Registry / T0_Spec_Purpose_Registry — this design CONSUMES them by FK, M3); the

boss-row pip columns pip_fill_event / pip_wipe_event / pip_neutral_event / chain_scope

(sekiro F1 → rank 16); hitzone_parts carve keys (the rank-16 hitzone lane — corrected M5:

this is NOT sekiro F7; F7 is the Ch-2 ParryOnly-scope finding, which this design carries as gate

assertion 1 in §4.1 and correctly calls "the F7 tooth"); tell_shape_class

counter-class-partition tooth (dqpm F3 → rank 16, though the tell_shape_class COLUMN lands

here on the attack rail so rank 16 has something to partition); the ally party-frame UI and bark

class (rank 22); T1_UI_UX_Spec (rank 20).

Two SURVIVING sekiro findings deferred WITH a recorded owner (reconciled M5). The lens-input

line asserts F1-F8 all survive; two were then neither designed nor deferred, and a survivor may be

deferred but may not be silent:

pips; canon says 5 / 7 / 9+", re-classed UPWARD by the refuter (*"F8 — understated. Re-classed

WEAKER → WEAKER + MISSING, LOW → MEDIUM-HIGH: the player HUD pip strip never reads a boss actor's

pips at all"*). Owner: the HUD / pip lane (rank 16), alongside F1's pip_fill_event columns

it is the twin of. Not owned here, and no attack-rail column presumes a cap.

consumers. Owner: the SFX consumer lane.** §4.1's telegraph_sfx_id_ref is F3's INCOMING-class

sting and is explicitly *not* F6's deflect-feedback channel; the two must not be conflated when

the SFX lane lands.

---

PART 1 — THE GEAR-IMPRINT LANE (addendum §8 · Combat Spec §13)

1.1 T0_Rarity_Grade — the shared grade PROPERTY table (NEW registry · 24 columns)

Why it exists. bl-loot F5 SURVIVES-STRENGTHENED: three live registries run three different

rarity_class vocabularies (T0_Rune_Registry {common 8, rare 3, epic 5, legendary 2, none 1},

T0_Flora_Registry {common 18, uncommon 4, rare 2, signature 1}, T0_Mineral_Registry {common 10,

uncommon 6, rare 3}), a FOURTH is spec'd in T0_Schema_Dictionary L958 for T0_Creature_Roster

(common, uncommon, rare, legendary, mythological), and T0_Weapon_Registry has no rarity column at

all — so RN_0018's ratified 1/2/3/4 slot scheme is not computable from data for any item. MYTHIC

is being added on top of that. One grade table with an explicit axis closes it.

RECONCILED M2 — the surrogate keyspace is GONE; this is a PROPERTY table, not a rival enum.

The first draft minted a new RG_\d{3} id space and re-pointed the live rarity_class columns at

it as FKs. That contradicts a binding refuter correction the design itself lists as an input:

Finding 8 — extend the existing rarity_class enum (which already carries none and
legendary), do not mint a parallel item_rarity; reconcile Flora's and Mineral's divergent
vocabularies in the same pass. — p1a_creature_collection_ally_ai.md L1020-1022

The reconciled shape satisfies bl-loot F5 (a grade table, FK-able, so imprint_slot_count /

obtainable_by_roll / the read channels get a home) and creature F8 (no parallel id space,

no live cell moved) simultaneously:

of the live vocabularies: none · common · uncommon · rare · epic · legendary ·

mythic · signature. mythic is the one token no live cell carries; uncommon

(10 live cells: Flora 4 + Mineral 6) and signature (1, Flora) are already in the data and

any ladder that omits them is broken by construction. *(Re-counted programmatically this pass —

Flora 25 rows {common 18, uncommon 4, rare 2, signature 1}, Mineral 19 {common 10, uncommon 6,

rare 3}, Rune 19 {common 8, epic 5, rare 3, legendary 2, none 1}; the critic's "11 uncommon"

over-counted by one. 11 cells in total had no legal value under Family A's first-draft enum.)* Family A cites this ladder and mints no rarity enum of its own.

docs/fk_spec.json: T0_Thread_Grid keys "primary_key": ["thread_id","chapter_id"], so the

composite is an exercised house shape, not an extension of the checker.

(axis, rarity_token) pair declared for it — the range_id/capability_ref _note idiom.

Parent / relation. Standalone shared dimension, referenced by token:

T0_Rune_Registry.rarity_class · T0_Flora_Registry.rarity_class ·

T0_Mineral_Registry.rarity_class (all axis=item_grade, all resolving today with zero cell

edits) · T0_Imprint_Affix.rarity_token_min · T0_RNG_Drop_Table.rarity_class ·

T0_Equipment_Registry.base_rarity_class · WS_046.rarity_class · and Family A's

T0_Bonus_Pool_Registry.grade_ceiling / T0_Bonus_Option_Registry.rarity_class at

axis=pool_option.

Key. composite PK (axis, rarity_token); id_formats.rarity_token = the closed 8-token

alternation, min_values floor 6 at landing. No RG_ ids exist anywhere.

columntypeenum / FKrequired
axisenumitem_grade · pool_option · creature_spawnyes (PK part 1)
rarity_tokenenumnone · common · uncommon · rare · epic · legendary · mythic · signaturethe shared ladder, stated onceyes (PK part 2)
ordinalint— (rank within axis; the ordering both families read; not a magnitude)yes
display_name_textFTextblank → natural-voice pass
string_statusenumFamily A's string_status_enum: placeholder (DEFAULT) · authored · voice_passed (M4)yes
power_sourceenumFamily A's power_source_enum (M4) — DEFAULT blank on the grade axis; carried so every effect-bearing §§7-12 row shares one vocabulary and defect D8 source_dominance can computeno
lifecycleenumFamily A's lifecycle_enum: active (DEFAULT) · deprecated · retired (M4)yes
superseded_byself-ref(axis, rarity_token) of the successor grade (M4)no
imprint_slot_countint— (RN_0018: 1/2/3/4)on axis=item_grade
ability_countint— (GDD §12.1: 0/1/2/3/4)nullable — see OPEN-1
name_rule_refstringnaming-ladder key (military-rank → generals → war-heroes)nullable
unique_per_typebooldefault FALSE
obtainable_by_rollboolyes (the MYTHIC tooth)
gate_kindenumnone · questline · mode · bothyes
gate_refFKT0_Questline_Index.questline_id \difficulty-tier tokennullable
roll_window_ordinalint— (F3-residue: the "better windows" band; magnitudes 5M)on axis=item_grade
quality_distributionenumuniform · centered · top_weightedon axis=item_grade
shape_tokenstringthe COLOUR-INDEPENDENT read glyph keyyes
colour_refstringpalette key (never the sole channel)nullable
pickup_sfx_id_refFKT0_SFX_Registry.sfx_idnullable
beam_vfx_refstringVFX keynullable
card_layout_refstringUI layout key (rank-20 consumer)nullable
source_refstringcanon citationyes
notesstringincl. examples_not_limits

Seed rows (the ratified ladder, verbatim-mapped).

PK (axis, rarity_token)ordinalimprint_slot_countobtainable_by_rollgate_kindsource
(item_grade, common)11TRUEnoneRN_0018; §13.1
(item_grade, rare)22TRUEnoneRN_0018; §13.1
(item_grade, epic)33TRUEnoneRN_0018; §13.1
(item_grade, legendary)44TRUEnoneRN_0018; §13.1
(item_grade, mythic)54FALSEquestline§12 "never produced by a drop table or an imprint roll"; §5I.4
(creature_spawn, legendary)FALSEnoneCVD §17.12 firewall (33 species / 22 slots)

ability_count is authored BLANK on all six pending OPEN-1.

Two further landing rows the reconciliation requires, both free: (item_grade, uncommon) and

(item_grade, signature) — the 11 live Flora/Mineral cells that Family A's first-draft ladder

could not express. Ordinals interleave without touching the ratified 1/2/3/4 slot scheme:

uncommon sits between common and rare and carries imprint_slot_count BLANK pending OPEN-1

(the 4-vs-5 grade question is exactly this row), signature is obtainable_by_roll = FALSE and

unique_per_type = TRUE. Neither invents a value: both tokens are already in the data.

The axis=pool_option rows Family A reads are authored in the same landing, one per token in use.

Consumer. the imprint foundry (slot count per item) · T0_RNG_Drop_Table (which grade a row may

emit) · the §15 build-space sweeps (grade ceiling per pool option) · rank-20 UI (the read channels) ·

the loot-read audio/VFX pipeline.

Gate / tooth additions.

"primary_key": ["axis","rarity_token"] (the T0_Thread_Grid precedent) +

id_formats.rarity_token (FULLMATCH alternation over the 8 tokens, min_values 6) +

foreign_keys. Entry shape per the verified live schema (n2): every FK object carries column /

references_registry / references_tab / references_column / min_tokens, plus

multi_value_separator on delimited columns and _note where the axis constraint is documented

rather than encoded.

(a) no row in T0_Familiar_Registry or T0_Creature_Roster carries an axis=item_grade value;

(b) mythic never appears in any creature-side column;

(c) no T0_RNG_Drop_Table row references a grade whose obtainable_by_roll=FALSE

this turns §12's prose invariant into a gate-able fact;

(d) every populated rarity_class cell across Rune/Flora/Mineral resolves to a rarity_token

at axis=item_grade (the creature-F8 reconciliation half, now satisfiable because the ladder

carries uncommon and signature);

(e) the affix-side twin of (c) (m9): no T0_Imprint_Affix.rarity_token_min names a grade

with obtainable_by_roll = FALSE unless the row carries 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. Family A's T-A4 clause (b) is the pool-side twin of the same guard;

(f) every referencing column resolves against the (axis, rarity_token) pair declared for it —

item columns to item_grade, Family A's pool columns to pool_option, creature columns to

creature_spawn. This is what keeps one token vocabulary from becoming three by drift.

Zero-token, permanent. Positive control: the creature-collection lens confirmed

grep -rn "rarity" harness/*.py docs/fk_spec.json = 0 today, so this gate is genuinely unbuilt.

OPEN-1 (surfaced, NOT ruled here — numerical canon, routes to the rank-18 bundled brief).

docs/original_predclaude/extracted/GDD_Humanity_Game_Complete.md §12.1 authors a FIVE-grade

ladder at ability-counts 0/1/2/3/4 with UNCOMMON present and a naming rule (military-rank → generals

→ war-heroes); the ratified scheme (RN_0018, §13.1) is a FOUR-grade ladder at slot-counts 1/2/3/4

with UNCOMMON dropped. The M2 reconciliation does NOT pre-empt this ruling: the uncommon

TOKEN must exist because 10 live Flora/Mineral cells already carry it (firewall class (d) cannot

pass otherwise), and its imprint_slot_count is authored BLANK — whether uncommon confers a

slot rung is precisely question (a), and it stays Josh's. Provenance: docs/original_predclaude/INGEST_GDD.md L141 (RECOVERED-NEW),

work order L185, queued in ledger 2026-07-24q, absent from the ranked 30. Two questions: (a) four

grades or five; (b) is ability_count the same axis as imprint_slot_count or a second axis on one

grade. The schema above is deliberately neutral on both — resolving either is an additive ROW

edit (insert an uncommon row, shift ordinals, populate ability_count), never a schema change.

---

1.2 T0_Imprint_Affix — the rollable affix definitions (NEW registry · 26 columns)

Why it exists. bl-loot F2 SURVIVES (mechanism refuted, schema gap real): RN_0018 fixes slot

COUNTS and nothing types a SLOT. Four untyped slots drawing one flat pool make "four copies of one

affix" and "four freely-stacking best-in-slot affixes" legal by schema; the §15 sweeps would find it

*after* the freeze. docs/proposals/systems/combat-and-spellcraft.md §C5 L330 shows the affix pool

is an unruled Josh item that fell out of the queue — RN_0018 ratified source, slot counts and the

re-roll model but NOT the pool. bl-loot F9 SURVIVES: per-class enumerated pools are an authoring wall

(72 weapons × 12 tiers alone ≈ 864 pools), and the answer is an eligibility PREDICATE, evaluated by

the shipped ConditionExpr engine (docs/CONDITION_EXPRESSION_GRAMMAR.md [ACTIVE v1.0] +

harness/condition_expr.py + Source/Humanity/Public/Quest/ConditionExpr.h) — an existing evaluator

with a new operand set, not a new architecture.

Parent / relation. Child of T0_Rune_Registry — the enchantment lane, anchor RN_0018

(rune_lane = enchantment). NOT the operator lane (RN_0016/RN_0017), never conflated (§13 opening).

Id format. affix_id = IMP_\d{4}. min_values floor set at the landed row count.

columntypeenum / FKrequired
affix_ididIMP_\d{4}yes (PK)
affix_name_textFTextblank → natural-voice pass
string_statusenumFamily A's string_status_enum, DEFAULT placeholder (M4)yes
rune_anchor_refFKT0_Rune_Registry.rune_id (RN_0018)yes
slot_axisenumper-family, closed: edge · haft · binding · pommel · barrel · stock · sight · weave · ward · lining · vessel · reagent · fuseyes
applies_to_tagsdelimited listpredicate operands: weapon_class · weapon_subclass · damage_type · element · equip_slot · item_class · trade · alignmentyes
excludes_tagsdelimited listsame vocabularynullable
eligibility_exprstringCONDITION_EXPRESSION_GRAMMAR expression (the reuse)nullable
conflict_groupstringtwo affixes in one group never co-roll on one itemnullable
stack_ruleenumunique · additive · diminishingyes
exclusive_with_refsdelimited listFK → T0_Imprint_Affix.affix_idnullable
rarity_token_mintoken FKT0_Rarity_Grade.rarity_token @ axis=item_grade (M2 — no RG_ surrogate)yes
bonus_axisenumdamage · resistance · crit · resource · timing_window · utility · procyes (sekiro F4)
spec_purpose_refFKT0_Spec_Purpose_Registry.purpose_id (Family A owns the roster — M3). The six seeds resolve directly: SPEC_VRIL_HEAL_PERSONAL · SPEC_VRIL_HEAL_AREA · SPEC_VRIL_DAMAGE_PERSONAL · SPEC_VRIL_DAMAGE_AREA · SPEC_VRIL_REGEN_RATE · SPEC_HEAL_OVER_TIMEnullable
role_axis_refFKT0_Role_Axis_Registry.role_axis_id (Family A owns the roster — M3): ROLE_GROUP_SUPPORT · ROLE_GROUP_HEAL · ROLE_GROUP_DAMAGE · ROLE_SINGLE_SUPPORT · ROLE_SINGLE_HEAL · ROLE_SINGLE_DAMAGE (+ ROLE_GROUP_TERRAIN, Tier-C)nullable
power_sourceenumFamily A's power_source_enum, DEFAULT gear_imprint (M4) — the column defect D8 source_dominance needs to see the gear side at allyes
lifecycleenumFamily A's lifecycle_enum, DEFAULT active (M4)yes
superseded_byself-FKT0_Imprint_Affix.affix_id (M4 — deprecate-never-delete, combinatorial F9)no
roll_scale_classenumflat · scaling · binaryyes
roll_window_overrideJSON blob{rarity_token: [min_ord, max_ord]} — exceptions only (M2: keyed on the shared token, not a retired RG_ id)nullable
lockablebool— (the ~5-re-roll lockable-affix floor)default TRUE
hand_authored_overrideboolsignature/bespoke affix, exempt from predicate derivationdefault FALSE
magnitude_refrefT0_Balance_Constant_Registry.constant_id — Family A's target, one column name one contract (M8)blank at landing
care_firewall_flagenumnone · review (mirrors T0_Rune_Registry)default none
source_refstringcanon citationyes
notesstringincl. examples_not_limits

Seed rows (Josh's verbatim §C5 seeds + the GDD's authored typed-pool axis).

affix_idname (blank, voice-pass)slot_axisapplies_to_tagsbonus_axissource
IMP_0001fire-affix grenadevesselitem_class=grenadedamagecombat-and-spellcraft §C5 (Josh seed)
IMP_0002homing weapon-enchantedgeweapon_class=*utility§C5 (Josh seed)
IMP_0003lifesteal poisonreagentitem_class=poisonresource§C5 (Josh seed)
IMP_0004chain-lightning bombfuseitem_class=bombproc§C5 (Josh seed)
IMP_0005catch-window widthbinding`defensive_class=parry\catch`timing_windowCombat Spec §12 Lane-A named exemplar

IMP_0005 is deliberately the fifth seed: §12's own named bonus kind ("catch-window width on the parry

weapons") is unauthorable until §1.7's weapon defensive_class exists — the two land together.

Reuse anchor recorded (bl-loot F9 refuter): Josh's GDD §12.1 already authors a typed pool axis —

"four good and four evil weapon abilities available for that weapon type" — the first

authored applies_to_tags[] instance, a (weapon_type × alignment) partition. The seed axis set is

harvested from there and from weapon_subclass, not invented.

Consumer. the imprint foundry (roll resolution) · T0_RNG_Drop_Table (payload) ·

T0_Equipment_Registry / T0_Weapon_Registry (slot_axis_set match) · **the §15 build-space

sweeps** — a pool is a QUERY over this table (pool_ref derived, never stored), which is the only

shape under which the "never-picked pool option = balance defect" tooth is cheap; the sweeps key

affix_id as a subject_ref on the per-option scorecard rows and populate keep_rate there

— combinatorial F7's rolled-layer analogue of pick share, which neither design carried before

reconciliation (m3; Family A §7.5 is the home) · rank-20 UI.

Gate / tooth additions.

T0_Rune_Registry.rune_id, FK rarity_token_minT0_Rarity_Grade.rarity_token (with the

axis=item_grade constraint in the _note), FK role_axis_ref

T0_Role_Axis_Registry.role_axis_id and FK spec_purpose_ref

T0_Spec_Purpose_Registry.purpose_id (Family A's registries, M3), FK

exclusive_with_refs (multi-value, self-referential, min_tokens at the landed count).

eligibility_expr parses under harness/condition_expr.py (reuse the shipped reference evaluator —

a malformed predicate must fail loudly, not silently match nothing: the

a-search-that-cannot-match-reports-zero class).

---

1.3 T0_RNG_Drop_Table — population schema + the imprint-loot extension group (10 added columns)

Why. bl-loot F4 SURVIVES: the ACTIVE T1_RNG_Sigma_Constraint_System §5 declares four consumer

fields "on every RNG-bound row"; the live 18-column header renames two (sigma_base_rate

base_rate_mean, sigma_reset_on_dropreset_condition) and is missing two

(sigma_window_length, sigma_constraint_enabled). Source/Humanity/Public/Data/RngDropTableRow.h

mirrors the CSV verbatim (18 columns, 0 rows at generation), so neither is first-class today (they

*could* ride the extensions JSON rail — the finder's "provably cannot read" was over-claimed — but

a runtime gating boolean read by three pipeline contracts belongs in a typed column). F10 SURVIVES

NARROWED: σ bounds each table, nothing bounds the aggregate; the budget must be scoped to ROLLED

events or it collides with the easter-egg hand-siting doctrine. F6 SURVIVES: mode_gate must be an

explicit enum, never a per-difficulty-tier roll multiplier (the ruled ladder's dial "is ONLY vril

density"). F7 SURVIVES-CORRECTED: the boss join already exists in reverse (linked_entity_id +

linked_entity_type) and rng_drop_anchor is the established anchor-column NAME on four registries —

do not mint drop_table_ref.

Vector B (columns, not rows) — justified: every one of these is exactly one value per drop row.

columntypeenum / FKdefault (reproduces current canon)
sigma_constraint_enabledboolTRUE (today's unconditional constraint)
sigma_window_lengthintordinal band; magnitude 5Mblank
drop_table_groupstringthe σ-counter SCOPE key (§8's per-drop-table rule made addressable — expressing the ruling, not re-ruling it)required on landing rows
acquisition_sourceenum**reuse the T0_Rune_Registry column NAME *and its live vocabulary* (m7): operator-library · crafted · crafted-and-bounded-drop · boss-drop · part-break-carve · easter-egg-hand-placed · milestone · quest-guaranteed · found-exploring · purchased. Reconciled: the first draft omitted operator-library — the DOMINANT live value (17 of 19 populated cells; crafted-and-bounded-drop ×1, blank ×1) — and mixed hyphen-case with snake_case inside one closed set. Reusing a column name means reusing its vocabulary, and no live cell moves, so hyphen-case wins for this column only**; every other enum in this design stays snake_caserequired
cadence_classenumambient · encounter · milestone · boss · hand_placedrequired
mode_gateenumnone · forgotten_onenone
rarity_classtoken FKT0_Rarity_Grade.rarity_token @ axis=item_grade (M2 — the shared ladder, no RG_ id)required
payload_refFKT0_Imprint_Affix.affix_id \T0_Equipment_Registry.equip_id \T0_Weapon_Registry.weapon_idnullable
payload_kindenumaffix · equipment · weapon · material · nonenone
part_refstringthe hitzone_parts part name this drop rides (§13.4 carve loop)nullable

linked_entity_id / linked_entity_type are hereby DOCUMENTED as the drop SOURCE binding (the

schema-dictionary entry is part of this landing) — payload_ref/payload_kind are the dropped THING.

The two were conflatable in an 18-column, 0-row table; they are not after this.

Invariants stated as data, not prose: `acquisition_source ∈ {easter-egg-hand-placed,

quest-guaranteed}sigma_constraint_enabled = FALSE` (§8's exemptions + §13.4's hand-siting);

cadence_class = hand_placed ⟹ counted for visibility, never gated by the cadence budget.

Seed rows — the first imprint-roll tables (per rarity, per §13.5 "imprint-roll tables per rarity").

drop_iddrop_table_groupacquisition_sourcecadence_classrarity_classpayload_kindsigma_constraint_enabled
DROP_IMPRINT_COMMONimprint_rollboss-dropbosscommonaffixTRUE
DROP_IMPRINT_RAREimprint_rollboss-dropbossrareaffixTRUE
DROP_IMPRINT_EPICimprint_rollboss-dropbossepicaffixTRUE
DROP_IMPRINT_LEGENDARYimprint_rollboss-dropbosslegendaryaffixTRUE
DROP_IMPRINT_CARVEimprint_carvepart-break-carveboss(per part)affixTRUE
DROP_IMPRINT_EASTERimprint_handeaster-egg-hand-placedhand_placed(per site)affixFALSE

No mythic row exists in this table by construction(item_grade, mythic) carries

obtainable_by_roll = FALSE and firewall class (c) fails any drop row that names it.

Each group is its own σ counter, so "a rarity tier's dry streak is bounded independently of any other

table" (§13.2) becomes computable. Note for the mint: the 9 populated

T0_Creature_Roster.rng_drop_anchor values (DROP_BIGGAME_HIDE_MEAT ×7, DROP_FISH_FLESH_ROE ×2)

are DANGLING against the 0-row table — the seed drop_id style above matches theirs so the

rank-26 population pass closes both dangles with one vocabulary.

Cadence budget (F10, scoped). rolled_reward_events_target as an **added column on

T0_Chapter_Index** (owner system imprint-loot), checked as a sum over drop rows whose

cadence_class is a rolled class. Authored placements (hand_placed) are counted for visibility and

never gated. The check is a sweep output, not a runtime — reported beside the §15

viability-breadth scorecard.

Consumer. the drop resolver (runtime) · the σ constraint system (per-drop_table_group counter) ·

the Phase-6 factory (per-boss/per-chapter rows, §13.5) · the sweeps (cadence sum).

Gate / tooth additions.

all ten columns + under T0_Chapter_Index/T0_Chapter_Index listing rolled_reward_events_target.

python harness/registry_fidelity.py --emit-baseline in the same commit (the standing rule).

REGISTRY_ROW_STRUCT_SPEC.md §5). sigma_constraint_enabled infers bool, sigma_window_length

int32, payload_ref/acquisition_source FString — no override needed.

---

1.4 T0_Equipment_Registry — the four unhoused imprint targets (NEW registry · 26 columns)

Why. bl-loot F8 SURVIVES-REFRAMED: §13 names five imprint targets — "weapons, armour, off-hand

items, grenades and bombs, potions and poisons" — and only weapons have a data home; off-hand rides

the 72 via §6's Sorcery Off-Hand Canonical Lock. No armour/consumable registry exists (verified

programmatically across all 40 registry dirs). REFRAME: the slot layout is **DESIGNED-UNBUILT with a

never-executed routing**, not missing — docs/original_predclaude/INGEST_GDD.md L144 recovers

"16 equipment slots (7 enhanceable element slots + 9 stat slots: glasses / earrings / armlets /

bracers / rings / gloves)" as RECOVERED-NEW with work order L188. "Armour" is the finder's word, not

canon's; the canonical framing is the recovered slot layout.

Id format. equip_id = EQ_\d{4}.

columntypeenum / FKrequired
equip_ididEQ_\d{4}yes (PK)
equip_name_textFTextblank → voice pass
string_statusenumFamily A's string_status_enum, DEFAULT placeholder (M4/§0.5)yes
equip_slotenumthe recovered 16-slot layout — 7 vril-seat element slots (seat_1..seat_7) + the 6 NAMED stat slots (glasses · earrings · armlets · bracers · rings · gloves) + unassigned_stat_slot ×3 placeholder — see OPEN-2yes
item_classenumwearable · offhand · grenade · bomb · potion · poisonyes
slot_axis_setdelimited listthe T0_Imprint_Affix.slot_axis values this base acceptsyes
base_rarity_classtoken FKT0_Rarity_Grade.rarity_token @ axis=item_grade (M2)yes
craft_trade_refFKT0_Trade_Registry.trade_id (Engineering / Alchemy)nullable
recipe_refstringrecipe key (recipe rows are a later lane)nullable
chargesintconsumables only; ordinalnullable
consumed_on_usebooldefault FALSE
element_enhanceableboolthe "7 enhanceable element slots" propertydefault FALSE
region_nativeFKT0_Region_Index.region_idnullable
canonical_chapter_acquisitionFKT0_Chapter_Index.chapter_idnullable
care_tierenummirrors the house care_tier vocabularynullable
mesh_id_refregeneration_trigger (8)the 8-column assetgen rail copied verbatim from the Creature / Character / Familiar / Boss form (which carries mesh_id_ref INSIDE the group), so the P2 AssetGen socket picks equipment up for free. Corrected m8: the T0_Weapon_Registry group is 7 columns — [mesh_pipeline_type, substrate_material_ref_path, mesh_tags, generation_status, generation_prompt_hash, last_generated_timestamp, regeneration_trigger] — because mesh_id_ref sits in Weapon's base header, not its group. A new registry has no base header to inherit it from, so the 8-column form is the right copy and the source is now namedper assetgen
equipment_sfx_id_ref_arraydelimited FK listT0_SFX_Registry.sfx_id (the sfx-pipeline group idiom)nullable
source_refstringyes
notesstringincl. examples_not_limits

Column arithmetic, corrected (m8). The first draft listed 16 domain columns and then reconciled

"15 + 8 + 1 = 24", which closes at neither end. The emitted header is 17 domain columns

(the 16 named above plus string_status from M4/§0.5) + 8 assetgen + 1 sfx = 26. A header

width is a freeze artifact, so it is stated once and it adds up.

Consumer. the imprint foundry (which slot_axis set a base accepts) · loadout sets (a set

references equipment instances) · the crafting lane (trade gates) · P2 AssetGen · the sweeps.

Gate / tooth. fk_spec.json entry (PK equip_id, pattern, FKs to Trade/Region/Chapter and the

token FK to T0_Rarity_Grade). **NO registry_extensions.json key is declared for this registry

(M6b).** The first draft added assetgen + sfx-pipeline manifest groups here; T0_Equipment_Registry

is a wholly-added registry with no frozen width, so those keys would carry neither added_columns

nor a stub_superseded entry and each would be an immediate I3 FAIL — verified: not one of the

12 added_registries carries a manifest key today. The assetgen and sfx columns still land as part

of the registry's own header; only the manifest keys are dropped.

OPEN-2 (surfaced, not ruled). The recovered layout names 9 stat slots and enumerates 6.

Three are unauthored detail. The enum above ships six named + three unassigned_stat_slot

placeholders so the count (16) is expressible without inventing three slot names. Routes with OPEN-1

to the rank-18 bundled brief; resolution is a row/enum-value edit, never a schema change.

---

1.5 T0_Rune_Registry — 2 added columns, NO manifest key (reconciled M6b)

The vector, corrected. T0_Rune_Registry is a wholly-added registry (it is in

added_registries), so it has no frozen reference width to exceed: adding columns to it is

free, it takes no added_columns entry, and it declares no registry_extensions.json key. The

first draft put an imprint-loot group on it, which would have tripped I3 and turned the gate RED

on the landing commit ("manifest key has no added_columns and no stub_superseded entry"). The

columns land exactly as designed; the manifest key does not exist.

Why. bl-loot F11 SURVIVES on the DENOMINATION half (the curve half is KILLED — §13.1 defers "the

exact re-roll cost curve" to Phase 5M, which is DESIGNED-DEFERRED, not a gap). No doc anywhere states

what a re-roll costs in; T0_Region_Index has no medium_of_exchange column, so the value

abstraction a numeric cost would need does not exist even in prospect. A scalar reroll_cost column

would bake the universal coin the economy ruling rejected, by omission. The reroll_model column

already exists on RN_0018 (cheap-rising-lockable-floor) — the denomination belongs beside it.

columntypeenum / FKdefault
reroll_cost_material_refsdelimited FK listT0_Flora_Registry.flora_id \T0_Mineral_Registry.mineral_idblank
imprint_affix_pool_refstringthe derived-pool query key over T0_Imprint_Affix (§10 pools apply to imprints too)blank

Denominating in materials is region-agnostic by construction under the no-universal-coin ruling,

routes the sink into the Engineering/Alchemy/Inscription trades RN_0018 already names as the lane's

source, and reuses the shipped spend primitive UHumanityGatherLedger::TryConsume(YieldsRef, Count)

a second caller, not a new economy.

Consumer. the re-roll transaction · the crafting lane · the sweeps (sink pressure).

---

1.6 The ITEM-INSTANCE rail — WS_036 inner shape + WS_046 (NEW worldstate row)

KEYSPACE NOTE (M1). This row was drafted as WS_043, which Family A also took. The
WS_043+ number space is now allocated ONCE, in mint_design_A_build_space.md §6.0 and
reproduced verbatim at §2.2 below: WS_043 bonus_selection_state (A) · WS_044
bonus_respec_ledger (A) · WS_045 loadout_set_state (B) · WS_046 item_instance_ledger
(B). The draft ids appear in no landed artifact.

Why, and why NOT a registry. bl-loot F1 SURVIVES with two evidence corrections. The doctrine is

per-object mutable state (rolled bonus, re-roll counter, locked-slot mask, owner) and every T0 registry

is a TYPE registry — but the finder's "no home exists anywhere" was wrong: T0_Worldstate_Variables

already carries WS_036 worn_rune_loadout (type object, default {}) and WS_035

spellcraft_authored_spells, already wired downstream (ws.worn_rune_loadout appears in

T0_Boss_Encounter_Registry BE_0015's ws_writes). The correct verdict is **the home exists and is

shapeless.** The registry's own convention is to spell the inner shape out inline in the domain

column (WS_008, WS_012, WS_019, WS_026, WS_027, WS_041 all do). **Do NOT mint a free-floating

T0_Item_Instance registry** — declare the rail as worldstate domains, per the refuter's correction.

Also corrected: the "only inventory-shaped runtime is the GatherLedger" claim is false —

Source/Humanity/Public/Quest/ConditionExpr.h:42 ships TSet<FString> Inventory (a key-FLAG

inventory, no object identity), read at ConditionExpr.cpp:569. The finding survives; the control

was wrong.

WS_036 worn_rune_loadout — declared inner shape (6 sub-fields).

`{ owner_kind (player|companion|familiar), owner_ref, instance_ref (→ WS_046 instance_id),

slot_index, affix_id (→ T0_Imprint_Affix.affix_id), locked (bool) }`

**WS_046 item_instance_ledger — NEW row (per the §6.0 allocation; the registry's max is WS_042).

15 sub-fields.**

sub-fieldtypeenum / FK
instance_ididII_\d{6} (runtime-minted)
base_type_refFKT0_Weapon_Registry.weapon_id \T0_Equipment_Registry.equip_id
base_type_kindenumweapon · equipment · consumable
rarity_classtoken FKT0_Rarity_Grade.rarity_token @ axis=item_grade (M2)
owner_kindenumplayer · companion · familiar · stash
owner_refFKT0_Character_Index.character_id \T0_Familiar_Registry.familiar_id \null
acquired_sourceenummirrors T0_RNG_Drop_Table.acquisition_source
acquired_chapterFKT0_Chapter_Index.chapter_id
reroll_countintthe ~5-re-roll lockable floor counter
sigma_seqintthe σ-counter sequence position of the roll that produced this instance, joined on T0_RNG_Drop_Table.drop_table_group (reconciled m3 — combinatorial F7's NET enumerates it, and without it the σ bound cannot be audited per instance; blank on non-rolled acquisitions)
locked_slot_maskintbitmask over slot indices
slot_rollsarray of objects{slot_index, slot_axis, affix_id, rolled_ordinal, roll_percentile, locked}
rolled_ability_refsdelimited FK listT0_Ability_Tree_Registry.ability_idthe GDD §12.1 requirement ("one/two/three/all four abilities assigned at random from the regional ability pool"; "two players using the same weapon type may have meaningfully different ability combinations based on what dropped for them")
unique_per_typeboolGDD §12.1 "only one legendary weapon per weapon type in the entire game"
departure_dispositionenumreturns_to_player · leaves_with_ally · player_level_unlock

departure_disposition is not free design spacedocs/spine/DECISIONS_PENDING_JOSH.md L38-40

records the applied interim three-way split verbatim: "intrinsic growth leaves with the ally, gear and

imprint items return per the departure contract, purchased 2nd/3rd loadout-set slots are player-level

unlocks that never depart (Integrity_Paths §8.11.6-§8.11.7)". The rail must express all three, not

just "returns".

Consumer. the inventory/Item-Rift runtime (the diegetic UI frame, T1_Ability_Tree L926, unlocked

Ch 15) · loadout sets (a set references *this rolled sword*, not "sword") · the departure-return

transaction (§8.11.6) · the re-roll transaction · save persistence.

Reuse-first. UHumanityGatherLedger stays the MATERIAL tally (stackable, no identity); this rail

covers only rolled/equippable objects. Two ledgers, two shapes, no overlap.

Recorded, not designed here: the Item Rift unlocks Ch 15, so the **Ch 2-14 slice — the AAAAA

slice — has no authored carry model at all.** That is a design gap for the factory/W10 lane, surfaced

by bl-loot F1 and unrefuted; it is not a schema question and is not resolved by this mint.

Gate / tooth. harness/check_ws_value_form.py — WS_036 and WS_046 domains must be extended in the

SAME commit, or every ws.worn_rune_loadout write becomes an unresolved-head finding. WS_046 must

also be added to the +-prefix legal set — an instance ledger is append/accumulate by nature. That

is a ruled-list edit, recorded as a required companion change rather than assumed.

The legal set's real size, verified this pass (m4 — corrected in both directions). The draft

said CG-25 names six append-legal object variables (WS_008, WS_012, WS_018, WS_019, WS_026,

WS_027); the critic read seven (adding WS_010) off a truncated first line of the constant. The

live constant holds TWELVE:

# harness/check_ws_value_form.py:116-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"})

with the reason at L112-115: *"EXTENDED 6->12 by Josh's ruling D-CG25-APPEND-SET (2026-07-24)"*,

the contract's CG-25 enumeration reconciled to the data in the same commit. **The landing edit is

therefore 12 → 14** (WS_044 from Family A and WS_046 here; WS_043/WS_045 are keyed-replace

objects and need no +), and the stale "six" in the L20 docstring is fixed in the same pass.

Standing lesson applied: read the constant, not the label — the label was wrong twice.

---

PART 2 — LOADOUT SETS (addendum §9 · Combat Spec §14 · IPW §8.11.6)

2.1 T0_Loadout_Set_Definition — the purchasable slot unlocks (NEW registry · 14 columns)

Why a table at all. The SETS' contents are runtime state (Part 2.2); what is authored canon is the

slot unlock: which set ordinals exist, what gates each, where quick-change is legal, and — per

§8.11.6's ratified reading — that the slots are **player-level unlocks that never depart with a

companion**. Three rows, and they carry the rules three runtimes read.

SOLE OWNER of loadout-set canon (reconciled M1/m1). Family A's draft restated the same fact as

WS_044 loadout_set_state {unlocked_count (int, DEFAULT 1, ceiling 3), active_set_index, …}

a double owner, and the weaker home: this table carries the unlock class, the gates, the venue

class, and the departs_with_companion = FALSE investment-protection invariant. **The ceiling is

the ROW COUNT of this table**, never a number restated elsewhere; A's unlocked_count /

active_set_index collapse into set_id + is_active on WS_045, and Family A keeps

loadout_set_id only as a key INTO that row, which is all its reachability classing needs.

Id format. set_id = LS_\d{2}.

columntypeenum / FKrequired
set_ididLS_\d{2}yes (PK)
set_ordinalint1 · 2 · 3 (canonical ceiling per §14; derived from the ruling's naming of a second and a third set — revisable at this schema pass, per the spec's own words)yes
unlock_classenumdefault · purchasedyes
unlock_cost_material_refsdelimited FK listT0_Flora_Registry.flora_id \T0_Mineral_Registry.mineral_id (no universal coin — same denomination rule as §1.5)nullable
unlock_gate_chapter_minFKT0_Chapter_Index.chapter_idnullable
unlock_gate_refFKT0_Questline_Index.questline_idnullable
owner_scopeenumplayer_level (fixed — the §8.11.6 ratified reading)yes
applies_to_alliesboolTRUE — "apply across whoever is on the bench"yes
departs_with_companionboolFALSE (fixed — the investment-protection invariant, stated as data)yes
switch_venue_classenumvril_recharge_zone · waterfallyes
switch_venue_refFKT0_Vril_Site_Registry.site_id (nullable = any site of the class)nullable
switch_in_encounter_allowedboolFALSE — derived from the siting rule, and the spec flags the derivation as revisable at this passyes
composition_kindsdelimited listgear · abilities · bonus_picks (§14: "its own gear, its own ability selection, and its own bonus picks")yes
source_ref / notesstringincl. examples_not_limitsyes

Seed rows.

set_idset_ordinalunlock_classswitch_venue_classdeparts_with_companion
LS_011defaultvril_recharge_zoneFALSE
LS_022purchasedvril_recharge_zoneFALSE
LS_033purchasedvril_recharge_zoneFALSE

Consumer. the build/loadout UI (W10 book screens — addendum §9's named owner) · the vril-site

interaction (HumanityVrilRechargeZone already ships as the actor) · the departure-return transaction

· the sweeps (a set is a build container the sweep enumerates over).

Gate / tooth. fk_spec.json entry (PK, pattern LS_\d{2} min_values 3, FK

switch_venue_refT0_Vril_Site_Registry.site_id, FK unlock_gate_chapter_min

T0_Chapter_Index.chapter_id). One invariant assertion: departs_with_companion is FALSE on every

row — a TRUE here would silently invert investment protection.

2.2 WS_045 loadout_set_state — NEW worldstate row (6 stored sub-fields + 1 derived)

THE WORLDSTATE KEYSPACE ALLOCATION — one table, allocated once (M1). *(Verbatim-identical to

mint_design_A_build_space.md §6.0. Both designs read the registry's max correctly as WS_042

verified, 42 rows, added_rows 17 — and both then took 043.)*

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, pool_id, from_option_id, to_option_id, cost_paid_ref, site_ref, refundable}
WS_045loadout_set_stateFamily Bno (keyed replace)below
WS_046item_instance_ledgerFamily Byes§1.6's 15 sub-fields

Stored: `{ owner_kind (player|companion|familiar), 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 (bool) }`

Derived, NOT stored (M1): bonus_pick_refs[] = the read of WS_043 filtered on

loadout_set_id = set_id. The draft stored them here while Family A stored the same selection

state under its own key — the selection-state shape was double-owned, which is worse than an id

clash. §14's "its own gear, its own ability selection, and its own bonus picks" is preserved by

T0_Loadout_Set_Definition.composition_kinds; what is removed is the second copy. One writer, one

home: Family A writes bonus selection, Family B writes gear + ability selection + is_active.

Companion parity is the same shape with owner_kind=companion — §8.11.6's "a companion has gear

slots, an ability loadout, the selectable minor and major bonus picks … and the purchasable second and

third loadout sets." No mirror table; one shape, an owner discriminator. That is what makes parity a

schema property rather than an authoring promise.

2.3 WS_028 extension — the return transaction (2 sub-fields)

WS_028 companion_loyalty_transition_events today carries `{character_id, event (DRAWN|WAVERING|

DEPARTED|REBONDED), chapter, integrity_at_event, rerouted_paths[]}`. Add:

returned_instance_refs[] (→ WS_046.instance_id) and retained_by_ally_refs[]. The DEPARTED event is

where the transaction lands (§8.11.6: "The return transaction rides the DEPARTED event at WS_028

beside rerouted_paths"). REBONDED returns the ally "as who they were" — spread/specialties/style

persist; re-equipping is the player's choice again, i.e. returned_instance_refs[] is not

auto-reversed.

Gate / tooth. check_no_dead_end.py already asserts every DEPARTED event carries a non-empty

rerouted_paths[]. Add the sibling assertion: every DEPARTED event whose ally held instances with

departure_disposition = returns_to_player carries them in returned_instance_refs[]. Same teeth

class, same script.

---

PART 3 — THE ALLY HOMES (addendum §12 · IPW §8.11.5-.9 · Tier-C §8.7-.9)

3.0 The stat-substrate reconciliation (creature-lens F1 — HIGHEST freeze relevance)

Two ACTIVE tier docs specify two incompatible six-stat vectors for the same entity:

T1_IPW §8.11.7 rules the canonical six attributes (Strength, Dexterity, Constitution, Agility,

Accuracy, Intelligence) with "No new attribute is minted for allies"; T3_Familiars_Named

§1.7 specifies the Garden six (Strength; Flight/Swim/Speed; Perception; Endurance; Bond; Specialty) —

no Intelligence — and that is the vector the Familiar Kindergarten, the per-stat training

minigames, and the sigma-bounded generational husbandry gains all key to. T0_Familiar_Registry's 40

columns carry zero stat fields, so neither vector has data today: this mint is the irreversible

moment.

The refuter's CORRECTION binds: the Garden scale has a second, non-ally consumer — §1.7's

husbandry loop runs on the 400-plus ordinary tameable roster owned by T3_Creatures_Tameable, not

on the 22 familiars. Collapsing the Garden six into "derived channels over the six attributes" would

drag the protagonist attribute roster onto 400+ ordinary creatures. **The designed shape is two

namespaced scales plus an explicit bridge on the 22 entities that sit in both:**

ally_stat_block      {str, dex, con, agi, acc, int}   # allies + familiars, per IPW §8.11.7
husbandry_stat_block {the Garden six}                 # creature-side, per T3 §1.7, sigma-bounded
garden_channel_map   channel_id -> ally_attr_expr     # the bridge the Kindergarten writes through
specialty_ref        role/spec tag, NOT a 7th stat

ally_stat_block lands on WS_012/WS_027 (§3.1, §3.2); husbandry_stat_block stays on WS_037

husbandry_menagerie_state; garden_channel_map is a small mapping declared in the WS_012 domain.

Suggested bridge seeds (the mapping is nearly free): locomotion → Agility; Endurance → Constitution;

Perception → a derived read over (Intelligence + Accuracy) preserving its vril-sight contribution;

Strength → Strength; Specialty → specialty_ref; Bond → its own non-attribute track (§3.2's

bond_value).

Required companion edit, flagged not applied: T1_IPW L725 records the defect as a *missing

reciprocal cite*, not as a rival vector, and supplies no mapping — so T3_Familiars_Named §1.7 and

T1_IPW §8.11.7 must stop specifying rival vectors in the living source at the same commit as

this mint (the source-docs-are-living rule). That is a DIRECTOR reconciliation, not an authoring task.

3.1 WS_027 companion_roster_state — the ally-build extension (10 added sub-fields)

§8.11.6 states it outright: "Persistence rides the per-companion roster object at WS_027 … which will

carry loadout state alongside the loyalty fields once the schema pass authors the columns; until

that pass lands, no consumer may read a loadout field on WS_027, because the field does not yet

exist." This is that pass.

sub-fieldtypeenum / FKdefault
ally_stat_blockobject{str,dex,con,agi,acc,int} — the canonical six, ally-sideauthored spread at join
ally_levelint1
stat_point_budgetintthe total spread points an ally may hold at ally_level — ordinal; the per-level grant CURVE is a Phase-5M magnitude and lands as a T0_Balance_Constant_Registry ref, blank until then (reconciled M9)blank
unspent_level_choice_pointsintthe player's level-up choice budget0
level_choice_logarray[{level, attribute, chapter}] — "the player makes the stat choices at each ally level-up"[]
derived_specialty_refsdelimited listDERIVED from the spread, never assigned (§8.11.7 property 2)derived
combat_style_refenumfrontline · precision · sustain · control · skirmish (seed set, examples-not-limits)derived
int_tierintordinal band on the twelve-tier numerical scale — the discrete band the behaviour tree selects onderived from int
equipment_influence_snapshotobjectthe §8.11.7 property-1 continuity: gear + imprints shift the profile without a respec{}
active_loadout_set_idFKT0_Loadout_Set_Definition.set_idLS_01

Discipline stated as schema: intelligence is a BUILD property, never an integrity property

(§8.11.8) — int_tier must never appear as an input to the loyalty arithmetic. The

loyalty_belief_axis / loyalty_departure_threshold fields are untouched by this extension, and the

gate below asserts it.

**THE §12 TRADEOFF IS SCHEMA-EXPRESSED, not just prose (reconciled M9 — the one §§7-12 ruling that

had no home in either family).** Addendum §12 rules it verbatim and mandatorily:

THE BALANCE TRADEOFF IS MANDATORY: "can't all be in intelligence or they won't be very
strong" — INT competes with the combat stats, so the player has to balance and customize per role.

As first drafted, nothing bound the six stats to a shared budget and no tooth asserted one: an ally

could be maxed in INT and in every combat stat, which makes the ruled competition unenforceable

and silently deletes the axis §10's build-space sweeps are supposed to vary

(unspent_level_choice_points is a spend counter, not a cap). stat_point_budget is that cap, and

the tooth is the ally-side twin of Family A's T-A12:

T-B1 (ALLY BUDGET COHERENCE). sum(ally_stat_block values) > stat_point_budget FAILs;
spent + unspent_level_choice_points must reconcile against the budget at ally_level; the
budget is blank-tolerant until Phase-5M sets the curve, and the tooth is armed the moment it
populates. Host: harness/check_ally_build.py (§3.5).

The ordinal is a ratified count, not a magnitude, so it sits inside the shared firewall's clause 2;

only the per-level grant curve defers.

3.2 WS_012 familiar_bond_state — the ally + slot-history extension (12 added sub-fields)

Today: `{familiar_id, bond_tier (approach|accepted|mastery), last_interaction_chapter, bond_quality

(realized|footprints|trace_only)}`, 99 writes across 38 nodes in the executed spine.

Creature-lens F2 SURVIVES-STRONGER: the deferred familiar-bond-ladder extension keys on a

5-rung bond_level (bond-formation / Bond-25 / Bond-50 / Bond-75 / Bond-100-Mastery = 110 rows)

while §8.11.5's ruled gating sentence names 3 values (approach, accepted, mastery). Two ACTIVE

canon artifacts specify different arities for the same gate. Creature-lens F3 SURVIVES: the Ch-58

recognition reads a slot-substitution history nothing records — slot_code (`W1..W7, G1..G7, F1..F7,

X22`) is STATIC identity, not runtime occupancy; there is no active-slot state anywhere.

sub-fieldtypeenum / FKdefault (back-compatible)
bond_valueintthe twelve-tier numerical scale, 0..200 (canon-grounded: §1.6 maps formation→Neophyte 1-9 … Bond 100→Philosophus 99 + Adeptus Minor 100, extending to Adeptus Major 101-150, Adeptus Exemptus 151-199, Magister Templi 200)derived from current bond_tier
bond_tierDERIVED viewapproach · accepted · mastery over bond_value thresholdsall 99 existing spine writes keep resolving unchanged
active_slotenumground · flying · water · path_variable · restingresting
slot_occupancy_roleenumprimary · sustained_baseprimary
first_bonded_in_slotboolthe "never replaced" recognition input (§1.2)TRUE at first bond
substitution_countintrotation-history depth0
abandonment_eventsint§1.8's permanent consequence, currently unrecorded0
ally_stat_blockobject{str,dex,con,agi,acc,int} — §8.11.7 "and familiars"authored at bond
stat_point_budgetintthe same §12 cap as WS_027, familiar-side — INT competes with the combat stats here too, or the ruled tradeoff has a hole exactly one entity class wide (M9); tooth T-B1blank
int_tierintordinal band (same scale as WS_027)derived
element_affinity_developedenumthe canonical eight-element roster (T1_Ability_Tree L25: five vril-seat + three trade-unlocked) — typed as the affinity a familiar develops toward, per §1.2's "Familiars do not possess vril capabilities at initial bond; vril-integration develops as the player teaches and imbues"blank
vril_integration_stateenumlatent · developing · integratedlatent

The Shell W1 case (from the kills-audit nuance, not assumed away). §6.1 closes: "Shell W1 is the

exception: as sustained-bond, Shell is always present when the Water slot is active. The other six

Water familiars rotate around Shell's always-present base." That reads as Shell occupying the

Water slot *alongside* a rotational water familiar — so active_slot cannot be a single-valued enum

per familiar without the companion flag. slot_occupancy_role is that flag. Whether the Water slot

can hold two occupants is a one-line confirmation the mint must make against §6.1 before landing;

the schema supports both readings, the data must state one.

Companion edit required at the same commit (creature-lens F2's added line). The deferred table's

5-value bond_level enum and §8.11.5's 3-value gating sentence must be reconciled **in the living

source**, or the mint hard-codes the contradiction into fk_spec.json. The design below carries BOTH

(bond_level enum for authoring + bond_threshold int for gating) so the reconciliation is a

living-source wording edit, not a schema migration.

3.3 T0_Familiar_Bond_Ability — the deferred bond_abilities table, minted (NEW registry · 15 columns)

Why now. docs/registry_extensions.json _deferred.familiar-bond-ladder has specified this table

and its COPY-ONLY discipline since it was registered; every one of the 22 T0_Familiar_Registry rows

carries a blank abilities_granted and a notes pointer to it. Addendum §11 names it outright

("the deferred bond_abilities table is this system's data home"); §8.11.5 and T1_Ability_Tree

§14A.3 both cite it as the home for the bond-gated capability grant.

Id format. bond_ability_id = BA_\d{4}. Shape: 22 familiars × 5 rungs = 110 rows.

columntypeenum / FKrequired
bond_ability_ididBA_\d{4}yes (PK)
familiar_idFKT0_Familiar_Registry.familiar_idyes
bond_levelenumbond_formation · bond_25 · bond_50 · bond_75 · bond_100_masteryyes
bond_thresholdintthe numeric gate on the twelve-tier scale (0..200), the computable left-hand side §8.11.5 lacksyes
ability_name_textFTextblank → voice pass
string_statusenumFamily A's string_status_enum, DEFAULT placeholder (M4/§0.5)yes
ability_effect_summarystringCOPY-ONLY from T3_Familiars_Named §2-§5 per-slot Abilities blocksyes
grants_classenumpassive · active · paired_operation · summon_ultimateyes
eam_pair_refFKT0_Ability_Tree_Registry.ability_id (the bond-gated EAM pairing availability, §8.11.5)nullable
element_affinity_requiredenumthe eight-element rosternullable
command_permissionenumnone · directed_with_trust_threshold · full — §1.4's integrity-gated command model, verbatim: L1/L2 "the player cannot override this behavior", L3 "can be directed to attack but with a trust threshold", L4/L5 "the player can attack with their familiar from the beginning of battle"yes
integrity_band_gateenumL1 · L2 · L3 · L4 · L5 (the §1.4 gate)nullable
path_variable_resolutionstringthe 22nd-slot path branch (§5.7)nullable
source_refstringCOPY-ONLY citation — no inventionyes
notesstring

Seed rows. COPY-ONLY from T3_Familiars_Named §1.6 (the rung→tier mapping) plus the per-slot

Abilities blocks (§2 W1-W7, §3 G1-G7, §4 F1-F7) and §5.7 (the path-variable 22nd slot). The extension

manifest's own words: "COPY-ONLY when minted — no invention." First authored rows are the W1 Shell

ladder, because §6.1's sustained-bond exception makes it the case that exercises both bond_level and

slot_occupancy_role.

Consumer. the bond-gate resolver · the EAM pairing availability check · the Ch-58 reunion

dispatcher · T1_Ability_Tree §14A.3 (familiar choice as an ability-build input) · the sweeps ("a

familiar whose bond ladder supports no viable build is a balance defect in the same sense that a

never-picked pool option is").

Gate / tooth. fk_spec.json: PK bond_ability_id, id_formats.bond_ability_id = BA_\d{4}

min_values 110, FK familiar_idT0_Familiar_Registry.familiar_id, FK eam_pair_ref

T0_Ability_Tree_Registry.ability_id. Coverage tooth (host: harness/check_ally_build.py,

§3.5 — the first draft left this tooth without a named script): **every one of the 22 familiar_ids

has all 5 rungs** (22×5=110 exactly — a coverage assertion, not a floor), and every

T0_Familiar_Registry.abilities_granted blank is now backed by a real join. Also: remove the

_deferred.familiar-bond-ladder block from registry_extensions.json in the same commit, or the

manifest points at a home that exists (a stale pointer is the defect class this project keeps catching).

3.4 T0_Familiar_Registry — the ally-build extension (4 added columns · Vector C)

Vector, corrected (M6a). T0_Familiar_Registry/Sheet1 is in fidelity_baseline.stub_superseded,

not in added_columns, and carries none of the 19 extension_hashes keys. So these four columns

land by extending its candidate_header and re-pinning it — check_registry_extensions.py

L59-69 satisfies a manifest key with no added_columns only when every manifest column appears in

stub_superseded[key].candidate_header. The ally-build system key still names the four columns

(I2: exactly one owner); what changes is where the width is declared.

columntypeenum / FKdefault
element_affinityenumthe eight-element roster — the affinity this familiar develops toward (see OPEN-3)blank
role_tagdelimited FK listT0_Role_Axis_Registry.role_axis_id (Family A's roster — M3): ROLE_GROUP_SUPPORT · ROLE_GROUP_HEAL · ROLE_GROUP_DAMAGE · ROLE_SINGLE_SUPPORT · ROLE_SINGLE_HEAL · ROLE_SINGLE_DAMAGE (+ ROLE_GROUP_TERRAIN)blank
bond_ability_ref_floorFKT0_Familiar_Bond_Ability.bond_ability_id (the formation rung)per row
is_sustained_baseboolShell W1's always-present property (§6.1)FALSE (TRUE on W1)

role_tag matters independently of the element question: rank 14 mints role tags for pools and specs;

nothing in the plan gives them to familiars, yet §14A.3 and §15 explicitly enter familiar choice into

the build-space sweeps. A sweep cannot count a role a familiar cannot be tagged with.

OPEN-3 (surfaced, not ruled — the second, smaller DIRECTOR call). §1.2 promises "Each familiar

type carries elemental associations within its category" and never assigns one across all 22 slot

entries; T0_Familiar_Registry has no element or affinity column (both zeros positive-controlled).

Two branches: (a) author 22 values grounded in each species' cultural substrate (Shell/Kasa

water-ancient, Khan earth-apex, Koi water→dragon cross-domain, Raven air-trickster) — a one-pass

factory job with citations; or (b) retire §1.2's promise in the living source. The lens recommends

(a); the column above supports either (nullable if (b) is ruled). Note the EAM leg is WEAKER than the

lens first framed it — §8.11.5 could gate *the player's* pairings without the familiar carrying an

element of its own — but the primary leg (an undischarged canon promise + §15's "familiar choice

shapes the ability build" having no data expression) stands.

3.5 T0_Ally_Behavior_Policy — the INT-tier AI schema (NEW registry · 21 columns)

Why, and the CORRECTION that must be applied. Creature-lens F5 SURVIVES **WITH A MATERIAL

CORRECTION**: the finder proposed adding int_tier to the ratified fallback key

(companion_id, relationship_state_bucket)do not. `RUNTIME_STRATEGY_TOKEN_SCHEMA

[RATIFIED v1.0] §3.4 and RUNTIME_GENERATIVE_LAYER` §A.4 rule combat zero-model ("in a fight the

companion/familiar is a GOAP/utility agent at 60 Hz … Deterministic executor owns: the entire combat

loop"), so that key belongs to the LLM layer's authored default — disposition bias and banter. Putting

a build property there would route INT across a ruled firewall.

The policy table is keyed by the DETERMINISTIC executor: (ally_ref, role_tag, int_tier).

combat_disposition remains the LLM's orthogonal *bias* over whatever the deterministic policy

selects. The LLM sets style; the deterministic layer executes actions; INT buys deterministic

behaviour depth. Both rulings preserved.

Id format. policy_id = AP_\d{4}.

columntypeenum / FKrequired
policy_ididAP_\d{4}yes (PK)
ally_refFKT0_Character_Index.character_id \T0_Familiar_Registry.familiar_id \* (role-generic)yes
ally_kindenumcompanion · familiar · anyyes
role_tagFKT0_Role_Axis_Registry.role_axis_id (Family A's roster — M3; the key is (ally_ref, role_tag, int_tier), so this column is the join the sweeps use and a bare enum would not resolve against a pool row)yes
int_tierintordinal band on the twelve-tier numerical scale (the KEY field — the spread is continuous, the tiering is discrete)yes
domainenumpattern_detection · proactivity · awareness — §8.11.8's three, verbatimyes
condition_exprstringthe CONDITION_EXPRESSION_GRAMMAR [ACTIVE v1.0] grammar — has() flag() at() read() ws.key ==/>=/<=/in, &/``. NOT a second language.yes
action_refFKT0_Ability_Tree_Registry.ability_id \the interpose/LOS-break/stagger verb keysyes
priorityintordinal ordering within a tieryes
autonomy_bandenumprompted · situational · autonomous — the fraction of the policy set an ally runs unpromptedyes
policy_sourceenumcanon_seed · factory_authored — a CLOSED enum with no player-authored memberyes
unlock_int_minintthe ordinal band at which this row becomes liveyes
disposition_legal_setdelimited listsubset of {protective, aggressive, cautious}a FUNCTION of integrity band, not the free triadyes
display_intent_textFTextthe readable "why" (rank-22 bark class renders it)blank → voice pass
string_statusenumFamily A's string_status_enum, DEFAULT placeholder (M4)yes
voice_register_refFKT0_Voice_Registry.voice_id — this table's string is a spoken line, so it takes the full Family-A treatment (§0.5)nullable
power_sourceenumFamily A's power_source_enum, DEFAULT ally_spread (M4) — without it defect D8 source_dominance cannot see the ally side at allyes
lifecycleenumFamily A's lifecycle_enum, DEFAULT active (M4)yes
superseded_byself-FKT0_Ally_Behavior_Policy.policy_id (M4)no
source_refstringCOPY-ONLY where seededyes
notesstringincl. examples_not_limits

THE GAMBITS-BUSYWORK GUARD, expressed structurally. FF12's gambit system degraded two ways:

*busywork* (drip-fed slots, each new party member's whole list re-authored and re-ordered, late-game

editing as spreadsheet maintenance) and *agency loss* ("the game plays itself"). Our ruling already

diverges correctly on the busywork half — **the player invests a stat and picks a role, and never

authors rules.** That divergence is enforced here by construction, not by convention:

1. policy_source is a closed enum with no player member — a player-authored policy row is

unspellable in data.

2. There is no slot_count column and no per-ally row ordering surface — slots-as-a-progression-

resource (FF12's actual busywork engine) has no home, deliberately.

3. The player's only two inputs to this table are int_tier (which rows unlock) and role_tag

(which rows apply). INT unlocks TIERS; the player never scripts a rule.

Seed rows — COPY-ONLY from canon prose that is already condition→action. T3_Familiars_Named

§1.4 is a set of policy rows in prose: "L1/L2: the familiar steps in voluntarily at 50% or less player

health … removes itself once health recovers above 50%." Those are the first authored rows, exactly

like the bond ladder. §8.11.8's three domains supply the seed spread (pattern detection: "recognizing

the counter-class a given attack demands"; proactivity: "pre-positioning before a telegraphed strike

lands, interrupting a cast worth interrupting, peeling a threat off the protagonist or off a

lower-durability ally"; awareness: "tracking adds, environmental hazards, arena changes, and the

states of the rest of the party"). §8.11.8 names them "**the seed set the factory expands per ally and

per chapter**" — recorded per pool.

Consumer. the deterministic ally executor (GOAP/utility @60 Hz — PRE_5090_BUILD_PLAN C1.17) ·

the rank-22 ally combat-line class (renders display_intent_text) · **the Phase-5M/5H build-space

sweeps** — authoring in the one shipped grammar is what makes §10's "ally spreads enter the sweeps"

*measurable* rather than asserted, because the sweeps can READ the rows · Tier-C §8.9 (the same

architecture at raid scale).

Gate / tooth additions — the NEW gate harness/check_ally_build.py (reconciled M9: three

ally-side assertions in this design had no named host script, and the §12 budget tooth needed one).

It is the third and last new gate this family adds, in the teeth class of check_entity_taxonomy.py

— zero-token and permanent. Joint gate roster: 25 today · 26 build_space (Family A) ·

27 rarity_firewall · 28 counter_class_coverage · 29 ally_build.

role_tagT0_Role_Axis_Registry.role_axis_id (Family A), FK

action_refT0_Ability_Tree_Registry.ability_id.

WS_027 and WS_012 alike; blank-tolerant until Phase-5M sets the curve.

malformed predicate fails the gate; it must never silently match nothing.

an out-of-enum goal. Grounding: §1.4 bars an L1/L2 familiar from attacking at all above 50% player

health, so an LLM-emitted aggressive bias in that window is mechanically illegal, and the ratified

triad carries no integrity constraint today. This validator is correct and cheap **regardless of how

OPEN-4 is ruled**.

discipline — "behavior quality is a build property, never an integrity property"); and no policy row

gates progression (§8.11.8's first discipline + check_no_dead_end.py's standing contract).

OPEN-4 (RE-ROUTED, not designed here). Creature-lens F6 SURVIVES RE-ROUTED: a player→ally

order channel (focus_target | hold | regroup) collides with RUNTIME_GENERATIVE_LAYER §A.4 L116's

ruled framing — "You don't configure your teammate in a menu — you earn how they show up for you."

The refuter's read: "configure in a menu" governs authoring/configuration while an in-combat order verb

is a live tactical input — a different surface — but the distinction is fine enough that **only Josh /

the director draws it. Routed to the rank-18 bundled brief. No order-verb column is minted here.**

The asymmetry that makes it worth a ruling is real and unrecorded: familiars have a canonical,

integrity-gated command-permission model (§1.4, carried as command_permission in §3.3 above); human

companions have no equivalent rule anywhere.

3.6 The peel seam — T0_Boss_Attack_Rail / enemy-state coordination (creature-lens F7)

§8.11.8 lists "peeling a threat off the protagonist or off a lower-durability ally" as a canonical

Proactivity behaviour. Register #1's applied engagement recommendation is aggro_radius + detection

channel + patrol + leash-and-reset, "No threat table." The refuter found the code is harder than

absence: HumanityEnemyCharacter.h L163-164's perception step is hard-wired to the player ("is

the player inside this enemy's sight cone right now?"), fields at L211-216 — so an ally **cannot

be a target at all**, and a peel has nothing to move.

Keep "no threat table" (a numeric threat meter is a WoW-register scoreboard the practitioner

framing rejects). Define a peel as a retarget CAUSE over the perception model that already ships:

enemy_state += current_target_ref : actor handle           (engine-side, W-SPACE spec)
enemy_state += retarget_cause     : enum {perception_lost | interposed | stagger_reacquire | leash_reset}
T0_Ally_Behavior_Policy.action_ref -> the interpose / LOS-break / stagger verbs (no new abilities minted)

All three causes are readable off existing fields; none requires a meter. **This is engine-side state,

not a registry — recorded here as the co-freeze dependency** so the §3.5 policy rows do not author

action_ref values pointing at nothing. The W-SPACE engagement spec and these policy rows are two

halves of one mechanic and must be authored against each other.

3.7 The MMO bridge — nothing new is minted (Tier-C §8.7-.9)

Recorded so the mint does not double-author: Tier-C §8.7 states the raid-role taxonomy "is owned by

T1_Combat_System_Spec and T1_Ability_Tree and is read here at group scale … a **non-authoritative

echo carried for legibility." The same role axes serve both arenas — one taxonomy, one

REGISTRY, two arena sizes**, per §8.7's third property ("group scale changes the role's expression,

not its identity").

Reconciled M3. The first draft asserted "one taxonomy, one enum" while carrying a bare

six-value enum (group_support · group_heals · … · st_damage) against Family A's FK'd

T0_Role_Axis_Registry (ROLE_GROUP_SUPPORTROLE_SINGLE_DAMAGE) — not one token matched,

so the sweeps could not join an imprint affix or an ally policy row to a pool row without a

translation table neither design minted. Every role_tag / role_axis_ref column in this design

(§1.2, §3.4, §3.5) is now an FK into Family A's registry, and spec_purpose_ref an FK into

T0_Spec_Purpose_Registry — which also repairs a worse defect than the id mismatch: the draft's

flat spec-purpose enum conflated function with scope (personal/aoe are scopes,

vril_healing is a function) and therefore could not express T1_Ability_Tree §5I.2's ruled

derivation — *"A vril-healing personal-scope specification is a single-target heal role; the same

healing purpose at area scope is a group heal role"* — which is a two-axis product that Family A's

function_class × scope_class → role_axis_ref models and enforces with tooth T-A6. Zero authoring

cost: all six purposes and all seven axes already exist as rows in Family A §9.4/§9.5. The four operational teams (Environmental

Manipulation 10-15 · Combat Core 25-30 · Spawnling Management 60 · Enhancement and Protection) are

role CLUSTERS over the same six axes, not a new taxonomy; they need no column of their own until the

Tier-C build phase. The only Family-B obligation is that role_tag stay a single shared enum and that

T0_Ally_Behavior_Policy be keyed generically enough to accept a raid-scale ally_ref later —

satisfied by ally_kind = any + a * role-generic ally_ref.

---

PART 4 — BOSS TIMING + THE PER-ATTACK RAIL (sekiro survivors, co-frozen with the counter-class law)

4.1 T0_Boss_Attack_Rail — the per-attack rail as DATA (NEW registry · 24 columns)

Why it must be minted, not extended. DESIGN_GAP_REGISTER #11 named a recovery_window field per

boss-attack row; W9 realized it only as a C++ struct (FHumanityAttackRow in

Source/Humanity/Public/Combat/HumanityAttackLibrary.h), never as a registry table — every moveset in

the game is hand-coded in .cpp (11 TelegraphShape assignments across

HumanityBossCharacter.cpp L632-706 and HumanityEnemyCharacter.cpp L170-198). Sekiro F3's scoping

condition, F2's schema note, and F5's per-class floor **all presuppose a rail that does not exist as

data.** This is that rail. It is a CHILD TABLE of T0_Boss_Encounter_Registry keyed

(boss_id, attack_id) — one attack is one row, and a boss has many, so §5H.4's rows-not-columns law

applies exactly.

Coordinate, do not duplicate — and this is the shared firewall's ONE enumerated exception (M8).

windup_seconds, active_seconds, recovery_seconds, damage and punish_damage_mult are raw

floats mirroring a shipped engine struct. That is legitimate reuse and the right call, but it is

also the complete and closed list of magnitude columns exempt from §0.4 clause 1 in either

family — stated in the firewall itself so the design and its own stated discipline no longer

disagree in writing. Values stay ILLUSTRATIVE until Phase-5M.

The first nine columns mirror the SHIPPED struct verbatim in

snake_case, per REGISTRY_ROW_STRUCT_SPEC.md §1 ("Member names mirror the CSV header VERBATIM …

any rename silently drops the column"). recovery_seconds IS register #11's landed

RecoverySeconds — the registry becomes its data source, not a second rail beside it. Same for

punish_damage_mult (PunishDamageMult 1.75, IsInRecoveryWindow()) and enabled (bEnabled

the W9-2 part-break toggle).

columntypeenum / FKrequired
attack_row_ididAT_\d{4}yes (PK)
boss_idFKT0_Boss_Encounter_Registry.boss_idyes
attack_idstringthe per-creature moveset key (mirrors FName AttackId)yes
telegraph_shapeenumpromoted from free string to a CLOSED key: whip_arc · low_sweep · high_feint · lunge · feint · grab · venom_spit · swipe · coil · disc (the nine authored + the struct default)yes
windup_secondsfloatILLUSTRATIVE / 5Myes
active_secondsfloatILLUSTRATIVE / 5Myes
recovery_secondsfloatthe #11 punish window — the existing rail, not a new oneyes
counter_classenumany · dodge_only · parry_only · neutralize (mirrors EHumanityCounterClass)yes
damagefloatILLUSTRATIVE / 5Myes
punish_damage_multfloatILLUSTRATIVE / 5M (struct default 1.75)yes
enabledboolthe part-break toggle (SetAttackEnabled)TRUE
min_tell_msintPER COUNTER CLASS — a row has one counter_class, so per-row IS per-class. Replaces the actor-wide MinTellSeconds = 0.15 scalar.blank / 5M
answer_window_msinthow long the correct answer stays availableblank / 5M
telegraph_lead_msinthow far ahead of the strike the CLASS read resolves — distinct from windup_seconds (Sekiro shows the class at the START of a long windup, not at its end)blank / 5M
tell_shape_classenumthe ground/space glyph FAMILY (rank-16 partitions it by counter_class)yes
tell_motion_classenumthe windup animation family — the body read that survives colour-blindness AND audio-offyes
telegraph_sfx_id_refFKT0_SFX_Registry.sfx_id — the class stingnullable
telegraph_vfx_refstringVFX keynullable
part_refstringthe hitzone_parts part this attack rides (breaking it disables the row)nullable
phase_indexintwhich boss phase the row belongs toyes
attack_kindenummelee · ranged · cast · grab · arena_mutationyes
cast_pattern_refFKT0_Ability_Tree_Registry.cast_pattern (the neutralize class's READ — the one class R2.2 already gives a differentiator)nullable
source_refstringyes
notesstring

Consumer. UHumanityAttackComponent::Moveset (loaded from the DataTable instead of hand-coded in

.cpp — the reuse that retires 11 hard-coded assignments) · the telegraph render path

(ShowTelegraphShape() currently ignores the row it already has) · the QA program's per-frame state

record (QA_WATCHING_PROGRAM.md L46 already carries counter_class and telegraph_shape) ·

rank-16 (the pip fill/wipe columns key off counter_class answers) · the sweeps.

Gate / tooth additions.

(boss_id, attack_id)**, FK boss_idT0_Boss_Encounter_Registry.boss_id, FK

telegraph_sfx_id_refT0_SFX_Registry.sfx_id.

1. The F7 tooth (the cheapest tooth in the sekiro lens, with 268 boss rows still to author):

per chapter, every counter_class present in that chapter's authored movesets has its answering

capability granted at or before that chapter. Grounding: the Ch-2 Kelimutu Guardian pair

(BE_0002_S1, chapter_id = CH_02) authors guardian_tail_swipe as ParryOnly while

bParryCapable defaults false with exactly one production grant (if (bIsCaci), the Ch-3 caci)

and WPN_033 Shield is canonical_chapter_acquisition = CH_03 — against a triple-sourced

ratified 2-of-3 scope (memory/puzzle-boss-chain-meter-design.md §7 · FUN_REBUILD_PLAN §4

ruling (5) + R2.2 · PRE_5090_BUILD_PLAN_VOL2 L1614/L1456).

2. The answerability invariant (F5): min_tell_ms[parry_only] >= reaction_budget_ms and

min_tell_ms + answer_window_ms >= reaction_budget_ms for every authored row at every dial

position. reaction_budget_ms is a declared symbolic constant in the combat spec; the gate is

authored against symbols NOW and armed when the magnitudes land at 5M.

3. **Telegraph disjointness (dqpm F3's surviving schema rule — rank-16 owns the tooth, this rail

owns the columns):** within one creature's moveset, no two distinct counter_class values share

a tell_shape_class, and every counter class in use has a distinct key. Arithmetic over a record

that already exists in the QA per-frame stream.

counter_classes_present (multiset, derived from this rail) and player_capability_gate (which

weapon/chapter grants the answer). Both default EMPTY, which reproduces current canon exactly.

Corrected M6a: T0_Boss_Encounter_Registry/Sheet1 is stub_superseded, so these two land by

extending its candidate_header and re-pinning — not via added_columns/extension_hashes.

Recorded, NOT designed here (routes to rank-18). Sekiro F2 SURVIVES-UNDERSTATED: Josh's

verbatim ruling is symmetric — "attacks that CANNOT be parried — dodge only; attacks that CANNOT

be dodged — parry only" — and the build implemented one half (dodge-only is genuinely unparryable)

while reinterpreting the other as chain-level-only (IsCurrentDodgeable() has zero call sites;

the dodge branch is a bare IsDodgeInvulnerable() with no class test). The lens's recommendation —

keep i-frames universal for DAMAGE and put the matrix's teeth in the CHAIN — is a **system-canon

change** and must route as a briefed Josh item, never be applied by the mint. The rail above is

neutral: it carries counter_class as data either way.

4.2 T0_Weapon_Registry — the defensive-properties extension (5 added columns · Vector C)

Vector, corrected (M6a). T0_Weapon_Registry/Sheet1 is stub_superseded — not in

added_columns, not among the 19 extension_hashes keys — so these five land by extending its

candidate_header and re-pinning it, which is the path check_registry_extensions.py L59-69

takes for a manifest key with no added_columns.

Why. Sekiro F4 SURVIVES — "the strongest schema-freeze hit in the set." Canon names the

parry-capable set in prose (T1_Combat_System_Spec §Parry L444-454: Rapier Parry · Long Sword

Halbschwerter/Meisterhau · Cutlass Parry Riposte · Madu Horn Catch "the only Trickery dedicated

parry weapon" · Sword 1H Riposte; §Block L435-442 for shields). The live registry is **72 rows × 18

columns with no defensive column of any name**, and the runtime capability is a single bool

bParryCapable (default false) granted from exactly one place. The freeze-collision is real:

§12 Lane-A's own named bonus kind — "catch-window width on the parry weapons" — has nothing to

attach to.

columntypeenum / FKdefault (reproduces current canon)
defensive_classenumnone · block · parry · catch · ripostenone (= today's bParryCapable=false on every weapon)
parry_window_msintordinal / 5Mblank
parry_stamina_costintordinal / 5Mblank
parry_generateenumnone · stamina · vril — §Parry's "generates Stamina or Vril per weapon class": the resource is per-class, so it must be a column, not a constantnone
riposte_followup_refFKT0_Ability_Tree_Registry.ability_idblank

Seed rows (canon prose → data, the five named parry weapons + the two shields). defensive_class

populated from §Parry/§Block; every other of the 72 rows takes the none default. The Madu row carries

defensive_class = catch and is the natural first parry_generate = stamina row ("every successful

catch generates Stamina at Mastery 8").

Reuse anchor. weapon_sfx_id_ref_array already reserves "hit, block, parry, ranged release…" slots

per weapon (T0_Schema_Dictionary L548) — the parry AUDIO contract already assumed a per-weapon

defensive property the registry never modelled. These columns sit beside damage_type /

vril_couple_eligibility (both 0/72, already queued as rank 26) so **one authoring pass fills all of

them**. Dedupe stated: rank 26 fills EXISTING empty columns; this ADDS absent ones — distinct work,

same pass.

bonus_axis cross-reference — scoped to this family (reconciled m2). T0_Imprint_Affix.bonus_axis

(§1.2) carries timing_window as a first-class value precisely so the sweeps can separate a

window-widening pick from a damage pick. A window-widener is the archetypal must-pick and

META-COLLAPSE is the named banned failure mode, so this tag is a direct requirement of the §10

doctrine, not an embellishment.

The draft then added "the same axis applies to Family A's tier-bonus rows" — an assertion about

a column Family A does not mint. Family A expresses the axis at a different granularity

(bonus_kind, the effect's identity, which carries the catch_window value; bonus_axis is the

effect's class), and one family may not declare a column on another's table. **The cross-family

claim is withdrawn**; bonus_axis is a Family-B column on rolled affixes. If the sweeps later want

one axis across both surfaces it is derivable from A's bonus_kind / effect_attribute pair —

a sweep-side mapping, not a schema claim, and not asserted here.

---

PART 5 — THE STATUS GRID

5.1 T0_Status_Table — the canonical status grid + the read channels (NEW registry · 26 columns)

Why. dqpm F1 SURVIVES (owner story corrected). Ten distinct status kind tags ship

(HumanityCombatTags.cpp L16-25: Status.DoT.Burn/.Poison/.Septic/.Scald/.Windburn, Status.HoT.Life,

Status.Impair.Slow/.Freeze/.Paralyze, Status.Stagger) and all ten fire the same cue

(HumanityStatusSubsystem.cpp L156, one tag, no kind, no FGameplayCueParameters); expiry and cure

are silent (CureStatusKinds L197-221, CureWithMaterial L223-239 fire no cue). No T0_Status_*

registry exists; T0_Creature_Roster has no immunity column, matching the subsystem's own admission

(HumanityStatusSubsystem.h L97-98). Window-plan rank 25 already names three deliverables (canon

grid · cure/antidote chains · status_immunity); the six read columns below are strictly ADDITIVE to

it, never a re-report.

Id format. status_id = ST_\d{3}.

columntypeenum / FKrequired
status_ididST_\d{3}yes (PK)
status_kindenumthe ten shipped tags (burn · poison · septic · scald · windburn · life_hot · slow · freeze · paralyze · stagger) — closed, extended only on attested demandyes
status_familyenumdot · hot · impair · staggeryes
cue_tagstringthe per-kind GameplayCue.Combat.Status.<Kind> tag — mirrors the SHIPPED Composure pattern (eight GameplayCue.Composure.Node.<Mode>.Broken tags routed through a table at HumanityDamageExecCalc.cpp L80-87)yes
read_channeldelimited enum setvfx_body · vfx_ground · audio · motion · hud_text · screen_edgeminimum 2, and never colour aloneyes
read_persistenceenumevent · persistent · both (dqpm F2's shared column)yes
persistent_cue_tagstringthe WhileActive cue key — required when read_persistence ≠ eventconditional
persistent_channelenumbody_vfx · silhouette · posture · audio_loop · screen_edgeconditional
icon_classenumthe FAMILY glyph: drain · restore · bind · stagger — distinct from status_kind, because CLASS reads at a glance and IDENTITY reads on inspectionyes
stack_displayenumnone · count · pips · intensityyes
stack_capintordinal (the §4.4 cap; magnitude 5M)blank
break_event_refstringthe cap-triggered break (COMBAT_ENCOUNTER_SYSTEM §4.4's chill→shatter)nullable
expiry_tellstringcue key for the currently-silent expiry transitionyes
cure_tellstringcue key for the currently-silent cure transitionyes
status_sfx_id_refFKT0_SFX_Registry.sfx_idnullable
cure_material_refsdelimited FK listT0_Flora_Registry.flora_id \T0_Mineral_Registry.mineral_id (the FL-10 tamarind/Komodo-septic proof case)nullable
immunity_tagstringthe token T0_Creature_Roster.status_immunity matchesyes
applies_to_allyboolally-side statuses exist and must be readableTRUE
duration_classenuminstant · short · sustained · until_cured (ordinal, not seconds)yes
magnitude_refrefT0_Balance_Constant_Registry.constant_id — Family A's target, one column name one contract (M8)blank
power_sourceenumFamily A's power_source_enum (M4) — which layer applied the status (proficiency · gear_imprint · ally_spread · familiar_bond · consumable · merge); vacuous on day one, and the column defect D8 needs to compute over status effects tooyes
lifecycleenumFamily A's lifecycle_enum, DEFAULT active (M4)yes
superseded_byself-FKT0_Status_Table.status_id (M4)no
string_statusenumFamily A's string_status_enum, DEFAULT placeholder (M4) — carried even though this table has no FText column today, so the natural-voice worklist query is uniform across the family and a later *_text column inherits the discipline rather than inventing ityes
source_refstringyes
notesstringincl. examples_not_limits

Seed rows. Ten, one per shipped kind — the runtime tags ARE the verbatim seed. burn/poison/

septic/scald/windburnstatus_family=dot, icon_class=drain; life_hothot/restore;

slow/freeze/paralyzeimpair/bind; staggerstagger/stagger. Every seed row carries

read_persistence = persistent (a status with a duration must render for its duration) except

stagger (both).

Consumer. UHumanityStatusSubsystem (the per-kind cue split) · the HUD status row (rides

MakeText/MakePip, HumanityPlayerHUDWidget.cpp L87-99 — a status row is a horizontal box of

widgets already constructed for the pip strip) · the herbalism/alchemy cure economy · the QA rubric

bands RB-9/QT-6 · rank-20 UI.

Reuse-first (both halves already exist in-repo). (1) The per-kind cue pattern is the shipped

Composure table one file over — zero new architecture. (2) The audio data home is the proven

sfx-pipeline extension group (ability_sfx_id_ref_array, boss_sfx_id_ref_array,

familiar_bond_sfx_id_ref_array); status_sfx_id_ref joins it.

Gate / tooth additions.

T0_SFX_Registry.sfx_id, FK cure_material_refs (multi-value, dual-target).

every row's read_channel set has ≥2 members and never resolves to colour alone — the ratified

colour-independent floor (docs/proposals/DIFFICULTY_SYSTEM.md §Accessibility — Attunements

L82-91; note the corrected citationT99_Translation_Combat §2.6 is a stale self-pointer that

the sekiro lens's refuter traced and corrected). Every row with read_persistence ≠ event has a

non-empty persistent_cue_tag and persistent_channel.

status_immunity (1 added column, default EMPTY = no immunity, which matches today's state

exactly). Same group name owns nothing else, satisfying I2.

Applied constraint (not re-litigated). no-mode-taxonomy-on-player-surfaces is respected

throughout: none of the columns above expose internal routing on a player surface. icon_class,

read_channel and persistent_channel are *perceptual* keys — a body that looks poisoned, a sound

that says bound — never a label, never a legend, never the debug HUD's VERB KIT.

Owner correction carried forward (dqpm F1's refuter). PRE_5090_BUILD_PLAN_VOL2 U11.1

(BUILD-NOW) enumerated "cue-driven status" as a deliverable and U11.4 the per-mode Composure

node-break read; the 2026-07-26d W10 landing record lists neither in its shipped list **nor in its

"Honest tail (TODO_CANON)"**. That is a BUILD-NOW deliverable that shipped without one of its own

enumerated elements and without the drop being recorded — a W10-tail bookkeeping item that must be

reinstated or honestly deferred. Recorded, not resolved by this mint.

---

PART 6 — MIGRATION NOTE: ADDITIVE-ONLY, EVERY DEFAULT REPRODUCES CURRENT CANON

6.1 No existing row is edited. Every landing is (a) a NEW registry directory declared in

added_registries, or (b) NEW columns appended beyond the frozen reference width and declared in

added_columns + registry_extensions.json (Vector B — only T0_RNG_Drop_Table,

T0_Chapter_Index, T0_Creature_Roster), or (b′) NEW columns on a stub_superseded registry

declared in its candidate_header + re-pinned (Vector CT0_Weapon_Registry,

T0_Familiar_Registry, T0_Boss_Encounter_Registry), or (b″) columns on a wholly-added registry,

which need no manifest key at all (T0_Rune_Registry, T0_Equipment_Registry), or (c) a

domain-cell declaration on an existing T0_Worldstate_Variables row (WS_012, WS_027, WS_028,

WS_036) plus two NEW WS rows (WS_045, WS_046 per the §2.2 allocation; the registry's current max

is WS_042). No frozen _source xlsx is touched. No expected_cell_diffs entry is added or changed.

JOINT arithmetic, one statement for both families (n5). Each design was internally right and

jointly wrong. Landed together: gates 25 → 29 (26 build_space A · 27 rarity_firewall ·

28 counter_class_coverage · 29 ally_build); added_registries 12 → 25 (A +5, B +8);

added_rows["T0_Worldstate_Variables/Sheet1"] 17 → 21 (A: WS_043-044, B: WS_045-046).

6.2 Every new-column default reproduces the current game exactly — by landing vector.

columnvectordefaultwhat it reproduces today
T0_Weapon_Registry.defensive_classC (candidate_header)nonebParryCapable default false on all 72
T0_Weapon_Registry.parry_*Cblankflat player constants ParryWindowSeconds 0.35 / ParryCooldownSeconds 0.25, read by no weapon
T0_RNG_Drop_Table.sigma_constraint_enabledB (added_columns)TRUEtoday's unconditional σ constraint
T0_RNG_Drop_Table.mode_gateBnoneno mode-gated loot exists
T0_RNG_Drop_Table.* (all)Bvacuousthe table is 0 rows — no cell can change
T0_Creature_Roster.status_immunityBEMPTY"no canon roster immunity column exists yet" (subsystem's own comment)
T0_Boss_Encounter_Registry.counter_classes_presentCEMPTYderived; empty until the attack rail populates
T0_Boss_Encounter_Registry.player_capability_gateCEMPTYno gate is asserted today
T0_Familiar_Registry.element_affinityCblank§1.2's promise is currently undischarged
T0_Familiar_Registry.role_tagCblankfamiliars carry no role tag today
T0_Rune_Registry.reroll_cost_material_refsnone (added registry)blankno doc states a denomination today
T0_Chapter_Index.rolled_reward_events_targetBblankno cadence budget exists today

6.3 The one behavioural-continuity guarantee that matters most. WS_012.bond_tier stays a

DERIVED view {approach|accepted|mastery} over the new numeric bond_value, so **all 99 existing

spine writes across 38 nodes keep resolving unchanged**. The numeric axis is added beneath, not

substituted for. Same discipline on WS_027: the loyalty fields (loyalty_score,

loyalty_belief_axis, loyalty_departure_threshold, the 90-cap arithmetic) are untouched, and the

gate asserts int_tier is not readable by them.

6.4 The commit-shape checklist (the gate-safe landing sequence).

1. Create the new registry directories with headers + seed rows.

2. Add every new column to its registry CSV (append at the end; column order is header order and the

generated struct diff is the review).

3. docs/registry_extensions.json, by vector (M6): add the Vector-B system keys

(imprint-loot on T0_RNG_Drop_Table + T0_Chapter_Index; status-framework on

T0_Creature_Roster) and the Vector-C system keys (defensive-properties on Weapon,

ally-build on Familiar, counter-coverage on Boss_Encounter) — the Vector-C three are

satisfied through stub_superseded[key].candidate_header, NOT added_columns.

Declare NO manifest key for T0_Rune_Registry or T0_Equipment_Registry (added registries;

each key would be an immediate I3 FAIL). Remove _deferred.familiar-bond-ladder (its table

now exists).

4. docs/fk_spec.json: register all 8 new registries (registry + tab + primary_key

composite ["axis","rarity_token"] for T0_Rarity_Grade — + id_formats with min_values, +

foreign_keys carrying references_tab and min_tokens), including the FKs into Family A's

T0_Role_Axis_Registry and T0_Spec_Purpose_Registry (M3), which therefore land first or in

the same commit.

5. python harness/registry_fidelity.py --emit-baseline — refresh added_registries,

added_columns, extension_hashes, and the Vector-C candidate_header pins in the same

commit (the standing rule; skip it and the gates go red).

6. harness/check_ws_value_form.py domain extensions for WS_012/027/028/036 + WS_045/WS_046,

plus the CG-25 +-prefix legal-set edit 12 → 14 for WS_044 (Family A) and WS_046

(a ruled-list edit — flagged, not assumed; the live constant holds twelve ids, not six).

7. Regenerate the affected row structs (Tools/gen_row_struct.py) — RngDropTableRow.h,

WeaponRegistryRow.h, plus the 8 new structs.

8. python harness/run_gates.py UNPIPED — the joint roster is 29 (25 + build_space +

rarity_firewall + counter_class_coverage + ally_build).

9. docs/DOC_MAP.md rows for all 8 new tables (a table is not done until it is listed there).

6.5 What this design does NOT do. It rules nothing that is Josh's. Four items are surfaced with

full framing and routed to the rank-18 bundled brief rather than decided: OPEN-1 the 4-vs-5 rarity

ladder + ability_count axis; OPEN-2 the three unnamed stat slots in the recovered 16-slot layout;

OPEN-3 familiar element affinity (author 22 vs retire the §1.2 promise); OPEN-4 the player→ally

order channel vs the ruled "you don't configure your teammate in a menu". Plus two system-canon

routings recorded and not applied: sekiro F2's universal-i-frame reinterpretation, and the

D-MYTHIC-GATE brief amendment (bl-loot F6 — the *third* edit point at

docs/proposals/DIFFICULTY_SYSTEM.md, which is headed RULED and already sites the rarity apex at The

Forgotten One, plus the unstated Sundered hard-mode prerequisite that CVD §12.1 gates the

post-Ch-77 prestige questline on Ch-77 completion with no difficulty condition of any kind). The

schema is neutral on every one of them: each resolution is a row or enum-value edit, never a shape

change.

6.6 The lens wave's standing correction, honoured. docs/original_predclaude/ is part of the

current-state corpus for any design-canon absence claim — it produced four of this design's binding

inputs (the five-grade rarity ladder + naming rule, the acquisition-source-by-rarity table, the 16

equipment slots, and per-instance rolled ability sets). Every "no home exists" statement above is

scoped to a search that included it.

---

TABLE ROSTER (what freezes here)

*(Counts and vectors below are POST-reconciliation. Where a number moved, the reason is the

finding id in the last column.)*

#homevectorcolumns / sub-fieldsreconciled
1T0_Rarity_Grade (composite PK (axis, rarity_token))new registry24M2 (−rarity_id), M4 (+4)
2T0_Imprint_Affixnew registry26M4 (+4)
3T0_Equipment_Registrynew registry26m8 arithmetic, M4 (+1)
4T0_Loadout_Set_Definitionnew registry14sole owner of set canon (m1)
5T0_Familiar_Bond_Abilitynew registry (retires _deferred)15M4 (+1)
6T0_Ally_Behavior_Policynew registry21M4 (+5), M3 (role FK)
7T0_Boss_Attack_Railnew registry (child of Boss_Encounter)24M8 (the one struct-mirror exception)
8T0_Status_Tablenew registry26M4 (+4)
9T0_RNG_Drop_Table + imprint-lootVector B added columns10m7 (vocabulary), M2 (token)
10T0_Weapon_Registry + defensive-propertiesVector C candidate_header5M6a
11T0_Familiar_Registry + ally-buildVector C candidate_header4M6a, M3
12T0_Rune_Registryno vector — added registry, NO manifest key2M6b
13T0_Boss_Encounter_Registry + counter-coverageVector C candidate_header2M6a
14T0_Creature_Roster + status-frameworkVector B added column1
15T0_Chapter_Index + imprint-lootVector B added column1
16WS_036 worn_rune_loadoutdomain declaration6M1 (points at WS_046)
17WS_046 item_instance_ledgernew WS row15M1 (was WS_043), m3 (+sigma_seq)
18WS_045 loadout_set_statenew WS row6 stored + 1 derivedM1 (was WS_044; bonus_pick_refs[] derived)
19WS_012 familiar_bond_statedomain extension12M9 (+stat_point_budget)
20WS_027 companion_roster_statedomain extension10M9 (+stat_point_budget)
21WS_028 companion_loyalty_transition_eventsdomain extension2M1 (refs WS_046)

New gates: 3harness/check_rarity_firewall.py (6 assertion classes incl. the affix-side

mythic twin, plus the affix-predicate lint), harness/check_counter_class_coverage.py (3 assertion

classes, one armed at 5M), and harness/check_ally_build.py (the §12 stat-budget tooth T-B1, the

110-row bond-ladder coverage assertion, the INT/loyalty firewall assertion, and the

disposition_legal_set validator — three of which had no named host before reconciliation). All

zero-token and permanent, in the teeth class of check_entity_taxonomy.py and

check_no_dead_end.py. Joint gate roster with Family A: 29.

---

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

(§2.2 here, verbatim-identical to Family A §6.0): 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:* contiguous per-family blocks over interleaving, so

each family's rows stay independently reviewable; the item ledger keeps the critic's prescribed

WS_046. One owner for loadout state = Family B (this table carries the unlock gates, the

venue class and the departs_with_companion = FALSE invariant), and **one owner for selection

state = Family A**: bonus_pick_refs[] is now a DERIVED read over WS_043, not a stored copy,

which closes the double-owned shape the critic called worse than the id clash. Every downstream

reference re-pointed (WS_036.instance_ref, WS_028.returned_instance_refs[], §2.2, §6.1, §6.4).

re-shaped from a new RG_\d{3} keyspace into a PROPERTY table keyed (axis, rarity_token); the

shared 8-token ladder is stated ONCE here and cited by Family A; every FK becomes a token FK

(rarity_token_min, rarity_class, base_rarity_class) and no live cell moves. Both halves

of the survivor are carried: bl-loot F5 gets its FK-able grade table, creature F8 gets no parallel

enum and the Flora/Mineral reconciliation (uncommon, signature are in the ladder, so

firewall class (d) can pass). Column count 21 → 24. Verified: composite PKs are live

(T0_Thread_Grid), and the live distributions were re-counted programmatically — 10 live

uncommon + 1 signature = 11 cells, correcting the critic's figure.

role_axis_ref / spec_purpose_ref in §1.2, §3.4 and §3.5 is now an FK into Family A's

T0_Role_Axis_Registry / T0_Spec_Purpose_Registry; §3.7's "one taxonomy, one enum" becomes

"one taxonomy, one REGISTRY". This also removes the function/scope conflation that made §5I.2's

ruled derivation inexpressible. Zero authoring cost — A's §9.4/§9.5 rows are the roster.

superseded_by) and string_status land on T0_Imprint_Affix, T0_Ally_Behavior_Policy,

T0_Rarity_Grade, T0_Status_Table; string_status additionally on T0_Equipment_Registry and

T0_Familiar_Bond_Ability (every FText-bearing table), and voice_register_ref on

T0_Ally_Behavior_Policy (the one spoken line). §0.5's voice_status marker is retired for A's

enum. All defaulted, all vacuous day one — and D8 source_dominance can now compute.

the HUD / pip lane, rank 16) and F6 (owner: the SFX consumer lane, explicitly distinguished

from §4.1's telegraph_sfx_id_ref, which is F3's channel), and the F7 mis-attribution is

corrected: the hitzone_parts carve keys belong to the rank-16 hitzone lane; F7 is the Ch-2

ParryOnly-scope finding this design implements as §4.1 gate assertion 1.

stub_superseded registry → extend candidate_header + re-pin) for Weapon / Familiar /

Boss_Encounter, and a fourth "no vector at all" case for wholly-added registries. The two

I3-tripping manifest keys are dropped (imprint-loot on T0_Rune_Registry, assetgen +

sfx-pipeline on the new T0_Equipment_Registry) — the columns still land, the keys do not.

§6.1, §6.2 and §6.4 step 3 are re-columned by vector.

to WARN on a declared seven-name list; both, because either alone leaves a hole).

Family A §0. magnitude_ref takes A's target (T0_Balance_Constant_Registry.constant_id) on both

T0_Imprint_Affix and T0_Status_Table. The five raw floats on T0_Boss_Attack_Rail are named

in the firewall itself as the complete, closed struct-mirror exception, so the design and its own

stated discipline no longer disagree in writing.

WS_012 (familiars carry ally_stat_block too, so a companion-only cap would leave a hole one

entity class wide), with tooth T-B1 in Family A's T-A12 class. *Choice recorded:* the tooth

needed a host script, and three further ally-side assertions (bond-ladder coverage, the INT/loyalty

firewall, the disposition_legal_set validator) had none either — so they are consolidated into

ONE new gate, harness/check_ally_build.py, rather than scattered into subject-mismatched

scripts or into Family A's gate (which would have added cross-family coupling). Joint roster 29.

MODERATE

ceiling is its row count, and A's unlocked_count is gone.

is a Family-B column on rolled affixes; the assertion about Family A's tier-bonus rows is

withdrawn, with the derivation noted as a sweep-side option, not a schema claim.

counter, without which the σ bound cannot be audited per instance); keep-rate homed in Family

A §7.5 via a subject_ref/subject_kind re-key, with this design's affix rows as the subject.

twelve ids, not the design's six and not the critic's seven — verified at

check_ws_value_form.py L116-118 with the D-CG25-APPEND-SET ruling comment at L112-115. The

landing edit is 12 → 14 (WS_044, WS_046); the stale "six" in the L20 docstring is fixed in

the same pass. Family A also now names the gate in its landing order.

19 populated cells) and the whole enum is hyphen-case to match the live column it reuses; the

seed rows and the σ-exemption invariant are restated in that case.

the assetgen rail is explicitly the 8-column Creature/Character/Familiar/Boss form, because

T0_Weapon_Registry's group is 7 (its mesh_id_ref sits in the base header).

mythic guard (no rarity_token_min on a non-roll-obtainable grade without

hand_authored_override), plus class (f), the per-column axis check that keeps one token

vocabulary from becoming three by drift.

MINOR

added_rows[WS] 17 → 21).

CONTESTED — director

None. Every finding was reconcilable without contradicting a ruled canon point or a lens

SURVIVES verdict. **OPEN-1 through OPEN-4 and the two system-canon routings (sekiro F2's

universal-i-frame reinterpretation, the D-MYTHIC-GATE brief amendment) remain Josh's and are

untouched by this pass — in particular the M2 reconciliation does not** pre-empt OPEN-1: the

uncommon token exists because 10 live Flora/Mineral cells already carry it, and its

imprint_slot_count is authored blank precisely because the 4-vs-5 grade question is his.

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