"Per-game audit of Fallout 3 compatibility — NIF v20.2.0.7, BSA v104, ESM via FNV-shared parser"
Instal·la
npx skillscat add matiaszanolli/byroredux/claude-commands-audit-fo3 Instal·la des del registre de SkillsCat.
Fallout 3 Compatibility Audit
FO3 rides the FNV path almost end-to-end (NIF v20.2.0.7 / BSVER 34, BSA v104, one ESM parser, one cell loader, one RT pipeline). This is NOT a re-run of /audit-fnv: it hunts the divergences — where FO3 content exercises a path FNV doesn't, where shared code carries an FNV-only assumption, and where a feature is verified on FNV but only assumed on FO3. Its data goes through shared mechanisms owned elsewhere (.claude/commands/_audit-owners.md); a defect in the mechanism is filed against its owner, but tag its FO3 reach: a shared-code regression hits all four classic games (the 2026-09-19 HIGH did).
Architecture: Orchestrator. Each dimension runs as a Task agent (max 3 concurrent).
Read .claude/commands/_audit-common.md (layout, methodology, dedup, finding format) and .claude/commands/_audit-severity.md for shared protocol.
Game Context
| Aspect | State |
|---|---|
| NIF / BSA | v20.2.0.7 BSVER 34 · BSA v104 · 7 mesh/texture archives (base + 5 DLC - Main.bsa) |
| Parse baselines (pull) | crates/nif/tests/data/per_block_baselines/fallout_3.tsv (17 172 NIFs, 6 mesh archives, 145 types, 0 unknown — the gate walks open_all_mesh_archives, #3041), ROADMAP.md FO3 row, docs/feature-matrix.md, .claude/audit-baselines/runtime/fo3-MegatonPlayerHouse.tsv |
| Reference data | /mnt/data/SteamLibrary/steamapps/common/Fallout 3 goty/Data/ |
| FO3 vs FNV | Both are GameKind::Fallout3NV. The only discriminator is CharacterRulesProfile (FALLOUT3 vs FALLOUT_NEW_VEGAS, #4448). A divergence branch keyed on GameKind cannot tell them apart; pins: obscript_dialect_follows_the_profile_not_the_game_kind (byroredux/src/cell_loader/references/attach.rs), fn586_condition_gate_is_profile_scoped_not_game_scoped (crates/plugin/src/consumables.rs) |
Authoring census (measured — each line is a checklist premise that has already rotted once; re-measure before asserting the opposite):
- Inline shader stack only: 0 BGSM/BGEM in the FO3 archives; 0
bump_texture; no bump-tiling field exists on anyBSShader*Property. - 0
XATO/XTNM/XTXRinFallout3.esm— no REFR texture overlays (#3511);byroredux/src/cell_loader/refr_texture_overlay_tests.rsfixtures are FO4-shaped and prove nothing about FO3. Fallout3.esm: 718 952 records (HEDR.numrec808 699 = records + GRUPs + the TES4 header), 1 257 SCPT, 54 SCOL bases / 389 REFRs, 244 TXST records (243 parsed — Bethesda's own NullTextureSet is skipped), 51 LTEX all carryingTNAM(the 51landscape_texture_setsentries).- NIF: 1 374
BSSegmentedTriShape(#3101's "zero" measured one archive), 112bhkConvexListShapechains, 0bhkMultiSphereShape, B-splines are 83% of base-archive.kf— never rule them out by era. - Object LOD: 114
<world>.levelN.high.x<X>.y<Y>.nifquads that no code path consumes (54 inFallout - Meshes.bsa— 28washmontop.level8, 26wasteland.level4; 60 inAnchorage - Main.bsa), every one with a plain sibling — censused-not-consumed by design (#4468, closed;probe_lod_corpus). - Known-open, do not re-file (
gh issue viewfirst): #4772 (a copied-save restore's first ragdoll solve throws the root to ~1e12 BU on FO3; the recovery masks it, Dim 5), #5642 (force-greet pass 2 opens every in-radius greeter against a staleopen_partnersnapshot, Dim 2/5), #5669 (the #5400 header census gates only Obliviontextures\menus\, not FO3/FNVtextures\interface\, Dim 4). Every FO3 finding of the 2026-10-08/09 audits is fixed — verify, don't re-file: #5428 (kill-script provenance follows the load order's last-writer table,335a0179c, Dim 2), #5429 (FO3 dialogue real-data floor + declared dt1 SKIP,c6e48cbc6, Dim 2/5), #5433 (the FO3 profile mountsFallout - Sound.bsa+Fallout - Voices.bsa+Fallout - MenuVoices.bsa,4ef386a1e, Dim 2), #5521 (voice names truncate only over 25,4d6294bb1, Dim 2), #5494 (an override's PNAM-less INFO heads fold in authored file order,5356c8780, Dim 2), #5499 (package selection continues past a fail-open Dialogue decline,f7ca4a60f, Dim 5), #5500 (Eat/Sleep Near-Linked-Reference / In-Cell anchors,bcaf63aa8, Dim 5), #5496 (LOD rings key on the PNAM "Use LOD Data" ancestor,2ca57c4bc, Dim 3), #5518 (legacy quad-index scan keys on either family table,5a549e664, Dim 3), #5520 (prune tie-break on authored-cell coverage,a9577fd69, Dim 3), #5073 (empty compressed BSA placeholders extract as empty files,fa2af0e89, Dim 4). Fixed 2026-10-08..09: #5387 (same-level LOD leftovers pruned,fbf1bed74, Dim 3), #5393 + #5395 (voice owner + file name,5b68792b7, Dim 2), #5390 (legacy sleep = sit fallback,9bdfdd1c6, Dim 5), #5423 (LOD rings + climate on the layout table,b3e679dba, Dim 3). Fixed 2026-09-29..10-05: #4469 (INFODATAdecoded,cc9353043), #5005 + #5223 + #5248 + #5304 (corpses, Dim 2), #5222 (legacy LOD quad index,b7987d813, Dim 3), #5224 (DIALTop-levelflag,305363122), #5225 (LOD census,4e9cf87b9), #5226 (unmatched--wrlderrors,c6cbbe9f9), #5238 (NPC Health curve,c71eeed80), #5271 (per-INFOQSTIquest gate,dbc07e8f0). Older guards: #4398 (emitter orientation), #4401 (clamp/parallax re-latch), #4468 (.high.quads), #4122 (SPT tail desync,/audit-speedtree).
Parameters (from $ARGUMENTS)
--focus <dimensions>: comma-separated numbers (e.g. 1,4). Default: all 5.
Phase 1: Setup
- Parse
$ARGUMENTS;mkdir -p /tmp/audit/fo3. - Dedup baseline:
gh issue list --repo matiaszanolli/ByroRedux --limit 200 --json number,title,state,labels > /tmp/audit/issues.json. - Confirm
Fallout 3 goty/Data/exists; if not, name the dimensions that lose real-data validation. - Run the real-data lane first — it is the only guard for shared-code regressions on FO3 and no CI lane runs it:
cargo test -p byroredux-nif --release --test parse_real_nifs --test per_block_baselines --test block_coverage_baselines -- --ignored fallout_3 real_archive_torch. A red gate is the headline finding; dimension agents then explain it. - Reconcile every count against the tables above and the ROADMAP/feature-matrix rows. Measure across all archives (base + DLC), never the base archive alone.
- Scope by delta:
git log --since=<last AUDIT_FO3 date> --format='%h %cs %s' -- <dimension Paths>. - Toolchain: the
byroreduxbin crate needs rustc >= 1.96 (wasmtime 49, 15a6b1d2d) — rustup cargo perdocs/contributing.md§ Toolchain note (#4466).
Phase 2: Launch Dimension Agents (parallel)
Dimension 1: NIF, Inline-Shader Material & Collision — FO3 Authoring
Subagent: legacy-specialist
Routing: block decode /audit-nif; single-boundary / no-fabrication / particle + collision translation /audit-nifal; Disney-BSDF gate (MAT_FLAG_PBR_BSDF must be 0, FO3 authors no BGSM) /audit-renderer; solver + phantoms /audit-physics.
Paths: crates/nif/src/blocks/shader/, crates/nif/src/blocks/particle.rs, crates/nif/src/shader_flags.rs, crates/nif/src/import/material/, crates/nif/src/import/collision/, crates/nif/src/import/walk/emitter.rs, byroredux/src/material_translate.rs
First step: the Phase 1 lane, plus git log --since=<date> -- crates/nif/src/import crates/nif/src/blocks/shader
- FO3 shader properties use the
BSShaderFlagsF1 +BSShaderFlags2F2 pair (fo3nv_f1/fo3nv_f2inshader_flags.rs) — never the Skyrim/FO4 vocabularies (same numeric bits, different meaning). Both properties are field-for-field with nif.xml on every BSVER gate (14/24/26/34). - Texture precedence: a
BSShaderTextureSetoutranksNiTexturingPropertyfor base + normal (#4235; census: 3 703 NoLighting base co-binds all name the identical path). Clamp mode + parallax pair re-latch with it (#4401;displacing_the_base_path_re_latches_the_clamp_mode,legacy_property_precedence_tests.rs). BSShaderNoLightingProperty->MATERIAL_KIND_NO_LIGHTING(102) fullbright with no distance term (crates/renderer/shaders/triangle.frag); decal bits honored on both properties; two-sided comes fromNiStencilProperty(no FO3 flag bit); legacy emissive isEmissiveSource::Materialonly.BSSegmentedTriShapedecodes the nif.xml 9-byte segment layout and feeds the plainNiTriShapegeometry arm; segment (dismemberment) metadata is consumed-and-discarded by design — route to/audit-nifal+/audit-characterwhen a consumer exists.- Emitter birth rate: FO3's leg of
real_archive_torch_meshes_surface_particle_emitters(crates/nif/tests/parse_real_nifs.rs,--ignored) must hold its per-game floor. #4261 broke it on every game from 2026-09-12 to 2026-09-19 (#4467) because the fix ran only the default lane — any change underwalk/orblocks/particle.rsneeds this lane. Spawn cones follow the emitter's composed orientation (#4398;flat_walker_composes_the_emitter_rotation). - Collision: all FO3 chains classify
CollisionAuthoring::Classic;havok_motion_typekeeps BOX_INERTIA crates Dynamic (1 612 in FO3); every FO3-authored bhk shape kind has aresolve_shapearm (a new dispatch arm needs a resolve arm).
Output:/tmp/audit/fo3/dim_1.md
Dimension 2: ESM Data Slice (Fallout3.esm)
Subagent: general-purpose
Routing: GRUP walk, SubReader accounting, dispatch, remap /audit-esm. This dimension owns FO3-only authoring and its counts.
Paths: crates/plugin/src/esm/records/, crates/plugin/src/esm/cell/, crates/plugin/tests/parse_real_esm.rs
First step: cargo test -p byroredux-plugin --release --test parse_real_esm -- --ignored parse_rate_fo3_esm (one test at a time; whole-file --ignored runs can spike >20 GB).
- Baseline (#3756):
index.total()>=FO3_TOTAL_FLOOR(44 000) is an index-sum over ~95 typed maps that double-counts by design — NOT a file record count. Also floor the cell tierindex.total()cannot see: placed refs >= 573 000 (REFR 568 107 + ACHR 2 154 + ACRE 3 349 + PGRE 350) and exterior cells >= 41 900; 0 walker errors on the master and all 5 DLCs. Never cite "44 657" or "13 684". - FO3 is a strict subset of FNV's
NPC_/DIAL/INFOsubforms (sole FO3-only subformINFO.SNDD, 1 record) and sharesCELL.XCLL(XCLL_SIZES_FALLOUT_ERA, FO3{36,40}); the SCOL gateis_scol_eramust keep FO3 dispatching (54 bases / 389 REFRs).SCHRu16 tail: see/audit-fnvDim 2. - The one FO3 TXST consumer is
LTEX.TNAM -> TXST -> TX00->EsmCellIndex.landscape_texture_sets(terrain splat diffuse); the other ~192 parsed TXST have no live consumer on this title. - Dialogue decode (consumer:
byroredux/src/systems/npc_dialogue.rs,/audit-gameplay): INFODATAstores the type byte + rawu16flags on all 22 327 INFOs, the per-game reading left to the consumer (#4469,cc9353043;parse_info_data_header_decodes_type_and_flags); DIALDATAbyte 1 is the Rumors 0x01 / Top-level 0x02 flags — only 844 of 5 130 Topic DIALs are top-level, the rest link-only (#5224,305363122). INFOQSTIis decoded intoInfoRecord.quest(all 23 247 measured FNV INFOs author it) and gates each INFO on its own quest's running state, ordered by quest priority viaDialogueQuestPriorities(#5271,dbc07e8f0;a_stopped_quests_info_does_not_speak_through_a_running_sibling,byroredux/src/systems/npc_dialogue.rs). INFO-sideSNAM,NEXTand the script family are still undecoded (none consumer-blocking). - #5367 runtime on FO3 (shared path; the only live gate,
docs/smoke-tests/dt1-dialogue-layers.sh, is FNV —dt1 fo3is a declared SKIP, exit 77, never a pass, #5429,c6e48cbc6; FO3's data premises are floored instead by the--ignoreddialogue_greeting_and_forcegreet_fo3_floorincrates/plugin/tests/parse_real_esm.rs: literalGREETING>= 2 500 INFOs +HELLO, >= 380 Dialogue-procedure PACKs (386 measured), >= 22 000 INFOs (22 327) with 0 quest-less; a measured FO3 cell / NPC / PACK live pin is the open work): the genericGREETINGfallback (oneGREETING/HELLODIAL per FO3 plugin, resolved once per load order asEsmIndex::generic_greeting_form, #5426); the positional Random stack, closed by a passing plain line or Random End (Flags1bit 5 on TES4/FO3/FNV; #5397,0436bea5c; pins incrates/scripting/src/dialogue.rs); DLC DIAL overrides fold their INFOs into the master topic by FormID instead of replacing it (#5375,168b81322;dialogue_override_folds_infos_into_the_master_topic), an override's PNAM-less head run composing in authored file order behind a per-override contribution cursor (#5494,5356c8780— The Pitt's 93 heads no longer let "Go away." outrank 92 greetings). Voice (byroredux/src/systems/dialogue_voice.rs): the owning plugin resolves throughGlobalFormIdResolver(#5393), the name cuts the quest EDID to 10 and the topic to a 25-char total only when quest + topic exceed 25, otherwise full EDIDs, one candidate (#5521,4d6294bb1), writes the plugin-local id and each segment's authored response number (19 FO3 INFOs skip 1..k) (#5395,5b68792b7; 11 955 / 11 955 joinableFallout3.esmlines resolve, 2026-10-09; pinsvoice_path_candidates_truncate_only_over_the_length_limit,voice_owner_resolves_masters_before_the_esm); a topic change or conversation close cuts the playing line (#5432,40b77828b). The FO3 profile (assets/debug_profiles.toml,[profiles.fo3]) mountsFallout - Sound.bsa,Fallout - Voices.bsaandFallout - MenuVoices.bsaasdefault_sounds_bsas(#5433,4ef386a1e; pinfo3_profile_declares_sound_and_voice_archivesincrates/game-detect/src/lib.rs);fo3.envstill passes onlyFallout - Sound.bsa. PKDD Dialogue Type is theu32at offset 16 (19 FO3 Say-To packages), so the #5376 Say-To decline gate fires (#5492,dae08000d). - Authored corpses (mechanism
/audit-gameplay): baseDATAhealth <= 0 marks 498 FO3 placements (#5005,fo3_corpses_key_on_base_health_not_xrgd), and the 85 dismember-triggerXLKRtargets + 3 self-killing bases are recognised at load because no FO3 object script runs (#5223,717f39a82;fo3_fnv_script_killed_corpses_match_the_measured_census). The set is computed once per load order over every cell (interior, grid, worldspace-persistent) as theScriptKilledCorpseFormsresource, because a trigger and its persistent target never share aload_references_budgetedcall (#5248,d4e8c31be; the union-over-all-cells census cannot see locality, so a per-call regression passes it). Recognition needs one of the 11 exact shippedGenericBiped*DismembermentSCRIPTEDIDs **and** a winning SCPT that resolves to a vanilla master, so name-alikes decline (#5304,2d47bf7f1;kill_on_load_recognition_requires_exact_edid_and_vanilla_master). A true override patch keeps the master's FormID, soscript_is_vanillaconsults theLoadOrderscript_winnerslast-writer table (SCPT FormID -> position of the last plugin that wrote it) rather than the FormID's slot byte, and declines it (#5428,335a0179c;kill_on_load_recognition_declines_a_true_override_of_a_vanilla_script, both passes); the slot owner is only the fallback for hand-built orders with no writer table. The whole-load-order scan returns the empty set up front off FO3/FNV (#5450,eaac75911). NPC Health seeds from the authored NPC curve (#5238; Nova = 40.0, Three Dog 25); a non-auto-calc NPC (ACBS bit 4 clear; ~712 FO3 actors) seeds its authoredDATASPECIAL (NpcRecord::data_attributes) instead of the classATTR(#5338,4957536ba).
Output:/tmp/audit/fo3/dim_2.md
Dimension 3: Cell Loading — Interior + Exterior
Subagent: general-purpose
Routing: terrain / WTHR / water / LOD mechanism /audit-exterior; unload hygiene /audit-safety Dim 3.
Paths: byroredux/src/cell_loader/ (load, unload, exterior, references/, spawn), byroredux/src/scene/, byroredux/src/cell_loader/legacy_lod_index.rs, crates/plugin/src/esm/cell/wrld.rs, docs/engine/exterior-readiness-plan.md
First step: git log --since=<date> --format='%h %cs %s' -- byroredux/src/cell_loader byroredux/src/scene crates/plugin/src/esm/cell
- Interior
MegatonPlayerHouse: 929 REFRs parse-side (never the stale 1609); fixture cell MegatonMoriartysSaloon 458 REFRs. GPU entity/FPS numbers come only from a Vulkan run — record "not measured" otherwise. - Exterior (Capital Wasteland): worldspace selection is data-driven (
select_worldspace_key, deterministic tie-break;--wrldoverrides #444's heuristic, and an unmatched--wrldnow errors naming the loaded EDIDs instead of silently loading Wasteland's copy of the cell — #5226,c6cbbe9f9) — FO3 data has nowastelandnvEDID, so an FNV-first preference can never mis-pick;wrld.rsmust hold no hardcoded worldspace name, origin or grid. EveryGameKinduse on the load path is asset-family classification, not a behavior branch. Gate:docs/smoke-tests/m-exteriors.sh fo3(MegatonWorld); last measured figures inexterior-readiness-plan.md(no FO3 scene is in the ROADMAP bench-of-record table). Default land texture isDirtWasteland01.dds(DefaultLandTexture::for_game). - Object LOD is
ObjectLodScheme::FalloutLegacyBlocks(placement_lod_supportedis Oblivion-only). It is not a flat ring (#3502): 7 of FO3's 15 worldspaces bake level-8 object quads with no level-4 sibling (93 of the 366 plain quads inFallout - Meshes.bsa— its 422blocks\entries also carry 54.high.variants and 2…postapocalypse.nif, variant files not quads; 366 base + 331 DLC = 697 plain corpus-wide:dcworld01/03/06/12/17,paradisefalls,washmontop);LodBandSelection::coarsen_to_availablemust stay **object-only** (terrain keeps subdividing —object_lod.rstrue /terrain_lod.rsfalse) and those worldspaces must show distant buildings inside 16 cells — the legacy family no longer derives a grid origin (#5222,b7987d813): 26 of 29 worldspace/level sets sit off(0,0)with no single origin, soLegacyLodQuadIndex(byroredux/src/cell_loader/legacy_lod_index.rs) scans the archive name tables once per streaming state andselect_authored_lod_quads(lod_bands.rs) picks quads by footprint (objects from the mesh BSAs, terrain from the diffuse DDS names,.high.variants riding their plain sibling; terrain tops up uncovered ring ground with level-4 synth tiles). Selection first keeps each level's majority lattice residue (prune_same_level_overlaps): six FO3 worldspaces ship same-level quads from different LOD generations whose footprints and geometry overlap — washmontop 65 overlapping pairs among 37 level-8 quads (#5387,fbf1bed74;same_level_leftover_generation_quads_are_pruned; a count tie in the residue vote goes to the class whose footprints cover more of the LOD source worldspace's authored exterior cells, residue order only on a coverage tie (#5520,a9577fd69;lod_source_cell_existsthreads throughselect_authored_lod_quadsfrom both ring call sites; exal.md keeps open which lattice the shipped game loads). The terrain ring gates onterrain_lod_layout(FalloutLegacy), notGameKind::Fallout3NV(#5423,b3e679dba); the quad-index scan (should_scan_legacy_lod_quads,byroredux/src/streaming_helpers.rs) fires when either the terrain-layout or the object-scheme table selects the legacy family (#5518,5a549e664). **LOD-inheriting children**: WRLDPNAMbit0x02("Use LOD Data") children — all four FO3 roof / vista worldspaces (StatesmanRoofWorld,GNRroofWorld, …) author zero quads — resolve every distant-ring key (legacy quad index, object archive paths,.btrpaths, generated distant textures + worldspace form id, band bounds) onExteriorWorldContext::lod_worldspace_key(), the nearestWNAMancestor that does not set the bit (lod_source_worldspace,byroredux/src/env_translate/lod.rs); full-detail residency stays on the child (#5496,2ca57c4bc; installed-FO3 pin walksStatesmanRoofWorld-> Wasteland).worldspace_lod_grid_origin(byroredux/src/cell_loader/lod_support.rs) still returns (0,0) for non-combined-LOD games but only the synth/placement grids consume it. Real-data pins (--ignored,byroredux/src/cell_loader/legacy_lod_index_tests.rs):dcworld03_level8_quads_select_near_the_worldspace_centre,washmontop_level8_spans_multiple_residues_and_all_select(name predates #5387 — it now pins the majority-generation selection and that no two selected same-level quads overlap). CachedNifImportArc cache: no re-parse and no leak across FO3 unload/load cycles.
Output:/tmp/audit/fo3/dim_3.md
Dimension 4: BSA v104 & Real-Data Validation
Subagent: general-purpose
Routing: reader discipline /audit-parsers. FO3's BSA is byte-identical in format to FNV's — a divergence here is a v104 regression, not a format gap.
Paths: crates/bsa/src/archive/, crates/facegen/, crates/spt/, crates/nif/examples/nif_stats.rs
First step: cargo test -p byroredux-bsa --release --test ba2_real -- --ignored fo3_bsa_corpus_opens_and_lists (#4665 — FO3's only committed BSA guard, in ba2_real.rs; it opens and lists every FO3 .bsa but extracts nothing, so extraction is still checked by sweep) and --test bsa_real -- --ignored fnv_meshes_bsa_v104.
- Sweep every FO3 archive:
Fallout - Textures.bsaextracts fully to valid DDS headers (12 261 / 12 261 at last measure), folder-hash census has 0 collisions over 1 810 folders, no game-conditional branch in the v104 path. The 1 vanilla zero-byte compressed.txtplaceholder extracts as an empty file —BsaArchive::extractdecides the empty-stream edge before any decoder, so a flate2 bump cannot reopen it (#5073,fa2af0e89). - Pick one deathclaw-class creature (skinned via
BSDismemberSkinInstance,crates/nif/src/import/mesh/skin.rs), one UIBSShaderNoLightingPropertyelement (fullbright route), one FaceGen head (crates/facegen/; EGM morph deltas are scaled int16, not half-floats — #4653, real-data pinparse_vanilla_headhuman_egmincrates/facegen/tests/parse_real_facegen.rs; may not render fully — note the gap), one.spt(parse_rate_fo3_spt: placeholder-billboard fallback, not a hard error). - Runtime telemetry diff:
/audit-runtime --game fo3.
Output:/tmp/audit/fo3/dim_4.md
Dimension 5: Animation, NPC Spawn, Gameplay Data & the Scripting Gap
Subagent: legacy-specialist
Routing: gameplay mechanism /audit-gameplay; MenuXml /audit-ui; scripting runtime /audit-scripting; clip registry /audit-ecs. The classic-era M41 guards (B-spline FLT_MAX pose fallback, clip-registry dedup, NPC hand meshes) and the spawn-time skin seam blend (tuned on Moriarty's Saloon) are listed in /audit-fnv Dim 4 — verify them on FO3 data here.
Paths: crates/nif/src/anim/, byroredux/src/npc_spawn.rs, byroredux/src/npc_spawn/seam_blend.rs, byroredux/src/hud.rs, crates/menuxml/, crates/plugin/src/consumables.rs, docs/smoke-tests/fixtures/fo3.env
First step: git log --since=<date> --format='%h %cs %s' -- crates/nif/src/anim byroredux/src/npc_spawn byroredux/src/hud.rs crates/menuxml
- FO3 kf-era spawn works because its
skeleton.nifresolves (unlike FO4); Megaton dwellers with no hands = the hand-mesh regression; the threemtforward.kfbody-class walk clips (humanoid_walk_kf_path) exist in FO3's archive. - HUD:
HudGameProfile::fallout3— menu art fromFallout - Textures.bsa(the shared anchor; FNV'sTextures2rides in as its numeric sibling), 8 font slots (FNV: 9), 2 bars keyed on AVIF editor ids resolved throughPlayerVitals(#4675). FO3 vs FNV is picked from the load order byfallout_profile(#4718), falling back to FO3 when neither base ESM is listed or beside the corpus. Guards:crates/menuxml/tests/fo3_corpus.rs(BYROREDUX_FO3_DATA) anddocs/smoke-tests/m48-5-fo3-hud.sh. - Consumables: Stimpak restores health + the seven body-condition AVIFs on FO3 as on FNV; FO3 has no Hardcore — CTDA fn 586 must be rejected under the FO3 profile (
fn586_condition_gate_is_profile_scoped_not_game_scoped). Real-master guard:real_stimpaks_restore_scaled_health_and_limbs_but_hardcore_only_healthinbyroredux/src/inventory.rs(--ignored). - Playable gates declared in
fo3.env(FIXTURE_GATES):p0-door-interaction,p5-save-restart,p5-f5-f9-quicksave,p2-melee-core(Moriarty's Saloon, target Nova; green at HEAD per273692be5). An undeclared gate exits 2 — that is unmeasured, not covered. - Eat / Sleep (M42,
byroredux/src/systems/eat_sleep.rs, mechanism/audit-gameplay):PKDTprocedures 3 / 4 walk to the authoredPLDTanchor (#5391,42aab4c09); Near-Linked-Reference resolves through the actor's ownXLKRedge, In-Cell searches the whole resident cell (radius is not authored), and an unresolved Near-Reference target retries on a coarse clock instead of caching the actor's position (#5500,bcaf63aa8; #5527); creatures never take furniture (#5495). Legacy furniture markers authoranimation_type0, so every marker reads Sit and on FO3 the sit fallback IS the sleep path — sleepers take the nearest sit marker, chairs included (documented contract, #5390,9bdfdd1c6;legacy_sleep_actor_seats_at_the_sit_fallback).docs/smoke-tests/m42-eat-sleep.shruns FNV only; FO3 posture is unmeasured. - Scripting gap (known, owned by
/audit-scripting): 1 257 SCPT parse; there is no general executing runtime for FO3 script logic. M47.3 ticks compiled quest scripts game-agnostically (101 / 192 QUSTs carry script refs, 403 / 1 257 scripts have executable GameMode blocks; FO3'sSetStage/GetStageids match the Oblivion-derived table). The narrowobscript_runtime.rsload-order-idiom interpreter does not reach FO3:obscript_dialect_forgivesFALLOUT3no compiled dialect. Object-script effects the slice depends on are recognised at load instead (the #5223 kill-on-load corpse idiom, Dim 2).
Output:/tmp/audit/fo3/dim_5.md
Phase 3: Merge
- Read all
/tmp/audit/fo3/dim_*.md. - Combine into
docs/audits/AUDIT_FO3_<TODAY>.md:- Executive Summary — compatibility level + delta vs FNV (what is shared, what diverges); state the real-data lane result first.
- Dimension Findings — grouped by severity per dimension.
- FNV-Shared Surface — record/block/shader paths FO3 inherits, plus any FO3-only gap inside them.
- FO3-Distinctive Gaps — inline-shader-only material universe, Capital Wasteland worldspace, the SCPT runtime gap.
- Validation Status — interior (Megaton 929 REFRs), exterior (population + image-health gates per
exterior-readiness-plan.md; no FO3 scene in the ROADMAP bench-of-record), creature/NPC. - Cross-Audit Routing — shared-mechanism findings handed to their owner.
- Remove cross-dimension duplicates.
Suggest: /audit-publish docs/audits/AUDIT_FO3_<TODAY>.md
(label every finding game:fo3 + legacy-compat, plus its own domain label.)