Audit de compatibilité Fallout 4

VérifiéPrudence

Audit approfondi de la compatibilité Fallout 4 (BA2, vertices half-float, matériaux BGSM, précombines CSG M49) via des agents Task parallèles.

Spar Skills Guide Bot
TestingAvancé
06/11/2026
Claude Code
#fallout-4#game-engine#asset-pipeline#code-audit#regression-testing

Recommandé pour

Synthèse automatique

Exécute un audit de compatibilité Fallout 4 pour ByroRedux en répartissant cinq dimensions (precombines M49, matériaux BGSM, drapeaux de shader BSVER, etc.) entre des agents Task.

Points forts

  • Découpe l'audit en cinq dimensions explicites, chacune avec ses chemins de fichiers et son type de sous-agent, et plafonne à trois Tasks concurrentes.
  • Un tableau de répartition du périmètre indique à quel skill d'audit frère renvoyer chaque défaut, ce qui évite les rapports en double ou mal placés.
  • Marque les fonctionnalités déjà livrées (BA2 v1/v7/v8, BSVER 130+, SCOL/PKIN, BSConnectPoint) comme garde-fous de régression, empêchant de les reproposer comme travail restant.
  • Documente précisément les bandes de version des shader flags (130 typés, 131 sans flags, ≥132 CRC) avec les tests qui les contrôlent.

Limites

  • Fortement lié au dépôt ByroRedux : chemins codés en dur, dépôt GitHub précis et données de jeu attendues sous un chemin Steam local.
  • Dépend de fichiers compagnons externes (`_audit-common.md`, `_audit-severity.md`) et des skills d'audit frères, absents du SKILL.md fourni.
  • Ne fait qu'inspecter et signaler : les défauts de mécanisme sont transmis à d'autres audits plutôt que corrigés.
Quand l'utiliser

À utiliser pour une passe de régression reproductible sur la compatibilité FO4 de ByroRedux, avant un jalon ou après une modification du chargement de cellules, des matériaux ou des precombines.

Quand l'éviter

Inadapté à l'audit d'autres jeux que Fallout 4, ou à l'implémentation et à la correction effective de fonctionnalités du moteur.

Analyse de sécurité

Prudence
Score qualité84/100

The skill is a read-mostly audit orchestrator: it inspects repository source, runs filtered cargo test gates, queries the project's own GitHub issues, and writes markdown reports. Every command is attributable and legitimate for its stated purpose, with explicit 'fail closed' and 'do not re-file' editorial rules. Risk comes only from the implicit, undeclared use of bash/git/network and local game-data access, so it warrants caution rather than a clean 'safe'.

Points d'attention
  • •Orchestrates shell/git/gh/cargo invocations (git log, `gh issue list` against a remote GitHub repo, `cargo test --ignored`, `mkdir -p /tmp/audit/fo4`) and spawns subagents, but declares no allowed-tools list, so the execution surface is implicit rather than bounded.
  • •Writes audit artifacts to fixed /tmp paths and a repo docs path (`docs/audits/AUDIT_FO4_<TODAY>.md`), and reads a local, user-specific game data directory (`/mnt/data/SteamLibrary/.../Fallout 4/Data/`) — environment-coupled but non-destructive.
  • •Reads and reasons about local repo source files and issue metadata; no credential, token, or exfiltration instructions, no obfuscated payloads, no destructive filesystem operations.
  • •Declares no allowed-tools while the body instructs shell execution (`mkdir -p /tmp/audit/fo4`, `git log`, `cargo test -- --ignored`, `gh issue list --repo matiaszanolli/ByroRedux`) and subagent orchestration — capability is implicit rather than least-privilege declared.
  • •Issues a network call (`gh issue list`) and reads a hardcoded host path (`/mnt/data/SteamLibrary/steamapps/common/Fallout 4/Data/`); both are read-only reconnaissance, but they tie the skill to a specific machine layout and remote repo.
  • •Writes output into the working tree (`docs/audits/AUDIT_FO4_<TODAY>.md`) and suggests a follow-on `/audit-publish` step that mutates repo docs; no cleanup or dry-run path described.
  • •Heavy reliance on `#[ignore]`d real-data tests and external game assets — running them spends significant disk/CPU on large BA2 archives, but nothing destructive or exfiltrating.
Comment cette analyse est faite

Exemples

Full FO4 audit
Run the Fallout 4 compatibility audit across all five dimensions and summarize any regressions versus the shipped baseline.
Precombine-only pass
Run the FO4 audit with --focus 1 after my cell_loader change: check M49 precombine decode, the XCRI skip set (not XPRI), and precombined spawn.
Material and shader-flag focus
Focus the Fallout 4 audit on materials and shader flags: verify BSVER 130/131/132 band guards and that BGSM/BGEM merge happens before translate_material.

description: "Per-game audit of Fallout 4 compatibility — BA2, half-float verts, BGSM materials, M49 precombines (CSG)" argument-hint: "--focus <dimensions>"

Fallout 4 Compatibility Audit

Deep audit of ByroRedux readiness for Fallout 4 content.

Architecture: Orchestrator. Each dimension runs as a Task agent (max 3 concurrent).

Read .claude/commands/_audit-common.md (layout, game data, dedup, finding format) and .claude/commands/_audit-severity.md. This file carries only FO4-specific context.

Scope: this skill owns FO4's data through the shared mechanisms. Defects in the mechanism itself go to the owner: BA2/CSG/BGSM/.uvd reader discipline → /audit-parsers; NIF block parsing → /audit-nif; ESM walker → /audit-esm; canonical-material invariants → /audit-nifal; Scaleform HUD (--hud, byroredux/src/scaleform_hud.rs, docs/smoke-tests/m48-7-fo4-hud.sh, AVM2/BGSCodeObj) → /audit-ui; ragdoll articulation incl. the FO4 bhkRagdollSystem decode (crates/nif/src/blocks/collision/np_ragdoll.rs) and docs/smoke-tests/fo4-ragdoll.sh → /audit-physics; the Havok 2014 behavior-graph reader (crates/hkx/) → /audit-parsers, its runtime (byroredux/src/asset_provider/{actor_graph,object_graph,archetype_idle}.rs, byroredux/src/systems/graph_locomotion.rs) → /audit-gameplay Dim 5; the LSCR loading model (FO4 TNAM → TRNS, byroredux/src/systems/loading_model.rs, docs/smoke-tests/p6-loading-model.sh) → /audit-gameplay Dim 6; terrain, ground cover (the Commonwealth is arid since 1a2330361) and WTHR → /audit-exterior; runtime telemetry (.claude/audit-baselines/runtime/fo4-InstituteBioScience.tsv) → /audit-runtime — run it after any precombine / SCOL / spawn change (#5484's skip-set fix, 777351ec1, moved its draw / entity / BLAS rows; that recapture is still owed).

Everything below is shipped — audit as regression guard, never re-propose as pending: NIF BSVER 130+ incl. Next-Gen, BA2 v1/v7/v8, the BGSM/BGEM parser, SCOL/PKIN expansion, M49 CSG precombines, BSConnectPoint attach graph.

Game Context

| Aspect | State | |---|---| | NIF | BSVER 130 + Next-Gen patches (FALLOUT4..FO4_DLC_UPPER = 130..=139 carries the DLC trailing fields, crates/nif/src/version.rs) | | Shader flags | typed u32 pair at BSVER 130 only; BSVER 131 (FO4_SHADER_GAP) has neither; BSVER ≥ 132 uses CRC arrays. Guard: bsver_shader_flag_band_tests (version.rs), gates carries_typed_shader_flags / carries_crc_shader_flags | | Materials | PBR params live in external .bgsm/.bgem; the NIF carries a path stub. crates/bgsm/ parses; merge_external_material folds into ImportedMesh.material before translate_material | | Precombines | crates/bsa/src/csg.rs → crates/nif/src/import/precombine.rs → byroredux/src/cell_loader/precombined.rs; per-REFR skip set = the CELL XCRI pair tail, never XPRI (#5484). Spec docs/engine/fo4-csg-format.md | | Data | /mnt/data/SteamLibrary/steamapps/common/Fallout 4/Data/; bench --cell MedTekResearch01 (ROADMAP) |

Parameters / Setup

--focus <dimensions> (comma-separated, default all 5). Setup: parse $ARGUMENTS; mkdir -p /tmp/audit/fo4; gh issue list --repo matiaszanolli/ByroRedux --limit 200 --json number,title,state,labels > /tmp/audit/issues.json; confirm Fallout 4/Data/ exists (else note dimensions losing real-data validation).

Dimensions

Dimension 1: M49 Precombined Geometry — Decode + Spawn (highest FO4 risk)

Subagent: general-purpose Paths: crates/nif/src/import/precombine.rs, byroredux/src/cell_loader/precombined.rs, byroredux/src/cell_loader/load.rs + exterior.rs + partial.rs, byroredux/src/cell_loader/spawn/{mesh_instance,precombined}.rs, byroredux/src/streaming/pre_parse.rs (worker pre-parse), crates/plugin/src/esm/cell/helpers.rs (XCRI decode), crates/bsa/src/csg.rs, crates/bsa/src/uvd.rs First step: git log --since=<last report> --format='%h %cs %s' -- crates/nif/src/import/precombine.rs byroredux/src/cell_loader/precombined.rs crates/bsa/src/csg.rs Guards (confirm live, not #[ignore]d/vacuous): precombine.rs tests decode_keeps_every_lod_band + lod_bands_skip_empty_bands_and_bound_the_read (#4234); csg.rs oversized_read_len_is_rejected_before_it_is_reserved (#3758 — read_psg must bound its length before Vec::with_capacity; reader discipline is /audit-parsers); precombined.rs tests resolve_precombine_owner_follows_form_id_mod_index, csg_paths_index_every_plugin_in_the_load_order, dedup_requires_both_a_cache_key_and_a_matching_length (#3510), oc_nif_paths_are_already_canonical_cache_keys; finish_partial_tests.rs::finish_partial_import_builds_precombine_geometry_entry; blend restore on both routes (#5101): precombined.rs::merge_precombine_materials_restores_blend_but_keeps_bgsm_flags + finish_partial_tests.rs::finish_partial_import_precombine_route_applies_the_material_merge; zero origin (#5228): exterior_apply_advances_precombine_at_zero_origin; #[ignore]d real-data dlc_rebake_of_a_master_owned_cell_decodes_from_the_dlc_csg + exterior_precombine_instances_are_world_absolute. The runtime baseline is an interior, so no telemetry gate sees exterior placement. Checklist (what the guards cannot see):

  • Stride / transform — psg_vertex_stride(vertex_desc) vs the BSPackedGeomObject layout (off-by-N shifts every vertex silently; cross-check the spec doc). into_imported_mesh applies Z-up→Y-up + instance transform once. cell_origin must be Vec3::ZERO on both routes (#5228, fixed f3e1bba62): exterior _oc.nif instance transforms are world-absolute (same frame as the exterior REFR DATA positions), so adding cell_grid_to_world_yup places every tile at ≈2× its world position — the "else precombines stack at origin" rationale was the disproved #1222 premise.
  • LOD bands (#4234) — the three bands are disjoint sub-meshes whose union is the model (12,096/12,096 BSMeshLODTriShape); every populated band is decoded. Picking one band deletes geometry (12.45% of MeshesExtra.ba2's baked triangles) and is not z-fighting. Distance LOD may drop tail bands, never pick one. An empty band's offset is untrusted.
  • Which CSG blob — the _oc.nif filename keys off the cell's owning plugin (form-id mod byte; DLC bakes under <plugin>.esm\), but the geometry blob is chosen by each object's BSPackedGeomObject::filename_hash → csg_paths_by_name_hash (#2369: DLCs re-bake ~460 master-owned cells into their own blob). A blob no loaded plugin answers to, or a missing CSG, must fail closed to per-REFR (0 spawns), never read another plugin's PSG space or panic.
  • REFR de-dup gate (#1188 / #5484, fixed 777351ec1) — the skip set is the XCRI pair tail, (remapped REFR form id, bake hash) pairs on CellData::absorbed_ref_bakes (crates/plugin/src/esm/cell/helpers.rs); XPRI is the disjoint previs participant list, validated and never stored. Pre-fix the two were inverted (every baked STAT/SCOL drawn twice, ~9.9k XPRI statics deleted); census 959,238 XCRI refs, 100% STAT/SCOL, XCRI ∩ XPRI = 0 — which also settles #2699's furniture question. effective_absorbed_refs(bakes, baked_hashes) (shared by interior load.rs — whose InteriorCellApplyJob now drives both the sync and the budgeted load, #5589 / a4496c79b — and exterior exterior.rs) suppresses a REFR only when its own bake drew geometry, so one missing _oc.nif un-skips only its refs (no holes, no double-draw with SCOL expansion). Guards: effective_absorbed_refs_un_skips_only_the_missing_bakes_refs; parse_cell_xcri_pairs_remap_and_keep_their_bake_hash + parse_wrld_exterior_cell_captures_precombined_xcri_xpri (XPRI populates nothing) in crates/plugin/src/esm/cell/tests/.
  • Texturing — each mesh takes its material from the owning shape's shader/alpha properties (collect_precombine_geom_refs + precombine_material_from_shape), then the BGSM merge; no REFR overlay on this path (pre_merge_materials empty by design, #4290). Regression = untextured/checker precombines.
  • Opaque-architecture blend guard — on this path only, merge_precombine_materials (called by both PrecombinedSpawnJob and the streaming drain in partial.rs) keeps the BGSM merge's two_sided/decal/alpha_test/texture flags but restores the pre-merge alpha-blend triple (has_alpha, src/dst_blend_mode): FO4 authors the "Standard" blend identically on lab glass and opaque Institute metal, so forwarding the merged has_alpha makes walls MATERIAL_KIND_GLASS (see-through, mirror-hazy).
  • Archive chain precedence (#3637) — --bsa / --materials-ba2 chains resolve last-listed-wins (a DLC's re-baked _oc.nif must not be shadowed; 1,871 DLC mesh entries were shadowed pre-fix per the #3637 title). Provider rebuilds now share opened handles (#5288, 5402b2530: Archive::open_shared, a process-wide registry validated by file length + mtime) and skip the shadow-count walk for a reused handle — precedence is unchanged, only that diagnostic count is. Loose Data\ files (the --esm plugin's directory) are appended after every archive in the texture, mesh and material pools, so a loose override wins (#6200, 48e422a71; vanilla installs carry none, so no baseline moved). Guards: byroredux/src/asset_provider/tests/archive_precedence.rs (real-data, #[ignore]d — run it), byroredux/src/asset_provider/tests/loose_override.rs.
  • Upload once per object (#3510) — CachedNifImport::geometry_dedup maps every instance to its object's representative; keying the cache on the flattened sub-mesh index reintroduces one upload + BLAS per instance (1.37x VRAM, 4.6x worst tile).
  • Exterior streaming — PrecombinedSpawnJob yields between hashes / meshes / BLAS batches, and PrecombinedPlacement (spawn/precombined.rs) between geometry groups, keeping the placement root + submesh numbering across yields; the synchronous spawn_precombined_meshes wrapper must stay behaviourally identical. The cell-stream worker pre-decodes each cell's precombine_oc_nif_paths via decode_precombine_csg (per-plugin CsgHandleCache) and the drain caches a geometry_only_cached entry under the same key so the job only spawns — the two routes must agree on owner resolution, cache key, fail-closed fallback and the blend restore (divergence = different spawn counts per route). Regression guard (#5522, fixed 2ca9bc313): lookup_precombine_cache separates Hit / KnownFailure / Unseen, so the worker's negative cache entry (Some(None): missing file, parse error, contained panic) is a terminal miss, never a main-thread re-parse outside catch_unwind; pinned by negative_registry_entry_is_a_known_failure_not_unseen.
  • .uvd previs — envelope only (parse_uvd_header, incl. exterior_cell_grid; PVS payload uncracked, no occlusion consumer, #3810). Verify nothing pretends to consume the payload. Output: /tmp/audit/fo4/dim_1.md

Dimension 2: BGSM / BGEM → ImportedMaterial (merge + roles)

Subagent: general-purpose Paths: crates/bgsm/src/, byroredux/src/asset_provider/material/{merge,mod,provider}.rs, byroredux/src/cell_loader/spawn/mesh_instance.rs (REFR overlay), byroredux/src/asset_provider/tests/{bgsm_merge,material_flags}.rs First step: git log --since=<last report> --format='%h %cs %s' -- crates/bgsm byroredux/src/asset_provider/material Guards: bgsm_merge.rs (bgsm_merge_forwards_alpha_blend_mode, bgsm_blend_to_gamebryo_is_identity_narrowing, the neutral-roughness pair, bgem_glass_forwards_authored_optics_and_overlay_roles); material_flags.rs::bgsm_metalness_*; crates/bgsm/src/template.rs resolve_breaks_*_cycle (#1148) + resolve_reports_per_file_parse_diagnostics (#5010, 746e0858e); crates/bgsm/tests/parse_all.rs real-data sweeps (hardened #5011, e8676b097) and asset_provider/tests/bgsm_diagnostics.rs. Parser discipline for crates/bgsm is /audit-parsers. Checklist:

  • Narrowed signature — merge_external_material takes &mut ImportedMaterial, never &mut ImportedMesh, and is the only exported fn in merge.rs (test merge_external_material_is_the_only_exported_fn_in_this_file); a widened signature is a NIFAL boundary violation. It runs before translate_material. merge_bgsm_arm is split into group helpers (apply_bgsm_texture_slots / apply_bgsm_scalars / apply_bgsm_alpha_and_addressing, #5735 / a6cef30a5) and size-pinned by merge_bgsm_arm_stays_within_its_size_pin; the helpers stay private.
  • Roles, not slots — BGSM texture paths and REFR/TXST overlays land in MaterialTextureSet (22 named roles + decals: [T; 4], crates/nif/src/import/types.rs); FO4 wire-slot numbers must not survive past the import boundary. Overlay output is carried as named roles, not wire slots (#4434). Texture-set slot 7 is the _s.dds smooth-spec map and routes to the smooth-spec role, not Specular (#4424: the BC5 map fed to the specular-colour multiply tinted every FO4 highlight warm); the gloss-sampler channel semantics are still an open question — do not guess.
  • Metalness from saturation, not luminance (#1476) — legacy spec-glossiness BGSMs (pbr == false): bgsm_metalness = (max-min)/max of specular_color (white spec → 0). Luminance for the non-PBR branch makes vanilla concrete read chrome; luminance is correct only for pbr == true.
  • Authored enable bits gate their blocks — specular_enabled == false zeroes specular and derives no metalness / conductor tint in either branch (#4654, #4836; bgsm_specular_disabled_*); the envmap fill requires the chain's environment_mapping bit (#4428; *_skips_envmap_fill_when_env_mapping_disabled); a dead NIF texture path yields to a resolvable BGSM-chain path (#4636; dead_nif_texture_path_yields_to_resolvable_bgsm_chain_path). Reading a disabled block's values is the regression.
  • smoothness→roughness exactly once at the merge ((1 - smoothness) clamped to the near-mirror floor); flag any downstream re-inversion.
  • Neutral-roughness fallback — smoothness == 1.0 with no resolvable gloss map → neutral 0.5 (NEAR_MIRROR_NEUTRAL_ROUGHNESS): #3639 at the merge (authored-nowhere; fires on the specular_enabled arm only — a spec-off BGSM keeps the NIF-side roughness, #5012 / e80f7e854; must not fire when a template parent supplies smooth_spec — pinned by bgsm_merge_keeps_the_floor_when_the_gloss_map_comes_from_the_template_parent, #5234 / 460c55a41), #3905 at spawn via material_translate::resolve_unresolved_gloss_neutral_roughness (authored-but-unresolvable; gated on the shader's glossMapIndex != 0u). The arms cover disjoint populations — collapsing them regresses. Regression guard (#5230, fixed 9f0a8a7cc): the spawn pass infers "hit the floor" from roughness <= 0.04, which the glass classifier's forced mirror pane (0.04, metalness 1.0) also hits; classify_glass_into_material_with_provenance now reports the forced mirror out through translate_material_with_provenance and resolve_unresolved_gloss_neutral_roughness skips it (a_forced_mirror_pane_is_exempt_even_sitting_at_the_floor, a_bgsm_mirror_pane_keeps_its_mirror_through_the_spawn_pass_gate in material_translate.rs). Both spawn sites must feed the provenance flag.
  • Blend factors pass through (#1823) — BGSM/BGEM src_blend/dst_blend are already Gamebryo-native (Standard (6,7), Additive (6,0), Multiplicative (4,1)); any 0↔1 swap (or a gl_to_gamebryo_blend) corrupts Additive/Multiplicative while leaving Standard untouched.
  • BGEM merge — merge_bgem_arm deliberately leaves metalness/roughness as NaN so resolve_pbr's classifier runs; effect data merges into the NIF payload (#4425). Glass is glass_enabled-driven and must not misclassify opaque architecture with a stuck flag.
  • Lookup — .bgsm/.bgem/.mat dispatch on content magic, not extension (#758); last-listed-wins across --materials-ba2 (#3637); template resolve is cycle-aware and depth-limited (DEPTH_LIMIT = 16) and surfaces parse diagnostics (lossy strings, unconsumed bytes, version past the ceiling) for every file in the chain through TemplateResolver::parsed, not only the recovery arm (#5010).
  • MNAM-only landscape TXSTs — 32 of FO4's 128 LTEXs point at a TXST that authors only MNAM; terrain resolves each layer through LandscapeLayerTextures (byroredux/src/cell_loader/terrain.rs) and MaterialProvider::fill_texture_set_from_bgsm fills still-empty roles first-wins along the template chain, so authored TX slots keep precedence (#6199, e62e258bd). A layer reading only TX00/TX01/TX07 is the regression (untextured grass / rubble / cliffs). Output: /tmp/audit/fo4/dim_2.md

Dimension 3: NIF BSVER 130 Geometry, Shader Flags, Collision (FO4 slice)

Subagent: legacy-specialist Paths: crates/nif/src/blocks/tri_shape/bs_tri_shape.rs, crates/nif/src/import/mesh/{bs_tri_shape,bs_geometry,skin}.rs, crates/nif/src/blocks/shader/lighting.rs, crates/nif/src/import/material/dedicated_shader.rs, crates/nif/src/import/collision/shape.rs First step: git log --since=<last report> --format='%h %cs %s' -- crates/nif/src/import/material crates/nif/src/blocks/shader Guards: fo4_shader_flag_tests.rs, alpha_flag_tests.rs (crates/nif/src/import/material/); bsver_shader_flag_band_tests; parse_rate_fo4_all_meshes (Dim 5). Parser mechanics are /audit-nif; the canonical handoff (single translate_material boundary, resolve-once metalness/roughness, glass classified after resolve_pbr) is /audit-nifal — file there. Checklist:

  • VF_FULL_PRECISION default-half unless set; binary16 decode incl. denormals/NaN. BSSubIndexTriShape segments walked (actors lean on it); skinned indices/weights honour the packed layout. Regression guard (#5389, fixed cf9dec258): a per-vertex bone index >= the skin's own bone count declines the whole weight set (bind pose), never clamps — decline_unbounded_packed_indices (skin.rs) covers the inline arrays, the SSE global-buffer payload and classic NiSkinData; pinned by bs_tri_shape_skin_with_out_of_range_bone_index_declines / bs_tri_shape_skin_last_bone_index_is_in_range (bs_tri_shape_partition_remap_tests.rs). Vanilla census: 0 out-of-range over 23,099 FO4 skinned meshes (largest list 141/144). The FO4 BsSkinInstance arm is pinned too (#5524, fixed 656e2bdc3): bs_skin_instance_out_of_range_bone_index_declines / bs_skin_instance_last_bone_index_is_in_range, and the decline warning is arm-neutral. Inline tangents when VF_TANGENTS | VF_NORMALS (shared with Skyrim SE) — consolidating with the NiBinaryExtraData path is a regression of #795/#796.
  • Render-affecting flags consumed, not just parsed (#1592) — dedicated_shader.rs ORs Model_Space_Normals (F4SF1 bit 12) and Alpha_Test (F4SF2 bit 25) into MaterialInfo, gated by carries_typed_shader_flags (BSVER 130 only). Glow_Map (F4SF2 bit 6) is not gated: the (Fallout4, 2) arm in slot_role.rs routes slot 2 to Emissive regardless — closed docs-only (#4430, 1a12670ae; routing unchanged on purpose — census: gating would strip 116 genuine _g.dds glow maps, not gating masks 20 with a _d.dds; the BGSM glowmap bool is parsed, never read). The rule still needs an FO4 source; do not re-file or guess. These are lower priority than the BGSM merge (vanilla is BGSM-backed; only inline/loose/modded NIFs exercise them).
  • Skin/Hair tint BSLightingShaderType variants sample different slots than the default path — the per-type map must match what triangle.frag reads (#563). A BGSM material must never fall back to Lambert (FO4's inverse of the FNV regression); bare BSShaderPropertyBaseOnly stubs route through MaterialInfo (#1244).
  • Parsed-then-dropped is FO4's recurring finding class (texture_clamp_mode on 7.9% of lit materials #3507; the greyscale→palette enable bit): every decoded FO4 shader/BGSM field must reach an ImportedMaterial sink and the canonical Material, with one default across the three material tiers (#3515). The palette row ("Color Remapping Index") has two carriers (#5497): the precombine per-instance grayscale_to_palette_scale is stamped by apply_instance_palette_row and restored across the BGSM merge in merge_precombine_materials (guards merge_precombine_materials_keeps_the_instance_palette_row, apply_instance_palette_row_stamps_finite_rows_only); the REFR-side MSWP CNAM (color_remap_index in mswp.rs) is applied as the palette row for a swapped placement, stamped on the raw-tier ImportedMaterial before translate_material (0b2ffed89, #5497).
  • Collision — BhkMultiSphereShape and BhkConvexListShape translate to CollisionShape in import/collision/shape.rs (two downcast_ref arms); an arm reverting to "unsupported + drop" removes power-armor / settlement / debris collision. Packed-Havok (BhkSystemBinary) collision is blocked on the hknpCompressedMeshShapeData decode (PHYSAL, /audit-physics) — the skeleton bhkRagdollSystem blob is a different payload and is decoded (e1bd40bcf); FO4 architecture uses synthesized ghost trimesh colliders. The precombine collision sibling is <cell_formid:08x>_physics.nif (not _precomb.nif, which appears in no archive) — forward scope. Output: /tmp/audit/fo4/dim_3.md

Dimension 4: ESM Architecture Records + Cell Expansion

Scope split with /audit-esm: it owns the parser as a parser (GRUP walk, SubReader accounting, FormID remap); this dimension owns FO4's data through it. Shared-mechanism defects → /audit-esm. Subagent: general-purpose Paths: crates/plugin/src/esm/records/{scol,movs,pkin,mswp,parse}.rs, crates/plugin/src/esm/records/actor/npc.rs, crates/plugin/src/equip.rs, crates/plugin/src/esm/cell/{mod,support,walkers,wrld}.rs, byroredux/src/cell_loader/{refr,references/,spawn.rs,nif_import_registry.rs} First step: git log --since=<last report> --format='%h %cs %s' -- crates/plugin/src/esm/records crates/plugin/src/esm/cell byroredux/src/cell_loader/refr.rs Guards: cell_loader/scol_expansion_tests.rs, pkin_expansion_tests.rs, attach_points_spawn_tests.rs, refr_texture_overlay_tests.rs; the real-data ESM harness (#819) before any parse-rate claim. Checklist:

  • SCOL/PKIN expand into per-instance synthetic REFRs with composed (parent × child) transform; recursion bounded by MAX_PKIN_DEPTH = 4 (vanilla has zero nesting; the cap guards modded cross-recursion); SCOL-of-SCOL has its own gate. Regression guard (#5523, fixed a10b5d578): scol_cm_path (byroredux/src/cell_loader/refr.rs) answers which combined mesh a SCOL draws — the authored MODL when it resolves, else the derived meshes\scol<owner>\cm<local id>.nif (114 DLCRobot SCOLs author dev-plugin MODLs) — and expand_scol_placements_if expands the SCOL into its parts when it answers None (13 vanilla placements name a CM that ships nowhere); the static spawn (byroredux/src/cell_loader/references/synth_child.rs) and the expansion gate in references/mod.rs read the same answer, so they cannot disagree. A SCOL nested under a PKIN keeps the emptiness-only gate. Pinned by scol_cm_path_prefers_the_authored_modl_then_the_derived_path + a_scol_with_an_absent_cm_expands_but_a_present_one_does_not (scol_expansion_tests.rs). Also: SCOL/PKIN FLTR is the CK object-window filter path, a zstring decoded with read_zstring into filter: String and never remapped (#5493, fixed 136048a95 — pre-fix 2,843 false malformed-FormID warns across the FO4 DLCs buried real remap failures; the *_expansion_tests.rs pins use real string payloads plus a raw-under-remap test); NPC_.TPTA decodes onto NpcRecord::template_actors: [u32; 13] (xEdit wbTemplateFlags order, 0 = use the TPLT default) and walk_inherited_records (crates/plugin/src/equip.rs) takes the per-flag entry for that flag's edge when non-zero (#5498, fixed 99c22a8db; 763 Fallout4.esm records resolved the wrong template before). MOVS is parse-only (physics runtime unwired). The TXST group arm is in records/parse.rs and its decode in esm/cell/support.rs — an unreachable_patterns warning there means b"TXST" matches earlier than intended. The FO4-architecture maps must surface in categories() (records/index.rs).
  • TXST DODT (DecalData) has zero consumers — 303 vanilla payloads parse onto TextureSet.decal_data and are never read (grep decal_data finds only the parser and its tests); DNAM is consumed (TXST_FLAG_MODEL_SPACE_NORMALS in refr.rs). Known and deferred — #3638 closed documentation-only (a decal-rendering feature build, not a parse bug); forward scope, don't re-file.
  • PKIN CNAM is a template CELL, not a content base — fixed d63131c57 (#5231): every vanilla PKIN CNAM resolves to a CELL (the census spans Fallout4.esm + four DLCs) and vanilla FO4 places 0 PKIN REFRs (the CK bakes contents into ordinary REFRs) — an FO4-only premise: Starfield places 97,981 (fixed #5489: the expander now instances a CELL-typed CNAM's template-cell references under the outer transform, outer PKIN entry first, via the O(1) EsmCellIndex::cell_by_form_id) and returns None only when nothing was placeable so the outer REFR reaches the default miss accounting; base-record children remain the mod-authored shape. Guards: expand_pkin_empty_template_cell_places_nothing, expand_pkin_empty_template_leaves_the_base_children_fanning_out, expand_pkin_instances_its_template_cell_under_the_outer_transform, the #[ignore]d starfield_cydonia_pack_ins_instance_their_template_cells, #[ignore]d fo4_pkin_cnam_targets_are_template_cells (crates/plugin/tests/parse_real_esm.rs).
  • Authored actor state — ACHR "Starts Unconscious" (0x2000, FO4/FO76/SF only) decodes onto PlacedRef::starts_unconscious and spawns the actor dormant (#5017, 3c08cfe50); XRGD corpse poses decode onto PlacedRef::ragdoll_pose (260afc33f); the consumer is byroredux/src/ragdoll_pose.rs, gated per rig by body-name set. FO4 (#5015 closed into follow-ups; e1bd40bcf + 28e1f413e): the skeleton's bhkRagdollSystem (hknpRagdollData) blob decodes into the classic ragdoll/limited-hinge records, and XRGD entries map to bodies by each body's pose_bone_id, not entry order; is_fo4_posable_ragdoll admits the human, feral-ghoul and super-mutant sets (979 of 994 corpses resolve) and refuses every other creature/robot rig (#6065 open). Material/motion rows take Skyrim's values (#6066 open); convex/compound shapes decode (fc4a15104), 64 bind-pose joint disagreements remain (#6067 open). The layout is corpus-derived, not sourced — widen the gate only when scripts/xrgd-fo4-rigs.py passes a rig on both checks, never on a count match. Live wiring (fc2b32d9e): FO4 RACE ANAM skeleton paths are read (were Skyrim-only, every FO4 actor got the human skeleton) and template_from_imported keeps pose_bone_id; the posed 18-body ghoul ragdoll ran at 0 of 17 joints live and was parked by the explosion recovery, so the guard against the one-body fallback overwriting it is held back and docs/smoke-tests/fo4-ragdoll.sh gates on all joints live (#6070 open). Articulation defects → /audit-physics.
  • ARMA female→male biped fallback is Skyrim-only (open sourcing question, not a bug) — resolve_armor_meshes (crates/plugin/src/equip.rs) falls back to the male biped model for a female wearer only when game == GameKind::Skyrim (#5510, fixed d678dc578: the Skyrim CK documents the rule; 172 of Skyrim.esm's 766 addons are male-only). FO4 deliberately keeps the strict reading because the FO4 CK page documents no such rule and none is sourced locally — a FO4 male-only addon renders nothing on a female wearer. Needs an FO4 source (xEdit/CK/engine) before any change; do not extend the fallback by analogy and do not file it as a defect.
  • CELL XCCM is game-dependent (#5463, 3b28dca71) — FO4 (like TES5) authors it as 'Sky/Weather from Region' [REGN] (xEdit wbDefinitionsFO4.pas), decoded onto CellData::sky_region; only TES4/FO3/FNV decode it onto climate_override (a CLMT). No consumer for sky_region yet (forward scope). A FO4 cell reading climate_override from XCCM is the regression.
  • BSConnectPoint — the import lifts BSConnectPoint::Parents/Children into AttachPoints / ChildAttachConnections (crates/core/src/ecs/components/attach_points.rs); spawn must materialise them (modular weapons / power-armor frames otherwise spawn base-receiver only). Output: /tmp/audit/fo4/dim_4.md

Dimension 5: Archives + Real-Data Validation + Forward Scope

Subagent: general-purpose Paths: crates/bsa/src/ba2.rs, crates/nif/tests/parse_real_nifs.rs, crates/nif/examples/nif_stats.rs, ROADMAP.md, docs/feature-matrix.md First step: BYROREDUX_FO4_DATA=… cargo test -p byroredux-nif --test parse_real_nifs -- --ignored fo4 Checklist:

  • BA2 (FO4 slice; reader discipline is /audit-parsers) — version dispatch is an exhaustive match (v1/v7/v8 FO4 → zlib; v2/v3 Starfield → /audit-starfield Dim 1); unknown majors bail at open() and a cascading if v == 1 … else with a silent v1 fallback is the regression (#811). GNRL byte-exact; DX10 reconstructs the DDS header from width/height/dxgi_format/mips (BC1/BC3/BC5/BC7, mip0 → mip_last).
  • Parse rate — parse_rate_fo4_all_meshes covers all 8 mesh-bearing archives (base pair + six DLC Main.ba2; DLCUltraHighResolution is textures-only), 235,082 NIFs incl. .bto/.btr (widened 2026-08-29 by #3466; re-measured 2026-10-09, 8/8 archives), 100.00% clean. Report the measured number, not ROADMAP's. Regression guard (#5232, fixed 3970c8d19): open_all_mesh_archives / open_ba2_by_name (crates/nif/tests/common/mod.rs) panic on a present-but-unopenable BA2 (None is reserved for an absent file) and run_all_meshes_gate asserts walked > 0; a reversion turns the gates into green no-ops — still confirm the archive count actually walked, not just the pass. DX10 records with chunk_hdr_len != 24 are now a hard InvalidData (#5008, cf2a36920; vanilla census: all 24).
  • Trace import_nif_scene on a workshop item, a creature (deathclaw / super mutant), a power-armor frame (heavy skinning + BSConnectPoint) and a modular weapon: mesh count, material_path, skinned vs rigid, connect points.
  • Forward scope (do not file as blockers): precombine _physics.nif collision and packed-Havok decode, .uvd PVS payload / occlusion consumer, MOVS physics runtime, DecalData consumer (above), XRGD poses for the unverified FO4 creature/robot rigs (#6065) and a stable live FO4 ragdoll (#6070), FaceGen NIF truncation tail, deeper cell coverage (LIGH power state / CONT leveled items / NPC_ face morph). Output: /tmp/audit/fo4/dim_5.md

Phase 3: Merge

  1. Read /tmp/audit/fo4/dim_*.md; combine into docs/audits/AUDIT_FO4_<TODAY>.md:
    • Executive Summary — measured parse rate; what is shipped vs pending (above).
    • Dimension Findings — grouped by severity per dimension.
    • BGSM Consumption Table — BGSM field × merged-into-ImportedMaterial by merge_external_material / surfaced-on-canonical-Material. Texture columns name the MaterialTextureSet role, never an FO4 slot number.
    • Forward Scope Chain — precombine collision / .uvd payload → MOVS physics → DecalData → deeper REFR/LIGH/CONT/NPC_ coverage.
  2. Remove cross-dimension duplicates.

Suggest: /audit-publish docs/audits/AUDIT_FO4_<TODAY>.md (label every finding game:fo4 + legacy-compat, plus its own domain label.)

Du fichier au premier essai

Le téléchargement contient exactement le contenu affiché sur cette fiche. Cette copie peut différer de la dernière version du dépôt source.

Consulter la source et ses fichiers annexes

Ce téléchargement contient uniquement SKILL.md. Les scripts, références, modèles et dépendances éventuels ne sont pas inclus. Récupérez les fichiers nécessaires depuis la source en conservant leur arborescence avant de poursuivre.

1. Télécharger le fichier

Télécharger SKILL.md

Depuis la racine d’un projet de test, enregistrez le fichier sous .skill-downloads/fallout-4-compatibility-audit-mvhm5lzr/SKILL.md, ou utilisez la commande suivante. Ce dossier sert à examiner la skill avant son installation.

Commande pour macOS/Linux ou WSL : un shell POSIX et curl sont nécessaires. Sous Windows sans WSL, utilisez le bouton de téléchargement et créez le dossier manuellement.

mkdir -p '.skill-downloads/fallout-4-compatibility-audit-mvhm5lzr' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/fallout-4-compatibility-audit-mvhm5lzr/download' --output '.skill-downloads/fallout-4-compatibility-audit-mvhm5lzr/SKILL.md.part' && mv '.skill-downloads/fallout-4-compatibility-audit-mvhm5lzr/SKILL.md.part' '.skill-downloads/fallout-4-compatibility-audit-mvhm5lzr/SKILL.md'

2. Vérifier les prérequis

Lisez SKILL.md avant de l’utiliser. Si le fichier cite des scripts ou services externes, examinez-les et préparez les accès nécessaires dans votre environnement de test.

Aucune section de prérequis reconnue dans ce fichier. Cela ne signifie pas qu’il est autonome : les bibliothèques, outils et accès peuvent être cités ailleurs dans le contenu ou dans le dépôt source.

Les plateformes de la fiche sont des indications du catalogue. Les chemins ci-dessous suivent la documentation des outils ; ils ne prouvent pas que cette skill y a été exécutée. Aucune version minimale de ces outils n’est attestée pour cette fiche.

3. Charger la skill

Le fichier ne fournit pas un en-tête name/description exploitable pour cette procédure native. Le téléchargement reste disponible pour lecture ; utilisez le mode manuel ci-dessous.

Mode manuel ou autre outil : joignez SKILL.md à une conversation, ou ouvrez-le dans un agent capable de lire les fichiers. Ajoutez les ressources annexes nécessaires. Il n’existe pas de dossier universel reconnu par tous les outils.

4. Faire un premier essai

Utilisez une entrée courte et fictive : un endpoint d’API, un petit document ou un brief d’interface. Dans une nouvelle conversation, joignez le fichier ou donnez son chemin à l’agent, puis adaptez cette demande :

Lis .skill-downloads/fallout-4-compatibility-audit-mvhm5lzr/SKILL.md et applique ses instructions à cet exemple : [décrire une entrée de test]. Indique les fichiers, dépendances ou accès qui manquent. Produis le résultat demandé par la skill sans inventer de données ni exécuter de script non examiné.

Résultat attendu : une sortie correspondant aux instructions de la skill, ou une liste précise des prérequis manquants. Une simple confirmation de lecture ne valide pas le premier usage. Si une ressource externe est indisponible, ce parcours reste à tester.

Skills similaires