description: "Per-game audit of Fallout 3 compatibility — NIF v20.2.0.7, BSA v104, ESM via FNV-shared parser" argument-hint: "--focus <dimensions>"
Fallout 3 Compatibility Audit
Deep audit of ByroRedux readiness for Fallout 3 content.
FO3 rides the FNV path almost end-to-end: same NIF era (v20.2.0.7 / BSVER 34),
same BSA format (v104), same ESM parser, same cell loader, same RT lighting. So
this audit is NOT a re-run of /audit-fnv — it hunts the divergences: where
FO3 content exercises a path FNV doesn't, where the shared code carries an
FNV-only assumption, and where a feature is verified on FNV but only assumed on
FO3. Order below is by FO3 risk, highest first.
Architecture: Orchestrator. Each dimension runs as a Task agent (max 3 concurrent).
See .claude/commands/_audit-common.md for project layout, game data locations,
methodology, deduplication, and finding format. See .claude/commands/_audit-severity.md
for the severity scale (including the NIFAL canonical-translation rows).
Game Context
| Aspect | State |
|-----------------|-----------------------------------------------------------------------------|
| NIF format | v20.2.0.7 (BSVER 34) — same as FNV |
| BSA format | v104 ✓ |
| ESM parser | Shared with FNV (crates/plugin/src/esm/); no FO3-specific arm |
| NIF parse rate | 100.00% (10 989) — ROADMAP compat matrix |
| ESM records | 44 657 = 37 459 structured + 7 198 NAVMs (re-verified 2026-05-26) |
| Interior | ✓ — Megaton, 929 REFRs (parse-side baseline; NOT the stale 1609 figure) |
| Exterior | Wired (Capital Wasteland WRLD); fresh GPU bench pending (R6a-stale-15) |
| Scripting | 1 257 SCPT records parse; no runtime executes them (M47.0; tail M47.2) |
| Reference data | /mnt/data/SteamLibrary/steamapps/common/Fallout 3 goty/Data/ |
FO3-vs-FNV divergence map (the actual audit surface)
- Inline shader stack only. FO3 ships
BSShaderPPLightingProperty/BSShaderNoLightingPropertywith the legacy single-u32 flag layout — neverBSLightingShaderProperty(Skyrim+) and never BGSM external materials (FO4+). Disney-BSDF and BGSM paths must be provably unreachable. - Earlier authoring conventions than FNV: pre-FNV record subforms (NPC_,
DIAL/INFO),
BSSegmentedTriShapebiped parts, FO3-era particle stacks. These are the FNV-shared paths most likely to hit an untested edge on FO3 data. - Different worldspace. Capital Wasteland is a distinct WRLD form ID with its own origin/CLMT curves — any FNV-hardcoded worldspace name or coord is a bug.
- B-splines are reachable (
NiBSplineCompTransformInterpolator) — do not rule them out by game era (feedback_bspline_not_skyrim_only.md). - SpeedTree 5.x (
crates/spt/) is the FO3/FNV.sptgeneration — placeholder billboard fallback only.
Parameters (from $ARGUMENTS)
--focus <dimensions>: Comma-separated dimension numbers (e.g.,1,4). Default: all 7.
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, note which dimensions lose real-data validation. - Before reporting a status/count claim, reconcile against the ROADMAP per-game
compat matrix and
docs/feature-matrix.md— both carry live FO3 numbers.
Phase 2: Launch Dimension Agents (parallel)
Dimension 1: FO3 Rendering Path — Inline Shaders (highest divergence)
Subagent: renderer-specialist
Entry points: crates/nif/src/import/material/mod.rs (+ walker.rs, shader_data.rs), byroredux/src/material_translate.rs (translate_material), crates/core/src/ecs/components/material.rs (resolve_pbr, EmissiveSource, classify_pbr_keyword), crates/nif/src/shader_flags.rs, crates/renderer/shaders/triangle.frag
Checklist:
BSShaderPPLightingPropertyflag bits mapped correctly (decal, alpha-test, two-sided, glow, window). Per-game flag bit positions differ across FO3/FNV/Skyrim — confirm FO3 uses the legacy single-u32 layout viacrates/nif/src/shader_flags.rs, not the FO4 u32-pair.- Normal map handle resolved from the dedicated
BSShaderTextureSetnormal slot (FO3+), NOT the bump slot — Oblivion reads normals from the bump slot viaNiTexturingProperty; FO3 must not regress into that path. BSShaderNoLightingProperty(UI / sky / glow / blood-splat) routes through the fullbright path (c351e0b6) and its decal flags are honored (crates/nif/src/import/material/mod.rs— the pre-#454 NoLighting branch had no flags2 check). Self-illumination must not dim with distance.- NIFAL single boundary (#1241 / #1244,
3ce98db8): FO3 materials flow through the SINGLEmaterial_translate::translate_material(ImportedMesh+ResolvedPaths→ canonicalMaterial).Material.metalness/Material.roughnessare plain resolvedf32(noOption, no per-draw classify). FO3 authors no BGSM, so they arrive as the NaN sentinel andMaterial::resolve_pbrfills them viaclassify_pbr_keyword. Confirm concretef32scalars out of the one boundary; no second per-game material site. EmissiveSourcediscriminator (#1280,2e884741): FO3BSShaderPPLighting/NoLightingself-illumination maps toEmissiveSource::Material(legacyNiMaterialProperty.emissive_multslot). All three variants currently share theemissive_multslot — the discriminator is provenance, not yet a render branch. Skyrim+Lighting/ FO4+Effectvariants must not bleed into the FO3 ~1.0 scale.- Disney-BSDF gate (#1248–#1252): zero FO3 materials author BGSM, so
MAT_FLAG_PBR_BSDF((1u << 5), defined incrates/renderer/shaders/include/shader_constants.glsl) must be 0 across the Fallout3.esm material universe — the Burley/anisotropic-GGX/per-material-IOR lobe (crates/renderer/shaders/include/pbr.glsl) is unreachable for FO3. If any FO3 scene activates it, the gate regressed. WaterShaderProperty(#1243,3509482a): FO3 water materials route throughMaterialInfofor distinctGpuMaterialentries (no dedup collapse with glass).- See also
/audit-nifal. Output:/tmp/audit/fo3/dim_1.md
Dimension 2: NIF v20.2.0.7 Parser — FO3 Block Subset
Subagent: legacy-specialist
Entry points: crates/nif/src/blocks/properties.rs, crates/nif/src/blocks/shader.rs, crates/nif/src/blocks/particle.rs, crates/nif/src/blocks/mod.rs (dispatch), crates/nif/src/import/walk/mod.rs (extract_emitter_params / extract_emitter_rate), byroredux/src/systems/particle.rs (apply_emitter_params)
Checklist:
BSShaderPPLightingPropertyfield completeness (refraction strength/period, parallax passes/scale, bump-map tiling) andBSShaderNoLightingPropertydecode.BSSegmentedTriShape(biped body parts) vertex-index handling.- Stream-position audit: any block type that passes on FNV but trips on FO3-era authoring. The dispatch arm count is in
crates/nif/src/blocks/mod.rs— a histogram shift fromnif_statsflags a mis-dispatched block. - Typed particle emitters (NIFAL particle slice,
5708b5b9/9db60714/8f856d35):NiPSysEmitter/NiPSysEmitterCtlr/NiPSysEmitterCtlrData/NiPSysGrowFadeModifierare TYPED blocks (crates/nif/src/blocks/particle.rs—parse_box_emitter/parse_sphere_emitter/parse_grow_fade_modifier), not the old opaque controller stack.extract_emitter_params/extract_emitter_ratedecode authored base kinematics + birth rate + GrowFadebase_scaleintoapply_emitter_params. Dispatch is version-agnostic so FO3 smoke/fire/dust emitters hit this path — but the NIFAL decode doc-comments verify only against FNV + Oblivion, so FO3 is an UNVERIFIED gap: confirm FO3 authored emitter params + rate + GrowFade scale extract correctly. See also/audit-nifal. Output:/tmp/audit/fo3/dim_2.md
Dimension 3: ESM Record Coverage (Fallout3.esm)
Scope split with /audit-esm (added 2026-08-13): /audit-esm owns the parser as a parser — GRUP walk, SubReader byte accounting, schema dispatch, FormID remap. This dimension owns this game's data through it: record counts, game-unique authoring, and the semantics that only show up on this title's masters. If the defect is in the shared mechanism, file it against /audit-esm instead of here.
Subagent: general-purpose
Entry points: crates/plugin/src/esm/records/, crates/plugin/src/esm/cell/ (post-Session-34 split — walkers.rs / helpers / support / wrld.rs), byroredux/src/cell_loader/refr_texture_overlay_tests.rs
Checklist:
- Parse
Fallout3.esmthrough the shared parser. Reconcile against the live baseline: 44 657 records = 37 459 structured + 7 198 NAVMs (re-verified 2026-05-26). A drop here is the regression signal — do NOT use any older "13 684 structured" figure. - FO3-unique authoring vs FNV: pre-FNV subforms for NPC_, DIAL, INFO. The parser deliberately keeps the soft/strict truncation read semantics (
crates/plugin/src/esm/sub_reader.rsmigration, R2 Phase B). - SCPT SCHR flags are a u16 (#1654,
590351c1): shared with Oblivion/FNV — the SCHR is exactly 20 bytes with au16flags tail (cursor @18).crates/plugin/src/esm/records/script.rsreads it viau16_or_default; the old "u32 tail on FO3+" comment was itself wrong. A regression to au32read fails on every real FO3 script and pinsScriptRecord.flagsto 0. - CELL XCLL / RCLR layout identity vs FNV (FO3 interior lighting uses the same
CellLightingRespath — confirm, don't assume). - WATR (rivers/ponds) and NAVM differences. WTHR / CLMT pulled through the shared parser.
- REFR per-instance texture overrides (XATO/XTNM/XTXR — #584): FO3 cell REFRs can carry per-instance texture-set overrides that resolve against
EsmCellIndex.texture_setsand feed theResolvedPathsconsumed bytranslate_material(Dim 1). Confirm FO3 overlays produce distinct resolved paths, not a collapse to the base mesh material. Regression tests:byroredux/src/cell_loader/refr_texture_overlay_tests.rs. - TXST/XATO/XTNM/XTXR dispatch lives in
crates/plugin/src/esm/cell/walkers.rs; anunreachable_patternswarning there is a smell. Output:/tmp/audit/fo3/dim_3.md
Dimension 4: FO3 Cell Loading End-to-End (interior + exterior)
Subagent: general-purpose
Entry points: byroredux/src/cell_loader/{load,unload,exterior,references/mod,spawn}.rs, byroredux/src/scene/{nif_loader,world_setup}.rs
Checklist:
- FO3 interior loads via the SAME
--esm Fallout3.esm --cell <id>CLI as FNV. Megaton parse-side baseline: 929 REFRs (down from 1609 pre-NIF-expand; #455+, cell-loader stale-comment cleanup #822 /ca6be24). Any audit citing 1609 references pre-expand stats — confirm against currentcell_loader/*.rscomments first. - Exterior is WIRED (ROADMAP: "Exterior wired; fresh GPU bench pending"). Capital Wasteland is a distinct WRLD form ID — audit
cell_loader/exterior.rs+crates/plugin/src/esm/cell/wrld.rsfor any FNV-hardcoded worldspace name, origin coord, or default grid that would mis-place FO3 exterior cells. The open item is a fresh GPU bench (R6a-stale-15), not a missing feature. - No FNV-only branch in the shared cell loader. WTHR→CLMT→WTHR resolution and FO3 CLMT sun-position curves resolve through the shared weather path.
CachedNifImportArc cache prevents duplicate parsing; no leak across FO3 unload/load cycles._far.nifdistant-object LOD (#1726/#1745, Session 52) — verify the Oblivion/FO3/FNV placement scheme + real LOD textures resolve on FO3's Capital Wasteland exteriors; entry pointscell_loader/object_lod.rs,cell_loader/placement_lod.rs. Output:/tmp/audit/fo3/dim_4.md
Dimension 5: FO3 Collision Import (Havok → CollisionShape)
Subagent: legacy-specialist
Entry points: crates/nif/src/import/collision/mod.rs (extract_collision, examine_collision_kind, CollisionAuthoring), crates/nif/src/import/collision/shape.rs (resolve_shape)
Checklist:
- FO3 Havok content is no longer merely skipped via
block_size—extract_collisionwalksbhk*CollisionObject→BhkRigidBody→ shape intoCollisionShape+RigidBodyData.examine_collision_kindmust classify FO3 chains asCollisionAuthoring::Classic(BSVER 34, legacy side), notNewPhysicsStub/Phantom/Unrecognised— a misclassified discriminator silently drops the rigid body. - #1277 /
9c6096aa:BhkMultiSphereShape(→ sphere path) andBhkConvexListShape(→CollisionShape::Compound, mirroringBhkListShape) now translate — they were dropped before. FO3 uses these in static/clutter collision; confirm FO3 meshes carrying them yield a non-Noneextract_collision, not a discarded shape. - bhk motion_type via the canonical Havok enum (#1652,
dc33ec7d):collision/mod.rs::havok_motion_typemaps the rawhkMotionTypebyte per the full nif.xml enum (1–5/8 → Dynamic, 6 KEYFRAMED → Keyframed, 7 FIXED → Static, 9 CHARACTER → CharacterKinematic, 0/other → Static). The pre-fix4 => Keyframed/_ => Staticcollapse mis-typed BOX_INERTIA (4) clutter (crates/ammo boxes/debris) as kinematic-frozen instead of falling — shared with FNV/Oblivion, so confirm FO3 dynamic clutter still simulates. - Cross-check the Dim 2 "skips via block_size" note — that is now only true for shape kinds WITHOUT a translator. See also
/audit-nifal(collision is part of the canonical tier) and/audit-niffor raw block decode. Output:/tmp/audit/fo3/dim_5.md
Dimension 6: BSA v104 + Real-Data Validation
Subagent: general-purpose
Entry points: crates/bsa/src/archive/, crates/nif/examples/nif_stats.rs, crates/nif/tests/parse_real_nifs.rs
Checklist:
Fallout - Meshes.bsalists + extracts cleanly; current NIF parse rate 100% / 10 989 (nif_stats).Fallout - Textures.bsaDDS extraction yields valid BC1/BC3/BC5 headers. Folder-hash collisions across FO3's subdirectories. Format is identical to FNV — divergence here would be a v104 regression, not a format gap.- Pick Megaton interior (validated baseline — should match 929 REFRs / current entity count; capture
/cmd statsand compare to feature-matrix, NOT the stale 1609/199-tex/42-FPS numbers). - Load a creature mesh (e.g. deathclaw): verify NiSkinData skinning extraction (
crates/nif/src/import/mesh/skin.rs). - Pick a UI/menu
BSShaderNoLightingPropertyelement: verify the fullbright (non-Phong) route. - Pick one FaceGen head mesh (
crates/facegen/): parses; may not render fully — note the gap, don't fail the dimension. - Load a
.spt(SpeedTree 5.x,crates/spt/): confirm placeholder-billboard fallback, not a hard parse error. Output:/tmp/audit/fo3/dim_6.md
Dimension 7: FO3 Animation / NPC Spawn + Scripting Gap
Subagent: legacy-specialist
Entry points: crates/nif/src/anim/ (Session-35 split: entry, sequence, controlled_block, transform, bspline, channel, keys, coord), crates/core/src/animation/, byroredux/src/anim_convert.rs, byroredux/src/npc_spawn.rs
Checklist — M41.0 long-tail regression guards (shared with FNV, Session 29; verify they hold on FO3 data):
- B-spline pose-fallback (#772,
3c32a5e): gated on theFLT_MAXsentinel. B-splines are reachable on FO3 (feedback_bspline_not_skyrim_only.md) — don't rule them out by era. AnimationClipRegistrydedup (#790,da99d15): case-insensitive interning by lowercased path; without it one keyframe set leaks per cell load (RAM growth on FO3 exterior streaming).- NPC hand-mesh load (#793 / M41-HANDS,
da8d7e2):lefthand.nif+righthand.nifloaded alongsideupperbody.nifon kf-era NPCs (byroredux/src/npc_spawn.rs). Megaton dwellers depend on this — bodies with no hands = #793 regression. FO3 kf-era spawn works because itsskeleton.nifresolves (unlike FO4). - Scripting gap (FO3-distinctive): 1 257 FO3 SCPT records parse but no runtime executes them (M47.0 event-hook + M47.1 condition-eval landed; the M47.2 compiled-Papyrus recognizer slice is in progress). This is the largest FO3-specific functional gap — note it as a known blocker for FO3 quest/world interactivity, not a bug to file. The scripting runtime itself is owned by
/audit-scripting(crates/scripting, crates/pex, crates/papyrus) — do not deep-audit it here. Output:/tmp/audit/fo3/dim_7.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's shared, what diverges).
- Dimension Findings — Grouped by severity per dimension.
- FNV-Shared Surface — Record types / block types / shader paths FO3 inherits from FNV coverage, plus any FO3-only gap inside them.
- FO3-Distinctive Gaps — Inline-shader-only material universe, Capital Wasteland worldspace, the 1 257-SCPT scripting runtime gap.
- Validation Status — Interior (Megaton 929 REFRs) + exterior (wired, bench pending) + creature/NPC.
- 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.)
TDD Red-Green-Refactor
Testing
Skill that guides Claude through the complete TDD cycle.
Web Accessibility Audit
Testing
Performs a comprehensive web accessibility audit following WCAG standards.
UAT Test Case Generator
Testing
Generates structured and comprehensive user acceptance test cases.