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

# 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; the synchronous interior load is `InteriorCellApplyJob` `begin()` + `advance()` under an unlimited budget, no longer a line-for-line twin in `load_cell_with_masters` (#5589, `a4496c79b`); every interior-load fix now lands once; 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 the live-state owners return to baseline — named entities (`entities`), `phys.stats` bodies / static colliders, `rt.integrity` TLAS + BLAS bytes, `skin.coverage` slots, `mesh.cache` entries. Not `stats` Entities: that is `World::next_entity_id`, a never-reused spawn counter that only grows (#6060).
- 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 in one batched pass per override (`fold_infos_into_topic` — same id replaces in place, a new one inserts after its `PNAM` predecessor; the per-INFO rescan it replaced was O(infos x master) per topic, #5644, `0c2bd4d6d`, pinned against the cfg(test) one-at-a-time reference by `batched_info_fold_matches_the_one_at_a_time_fold`); 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.
- **ARMO `DNAM`** is `AR` (DR x 100, s16), 2 unused, `DT` f32, flags on FNV and only `AR` + flags (4 bytes) on FO3 — the decode once read DR as DT and the DT float as DR; New Vegas Damage Threshold composes from it (`52b59e43d`; `fo3_armo_dnam_is_damage_resistance_only`, real-data `fallout_armor_damage_threshold_and_resistance_decode` — Legate armor DT 15, Reinforced Combat Armor Mk II DT 20, `--ignored`). CELL `XCCM` is a CLMT on TES4/FO3/FNV (`CellData::climate_override`) and a REGN only on TES5/FO4 (`sky_region`) — an FNV cell must still populate `climate_override` (#5463, `3b28dca71`; `parse_cell_oblivion_fo3nv_xccm_populates_climate_override`).
- **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`) — the `XRGD` pose applier (`byroredux/src/ragdoll_pose.rs`, `18b3d87a7`, #5015 still open) is pinned to Skyrim's 18-body humanoid skeleton and refuses any other, so FNV corpses are outside it and keep collapsing from their idle pose — 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 gates each candidate through its quest's own `QUST` conditions first (`DialogueQuestConditions`, #5734, `6709eb65e`; fail-closed — a gate on an uncatalogued function such as `GetIsVoiceType` declines the line instead of letting the top-priority quest's unconditioned greeting hijack every speaker it outranks, FNV's ED-E beeps; the guard is released before evaluation so it never nests with `QuestStageState`, `8e4c6e40a`) 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 — re-read per open, so a second same-frame greeter holds rather than stripping the first's line (#5392, `16544d4c9`; #5642, `c0c9c9d1b`; `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`). The per-frame actor gather lives in persistent `EatSleepScratch`, seated actors skipped at the gather and the retry maps pruned against a reused membership set (#5707, `a08156579`). Gate: `docs/smoke-tests/m42-eat-sleep.sh` (Prospector settler, `time.set 23`): it asserts the *selection* leg (`SleepBehavior` handed over) and an *idle* leg — the settler's Sleep package is In-Cell for *GSHouseInterior02*, not the loaded saloon, so he must neither walk nor carry `Seated` (#5391); the seat leg is unit-gated only, since no NPC in that cell has a resident-cell Eat/Sleep package (`5f205f0ca`, which replaced the #5427 seat assertion that only held while an unresolvable anchor froze the actor in place). 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`; the `HudBar` / `bar_fractions` docs now state the editor-id -> `PlayerVitals` -> `PlayerEntity` path, #5033, `468c66142`) (#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`; the corpus file also pins a measured `textures\interface\` DDS census, 1,767 entries split across both texture archives, #5669, `065c9d31d`), 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; FNV hits now lose the target's Damage Threshold in `combat_damage_system`, so the gate checks each swing's applied damage is positive, consistent and <= the incoming loadout damage, not equal to it — `dbe562c1f`, `52b59e43d`), `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.)
