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 qui guide Claude a travers le cycle TDD complet.
Audit d'Accessibilité Web
Testing
Réalise un audit d'accessibilité web complet selon les normes WCAG.
Générateur de Tests UAT
Testing
Génère des cas de test d'acceptation utilisateur structurés et complets.