pipelines/MINT_DESIGN_CRITIC_2026-07-27.md
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.
---
Issue. Both designs mint new T0_Worldstate_Variables rows off the same free number and collide.
| id | Family A (§6) | Family B (§1.6, §2.2) |
|---|---|---|
WS_043 | bonus_selection_state | item_instance_ledger |
WS_044 | loadout_set_state | loadout_set_state — different sub-fields |
WS_045 | bonus_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.
---
Issue. A extends the existing enum; B mints a parallel FK'd registry. Both cannot land.
rarity_class_enum = common · rare · epic · legendary · mythic · none — a closed enum on grade_ceiling (A1) and rarity_class (A2). "mythic is the one new value."
T0_Rarity_Grade, a NEW registry, rarity_id = RG_\d{3}, 8 tokens (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 existingrarity_classenum (which already carriesnoneand
legendary), do not mint a parallelitem_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.
---
Issue. §11 rules "one role taxonomy, two arenas". The two designs mint two.
| Family A | Family B | |
|---|---|---|
| role axis | T0_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 purpose | T0_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.
---
Issue. A §2.4 and §10 declare a "cross-family contract (do not diverge)". Grep of
mint_design_B_item_ally.md:
| contract | A | B (grep count) |
|---|---|---|
power_source | power_source_enum on every option row; sweep emits power_source_share{}; defect D8 source_dominance | 0 |
lifecycle | lifecycle_enum + superseded_by on A1/A2/A3/A4/A5; tooth T-A8 (id reuse) | 0 |
string_status | enum on A1/A2; tooth T-A10 is the natural-voice worklist query | 0 |
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.
---
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.
---
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.
imprint-loot group on T0_Rune_Registry (2 columns).assetgen + sfx-pipeline groups on the **new 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.
---
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.
---
magnitude_ref means two different things, and both designs leak raw numbersIssue 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.
T0_Boss_Attack_Rail (§4.1) mints 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.
---
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.
---
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.
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.
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.
check_ws_value_form.pyB §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.
capability_kind_enum *"the §5I.3 §3 roster verbatim."* §5I.3 verbatim reads: *"thesix 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.
rarity_class)" — see M2;only one of the three is covered.
§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.
acquisition_source diverges from the column it claims to reuseB §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.
T0_Equipment_Registry's column arithmetic does not close, and the assetgen rail is 7 not 8B §1.4 lists 16 domain columns (equip_id … notes), 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.
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.
---
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.
---
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.
---
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. M4 — power_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.*