MINT_DESIGN_CRITIC_2026-07-27.md

pipelines/MINT_DESIGN_CRITIC_2026-07-27.md

FRESH-CONTEXT ADVERSARIAL CRITIC — the §§7-12 schema-mint designs (Families A + B)

Read-only pass over C:/dev/humanity-forgotten @ HEAD ab5d32c and C:/dev/Humanity/Humanity.

Nothing in either repo was modified; this file is the sole write.

VERDICT: NO-GO as a PAIR. Each design alone is GO-WITH-FIXES.

The two families are individually strong and, on most axes, unusually disciplined. They are not

landable together as written: they collide on the worldstate keyspace, on the rarity ladder, on the

role-axis keyspace, and on the magnitude firewall — and each carries one defect that turns its own

gate red on day one (A: tooth T-A5 vs its own seed rows; B: invariant I3 on two manifest keys).

Every blocking item is a reconciliation or a scoping edit, not a redesign.

Severity key: MAJOR = blocks the freeze · MODERATE = must be fixed before rows land ·

MINOR = accuracy/wording, fix in place.

---

PART 1 — MAJOR FINDINGS

M1 · CROSS-DESIGN · The worldstate keyspace is double-allocated

Issue. Both designs mint new T0_Worldstate_Variables rows off the same free number and collide.

idFamily A (§6)Family B (§1.6, §2.2)
WS_043bonus_selection_stateitem_instance_ledger
WS_044loadout_set_stateloadout_set_statedifferent sub-fields
WS_045bonus_respec_ledger

WS_044 is worse than the id clash: same name, two shapes.

A declares `{unlocked_count (int, DEFAULT 1, ceiling 3), active_set_index, purchase_beat_refs[],

last_switch_site_ref → T0_Vril_Site_Registry}; B declares {owner_kind, owner_ref, set_id (→

T0_Loadout_Set_Definition.set_id), gear_instance_refs[], ability_selection_refs[], bonus_pick_refs[],

is_active}. B's bonus_pick_refs[]` points into Family A's option rows while A stores the same

selection state in WS_043 under a different key — the selection-state shape is double-owned.

Evidence. registries/T0_Worldstate_Variables [ACTIVE v0.1]/Sheet1.csv = 42 rows, last id

WS_042 (verified: tail reads WS_037…WS_042). docs/fidelity_baseline.json

added_rows["T0_Worldstate_Variables/Sheet1"] = 17. Both designs independently and correctly assert

"the registry's current max is WS_042" — and then both take 043.

Fix. One allocation table in the mint plan, resolved before either family writes a row.

Recommended: A keeps WS_043 (bonus selection) / WS_044→ renamed to avoid the clash /

WS_045; B's item ledger takes WS_046. Then pick ONE owner for loadout state — B's is the

better home (it carries the unlock gates, the venue class, and the investment-protection

invariant); A's unlocked_count/active_set_index collapse into B's set_id + is_active, and

A keeps loadout_set_index only as a key INTO that row, which is all its reachability classing

actually needs.

---

M2 · CROSS-DESIGN + LENS · Two incompatible rarity ladders, and one binding refuter correction contradicted

Issue. A extends the existing enum; B mints a parallel FK'd registry. Both cannot land.

enum on grade_ceiling (A1) and rarity_class (A2). "mythic is the one new value."

(none·common·uncommon·rare·epic·legendary·mythic·signature), with the live rarity_class

columns on Rune/Flora/Mineral re-pointed at it as FKs.

The creature-collection lens's refuter correction is explicit and binding, and B lists that lens as

an input with "4 corrections applied":

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

B contradicts it with no recorded reason, citing only bl-loot F5 ("rarity as an FK'd grade").

Conversely A drops the reconciliation half: A claims its enum "reuses the live vocabulary

(3 registries already carry rarity_class)", but only one of the three matches.

Evidence (programmatic, this pass).

T0_Rune_Registry{common 8, epic 5, rare 3, legendary 2, none 1} (A's enum covers it).

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

T0_Mineral_Registry{common 10, uncommon 6, rare 3}.

A's closed 6-value enum does not cover 11 live uncommon cells + 1 signature cell.

B's 8-token table does cover them, but via the structure the refuter told the mint not to build.

Fix. Choose one representation in the mint plan, and make it carry BOTH halves of the survivor.

The honest reading of the two lenses together: keep rarity_class as the shared token vocabulary

(creature F8), and let B's T0_Rarity_Grade be the property table keyed on

(axis, rarity_token) rather than a new RG_ surrogate keyspace — so imprint_slot_count,

obtainable_by_roll, and the read channels get a home without minting a rival id space or moving a

single live cell. That satisfies bl-loot F5 (a grade table, FK-able) and creature F8 (no parallel

enum) simultaneously. Whichever way it goes, one vocabulary, stated once.

---

M3 · CROSS-DESIGN · The role-axis and spec-purpose keyspaces fork

Issue. §11 rules "one role taxonomy, two arenas". The two designs mint two.

Family AFamily B
role axisT0_Role_Axis_Registry, FK, ids ROLE_SINGLE_HEAL, ROLE_GROUP_DAMAGE (A3, §9.4)bare enum group_support · group_heals · group_damage · st_support · st_heals · st_damage (§1.2, §3.4, §3.5)
spec purposeT0_Spec_Purpose_Registry, FK, ids SPEC_VRIL_HEAL_PERSONAL (A4, §9.5)bare enum vril_healing · vril_damage · regen · hot · personal · aoe (§1.2)

B §3.7 asserts "the same role_tag enum … one taxonomy, one enum, two arena sizes" — but A's is

a registry FK, not an enum, and no token matches (st_heals vs ROLE_SINGLE_HEAL). The sweeps

cannot join an imprint affix or an ally policy row to a pool row without a translation table that

neither design mints.

The spec-purpose fork is worse than cosmetic: B's enum conflates function with scope (personal

and aoe are scopes; vril_healing is a function), which defeats the §5I.2 derivation A models as

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

Evidence. T1_Ability_Tree [ACTIVE v1.4] §5I.2: *"A vril-healing personal-scope specification is

a single-target heal role; the same healing purpose at area scope is a group heal role."* That is a

two-axis product, and B's flat six-value enum cannot express it.

Fix. B references A's registries by FK (role_axis_id, purpose_id). A's tables are the

authoritative rosters; B's role_axis_ref / role_tag / spec_purpose_ref become FK columns.

Zero cost — the rows exist in A's §9.4/§9.5 seeds.

---

M4 · LENS + CROSS-DESIGN · Three cross-family contracts A declares are absent from B

Issue. A §2.4 and §10 declare a "cross-family contract (do not diverge)". Grep of

mint_design_B_item_ally.md:

contractAB (grep count)
power_sourcepower_source_enum on every option row; sweep emits power_source_share{}; defect D8 source_dominance0
lifecyclelifecycle_enum + superseded_by on A1/A2/A3/A4/A5; tooth T-A8 (id reuse)0
string_statusenum on A1/A2; tooth T-A10 is the natural-voice worklist query0

The power_source gap is a lens-survivor failure, not a style difference. The combinatorial

lens's NET instruction is unambiguous:

(F6) ONE shared power_source enum (`proficiency|gear_imprint|ally_spread|familiar_bond|
consumable|merge`) across every effect-bearing §§7-12 row — bonus, imprint, ally-spread alike.
The shared vocabulary is the load-bearing part.
p1a_combinatorial_build_space.md L866-869

A's own §2.4 names B's rows as the other half of the contract ("imprint affixes (Family B/C,

gear_imprint)"). Without the column on T0_Imprint_Affix and the ally rows, D8 cannot compute

and the gear-eclipses-build collapse stays invisible — which is the specific failure F6 exists to

catch. lifecycle (F9's "deprecate-never-delete") and string_status are the same class, one size

down: B has no id-lifecycle discipline on 8 new registries and no natural-voice worklist column

despite §0.5 declaring a voice_status = pending_natural_voice marker that appears in none of

its 8 table definitions.

Fix. Add power_source, lifecycle (+ superseded_by), and string_status to

T0_Imprint_Affix, T0_Ally_Behavior_Policy, T0_Rarity_Grade, and T0_Status_Table — the four

effect-bearing / string-bearing B tables. Four columns × four tables, all defaulted, all vacuous on

day one.

---

M5 · LENS · Family B drops two SURVIVING sekiro findings with no recorded reason

Issue. B's lens-input line asserts "p1a_sekiro_timing_defense.md (F1-F8 all survive…)" and §0.7

enumerates what B deliberately does not own. Two survivors appear in neither place.

refuter re-classed it upward: *"F8 — understated. Re-classed WEAKER→ WEAKER + MISSING, LOW →

MEDIUM-HIGH: the player HUD pip strip never reads a boss actor's pips at all"*

(p1a_sekiro_timing_defense.md L19-21). Grep of B for pip: the only hits are the §0.7 rank-16

deferral of F1's pip_fill_event columns and an unrelated stack_display enum value. F8 is

not designed, not deferred, not listed.

consumers." Grep of B for deflect|SFX_000: 0 hits. B's §4.1 rail carries

telegraph_sfx_id_ref (the incoming class sting), which is F3's channel, not F6's deflect

feedback.

Also: §0.7 mis-attributes F7. B writes "hitzone_parts carve keys (sekiro F7 → rank 16)".

Sekiro F7 is *"Ch 2 ships a ParryOnly attack the Ch-2 player cannot parry, against a ratified 2-of-3

scope"* — which B §4.1 correctly implements as gate assertion 1 and correctly calls "the F7 tooth".

The scope note and the design contradict each other on the same finding number.

Fix. Add F6 and F8 to §0.7's not-owned list with their real owners (F8 → the HUD/pip lane;

F6 → the SFX consumer lane), or carry them. A survivor may be deferred; it may not be silent — that

is the standing "recorded reason" discipline.

---

M6 · HOUSE MECHANICS · Family B's extension-rail idiom is wrong for 3 targets and gate-red on 2 more

Verified against docs/fidelity_baseline.json, docs/registry_extensions.json, and the checker

source harness/check_registry_extensions.py.

(a) Three of B's five extension targets are stub_superseded, not added_columns.

B §0.1 defines Vector B as: *"columns beyond the frozen _source 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."*

That is the wrong mechanism for defensive-properties (Weapon), ally-build (Familiar), and

counter-coverage (Boss_Encounter). Verified:

fidelity_baseline.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 the three appears in added_columns; none appears in extension_hashes (19 keys, listed).

The checker handles them on a separate path — check_registry_extensions.py L59-69: 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 those three is the

candidate_header + its pin, not added_columns/extension_hashes. B §6.2's migration table

frames all of them under the added_columns story.

(b) Two manifest keys B plans would trip I3 and turn the gate RED.

T0_Equipment_Registry**.

Both are wholly-added registries (T0_Rune_Registry is in added_registries; T0_Equipment_Registry

would be). Verified: not one of the 12 added_registries carries a manifest key today — the

extensions manifest holds 18 keys and none is an added registry. The checker's I3:

findings.append({"rule": "I3", "key": key,
                 "detail": "manifest key has no added_columns and no stub_superseded entry ..."})

An added registry has neither, so each key is an immediate FAIL. Adding columns to a wholly-added

registry is free — there is no frozen width to exceed — and the house answer is to declare no

manifest key at all.

Contrast, and credit. Family A gets this exactly right and says so explicitly (§0 point 4):

*"registry_extensions.json.extensions is NOT used by this family. That manifest owns columns on

existing registries, and Family A adds zero columns to any existing registry."* Verified true — A's

only live-registry touch is three new rows on T0_Worldstate_Variables.

Fix. B §0.1 grows a third vector ("columns on a stub_superseded registry → extend

candidate_header"), §6.4 step 3 drops the Rune and Equipment manifest keys, and §6.2's table is

re-columned by vector.

---

M7 · HOUSE MECHANICS · Family A's own seed rows fail Family A's own tooth T-A5

Issue. A's tooth T-A5 fails a row when effect_attribute *"names no live GAS attribute and no

live registry enum column."* 7 of A's 12 authored option rows name neither.

Evidence — the live GAS roster

(C:/dev/Humanity/Humanity/Source/Humanity/Public/Combat/HumanityAttributeSet.h, read this pass):

Health · MaxHealth · Vril · MaxVril · Stamina · MaxStamina · Rage · MaxRage ·
Composure · MaxComposure · MaxComposureNode ·
Composure_Direct · Composure_Stealth · Composure_PuzzleRouted · Composure_Environmental ·
Composure_VrilManagement · Composure_Familiar · Composure_Astral · Composure_Character

Evidence — the live registry enum columns (T0_Ability_Tree_Registry [ACTIVE v0.1]/Sheet1.csv,

35 columns, 185 rows): cast_pattern, persistence_class, physical_properties_array,

cooldown_class, vril_cost_class, range_class, duration_class, status_effects — all present.

The failing seeds (A §9.2, §9.3): cast_time, target_elemental_resistance,

elemental_superiority, damage_magnitude, crit_chance, movement_speed, projectile_count.

None is a GAS attribute; none is a registry column. A §8.2 promises the gate *"arms the moment rows

land"*, so all five Lane-A seeds plus two Lane-B seeds go red on the landing commit.

Positive control (per the standing "a search that cannot match reports zero" rule): Composure

and Rage DO resolve against the header, and cast_pattern/persistence_class/status_effects

DO resolve against the registry — so the check discriminates and the zero is real.

A's §2.3 acknowledges the dependency in a parenthetical — *"(+ derived damage/crit/resist channels

as the attribute set grows — the enum tracks the header)"* — but A's §10 landing order never names

the AttributeSet extension as a co-landing blocker, and A's pipeline_consumer table promises the

foundry binds "with no translation layer" against attributes that do not exist.

Fix. Either (i) name the UHumanityAttributeSet extension (damage/crit/resist/cast-time/

movement/projectile channels) as an explicit step-0 co-landing dependency in §10's ordering, or

(ii) scope T-A5 to WARN until the attribute set lands and say so in the tooth's own row. Silent

red is the one option that is not available.

---

M8 · FIREWALL · magnitude_ref means two different things, and both designs leak raw numbers

Issue 1 — one column name, two semantics. A routes every magnitude through an indirection with a

declared home: magnitude_ref / threshold_ref / breadth_floor_ref

T0_Balance_Constant_Registry.constant_id, minted as a new _deferred address (A §0). B's

magnitude_ref is *"string | Phase-5M placeholder key"* (§1.2, §5.1) with no target, and B never

mentions T0_Balance_Constant_Registry. Same column name across a freeze, two contracts — precisely

the outcome A §10 calls "unrecoverable".

Issue 2 — each design's stated firewall is stricter than its own tables.

five raw float magnitude columns — windup_seconds, active_seconds, recovery_seconds,

damage, punish_damage_mult — the last with the literal value stated in the design

("struct default 1.75"). Mirroring the shipped FHumanityAttackRow is legitimate reuse and

probably the right call, but the stated firewall and the table disagree in writing.

expected_pick_band_min / expected_pick_band_max are raw floats holding authored balance

shares — the one place A grants no ref indirection, while threshold_ref two columns over gets it.

(pick_budget / pick_cost as literal ints are defensible: §5A explicitly deferred that dial to

this pass, and A argues the case.)

Fix. One firewall sentence, stated once, in the shared preamble: magnitudes are refs; ordinals

and ratified counts are literals; a column that mirrors a shipped engine struct is a documented

exception and is listed. Then make B's magnitude_ref the same FK-to-be as A's, and either give

expected_pick_band_* the ref treatment or list it as the second exception.

---

M9 · RULING FIDELITY · §12's MANDATORY INT tradeoff has no schema expression

Issue. Addendum §12 rules the tradeoff as mandatory, verbatim:

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.
docs/COMBAT_PROGRAM_ADDENDUM.md §12

B's WS_027 extension (§3.1) carries ally_stat_block {str,dex,con,agi,acc,int}, ally_level,

unspent_level_choice_points, and level_choice_log. Nothing binds the six stats to a shared

budget, and no tooth asserts one. As schema'd, an ally can be maxed in INT and in every combat

stat — which makes the ruled competition unenforceable and silently deletes the axis that §10's

build-space sweeps are supposed to measure ("ally stat spreads are part of the build combinatorics").

unspent_level_choice_points is a spend counter, not a cap.

Neither family mints a budget. This is the one §§7-12 ruling I can find with no home in either

design.

Fix. A stat_point_budget (ordinal; magnitude at 5M) on the ally spread plus a sum-vs-budget

tooth in the same class as A's T-A12 (sum(pick_cost of held options) > pick_budget). Cheap, and it

is what turns "INT competes" from prose into a measurable constraint the sweeps can vary.

---

PART 2 — MODERATE FINDINGS

m1 · The loadout-set ceiling is authored twice

B mints T0_Loadout_Set_Definition (LS_01/02/03) carrying the unlock class, gates, venue, and the

departs_with_companion = FALSE invariant. A's WS_044 restates the same fact as

unlocked_count (int, DEFAULT 1, ceiling 3). Double-owner. B's registry is the correct home; A

should hold set_id and let the ceiling be the row count.

m2 · B asserts a column onto Family A that Family A does not mint

B §4.2: *"The same axis applies to Family A's tier-bonus rows."* Family A carries no bonus_axis

column anywhere. A's nearest analogue is a catch_window value inside bonus_kind_enum — a

different axis at a different granularity (bonus_kind is the effect's identity; bonus_axis is its

class). B presents timing_window as "a direct requirement of the §10 doctrine", which is a fair

reading — so either A adds bonus_axis, or B drops the cross-family claim. It cannot stand as an

assertion about someone else's table.

m3 · Combinatorial F7's rolled-instance list lands 5 of 7, and keep-rate lands 0 of 1

The lens NET item 6 enumerates: instance_id, archetype_ref, per-affix rolled_value,

reroll_count, locked_affix_mask, sigma_seq, source_context — *"plus keep-rate as the

rolled-layer analogue of pick share."* B's WS_043 covers five (instance_id, base_type_ref,

slot_rolls.rolled_ordinal/roll_percentile, reroll_count, locked_slot_mask, acquired_source).

sigma_seq is absent — and it is the join back to the per-drop_table_group σ counter B mints

in §1.3, so without it the σ bound cannot be audited per instance. Keep-rate appears in neither

B nor A's §7.5 per-option scorecard rows. Both are unrecorded drops.

m4 · Family A never names check_ws_value_form.py

B §1.6/§6.4 correctly identifies that the WS domain declarations must land in the same commit and

that the CG-25 +-prefix legal set is a ruled-list edit (flagged, not assumed) — good practice.

A mints three WS rows, one of them (WS_045 bonus_respec_ledger) an append/accumulate ledger,

exactly B's case, and A's §10 landing order omits the gate entirely.

*Sub-note against B:* B says CG-25 names "six append-legal object variables (WS_008, WS_012,

WS_018, WS_019, WS_026, WS_027)". The code constant holds seven:

# harness/check_ws_value_form.py:116
APPEND_LEGAL_IDS = frozenset({"WS_008", "WS_010", "WS_012", "WS_018", "WS_019", "WS_026", "WS_027"})

WS_010 is missing from B's list. The L20 docstring says six; the constant at L114-116 carries a

reconciliation comment and says seven. B read the label, not the content.

m5 · Two of A's "verbatim" provenance claims are approximations

six attributes, the seventy-two weapon proficiencies, the ten trades, familiar bond, language

fluency, inscription, Intuition, and Astral Projection — and gear imprints carry pools of their

own."* A adds ability and companion. Both are justified (this doc owns the ability instance;

§5I.3 assigns the companion layer to T1_Integrity_Paths) — but they are not verbatim.

Neither skill nor trait is a capability_kind; §5I.3 already translated them into the §3

roster. That translation should be recorded in the mint (a notes line mapping

skill/trait → attribute + proficiency) so the verbatim seed stays traceable to its home. Without

it, a later reader auditing §10 against the enum finds two ruled words with no row.

only one of the three is covered.

m6 · Merge-combinatorics-as-discovery has no home and no recorded owner

§11 rules: *"the merge combinatorics are DISCOVERY CONTENT: exploring what fuses is itself the

endgame play."* A's build_fingerprint consumes a merge_set and power_source_enum carries

merge, so the sweeps assume the axis exists — but nothing records **which merges a player has

discovered**. B's §0.7 not-owned list does not mention it. WS_035 spellcraft_authored_spells is

live and is the obvious host. Either wire it or record the owner (§2b / the Rune Forge rank) with a

pointer; an §§7-12 ruling should not fall through the gap between two families.

m7 · B's acquisition_source diverges from the column it claims to reuse

B §1.3: *"reuse the T0_Rune_Registry column NAME"*, then defines

`crafted · crafted-and-bounded-drop · boss_drop · part_break_carve · easter_egg_hand_placed ·

milestone · quest_guaranteed · found_exploring · purchased`. Verified live values in

T0_Rune_Registry.acquisition_source: operator-library ×17, crafted-and-bounded-drop ×1,

blank ×1. B's enum omits the dominant live value and mixes hyphen-case with snake_case inside one

closed set. Two registries, one column name, incompatible vocabularies — M2's defect class, one size

down. Fix: include operator-library, pick one case convention.

m8 · T0_Equipment_Registry's column arithmetic does not close, and the assetgen rail is 7 not 8

B §1.4 lists 16 domain columns (equip_idnotes), then reconciles: *"15 domain columns + 8

assetgen + 1 sfx = 24."* 16 + 8 + 1 = 25. Separately, the verified assetgen group on

T0_Weapon_Registry is 7 columns — mesh_id_ref sits in the base header, not the group:

T0_Weapon_Registry/Sheet1 → assetgen = [mesh_pipeline_type, substrate_material_ref_path, mesh_tags,
    generation_status, generation_prompt_hash, last_generated_timestamp, regeneration_trigger]

so "the assetgen rail copied VERBATIM from T0_Weapon_Registry" as an 8-column group is inaccurate

(the 8-column form is the one on Creature/Character/Familiar/Boss, which do carry mesh_id_ref in

the group). Trivial to fix, but a header width is a freeze artifact.

m9 · B's mythic firewall has an affix-side hole

check_rarity_firewall.py class (c) asserts no T0_RNG_Drop_Table row references a grade with

obtainable_by_roll = FALSE. Nothing stops T0_Imprint_Affix.rarity_id_min = RG_005 (mythic),

which would define an affix reachable only through a roll that can never produce it — a dead row

that reads as authored content. A's T-A4 clause (b) has the analogous pool-side guard

(grade_ceiling < mythic ⇒ no mythic option in that pool); B needs the affix-side twin.

---

PART 3 — MINOR FINDINGS

n1 · A's internal-vocabulary firewall rationale is mechanically wrong (outcome is correct).

A §0 says *_token / *_class columns stay out of the FText flow because of

*"REGISTRY_ROW_STRUCT_SPEC rule 2's exclusion list."* Verified rule 2

(docs/REGISTRY_ROW_STRUCT_SPEC.md §2): the match set is

(^|_)(title|name|description|summary|prose|caption|label|display|line|text|blurb)$ and the

exclusion set is _id|_ref|_tag|_tags|_status|_class|_type|_key. _token is in neither — those

columns never match rule 2 at all and fall through to rule 7 (FString). *_class is genuinely

excluded; *_token is merely unmatched. Right answer, wrong reason — worth correcting because the

next author will reason from the stated rule.

n2 · Both designs under-specify the fk_spec.json entry shape. Verified across all 21 live

entries, each carries registry + tab + primary_key + id_formats + foreign_keys, and FK

objects use column / references_registry / references_tab / references_column /

min_tokens (+ optional token_pattern, target_token_pattern, _note). Neither design names

tab or min_tokens. A's multi_value_separator (§8.1) is verified real and correctly used.

n3 · A's "register at first data" rationale runs against the house precedent. A §0 point 3

argues new tables enter fk_spec.json only once seeded, because *"a min_values floor of 0 is a

rule that cannot fail."* The live convention registers at draft time with a low anchor:

"T0_Rune_Registry": { "id_formats": { "rune_id": { "pattern": "RN_\\d{4}", "min_values": 2 } },
  "_note": "WS7 new-registry anchor (DRAFT v0.1). PK/id-format validated; FK enforcement DEFERRED
            until populated (fk_spec convention)." }

(19 live rows against a floor of 2.) A's discipline is stronger and should be kept — it should

just cite the convention it is tightening rather than imply the sequencing is the house rule.

n4 · A §1.3 leaves two FK targets unnamed. "T0_Language_Script_Registry PK" and

"T0_Inscription_Spine PK" — verified as script_id and spine_id. Name them; an unnamed PK in a

resolution map is how a mis-named FK survives a review.

n5 · Roster arithmetic collides across the two designs. harness/gates_config.json holds 25

gates today. A enrolls gate 26; B says "25 gates + the 2 new ones". Landed together the roster is 28,

not 26 or 27. Same for added_registries: 12 today; A says 12 → 17, B implies 12 → 20; together it

is 12 → 25. Each design is internally right and jointly wrong — the mint plan needs one arithmetic.

---

PART 4 — WHAT VERIFIED CLEAN (stated so the fixes are not mistaken for a rewrite)

Numbers. Every load-bearing repo number either design leans on checked out this pass:

expected_cell_diffs 4215 · added_registries 12 · extension_hashes 19 keys ·

added_rows[T0_Worldstate_Variables/Sheet1] 17 · WS max WS_042 · gates 25 ·

T0_Weapon_Registry 72×18 · T0_Ability_Tree_Registry 185×35 with 54 distinct ability_class

values · T0_RNG_Drop_Table 18 cols / 0 rows and genuinely missing sigma_window_length +

sigma_constraint_enabled · T0_Familiar_Registry 22 rows with blank abilities_granted ·

T0_Boss_Encounter_Registry 281 rows · WPN_033 Shield = CH_03 · Rune/Flora/Mineral rarity

distributions exactly as B reports them.

A's seed resolution. capability_ref values combat, mobility, healing all resolve against

the live ability_class column; A_F_002 = Fire Bolt and A_E_002 = Tremor Stomp verified by row.

Tooth T-A3 passes on the authored seeds.

A's two-index tooth is verbatim-correct. T-A2's gate_index ∈ {6,10} ⇒ no grade_index matches

§5I.1 exactly: *"The Portal at Gate 6 and the Crossing of the Abyss at Gate 10 confer no grade, so

each grants a major pick alone."* This is the sharpest piece of schema in either file — a single

tier_index column genuinely could not express those two rows.

MYTHIC is schema-expressed in BOTH, correctly and compatibly. A's T-A4 is a three-clause

invariant (gate ref + pool ceiling + a positive-controlled cross-table zero against

T0_RNG_Drop_Table); B's is obtainable_by_roll = FALSE on RG_005 plus firewall class (c). Both

correctly leave LEGENDARY roll-able, which matches §5I.4's *"the gear-imprint rune lane … reaches its

own ceiling by rolls, and the earned apex sits above what any roll can reach."* Both correctly treat

D-MYTHIC-GATE as a row value, not a schema question.

KILLED findings stay dead in both. A does not resurrect option_source (dqpm F4), a parallel

magnitude_class ladder (dqpm F5), a second allocation ledger (dqpm F6), and proposes **no tier-doc

amendment** (combinatorial F1 — correctly, since T1_Integrity_Paths §8.11.5 already calls the

deferred child table "the T0_Familiar_Registry extension registered per

docs/registry_extensions.json"). B does not resurrect the acquisition-σ / roll-quality-σ split

(bl-loot F3), does not mint drop_table_ref (bl-loot F7's correction — it reuses rng_drop_anchor),

does not relocate respec to the vril well (combinatorial F8's correction), does not add int_tier to

the ratified (companion_id, relationship_state_bucket) fallback key (creature F5's correction —

and B's reasoning about the ruled combat zero-model firewall is the best passage in either file), and

mints no player→ally order verb (creature F6's re-route).

EXAMPLES-NOT-LIMITS is preserved as data, not just prose. A carries it per pool in notes +

populated_from and states the enum-growth rule explicitly; B carries an examples_not_limits note

per pool-bearing table and in the DOC_MAP row. No pool is closed by construction in either.

Natural-voice discipline holds in both. No player-facing string is authored as system voice

anywhere — every one is a declared placeholder for the rewrite pass. A's pool_display_name /

option_name / player_text and B's *_name_text / display_name_text / display_intent_text all

correctly auto-route to FText under rule 2, and both correctly keep machine tokens (*_class,

*_ref, *_status) out of the localization flow. A additionally mints the pipeline's worklist

(string_status) and a voice_register_ref FK to the live T0_Voice_Registry.voice_id — the

stronger of the two treatments, and the one B should adopt (see M4).

Additive-only holds in both, on the specifics that matter. Neither design adds a column to a

frozen base row; neither edits an existing cell; A's zero-column claim is verified; B's

back-compatibility guarantee on WS_012.bond_tier (a derived view over the new bond_value, so all

99 existing spine writes keep resolving) is the right instinct and correctly reasoned.

---

PART 5 — THE FIX LIST, ORDERED

Blocking, in the order they should be resolved:

1. M1 — one worldstate allocation table; one owner for loadout state.

2. M2 — one rarity representation; carry both halves of the creature-F8 survivor.

3. M3 — B's role/spec columns become FKs into A's registries.

4. M4power_source + lifecycle + string_status onto B's four effect/string-bearing tables.

5. M8 — one firewall sentence; B's magnitude_ref gets A's target; exceptions listed.

6. M6 — B's §0.1 gains the stub-superseded vector; drop the two I3-tripping manifest keys.

7. M7 — A names the AttributeSet extension as a co-landing dependency, or scopes T-A5 to WARN.

8. M5 — sekiro F6 + F8 get a recorded owner; fix the F7 attribution in §0.7.

9. M9 — mint the ally stat budget + its tooth.

Then the MODERATEs (m1-m9) before rows land, and the MINORs in place.

*Critic pass: read-only. Nothing in C:/dev/humanity-forgotten or C:/dev/Humanity/Humanity was

modified; this file is the sole write.*

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