GENERATED VIEW · PRIVATE ARCHIVE · DO NOT SERVE
RobCo Industries · Archive Museum

AUDIT_FO3_U8.md



RELEASE

planning/2.8.5/audits/FO3/AUDIT_FO3_U8.md

sha256 07e10a799c5cb0ec · 16014 bytes · original held in the private archive

# FO3 PIP-BOY — UNIT U8 · PROTOCOL 8 STAGE 3 (INDEPENDENT AUDIT) **Auditor:** Opus (stage 3 — independent audit). **No code changed. No commit. No push.** **Commit audited:** `62ff4ab` on `dev` ("FO3 U8"). **Predecessor checklist:** `planning/AUDIT_FO3_U7.md`. **Method:** started from the diff and the pixels, not the implementer's report. Read the figure markup, the limb apply loop, the CSS grid that flanks the figure, the render-integrity allowlist change, and the full test diff. Took my own Playwright screenshots (my own harness, not the implementer's saved PNGs) of STATUS with limbs crippled on the LEFT only, the RIGHT only, and ALL limbs incl. head; SPECIAL/SKILLS/PERKS/GENERAL/MANIFEST; FO3 portrait; FO3 desktop; and NV at 360. Read the computed colour of every element on the FO3 glass. Ran the 3199-test Node gate myself (all pass). Verified the MANIFEST filter is still reachable in both orientations. **Verdict: BACK TO STAGE 2.** Most of the punch-list genuinely landed — but the unit ships a **live mirrored-controls bug** (the one the owner already reported) and a **false user-facing CHANGELOG line**. Both are blocking. Details below. --- ## ⭐ THE ONE-LINE ANSWER (for the phone) **The owner is right, and I found exactly why. On the Fallout 3 character screen, the body-part boxes are laid out on the *opposite* side from the matching arm/leg on the Vault Boy figure — so tapping "L.ARM" (which sits on the left) lights up the figure's *right* arm, and vice versa. Nobody's data is wrong — tapping L.ARM really does record a hurt left arm — but the boxes and the figure point at opposite sides, so it *looks* mirrored, exactly as reported.** Separately, the release notes claim "fixed the last remaining red element on the screen," and that's **not true** — there are still several red things on the Fallout 3 glass (a red ✕ next to your status effects, the radiation readout, a red "RadAway needed" warning, and a pulsing red edge glow when your health is low). The new figure itself looks great and reads clearly at real size, the "CRIPPLED" wording and green perk- delete button both landed, and New Vegas is untouched. But the mirrored taps and the false red claim have to go back for another pass. --- ## ⭐⭐ THE MIRRORED-LIMB BUG — CONFIRMED, ROOT CAUSE NAILED **Confirmed with my own eyes and the live DOM, on BOTH FO3 landscape and FO3 desktop.** I crippled only the two LEFT boxes (L.ARM + L.LEG) and screenshotted STATUS: both "CRIPPLED" marks appeared on the figure's **right** side. I then crippled only the two RIGHT boxes (R.ARM + R.LEG): both marks jumped to the figure's **left** side. That is the owner's report, reproduced exactly. ### What is actually happening (precise root cause) Three things each have to be checked separately — the state wiring, the figure drawing, and the box placement. Here is what each one does: 1. **The control boxes are wired correctly.** `btn_l_la` calls `toggleLimb('la')`, which writes `state.la` (the left arm). The box labelled L.ARM really does control the left arm. Same for all five. (index.html ~1704-1750; the labels and handlers match.) 2. **The figure is drawn correctly (anatomically).** In the SVG, `data-limb="la"` (left arm) is drawn on the **viewer's right** (x ≈ 194–296 in a viewBox centred at x≈170); `data-limb="ra"` (right arm) is drawn on the **viewer's left** (x ≈ 56–146). Legs the same: `ll` right, `rl` left. That is the correct front-facing convention — a person facing you has their left arm on *your* right — and it is what Fable's mockup documents. The apply loop toggles `.crippled` on the matching `[data-limb]`, so the figure always dashes the anatomically-correct limb for the state. The **display is NOT lying** about which real limb is hurt. 3. **The control boxes are placed on the WRONG side.** The CSS grid (`css/60-fo3-pipboy.css` ~772–806) puts **HEAD / L.ARM / L.LEG in the left column** (grid-column 1) and **R.ARM / R.LEG in the right column** (grid-column 3). So the L.ARM box sits on the viewer's **left**, but the figure limb it controls (`la`) is drawn on the viewer's **right**. Every arm/leg box is on the opposite side of the figure from the limb it toggles, and the little dash "leader lines" (`::after`, ~829-851) reinforce the wrong pairing. **So which side is wrong?** Neither the wiring nor the figure is individually wrong. The figure uses the anatomical (front-facing) convention; the boxes are placed by naive screen-side (L on the left). The two conventions **contradict each other**, and that contradiction is the whole bug. It is a **layout mismatch — the box column assignments** — not a mislabelled figure and not a mis-wired handler. **Is the damage DISPLAY mirrored / misinforming?** No — not in the dangerous sense. If the state says the right arm is crippled, the figure dashes the limb on the viewer's left, which *is* the character's right arm (front-facing). The figure never shows the wrong anatomical limb. The only confusion is spatial: the dashed figure limb is on the opposite side from the box you tapped. So a player who trusts the box **labels** records their damage correctly; the figure just appears to react on the "wrong" side. That makes this a serious UX/coherence bug, but **not** a silent data-corruption bug. **Does the bug live in the boxes too, or only the figure?** The box **labels and wiring are fine** — no relabelling is needed. Only their **column placement** is on the wrong side relative to the figure. ### The unambiguous fix (for Stage 2 — do NOT apply here) Keep the anatomically-correct figure and **swap the two box columns**: move L.ARM / L.LEG to grid-column 3 (the viewer's right, beside the figure's `la`/`ll`), and R.ARM / R.LEG to grid-column 1 (beside `ra`/`rl`), and swap the matching `::after` leader-line side rules. Then each box sits next to the exact limb it controls and the perceived mirror disappears. (The alternative — redrawing the figure un-mirrored — is worse: it breaks Fable's approved mockup and the front-facing convention.) Files: `css/60-fo3-pipboy.css` grid rules ~782–806 and leader-line rules ~829–851. **Why it escaped the gate:** the new tests confirm the figure has five `data-limb` groups and that the apply loop toggles `.crippled` — but **no test checks that a box sits on the same side as the figure limb it controls.** Same shape as the U5 "green gate, invisible panel" escape. The Stage-2 fix must ship a Protocol 13 regression guard for the box↔figure side correspondence. --- ## THE U7 PUNCH-LIST — VERIFIED EACH, INDEPENDENTLY ### 1 · render-integrity allowlist tightened (bare tag name → dock membership) — ✅ FIXED The filter no longer matches occluders by bare tag name. `pageProbe()` now records `hitInBezelDock = hit.closest('.bezel')` on each occlusion (live, inside the page), and `filterKnownPreexisting()` filters on `!o.hitInBezelDock`. The old `CONFIRMED_PREEXISTING_DEFECT_BEZEL_DOCK_OCCLUSION_HITS` set (which literally contained `'DIV'`, `'SPAN'`, `'NAV'`) is deleted. **The hole is genuinely shut, by construction:** an id-less non-dock `<div>` occluder now reports `hitInBezelDock=false` and surfaces as a failure, where the old code saw `o.hit === 'DIV'`, matched the set, and forgave it. Tests 224.13a/b lock both the new predicate and the removal of the old set. Solid. ### 2 · Fable's variant A figure dropped in — ✅ LANDED, and legible at real size The placeholder stick figure is replaced by Fable's variant A drawing (quiff, face, spread fingers, condition bars, per-limb CRIPPLED labels). I rendered it at the real 780×360 at 2× **and** raw 1×: **it holds up** — the face, quiff, individual fingers and dashed limbs all read clearly; Fable's own worry about the thin stroke turning to mush did not materialise. The **head-wail face swap** on a crippled head works (verified with all limbs crippled). Legibility: PASS. (The figure being *anatomically mirrored vs. the boxes* is the separate blocking bug above — the drawing itself is fine.) ### 3 · MANIFEST density — ⚠️ IMPROVED, still marginally under the mockup's 6 The always-visible filter search row now collapses behind a small `⌕` toggle (FO3 landscape only, hidden by default). My screenshot shows **Test Items 1, 3, 5, 7, 9 fully + 11 partially = ~5½ rows**, up from U7's ~4–5, against the mockup's 6. Better, honestly disclosed, but not quite 6. Non-blocking. ### 4 · CRIP → CRIPPLED — ✅ FIXED The limb chips render `[░░░░░░] CRIPPLED` in full. Verified in the live DOM and every STATUS screenshot. Tests 227.13a/b lock it and guard the old "CRIP" from returning. ### 5 · Perk-delete red ✕ → green — ✅ FIXED On the PERKS board the SLOT 01/02 delete ✕ buttons are green (`--robco-green`), not red. Verified by pixels and computed style. Tests 227.14a/b lock it green and guard `--robco-danger` from returning. --- ## ⭐ THE TWO THINGS DISPATCH SAW IN THE SCREENSHOTS — VERIFIED ### A · RED IS STILL ON THE GLASS — ✅ CONFIRMED, and it's MORE than one element The commit message and the CHANGELOG both call the perk ✕ **"the last remaining red / non-green element on the glass."** That is **false.** Reading the computed colour of every element on the FO3 landscape STATUS board, these remain red (`rgb(231,76,60)`), all on the landscape screen: 1. **The ACTIVE EFFECTS purge ✕** (`.stlamp-purge`) — the red ✕ next to "Well Rested". Visible in the viewport. (The implementer disclosed this stays red — but the CHANGELOG line contradicts the disclosure.) 2. **The RAD (RADS) value field** (`#stat_rads`) — red text at high radiation. 3. **The "RAD TREATMENT / RadAway needed — NONE IN PACK" alert** (`#radAwayAlert` + its lamp) — bright red, and quite prominent when the vitals column is scrolled. 4. **The critical-HP edge vignette** (`body.hp-critical-vignette .glass-frame`, `css/55-feedback-animations.css`) — a pulsing red inset glow around the **entire** glass whenever HP < 25%. It is **unscoped** (shared global, applies on every FO3 board), so it reddens the whole Pip-Boy edge. Pre-existing, not introduced by U8 — but it is red on the FO3 glass and contradicts "one green." So "the last remaining red element" is a **false user-facing CHANGELOG claim** — the exact class of defect this stage exists to catch, and the exact thing Dispatch asked me to confirm. The perk ✕ fix is real and good; the *claim wrapped around it* is not. ### B · RIGHT-HAND VITALS COLUMN CLIPPING — ⚠️ PARTIALLY still clipping The vitals panel is heavily scroll-gated: `#opVitalPanel` measures scrollHeight **495px** inside a **141px** visible box (28% shown). In the populated state, the **RAD value/slider clips** at the panel's bottom edge and the RAD-AWAY alert sits below the fold; the CONDITION (HP 22/100 CRITICAL) and the "Well Rested" effect name + ✕ are visible. So it is **not** the clean "radiation and active effects visible without scrolling" the U7 changelog claims — the effect name is visible, but the radiation *value* still clips. This is inherited from U7 (U8 did not touch the vitals layout), so it is not strictly U8's regression, but the standing claim is optimistic. Non-blocking for U8 on its own, but note it did not get better. --- ## ALSO VERIFIED - **Nothing became read-only.** MANIFEST's filter search is still fully reachable: on FO3 **landscape** the `⌕` toggle reveals the row and focuses the input (probed: closed→open, input reachable); on FO3 **portrait** and NV the row stays always-visible (probed: rowVisible=true, input reachable) — because both the row-hide and the toggle-reveal rules are correctly inside the `@media(orientation:landscape)` block. One extra tap on landscape, **no capability lost.** Perk delete stays one-tap; STATUS steppers present. - **Test-suite integrity — no covert weakening.** Count moved **3187 → 3199 (+12)** and it reconciles exactly: 224.13 (×2), 227.6e (×1), the 227.11c swap (net 0), 227.12 (×5), 227.13 (×2), 227.14 (×2). The one assertion that *looks* narrowed — 227.6a's regex changed from `<g class="limbline" data-limb=…>` to `<g data-limb=…>` — is a **faithful update to the restructured markup** and still requires exactly five correctly-keyed limb groups; 227.6b actually got **stronger** (exactly five `slottxt` CRIPPLED labels vs. mere presence). No regex was quietly loosened. **I ran the runner myself: all 3199 pass.** (The only real gap is *missing* coverage for the box↔figure side correspondence — see the mirror section.) - **NV untouched.** My NV 360 screenshot renders correctly (cyan scheme, legacy top-down zone plate, flat layout); the diff introduces no NV selectors. PASS. - **Protocol 38.** Every new FO3 rule (figure classes, limb grid, MANIFEST toggle) is scoped `[data-game='FO3']`; `toggleManifestFilterRow()` is game-agnostic (flips `hidden`, no game literal). PASS. (The red critical-HP vignette is a pre-existing unscoped rule, not a U8 addition.) - **Protocol 1.** Cache bumped `r23 → r24`. PASS. - **Protocol 2/2a.** Counts synced to 3199 across CLAUDE.md / README.md / ARCHITECTURE.md / RULES.md / CHANGELOG.md; no stale 3187 anywhere. PASS. - **Protocol 13.** Each landed fix ships a guard (224.13, 227.12/13/14, 227.6e) — **but the headline mirror bug has no test and is not fixed.** - **Protocol 41.** Tree clean (my screenshots live under gitignored `planning/`). - **Deploy.** `62ff4ab` is on `origin/dev` (correct — unreleased work stays on `dev`, Protocol 43). --- ## CHANGELOG ACCURACY — every new line checked against the running app - "Redrew the Vault Boy figure… quiff, face, spread fingers… crippled head swaps to a distressed face" — ✅ **true** (verified). - "cargo screen now shows another row of items… filter search box tucks behind a small tap-to-reveal search button… filter still there, one tap away" — ✅ **true** (≈5½ rows, `⌕` toggle, reachable). - "crippled-limb readout… now spells out CRIPPLED in full" — ✅ **true**. - **"Fixed the last remaining red element on the Fallout 3 Pip-Boy's landscape screen"** — ❌ **FALSE.** Multiple red elements remain on that very screen (§A above). This line must be corrected. --- ## VERDICT: BACK TO STAGE 2 Good work landed — the render-integrity hole is genuinely shut, Fable's figure is in and legible, the CRIPPLED wording and green perk-delete are done, NV is untouched, and the tests are honest. But two blocking issues stand: 1. **[BLOCKING] The mirrored limb controls.** A live bug in the owner's hands: tapping L.ARM/L.LEG lights up the figure's right side and vice versa, on both FO3 landscape and desktop. Root cause: the box grid columns are placed on the opposite side from the anatomically-drawn figure limbs. Fix: swap the L/R box columns (and their leader-line sides) in `css/60-fo3-pipboy.css`, keeping the figure as- is. **Must ship a Protocol 13 regression guard** asserting each box sits on the same side as the figure limb it controls — the current tests do not cover this. 2. **[BLOCKING] The false "last remaining red element" CHANGELOG line** (and the same claim in the commit message). At minimum the line must be corrected to the truth. Better: also decide what to do about the remaining reds — the ACTIVE EFFECTS ✕, the RAD value, the RadAway alert, and the global critical-HP vignette — under the "one green" rule, and make the changelog say only what's true. 3. **[NON-BLOCKING, carry forward] MANIFEST at ~5½ rows** (target 6), and the **right vitals column still scroll-gates the RAD value** (the U7 "visible without scrolling" claim is optimistic). --- *End of Stage 3. No code was changed, no commit made, no push. Evidence screenshots saved as `planning/mockups/fo3/audit-u8-*.png` (gitignored).*
STAMP · generated for RELEASE v2.8.5 commit 06e5180 (06e51801b38a) · archive input-tree hash c07fbfbdd2e1ddeb · 754 files · no wall-clock timestamp (regenerates identically when nothing changed).