matiaszanolli

Fallout New Vegas Compatibility Audit

"Per-game audit of Fallout New Vegas compatibility — reference title: cell load, ESM/NIF data, ragdoll, ambient AI + dialogue, consumables, HUD profile"

matiaszanolli 28 3 Actualitzat fa 1 setm.
GitHub

Instal·la

npx skillscat add matiaszanolli/byroredux/claude-commands-audit-fnv

Instal·la des del registre de SkillsCat.

SKILL.md

Fallout New Vegas Compatibility Audit

FNV is the reference title — the most-validated end-to-end path and the reference realization for NIFAL material/physics and PHYSAL ragdoll. This audit owns FNV's data through the shared mechanisms (routing: .claude/commands/_audit-owners.md); a defect in the mechanism itself is filed against its owner audit, named under each dimension. A foundation that broke on FNV is the highest-severity finding this command can produce; the rest is regressions and unshipped polish.

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 (bsver::FO3_FNV) · BSA v104 (crates/bsa/src/archive/)
Archive priority Last-listed wins per pool; Update.bsa is listed last in all three FNV pools (assets/debug_profiles.toml). every live FNV gate/bench harness mounts it last too (#5257, a4ede5fa0). Guard: byroredux/src/asset_provider/tests/archive_precedence.rs
Reference data /mnt/data/SteamLibrary/steamapps/common/Fallout New Vegas/Data/
Baselines (pull, never hardcode) ROADMAP.md FNV row (parse rate + Prospector bench-of-record and its commit), docs/feature-matrix.md, .claude/audit-baselines/runtime/fnv-FreesideAtomicWrangler.tsv, crates/nif/tests/data/per_block_baselines/fallout_nv.tsv

Authoring census (byte-scan of the shipped data, 2026-09-19 — these prevent false findings):

  • 20 archives / 182 177 entries: **0 _far.nif, 0 distantlod\**. FNV object LOD is ObjectLodScheme::FalloutLegacyBlocks; placement_lod_supported is Oblivion-only (placement_lod_supported_is_oblivion_only). FNV also ships 25 <world>.level4.high.x<X>.y<Y>.nif quads (6 in Fallout - Meshes.bsa, 19 in LonesomeRoad - Main.bsa) that no code path consumes: censused-not-consumed by design (#4468, closed — probe_lod_corpus counts them, ObjectLodScheme's doc explains why only the plain form is built); every one has a plain sibling, so it is fidelity only, not a coverage hole.
  • FalloutNV.esm: 98 SCOL bases / 1 084 REFRs; 0 MOVS / PKIN / MSWP; 219 XATO (all Activation Prompt strings, #3511 — not texture overlays) and 0 XTNM / XTXR.
  • 989 BSSegmentedTriShape blocks (fallout_nv.tsv).

Parameters (from $ARGUMENTS)

--focus <dimensions>: comma-separated numbers (e.g. 1,3). Default: all 6.

Phase 1: Setup

  1. Parse $ARGUMENTS; mkdir -p /tmp/audit/fnv.
  2. Dedup baseline: gh issue list --repo matiaszanolli/ByroRedux --limit 200 --json number,title,state,labels > /tmp/audit/issues.json.
  3. Confirm Fallout New Vegas/Data/ exists (required — FNV is the baseline).
  4. Read the FNV rows above; every "regression" is judged against them, not against numbers in this skill.
  5. Scope by delta: git log --since=<last AUDIT_FNV date> --format='%h %cs %s' -- <dimension Paths>; skim dimensions whose Paths did not change.
  6. Toolchain: the byroredux bin crate needs rustc >= 1.96 (wasmtime 49, 15a6b1d2d) — use the rustup cargo per docs/contributing.md § Toolchain note (#4466) or bin-crate tests give no feedback.

Phase 2: Launch Dimension Agents (parallel)

Ordered by FNV risk: cell load first (highest blast radius), gameplay-data slices last.

Dimension 1: Cell Loading & Streaming

Subagent: general-purpose
Paths: byroredux/src/cell_loader/ (general files; terrain*, water.rs, lod*, object_lod.rs, placement_lod.rs are /audit-exterior), byroredux/src/scene/, byroredux/src/streaming/, docs/engine/pipeline-overview.md, docs/engine/exterior-grid-streaming.md
First step: git log --since=<date> --format='%h %cs %s' -- byroredux/src/cell_loader byroredux/src/scene byroredux/src/streaming

  • Interior GSProspectorSaloonInterior: entity/draw counts vs the ROADMAP row; XCLL lighting resolves (fog_far_color optional field; an authored LIGH falloff of 0.0 must resolve to the pre-Skyrim quadratic default, falloff_exponent_sentinel_resolves_per_layout_generation in byroredux/src/systems/light_anim.rs); NiAlphaProperty decal routing.
  • Exterior WastelandNV radius 3 and the FNV-specific data: default land texture DirtWasteland01.dds via DefaultLandTexture::for_game (guard default_land_textures_exist_in_vanilla_archives, --ignored); WTHR/CLMT/terrain/water translation mechanism -> /audit-exterior. Repeatable gate: docs/smoke-tests/m-exteriors.sh fnv static|boundary|soak|cycle|water.
  • Cache and unload hygiene (mechanism: /audit-safety Dim 3, /audit-performance): NifImportRegistry Arc cache (byroredux/src/cell_loader/nif_import_registry_tests.rs); unload frees BLAS / Rapier / skin / inventory state (rapier_release_tests.rs, inventory_release_tests.rs, unload_skin_cleanup_tests.rs, unload_greyscale_lut_tests.rs, all under byroredux/src/cell_loader/). FNV check: after a Prospector -> Goodsprings -> Prospector round trip stats returns to baseline.
  • Persistent reference state across a cell round trip (door/loot/pickup state, byroredux/src/cell_loader/reference_state.rs — mechanism /audit-gameplay, /audit-save): docs/smoke-tests/p0-door-interaction.sh fnv, p5-save-restart.sh fnv.
    Output: /tmp/audit/fnv/dim_1.md

Dimension 2: ESM Data Slice (FalloutNV.esm)

Subagent: general-purpose
Routing: GRUP walk, SubReader byte accounting, schema dispatch, FormID remap -> /audit-esm. This dimension owns the semantics that only show on FNV's masters.
Paths: crates/plugin/src/esm/records/, crates/plugin/src/esm/cell/, crates/plugin/src/equip.rs, crates/plugin/tests/parse_real_esm.rs
First step: cargo test -p byroredux-plugin --release --test parse_real_esm -- --ignored parse_rate_fnv_esm (one test at a time; whole-file --ignored runs can spike >20 GB).

  • index.total() >= FNV_TOTAL_FLOOR and the ROADMAP/feature-matrix record counts; do not transcribe counts into this skill.
  • Gameplay-record spot checks: Varmint Rifle stats, NCR faction relations, VATS AVIF entries; the FNV actor-value roster and Health resolution (fnv_actor_value_roster_and_health_resolve_on_shipped_master); NPC Health seeds from the authored NPC curve — NPC_ DATA Base Health + the fAVDNPCHealth* slopes, never the player curve (#5238, c71eeed80; fo3_fnv_named_npc_health_matches_the_authored_curve); a non-auto-calc NPC (ACBS bit 4 clear, ~40% of the census) seeds its authored DATA SPECIAL (NpcRecord::data_attributes) instead of the class ATTR, shells fall back to the class (#5338, 4957536ba); PLDT decode (parse_rate_fnv_pack_pldt_location); PKDD carries the topic (offset 4) and the Dialogue Type (PackRecord::dialogue_type, 0 Conversation / 1 Say To, #5376) as the u32 at offset 16 — byte 0 is the low byte of the FOV float, so the old read left the Say-To decline dead (#5492, dae08000d; pkdd_dialogue_type_is_the_u32_at_offset_16, floor parse_rate_fo3_fnv_pkdd_say_to_floor: FO3 19 / FNV 21 Say-To packages).
  • DIAL overrides fold INFO children (#5375, 168b81322): EsmIndex::merge_from takes an override's topic header but folds its INFOs by FormID (fold_info_into_topic — same id replaces in place, a new one inserts after its PNAM predecessor); a Deleted-INFO tombstone prunes one line, a DIAL tombstone drops the topic. The old whole-DialRecord last-write-wins let every FNV story DLC gut GREETING. An override's PNAM == 0 run composes in authored file order through one per-override contribution cursor — the first contribution goes to the front, each later head lands after the previous one (#5494, 5356c8780; dialogue_override_head_run_composes_in_file_order; before it The Pitt's unconditional "Go away." head won over 92 conditioned greetings); the master-relative position of the head run is an unsourced engine choice. generic_greeting_form is resolved once at merge end (#5426, 411d0eeaf). Guards are two-plugin fixtures (dialogue_override_folds_infos_into_the_master_topic, dialogue_override_without_children_keeps_master_infos, merge_resolves_the_generic_greeting_form_once, all crates/plugin/src/esm/records/index.rs); the real-data floor dialogue_greeting_and_forcegreet_fnv_floor parses FalloutNV.esm alone, so no test measures GREETING under a DLC load order.
  • Authored corpses (mechanism /audit-gameplay): the FO3/FNV marker is the base's DATA health <= 0 — XRGD is pose-only and ACBS bit 23 is not a marker (#5005, de6bdb381; fnv_corpses_key_on_base_health_not_xrgd) — plus the kill-on-load script idiom (dismember-trigger XLKR targets and self-killing bases) recognised at load because no FO3/FNV object script runs (#5223, 717f39a82; script_killed_corpse_forms, fo3_fnv_script_killed_corpses_match_the_measured_census, FNV 10 + 2). The set is computed once per load order over every cell, so exterior trigger -> persistent-target links across separate load_references_budgeted calls are not missed (#5248, d4e8c31be); it matches only the exact shipped GenericBiped*DismembermentSCRIPT EDIDs and requires the winning SCPT to resolve to a vanilla master, so name-alike or override scripts are declined (#5304, 2d47bf7f1) — "winning" is the LoadOrder per-SCPT last-writer table (script_is_vanilla in reference_state.rs), because a true override keeps the master's FormID and slot byte (#5428, 335a0179c; kill_on_load_recognition_declines_a_true_override_of_a_vanilla_script); the whole-load-order scan returns empty on every game but FO3/FNV (#5450, eaac75911). FO3/FNV XLKR is 4 bytes (target only), not Skyrim's 8 — a len >= 8 gate drops every link.
  • SCOL is FNV-era (#1538): is_scol_era in crates/plugin/src/esm/records/parse.rs must keep dispatching parse_scol_group for Fallout3NV; re-narrowing it to FO4-only silently drops 1 084 placements. MOVS/PKIN/MSWP are FO4+-only and must not take FNV dispatch. An unreachable_patterns warning in esm/cell/walkers.rs is a smell.
  • SCPT SCHR is a 20-byte header with a u16 flags tail on Oblivion/FO3/FNV (#1654): ScriptRecord.flags is read via u16_or_default in records/script.rs; a u32 read fails every real script and pins flags to 0. Guard: parse_scpt_extracts_schr_scda_sctx_and_vars + the real-data script counts.
  • LVLI flattening: expand_leveled_form_id / expand_leveled_loot (equip.rs) — NPC outfits and container loot must resolve to base items, not empty. NPC CNTO carry lists expand through expand_leveled_loot with LVLO counts (#4696) at the TPLT terminal's level, not the shell's (#4812; 643 FNV shells differ). Guards: fnv_leveled_item_multi_pick_semantics_are_pinned_on_the_shipped_master, equip.rs expand_leveled_* tests, cnto_leveled_counts_match_the_container_path (byroredux/src/npc_spawn/tests.rs).
    Output: /tmp/audit/fnv/dim_2.md

Dimension 3: NIF / NIFAL Slice — the Reference Realization

Subagent: legacy-specialist
Routing: block decode -> /audit-nif; the single-boundary / no-fabrication / no-render-time-fallback rules and collision/particle translation -> /audit-nifal; the Disney-BSDF gate (MAT_FLAG_PBR_BSDF must be 0 — FNV authors no BGSM/BGEM) -> /audit-renderer.
Paths: crates/nif/src/blocks/, crates/nif/src/import/, byroredux/src/material_translate.rs, crates/nif/tests/parse_real_nifs.rs, crates/nif/tests/per_block_baselines.rs
First step: cargo test -p byroredux-nif --release --test parse_real_nifs --test per_block_baselines --test block_coverage_baselines -- --ignored fallout_nv real_archive_torch (real-data lane; plain cargo test never runs it).

  • Parse rate and per-block histogram hold vs fallout_nv.tsv / ROADMAP; a histogram shift = a mis-dispatched block.
  • FNV legacy emissive is EmissiveSource::Material (emissive_source_tests.rs); Skyrim/FO4 variants must not bleed in.
  • FNV must place on the post-Oblivion side of every bsver gate (bsver::FO3_FNV = 34); examine_collision_kind classifies FNV chains CollisionAuthoring::Classic; havok_motion_type maps BOX_INERTIA (4) to Dynamic (havok_motion_type_maps_full_enum).
  • Emitter birth rate reaches the ECS from the authored controller chain, per emitter instance: the per-game rate floor real_archive_torch_meshes_surface_particle_emitters (--ignored) must be green for FNV. It was red on main 2026-09-12..19 (#4467) because the fix session ran only the default lane — any change under crates/nif/src/import/walk/ needs this lane run.
  • MAX_NIF_NODE_DEPTH (128) never trips on a legit FNV scene (crates/nif/src/import/walk/tests.rs); since #5485 (cf8730adc) all five scene-graph walkers share one per-walk revisit_guard (visited bitset + the depth cap), which must skip nothing on vanilla FNV trees (no multi-parent or self-referenced children ship) — a node or emitter count drop after that change is the regression.
    Output: /tmp/audit/fnv/dim_3.md

Dimension 4: Animation, Skinning & PHYSAL Ragdoll (FNV reference slice)

Subagent: legacy-specialist
Routing: the solver end (collider translation, fixed-step, build_ragdoll, controller) -> /audit-physics; clip registry / lock shape -> /audit-ecs. This dimension owns the source axis: does FNV's authored bhk chain reach the canonical spec intact.
Paths: crates/nif/src/anim/, crates/nif/src/import/collision/, byroredux/src/ragdoll.rs, byroredux/src/anim_convert.rs, byroredux/src/npc_spawn.rs, byroredux/src/npc_spawn/seam_blend.rs, docs/engine/physal.md
First step: cargo test -p byroredux-nif --release --test ragdoll_import -- --ignored fnv_ and docs/smoke-tests/m41-ragdoll.sh.

  • Classic-era guards, verified on FNV data (FO3 re-verifies on its own): B-spline pose fallback gated on the FLT_MAX sentinel (crates/nif/src/anim/bspline.rs; B-splines are reachable on FNV/FO3); since #5486 (0c4d4af08) resampling is clamped to the owning sequence's span (only a finite, forward span clamps — #5575; the curve parameter still maps over the interpolator's own span, the clamp only picks which times are emitted — #5572) and bounded by BSPLINE_MAX_SAMPLES_PER_CHANNEL plus one BSPLINE_IMPORT_KEY_BUDGET per import_kf pass — a declined-channel count logged once per import (#5577, static-pose fallback) on a vanilla FNV clip is a regression; clip registry dedup by lowercased path (get_or_insert_by_path_dedupes_repeated_calls); NPC hand meshes (lefthand.nif / righthand.nif, the Fallout3NV arm of the body table — Oblivion has its own four-part table since #5487, 1b45763fa) load beside upperbody.nif on kf-era NPCs (byroredux/src/npc_spawn.rs) — bodies with no hands are the regression.
  • Ragdoll: template_from_imported / extract_ragdoll warn on dropped bodies/constraints rather than silently shrinking; FNV's dominant constraint is a bhkMalleableConstraint wrapping a Ragdoll (docs/engine/physal.md § FO3/FNV) and must yield a jointed body. Real-data guard: fnv_protectron_skeleton_is_one_connected_component (crates/nif/tests/ragdoll_import.rs). bhkBallAndSocketConstraint / bhkStiffSpringConstraint / the ball-socket chain are decoded (#4212) but extract_ragdoll warns and drops them (no canonical joint kind) — a sole-link drop detaches a limb; no FNV occupancy census exists (#3792, closed, only covered the four decoded types; breakable_wrapped_ball_and_socket_still_drops pins the rest), so measure before assuming there is no FNV example. Writeback must not corrupt the skinned palette (byroredux/src/ragdoll_installed_tests.rs). Solver explosion containment (velocity clamp -> park -> articulation detach, #5161 5ae7f8ad4, #5246 e8de9f8c8) is /audit-physics; its killer repro is FNV SLscorpionBurrowINT — a multi-SAP panic there is a regression.
  • No per-game branch in ragdoll.rs or the solver bridge — the only per-game seam is the constraint CInfo decode.
  • Spawn-time skin seam blend (seam_blend.rs, Oblivion/FO3/FNV only; mechanism /audit-nifal, /audit-gameplay): a head/hand part's open-edge vertices match skin neighbours (is_skin_texture — texture under textures\characters\) within SEAM_MATCH_RADIUS, take their normals, and bake a tone ratio into vertex colour fading over SEAM_FADE_DISTANCE (both engine tuning, set by eye on FO3). It must touch only the part being spawned, never the cached body/outfit import; blending into collars/sleeves is the regression.
    **Output**: /tmp/audit/fnv/dim_4.md

Dimension 5: Ambient AI, Dialogue, Consumables & HUD — FNV Data Through Gameplay Mechanisms

Subagent: general-purpose
Routing: procedure runtimes, package selection, seat reservation, CTDA fail-open, consumable/restoration/loot mechanics, HUD driver -> /audit-gameplay; MenuXml eval/layout/raster -> /audit-ui, parse side -> /audit-parsers; character formulas -> /audit-character. Check here only what FNV authors.
Paths: byroredux/src/npc_spawn.rs, byroredux/src/boot/schedule/post_update.rs, byroredux/src/player_body.rs, byroredux/src/systems/{npc_dialogue,forcegreet,dialogue_voice,eat_sleep}.rs, crates/scripting/src/dialogue.rs, byroredux/src/hud.rs, byroredux/src/inventory.rs, crates/menuxml/src/profile.rs, docs/engine/npc-spawn-ai-packages.md, docs/engine/dialogue-trees.md, docs/engine/playable-vertical-slice.md
First step: git log --since=<date> --format='%h %cs %s' -- byroredux/src/npc_spawn byroredux/src/systems/npc_dialogue.rs byroredux/src/systems/forcegreet.rs byroredux/src/systems/dialogue_voice.rs byroredux/src/systems/eat_sleep.rs crates/scripting/src/dialogue.rs byroredux/src/hud.rs byroredux/src/inventory.rs crates/menuxml

  • Ambient locomotion is default-on (M42.10): sandbox seat, Wander/Travel/Follow/Escort/Guard/Patrol, Eat/Sleep and walk playback register unconditionally behind the single BYRO_NO_AI_LOCOMOTION=1 kill-switch; the seven older BYRO_* opt-in variables are not read. Guard: ambient_locomotion_default_on_tests in byroredux/src/boot/schedule/mod.rs. A finding that "NPCs walk without an opt-in" is a false premise.
  • Walk clips are FNV assets: humanoid_walk_kf_path resolves locomotion\{male,female,child}\mtforward.kf under meshes\characters\_male\ per (gender, is_child), child gated on the RACE child flag; walk_speed_for derives per-actor speed from the clip's authored stride, sane range [30, 250] u/s, fallback LOCOMOTION_WALK_SPEED. Confirm on real FNV NPCs that female/child actors get their own clip and a measurable stride.
  • Slice features landed Skyrim-first — check FNV reach, do not assume it: ambient faction hostility starts and disengages combat and suspends the ambient package (#4414, #4816, #4703; FNV's p2-melee-core target is GSSettlerCM 00104F08 — GSTrudy is authored Initially Disabled, #5156); the player body's kf arm reuses humanoid_walk_kf_path (kf_capsule_resolves_gendered_walk_and_shared_idle_from_the_registry) but p3-player-body.sh is Skyrim-only.
  • Dialogue layers (mechanism /audit-gameplay Dim 2, /audit-scripting Dim 5; spec docs/engine/dialogue-trees.md): npc_dialogue.rs binds topics through running-quest alias bindings (running_quests_binding_entity) and FNV QUST authors no ALST/ALLS, so FNV rides the FO3/FNV layers of #5367 (closed, all phases landed — G/L/F 14cff35ae, voice f8950e7cc). open_conversation falls back to the generic GREETING DIAL for a quest-less NPC (Doc Mitchell), read from EsmIndex::generic_greeting_form and borrowed rather than cloned (#5426, 411d0eeaf). select_info honours each INFO's owning quest via QSTI + quest priority (#5271, dbc07e8f0) and the authored positional Random stack — a passing Random first INFO rolls among the immediately following passing Random INFOs, ended by the next passing non-Random or a Random End INFO (#5397, 0436bea5c); Say-Once INFOs are ledgered per speaker as (speaker ref, INFO) pairs in the saved DialogueSpokenInfoForms (#5300, f18224b02), and re-selecting the same INFO fires its OnEnd before the next OnBegin. Force-greet (byroredux/src/systems/forcegreet.rs) takes the Dialogue-procedure PACK's PKDD topic, walks the cached NAVM path and opens in place once held against an obstacle (#5452, 6316719ed), and its walk step honours BYRO_NO_AI_LOCOMOTION (#5430, bd366e300); the ambient arm installs only when the package's conditions are fully modeled (no fail-open pass), PTDT targets the player (0x14) or nothing, and the Dialogue Type is Conversation, and a failed open consumes the directive (#5376, 4e58f241d; dialogue_ambient_install_declines_unmodeled_offtarget_sayto) — console dialogue.forcegreet still installs any Dialogue package. Selection skips a Dialogue package whose pass was manufactured by fail-open (any uncatalogued CTDA function) and continues to the next eligible package, so a declined one no longer starves the Sandbox/Travel/Eat/Sleep packages scheduled below it — 56 FNV NPC bases stood at spawn around the clock before (#5499, f7ca4a60f; two-package pin in byroredux/src/npc_spawn/ai_package.rs). A dead player, or a conversation open with another NPC, holds the directive (#5392, 16544d4c9; dead_player_holds_the_forcegreet_directive, open_conversation_holds_or_consumes_the_forcegreet_directive). Gate: docs/smoke-tests/dt1-dialogue-layers.sh. Decoded data: INFO DATA type/flags (#4469, cc9353043) and the DIAL Top-level flag that keeps choice-only topics link-only (#5224, 305363122).
  • Dialogue voice (byroredux/src/systems/dialogue_voice.rs; playback mechanism /audit-audio): Fallout - Voices1.bsa rides the FNV sounds profile. The path is sound\voice\<owning plugin>\<VTYP EDID>\<quest>_<topic>_<local id>_<response n>.ogg — owner through GlobalFormIdResolver, since masters own the low slots (#5393), quest EDID cut to VOICE_QUEST_CHARS and the pair to VOICE_NAME_CHARS only when quest + topic exceed 25 (a length test, one candidate — #5521), id plugin-local, <n> the authored response number (#5395; both 5b68792b7; voice_path_candidates_truncate_only_over_the_length_limit, voice_path_candidates_strip_the_load_order_byte, voice_owner_resolves_masters_before_the_esm). FNV DLC voice ships in each DLC's Main.bsa, which no profile mounts (pass --sounds-bsa), so unvoiced DLC lines under the default profile are expected, not a finding. Decoded PCM rides the byte-budgeted VoiceSoundCache LRU (#5382, 8410ad1e5) and segments follow the speaker (#5410, d1a7ee8c6); a topic change or conversation close cuts the playing line (#5432, 40b77828b).
  • Eat / Sleep (FO3/FNV PKDT procedures 3 / 4, byroredux/src/systems/eat_sleep.rs; mechanism /audit-gameplay Dim 5): walk once to the PLDT anchor (EatSleepLocation — NearReference at the reference; NearLinkedReference at the actor's own XLKR target through PackageTargetRegistry::linked_reference; NearEditorLocation at the spawn-stamped EditorPlacement; InCell spans the seat search over the whole resident cell (every FNV In-Cell package authors radius 0); the rest stay put — #5391, 42aab4c09, #5500, bcaf63aa8. An unresolved reference or non-resident cell resolves to None and retries on ANCHOR_RETRY_SECS, never cached as the actor's position — 163 FNV actor/target pairs place the target after the actor; arrived actors that cannot seat retry on SEAT_RETRY_SECS — #5527, #5449; the walk uses the cached NAVM path and attempts the seat once wall-held — #5452), then seat through the sandbox path. FNV furniture markers author animation_type 0, so FurnitureMarkerKind::Sleep never resolves and every FNV sleeper takes the nearest sit marker — chairs included, and an Eat actor can take a bed's: the documented v0 contract, not a bug (#5390, 9bdfdd1c6; legacy_sleep_actor_seats_at_the_sit_fallback). Gate: docs/smoke-tests/m42-eat-sleep.sh (Prospector settler, time.set 23, seat leg scoped to the target NPC — #5427, 6a72c6042). Creatures never take furniture: the CreatureActor marker (stamped in prepare_creature_state) gates both seat paths, so Sandbox's wander/idle and Eat/Sleep's walk stay but no CREA is seated — 59 FNV placements across 14 cells were frozen in furniture before (#5495, 9bb8bc475; a_creature_actor_never_takes_furniture). A seated actor restored at a stream boundary re-runs the seating write path (parked sit pose, heading, SeatReservations re-claim) or drops the Seated restore for its package to re-seat (#5501, b1fed839c). The docs no longer call Eat/Sleep/Dialogue parse-only (#5471, 3bb9748f0).
  • Consumables / Hardcore (mechanism: /audit-gameplay Dim 3): FNV's eligible plans per the spec (docs/engine/playable-vertical-slice.md § P3) are Stimpak (00015169), Blood Pack, Bitter Drink. IsHardcore (CTDA 586) selects the saved HardcoreMode flag (crates/core/src/ecs/resources/hardcore.rs); hunger/thirst/sleep/ammo weight/companion death are documented as unbuilt (that doc, re-read 2026-09-29). Real-master tests (--ignored): Stimpak real_stimpaks_restore_scaled_health_and_limbs_but_hardcore_only_health (byroredux/src/inventory.rs, needs FO3 + FNV) and real_stimpaks_survive_disk_overlay_in_normal_and_hardcore_modes; Blood Pack + Bitter Drink real_new_vegas_timed_restoratives_survive_disk_overlay (both byroredux/src/save_io/consumable_tests.rs).
  • HUD profile (HudGameProfile::fallout_nv): assembled style (meters grafted from menus\prefabs\meter.xml, compass from template_compass_window); 2 bars keyed on AVIF editor ids Health / ActionPoints, resolved per load through PlayerVitals and read from the player only, with the bar fraction composed through ActorValue::undamaged so a routed SetBase override reads back (#5508, 627149b62) (#4675 — the old literal 0x2C9/0x2D0 were fallout.rs test-fixture ids and never matched real content); 9 font slots (FO3 has 8) from Textures2, which rides in as the numeric sibling of the Fallout - Textures.bsa anchor; menu XML from Fallout - Misc.bsa. FO3 vs FNV is decided by the load order (fallout_profile: a base ESM among --master/--esm, else the one beside the corpus — #4718; the old --esm-name match gave DLC launches the FO3 profile). Guards: profiles_pin_corpus_facts (crates/menuxml/src/tests.rs), fallout_profile_follows_the_load_order_not_the_esm_name (hud.rs), fnv_corpus_facts (crates/menuxml/tests/fnv_corpus.rs, BYROREDUX_FNV_DATA), smoke docs/smoke-tests/m48-5-fnv-hud.sh (DLC launch shape; exits 77 on missing data and sits in the contract checker's HUD loop since #5276, c47b2d72d).
    Output: /tmp/audit/fnv/dim_5.md

Dimension 6: Real-Data Validation, Bench-of-Record & Smoke Gates

Subagent: general-purpose
Routing: renderer correctness of RT lighting / denoise / sky on FNV scenes -> /audit-renderer, /audit-exterior; runtime telemetry diff -> /audit-runtime --game fnv.
Paths: assets/debug_profiles.toml, byroredux/src/game_profiles.rs, scripts/fsr-bench-matrix.sh, docs/smoke-tests/, .claude/audit-baselines/runtime/
First step: git log --since=<date> --format='%h %cs %s' -- scripts/fsr-bench-matrix.sh docs/smoke-tests assets/debug_profiles.toml

  • Use --game fnv for anything not the bench-of-record (#3346): it expands to absolute --esm / --bsa / --textures-bsa paths, so CWD cannot break it. A vanilla Data/ has no bare Meshes.bsa (Fallout - Meshes.bsa; --bsa opens the literal path) and a bare-name run from the wrong CWD loads ~36 entities with a spurious FPS.
  • Bench-of-record: scripts/fsr-bench-matrix.sh 3 300 (encodes archives, CWD, upscaler sweep and the #3347 sanity gates), or single-config cargo run --release -- --game fnv --cell GSProspectorSaloonInterior --upscaler taa --bench-frames 300 --bench-hold then byro-dbg (port 9876) stats. --upscaler taa is mandatory for comparison: with no flag the run uses fsr3/quality or a persisted render.upscaler from the settings file (BYROREDUX_SETTINGS_PATH, else ~/.config/byroredux/settings.toml — discover_settings_path in crates/settings-io/src/lib.rs; the Renderer upscaler selection: … (source: …) boot line and the bench line's upscaler= token name which, #4947), and comparing FSR-Quality FPS to the ROADMAP TAA-native headline reads as a fake ~75% win (#2560). Compare entity/draw/FPS/fence to the ROADMAP FNV row at its recorded commit; the pre-collider baseline was never recovered, so read ROADMAP Known Issues before flagging fence/FPS.
  • Chrome/posterized surfaces: run tex.missing first (Update.bsa + Fallout - Textures2.bsa split the texture set). The committed v104 real-data guard is fnv_meshes_bsa_v104_extracts_nif_with_gamebryo_magic (crates/bsa/tests/bsa_real.rs, --ignored); reader discipline is /audit-parsers.
  • Playable-slice gates on FNV (docs/smoke-tests/README.md): p0-door-interaction.sh fnv, p1-character-traversal.sh fnv, p2-melee-core.sh fnv (GSSettlerCM kill — Health 45.0 on the authored NPC curve, 18 ragdoll bodies), p5-save-restart.sh fnv, dt1-dialogue-layers.sh, m42-eat-sleep.sh, p5-f5-f9-quicksave.sh fnv, p5-door-transition.sh fnv, p5-soak.sh fnv, w1-water-traversal.sh fnv (real capsule Lake Mead shore -> swim -> dive -> surface -> shore -> cell boundary), m-exteriors.sh fnv. Missing data is exit 77, never a pass — scripts/check-playable-smoke-contracts.sh enforces it, and dt1-dialogue-layers.sh / m42-eat-sleep.sh joined its loops only in #5427 (6a72c6042), so a new FNV gate absent from the checker is a finding.
  • Look baseline: the Prospector saloon overexposure (#5158) closed on the 7d99ba7f0 exposure-envelope retune, and 3bcf6c8e8 (#5482) moved the IMGS/IMAD contrast grade after exposure with a shadow toe for every game, FNV included — compare FNV captures against post-3bcf6c8e8 frames; the grade itself is /audit-renderer.
    Output: /tmp/audit/fnv/dim_6.md

Phase 3: Merge

  1. Read all /tmp/audit/fnv/dim_*.md.
  2. Combine into docs/audits/AUDIT_FNV_<TODAY>.md:
    • Executive Summary — FNV is the baseline; any regression against the ROADMAP-recorded numbers is at least HIGH (CRITICAL if it breaks a shipped foundation).
    • Dimension Findings — grouped by severity per dimension.
    • Baseline Comparison Table — ROADMAP number vs observed for entity count, draw count, FPS, fence, parse rate, record count (cite the ROADMAP commit compared against).
    • Regression Guard List — previously-fixed issues verified still correct.
  3. Remove cross-dimension duplicates.

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