{
 "_README": "Curated PROSE that states a rule read out of the game code (not a table value). Each claim names the methods it depends on; pipeline/check_code_claims.py hashes those method bodies from the new build's arm64 slice and update.sh prints RE-CHECK when one changed. After re-reading a changed body, fix the prose, then run `python3 pipeline/check_code_claims.py --stamp <id> <build>`. Never stamp a claim you did not re-read. A claim with no hashes has never been checked against a build and stays on the RE-CHECK list until someone does. Symbols are Class.Method as in the dump; code_truths.json citations are covered automatically and are not repeated here.",
 "depletion_per_floor": {
  "claim": "The Dungeon Depletion drop penalty applies only to the floor whose counter is 0, not to the whole region. The boss floor has no counter. The wiki said region-wide until 2026-09-25; every local dump since B.0.3.40 (24354931) has the per-floor body.",
  "where": [
   "data/curated/mechanics.json#depletion",
   "data/curated/mechanics.json#beginner-guide",
   "data/curated/glossary.json#Depletion",
   "pipeline/gen/common.py#MECHANIC_SOURCES"
  ],
  "symbols": [
   "DropHelper.GetDropCoefficient",
   "EnvironmentDataContainer.DecreaseDepletionData",
   "EnvironmentDataContainer.CheckDepletionInterval",
   "EnvironmentDataContainer.InitDepletionData"
  ],
  "reviewed_build": "25284551",
  "hashes": {
   "DropHelper.GetDropCoefficient": [
    "c61958517a3b1bad"
   ],
   "EnvironmentDataContainer.DecreaseDepletionData": [
    "999872842f4210d1"
   ],
   "EnvironmentDataContainer.CheckDepletionInterval": [
    "ebaaea7d55a9ca9b"
   ],
   "EnvironmentDataContainer.InitDepletionData": [
    "dd3d47240b139fe9"
   ]
  }
 },
 "safe_floor_routing": {
  "claim": "Veil of Silence and the Tutorial never get a safe floor; Abandoned Mine forces its safe floor and ignores the skip option.",
  "where": [
   "data/curated/mechanics.json#safe-floors",
   "data/curated/glossary.json#Safe floor"
  ],
  "symbols": [
   "MapTransitionTargetPrepareService.GetProperFloor",
   "ExpeditionPlanPresenter.ShouldForceSafeFloor"
  ],
  "reviewed_build": "25284551",
  "hashes": {
   "MapTransitionTargetPrepareService.GetProperFloor": [
    "be9b7e3a65296dcc"
   ],
   "ExpeditionPlanPresenter.ShouldForceSafeFloor": [
    "57f2182cf28b29b0"
   ]
  }
 },
 "region_unlock_chain": {
  "claim": "Region unlock is stored in the save and loaded as saved; the load never re-opens linked regions. Veil of Silence starts open. Clearing a region opens the regions its SetAdjacency row links (Veil -> Festering Burrow; Festering Burrow -> Abandoned Mine and the Infinite Abyss; Forgotten Abyss <-> Dead Swamp; Abandoned Mine -> nothing). In play, clearing a region is the only thing that opens another one.",
  "where": [
   "data/curated/mechanics.json#region-unlock",
   "data/curated/mechanics.json#save-files",
   "data/curated/mechanics.json#beginner-guide",
   "data/curated/mechanics.json#quests"
  ],
  "symbols": [
   "ExpeditionMapData.GetAvailableRegion",
   "ExpeditionMapData.OpenAdjacentRegion",
   "ExpeditionRegionAccessPolicy.SanitizeRequestedRegion",
   "ExpeditionRegionAccessPolicy.IsRegionBlocked",
   "EntityEventHandler.TryMarkCurrentRegionBossDefeated",
   "ExpeditionMapData.Deserialize",
   "ExpeditionMapData.InitializeDungeonDatas",
   "ExpeditionMapData.SetAdjacency"
  ],
  "reviewed_build": "25284551",
  "hashes": {
   "ExpeditionMapData.GetAvailableRegion": [
    "803722ed1834d8c6"
   ],
   "ExpeditionMapData.OpenAdjacentRegion": [
    "4e8fcfd3629662e6"
   ],
   "ExpeditionRegionAccessPolicy.SanitizeRequestedRegion": [
    "95a1a0cde11f677c"
   ],
   "ExpeditionRegionAccessPolicy.IsRegionBlocked": [
    "842f2d869c4ac737"
   ],
   "EntityEventHandler.TryMarkCurrentRegionBossDefeated": [
    "d59cde18394a73e2"
   ],
   "ExpeditionMapData.Deserialize": [
    "924da14380c9078f"
   ],
   "ExpeditionMapData.InitializeDungeonDatas": [
    "5d3017f11799d464"
   ],
   "ExpeditionMapData.SetAdjacency": [
    "0d3c9649078f7b76"
   ]
  }
 },
 "savegen_item_proc_holders": {
  "claim": "Equipping an item adds each of its Equipment_OnEquipAffecters to the unit's AffecterHolders, and loading a save re-registers only the holders the file carries (nothing is re-derived from the equipment). So the Builder's save generator must write one holder per OnEquip affecter of every worn item, or the item never procs.",
  "where": [
   "pipeline/gen/pages_builder.py#_savegen_data",
   "pipeline/gen/pages_builder.py#addUnit",
   "pipeline/check_savegen_holders.py"
  ],
  "symbols": [
   "ItemControlProcessor.ProcessEquip",
   "EntityLoadHelper.LoadUnit",
   "AffecterComponent.Deserialize"
  ],
  "reviewed_build": "25846389",
  "hashes": {
   "ItemControlProcessor.ProcessEquip": [
    "90c6a0b8b726143f"
   ],
   "EntityLoadHelper.LoadUnit": [
    "fee61852bcfe9701"
   ],
   "AffecterComponent.Deserialize": [
    "a50f7b5a0efc8f11"
   ]
  },
  "checked": "2026-10-12 re-read on 25846389 (decomp_25846389 ProcessEquip @0xd496d4): only the ItemControlProcessor field offsets moved (+8, new _itemDrops dictionary at 0x30); the body still loops ItemTableData.Equipment_OnEquipAffecters (+0x70) and requests one AffecterApplyData per entry. LoadUnit and AffecterComponent.Deserialize hashes unchanged. Rule holds."
 },
 "elixir_permanent_stats": {
  "claim": "A stat elixir (ITEM_<Major>Elixir) adds its skill's FloatValues[0] to that major PERMANENTLY: SKILL_<Major>Elixir.SkillRoutine calls AddPermanentStatus(caster, StatType.<Major>, FloatValues[0]); StatusApplier.Apply sends a Permanent status to StatusComponent.AddPermanentValue, which adds it to the live stat AND to _permanentStats, serialized as the save's PermanentStats. The builder counts elixir uses into the majors, reads whole uses back from PermanentStats on save import, and the save generator writes them there.",
  "where": [
   "pipeline/gen/consumables.py#stat_elixirs",
   "pipeline/gen/pages_builder.py#elixAmount",
   "pipeline/gen/pages_builder.py#majorSplit",
   "pipeline/gen/pages_builder.py#dsbExtractUnit"
  ],
  "symbols": [
   "SKILL_StrengthElixir.<SkillRoutine>d__0.MoveNext",
   "SKILL_ConstitutionElixir.<SkillRoutine>d__0.MoveNext",
   "SKILL_WillPowerElixir.<SkillRoutine>d__0.MoveNext",
   "SKILL_IntelligenceElixir.<SkillRoutine>d__0.MoveNext",
   "SKILL_AgilityElixir.<SkillRoutine>d__0.MoveNext",
   "SKILL_PerceptionElixir.<SkillRoutine>d__0.MoveNext",
   "StatusComponent.AddPermanentValue",
   "StatusApplier.Apply"
  ],
  "reviewed_build": "25284551",
  "hashes": {
   "SKILL_StrengthElixir.<SkillRoutine>d__0.MoveNext": [
    "2fd83cc4157c40d3"
   ],
   "SKILL_ConstitutionElixir.<SkillRoutine>d__0.MoveNext": [
    "251606ebf5e177f2"
   ],
   "SKILL_WillPowerElixir.<SkillRoutine>d__0.MoveNext": [
    "471ddd072975be36"
   ],
   "SKILL_IntelligenceElixir.<SkillRoutine>d__0.MoveNext": [
    "b6eceb67687c103e"
   ],
   "SKILL_AgilityElixir.<SkillRoutine>d__0.MoveNext": [
    "7dad84d17495fce8"
   ],
   "SKILL_PerceptionElixir.<SkillRoutine>d__0.MoveNext": [
    "a0857b8b317fc6fe"
   ],
   "StatusComponent.AddPermanentValue": [
    "c8cf11f9ec278d8e"
   ],
   "StatusApplier.Apply": [
    "03b91666fef4cd45"
   ]
  }
 }
}
