Gamebryo 2.3 → Redux Compatibility Audit

VerifiedCaution

Audits mapping gaps between Gamebryo 2.3/Creation engines and Redux: coordinate/placement math, legacy subsystem cross-checks and cross-game translation patterns.

Sby Skills Guide Bot
DevelopmentAdvanced
11/2/2026
Claude Code
#game-engine#compatibility-audit#coordinate-systems#legacy-migration#code-review

Recommended for

Automated summary

This skill audits compatibility gaps between the legacy Gamebryo 2.3 / Creation engines and the Redux engine, focusing on coordinate and placement math, legacy subsystem cross-checks, and cross-game translation patterns.

Strengths

  • Explicitly scopes itself against sibling audits (/audit-nifal, /audit-physics, /audit-exterior) so findings are not duplicated
  • Gives concrete file paths, named guard tests, and ready-to-run git log/grep commands as a first step
  • Separates documented engine limitations from genuine findings and points to layer leak inventories to avoid re-filing closed issues

Limitations

  • Tightly coupled to one private repository layout and to internal spec documents not included here
  • Assumes a mounted Gamebryo 2.3 source drive or the docs/legacy/ fallback copies
  • The provided document is truncated and assumes deep familiarity with the project's NIF/ECS pipeline
When to use it

Use it after changes to coordinate, Euler or cell-translation code to confirm no legacy mapping or placement regression slipped in.

When not to use it

Don't use it to audit a single layer's internals (NIFAL, PHYSAL, EXAL) or for general code review outside this codebase.

Security analysis

Caution
Quality score84/100

The content is a read-only code-audit playbook: it greps, reads specs, inspects git history and diffs, and writes a local markdown report. There is no destructive command, no curl|sh, no obfuscated payload, no secret handling, and no attempt to alter the auditor's role or bypass safety. Risk is limited to ordinary shell/network use (`gh`) and local file writes, hence caution rather than safe.

Findings
  • •No allowed-tools are declared, yet the procedure instructs the agent to run shell tooling (`git log`, `grep -rn`, `gh issue list`) and to write a report file into `docs/audits/`; this is legitimate read-only auditing but is un-declared capability use.
  • •`gh issue list --search ...` invokes the GitHub CLI over the network with ambient credentials; scope should be confirmed before running.
  • •The skill depends on sibling files (`_audit-common.md`, `_audit-severity.md`) that are not included in the submitted content, so the full instruction set is not visible for review.
  • •Relies on shell tooling (grep, git log, `gh issue list`) and writes a report file under docs/audits/; all read-only analysis plus one Markdown write, but `gh issue list` implies network access and GitHub auth in the agent's environment.
  • •Instructs the agent to trust in-repo documents (`_audit-common.md`, `_audit-severity.md`, `docs/engine/*.md`) as protocol; if those files were tampered with, behaviour would follow them — no verification step is specified.
How this analysis is made

Examples

Post-change placement audit
Run the legacy compatibility audit for coordinate and placement gaps since the last report — check whether any new duplicated (x, z, -y) swaps or 4096.0 cell literals appeared in byroredux/src or crates.
REFR Euler regression check
Verify that the REFR Euler conversion still uses the Bethesda CW-positive Rx·Ry·Rz product and that no path bypasses coord.rs for quaternion conversion.
Legacy subsystem cross-check
Cross-check the Gamebryo 2.3 headers against Redux and list mapping gaps in the seams not owned by /audit-nifal, /audit-physics or /audit-exterior.

description: "Audit compatibility gaps between Gamebryo 2.3 and Redux — what's mapped, what's missing"

Legacy Compatibility Audit

Read _audit-common.md and _audit-severity.md for shared protocol (layout, game-data + legacy-source locations, severity, NIFAL severity rows, dedup, report format).

Purpose and scope

Compare Gamebryo 2.3 / Creation behaviour with Redux and surface mapping gaps — content the source engines render or simulate that Redux drops, mis-maps or diverges on — in the seams no layer or per-game owner covers. Each abstraction layer has its own deep audit; findings about a layer's internals go there, not here:

| Layer / seam | Owner | Spec | |---|---|---| | NIFAL (NIF → canonical ECS, material boundary) | /audit-nifal | docs/engine/nifal.md | | EXAL / SKYAL / WATAL (exterior, sky, water translation) | /audit-exterior | docs/engine/{exal,skyal,watal}.md | | PHYSAL (Havok → Rapier; constraint CInfo decode is the only per-game seam) | /audit-physics (+ /audit-nif for the decode) | docs/engine/physal.md | | CHARAL (rulesets) | /audit-character | docs/engine/charal.md | | Per-record / per-block decode divergence | /audit-esm, /audit-nif | — |

This skill keeps three dimensions: the coordinate/placement math (no other owner), the legacy-subsystem cross-check (the only audit that reads the 2.3 headers) and the cross-game translation-pattern spot-check. The former NIFAL, material-boundary, PHYSAL and EXAL dimensions were re-homed to the layer owners above: PHYSAL and the material boundary yielded only duplicates of /audit-physics / /audit-nifal; EXAL/WATAL yielded real boundary-completeness finds, which is exactly /audit-exterior's charter.

Documented limitations are not findings (FO4+ packed Havok blobs, phantoms, NiFogProperty's deliberate non-dispatch — no Material landing site, cell-scope CellLighting only — and the measured ~1.0 shared emissive scale, nifal.md §4). Cross-check the layer specs' leak inventories so closed leaks are not re-filed. If the Gamebryo 2.3 drive is unmounted, /mnt/data/src/reference/gamebyro-v26 / gamebyro-v32 and docs/legacy/ carry the same class shapes.

Dimensions

1. Coordinate + placement fidelity (Z-up → Y-up)

The most catastrophic mapping-bug class: one wrong transform mis-places or mirrors all content silently. Reference: docs/engine/coordinate-system.md. Paths: crates/core/src/math/coord.rs, crates/nif/src/import/coord.rs, crates/nif/src/rotation.rs, crates/nif/src/blocks/strip.rs, byroredux/src/cell_loader/euler.rs, crates/core/src/ecs/components/camera.rs First step: git log --since=<last report> --format='%h %cs %s' -- crates/core/src/math crates/nif/src/import/coord.rs byroredux/src/cell_loader/euler.rs and grep -rn '(x, z, -y)\|4096.0' byroredux/src crates --include='*.rs' for new duplicated swaps / cell literals. Guards: coord.rs tests euler_matches_gamebryo_from_euler_angles_xyz + zyx_product_disagrees_with_gamebryo_on_multi_axis + modes_zero_and_one_agree_only_on_z_only_rotations; cell_loader/euler_zup_to_quat_yup_tests.rs; strip.rs::even_odd_winding_matches_opengl_convention.

  • One implementation — the (x, z, -y) swap and quaternion conversions live in coord.rs (zup_to_yup_pos, zup_to_yup_quat_wxyz, euler_zup_to_quat_yup, normalize_quat, cell_grid_to_world_yup); the NIF-typed flavour (zup_point_to_yup, zup_matrix_to_yup_quat) wraps them in import/coord.rs. Any new duplicated swap or matrix→quat path that bypasses them is a finding (the pre-#1044 five-site duplication kept the #333 unit-quaternion fix at only one).
  • REFR Euler — Bethesda CW-positive, Gamebryo FromEulerAnglesXYZ product from_rotation_x(-rx) * from_rotation_z(ry) * from_rotation_y(-rz) (Rx·Ry·Rz in Z-up; mode 0 = REFR_ROTATION_MODE_SHIP). The ZYX product (mode 1) was the 2026-05-26 → 2026-10-16 ship, from reading OpenMW's osg::Quat expression as a Hamilton product (OSG multiplies in reverse order, so OpenMW agrees with XYZ); it matches only Z-only REFRs and misplaces every multi-axis one (2a8b8e505; kept as an A/B knob only). REFR placement goes through the --rotation-mode diagnostic dispatcher euler_zup_to_quat_yup_refr (default mode 0); XCLL lighting calls the canonical helper directly. Flag any caller that hardcodes a mode or re-derives the formula. --rotation-mode reaches the library unclamped (boot::cli::rotation_mode_arg, #4126/#4764), so an out-of-range value falls back to the shipping formula — a CLI-side clamp is the regression.
  • Winding — NIF CW → projection Y-flip (Camera::projection_matrix, Vulkan clip space) → CCW front face. Strip de-stitch has ONE implementation (strip::destrip, #2298): odd triangles swap the last two indices; a D3D-style first-two swap re-introduces inside-out geometry, and a hand-copied destrip is the regression.
  • Exterior grid — EXTERIOR_CELL_UNITS = 4096.0 + cell_grid_to_world_yup are the sole source (#1112 collapsed six divergent literals, one with a Z-flip sign bug); new literal 4096 cell math is a regression (distance literals are not). The one sanctioned re-declaration is crates/bsa/src/uvd.rs (the bsa crate cannot depend on core), re-exported as UVD_CELL_UNITS and const-asserted equal to the core constant in byroredux/src/cell_loader/precombined.rs (27002ed99, #4939). Also check frame composition, not just the literal: FO4 exterior _oc.nif precombine instances are already world-absolute, so bakes spawn at a Vec3::ZERO root — composing cell_grid_to_world_yup on top placed every exterior bake one cell out (#5228, f3e1bba62).
  • Transform model — Gamebryo's NiTransform scale is uniform by format (docs/legacy/api-deep-dive.md), so Redux's Transform.scale: f32 is not a collapse — a "non-uniform scale is dropped" finding is a false premise. Matrix3→Quat at import (Shepperd + SVD repair for degenerate rotations) and local * parent propagation are the fidelity surface. Non-finite input is neutralised at the boundary: rotation.rs::sanitize_rotation (identity) + the read_ni_transform* readers (translation 0, scale 1, #4549); animation rotation keys go through the one sanitizer anim/keys.rs::normalized_rotation_sample (#4396). Core normalize_quat is deliberately lenient — a new caller using it as a sanitizer is a finding.
  • Unit scale — Starfield authors metric; crates/plugin/src/esm/records/spatial_units.rs::normalize lifts ESM placement/light/fog/weather/water/navmesh distances to 70 units/m once per plugin walk (FO76 is BU-native; its only lift is the shared-decoder WATR per-metre absorption lane, #5169), and NIF import does the matching mesh/bone conversion. A second game-dependent distance multiplier downstream (lighting, skinning, camera) is the regression; per-field coverage is /audit-esm Dim 5.

2. Legacy subsystem coverage

What the 2.3 engine drives that Redux maps incompletely or not at all: cross-check SDK/Win32/Include/, CoreLibs/Ni*/ (see _audit-common.md Legacy Source; /legacy-lookup) against the Redux side. Audit fidelity, not existence — the import-critical set exists. Paths: docs/legacy/api-deep-dive.md (mapping table), crates/core/src/ecs/components/, crates/core/src/animation/, byroredux/src/anim_convert.rs, crates/nif/src/import/{material,walk}/ First step: read the mapping table against crates/core/src/ecs/components/; gh issue list --search 'SUBSYS' --state open for what is already tracked.

  • Property → pipeline — for each NiProperty type: does its authored effect land in dynamic pipeline state (cull, blend, stencil two-sided) or a Material/per-object component? Flag any property whose authored effect is parsed and dropped.
  • Animation model — NiTimeController → NiInterpolator → keys converge at import (nifal.md Animation; B-spline / Euler / TBC → quaternion keys; KF + embedded through convert_nif_clip; text keys → AnimationTextKeyEvents). Only per-light ambient colour channels (ColorTarget::LightAmbient, no light-buffer slot, #983) are parked; morph-weight channels reach AnimatedMorphWeights and deform on the GPU in skin_vertices.comp (#3231/#4399). The timing envelope (cycle type, frequency, phase) and the NiControllerManager / KFM sequence state machine are the known-fragile spots (#4128 open).
  • Scene graph — each NiAVObject field → Redux component (Parent, Children, GlobalTransform, WorldBound, Name, flags) with fidelity, not existence.
  • String interning — NiFixedString + GlobalStringTable ↔ StringPool + FixedString: semantic equivalence; flag any gap that breaks bone-name → entity resolution (load-bearing for skinning and PHYSAL bone binding).
  • Typical yield is the shape "authored input parsed, no canonical sink" — weapon reach/speed, XLOC lock state, the controller timing envelope and Oblivion's parallax mode were each MEDIUM in past reports and are since fixed (#3096–#3098). Confirm against /audit-gameplay scope before filing gameplay-facing gaps.

3. Cross-game translation-pattern spot-check

Reference: docs/engine/per-game-translation-survey.md §4 (per-layer inventory), §5 (Patterns A/B/C), §7 (why Fallout is the stress case). Verify a survey claim against code before citing it — the doc last changed 2026-10-10 (stale file/line cites re-pointed, #5472) and has carried stale examples before. Paths: crates/nif/src/version.rs, crates/plugin/src/esm/reader.rs (GameKind), crates/plugin/src/esm/records/ First step: grep -rnE 'bsver(\(\))? *[<>=]+ *[0-9]{2,3}\b' crates/nif/src --include='*.rs' | grep -v test then drop // comment lines (grep -vE '^[^:]+:[0-9]+: *//') — literal thresholds; at 2026-10-15 the only non-comment hits are three test asserts in blocks/base.rs. Then grep -rn 'game == \|GameKind::' byroredux/src/cell_loader byroredux/src/scene --include='*.rs'.

  • The renderer/shader side is clean; per-game branches live upstream (parser, importer, cell loader). Look there.
  • Pattern A — hardcoded BSVER threshold literals that should be a named version::bsver::* constant. This is not a bypassed NifVariant helper: those feature-flag predicates were removed deliberately (#938/#1511/#1840/#1897) and version.rs records the raw-bsver doctrine as fully enforced (search raw-bsver doctrine). Do not flag a raw bsver() comparison as "should call a helper".
  • Pattern B — feature flag on an enum where the wire format already discriminates the game (the correct shape; flag mis-dispatch, not "needs a trait").
  • Pattern C — divergent decode of one wire structure across games/eras (same record, different offsets or sizes): FO4 WEAP with no DATA and WATR simulator blocks decoded one field off were the HIGH finds. Depth belongs to /audit-esm / /audit-nif; this dimension checks the cross-game shape (a new per-game size/offset split with no test per era).
  • Scattered new if game == … in the cell loader / exterior assembly is a finding (one GameKind-keyed decision or a table-shaped match returning data is fine).

Process

  1. Read the live spec for the seam under audit; its leak inventory is the baseline — do not re-file what it records as closed or a limitation.
  2. Trace each claimed boundary to its callers (grep the symbol) and confirm single-producer.
  3. Cross-reference Redux components / translate sites against the legacy headers and the survey.
  4. Classify per _audit-severity.md (a wrong/divergent canonical out of a translate() = HIGH; a translatable input silently dropped = MEDIUM, escalate if it removes visible content). Disprove every finding before keeping it.
  5. Finalize per _audit-common.md "Report Finalization" (save to docs/audits/AUDIT_LEGACY_COMPAT_<TODAY>.md; do not open issues directly). Suggest /audit-publish (label legacy-compat + the domain label).

From the file to a first result

The download contains exactly the content displayed on this page. This copy may differ from the latest version in the source repository.

View the source and supporting files

This download contains SKILL.md only. Any scripts, references, templates and dependencies are not included. Get the required files from the source, preserving their directory structure, before continuing.

1. Download the file

Download SKILL.md

From the root of a test project, save the file as .skill-downloads/gamebryo-2-3-redux-compatibility-audit-mvg6ty78/SKILL.md, or use the command below. This folder is for inspecting the skill before installation.

Command for macOS/Linux or WSL: requires a POSIX shell and curl. On Windows without WSL, use the download button and create the folder manually.

mkdir -p '.skill-downloads/gamebryo-2-3-redux-compatibility-audit-mvg6ty78' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/gamebryo-2-3-redux-compatibility-audit-mvg6ty78/download' --output '.skill-downloads/gamebryo-2-3-redux-compatibility-audit-mvg6ty78/SKILL.md.part' && mv '.skill-downloads/gamebryo-2-3-redux-compatibility-audit-mvg6ty78/SKILL.md.part' '.skill-downloads/gamebryo-2-3-redux-compatibility-audit-mvg6ty78/SKILL.md'

2. Check prerequisites

Read SKILL.md before using it. If it references scripts or external services, inspect them and prepare the required access in your test environment.

No recognized prerequisites section in this file. This does not mean it is self-contained: libraries, tools and access requirements may be mentioned elsewhere in the content or source repository.

The platforms on this page are catalog indications. The paths below follow tool documentation; they do not prove this skill has been run in those tools. No minimum tool version is confirmed for this listing.

3. Load the skill

This file does not provide a usable name/description header for this native procedure. It remains available to download and inspect; use the manual method below.

Manual method or another tool: attach SKILL.md to a conversation, or open it in an agent that can read files. Include any required supporting resources. No universal folder is recognized by every tool.

4. Try a first task

Use a short, synthetic input: an API endpoint, a small document or an interface brief. In a new conversation, attach the file or give the agent its path, then adapt this request:

Read .skill-downloads/gamebryo-2-3-redux-compatibility-audit-mvg6ty78/SKILL.md and apply its instructions to this example: [describe a test input]. Identify any missing files, dependencies or access. Produce the result requested by the skill without inventing data or running unreviewed scripts.

Expected result: output matching the skill instructions, or a precise list of missing prerequisites. A read confirmation alone does not validate a first use. If an external resource is unavailable, that path remains untested.

Related skills