RELEASE
planning/2.8.5/audits/TEST_STRENGTH_U2.md
sha256 5da4aa10c2be7b86 · 35012 bytes ·
original held in the private archive
# Health Batch U2 — Assertion-Strength + Dedup Audit (the ledger that steers U3)
**What this is.** The U2 unit from `planning/HEALTH_BATCH_PLAN.md`: every one of the runner's ~232 suites (45,565 lines, `tests/robco-diagnostics.js`) was read and classified — which static suites are *legitimately* static (Protocol 20), which are false confidence (a grep pretending to verify behavior), and which tests are redundant or tautological. Analysis only — no code changed, nothing committed.
**Snapshot:** branch `dev`, clean at `92f614e`, 2026-07-16. Method: one mechanical pass (suite boundaries, vm-usage, duplicate-literal scan) + a full manual read of every suite body (7 parallel readers over contiguous line ranges, shared rubric), cross-checked against the push-gate browser checks (`test.html`'s 22 runtime suites, `render-integrity`'s 12-config matrix, `save-survival`, `offline-first`, `boot-smoke`).
---
## 0. The headline, up front
**The "75% static" figure is real but mostly LEGITIMATE.** Of ~173 static-dominant suites:
| Bucket | Suites | Share of static mass |
| --- | --- | --- |
| **KEEP-STATIC** — grep is the right tool (Protocol 20 CSS/SW/security pins, data golden-masters, config guards, absence/retirement ratchets, doc-sync) | **~159** | **~92%** |
| **CONVERT** — static grep standing in for behavior it never executes | **12 whole suites** + surgical asserts in ~25 more | ~7% of suites, but the highest-risk 7% |
| **PRUNE** — redundant or tautological, safe to delete | 1 whole suite + ~40 scattered asserts | ~1.2% of the 3,277 tests |
The suite is **not** rotten — the static mass is dominated by exactly the classes Protocol 20 sanctions, and the newest third of the runner (Suites 200+) already practices the extract-and-execute vm pattern consistently. The problem is concentrated: a specific, named list of suites guards **user-critical behavior** (AI→state import semantics, save migrations, native calculators, inventory write paths, destructive-op ordering) with source-text greps that stay green while the logic is broken. That list is §2.
Also found and worth as much as any conversion: **two behavioral tests that cannot fail** (a vacuous-async bug — §4), and a class of **silent-empty extraction anchors** where a benign edit makes a guard scan an empty string and pass vacuously (§5.4).
---
## 1. The three buckets, with evidence
### 1a. KEEP-STATIC (~159 suites) — correct as-is
These break down into recognizable families, each inherently textual:
- **Protocol 20 named classes:** critical-CSS presence (Suites 15, 61, 92, 94, 120, 129, 160, 183, 188, 209, 225…), SW invariants (16, 27, 49), render markup contracts (14, 88), security pins — XSS/escape/CSP/auth patterns (21, 44, 45, 54, 55). The failure mode is "a refactor deletes the safeguard" — grep catches exactly that.
- **Data golden-masters (Protocol 3):** CSV structure + canon values (9, 19, 20, 38–41, 68, 70, 74, 75, 78–83, 104), the FO3/NV weapon-data pins with red+green validator proofs (230, 231, 232), rails/identity data contracts (222). Suite 124 (theming) even computes real WCAG contrast from parsed data — the strongest form static takes.
- **Prohibited-pattern absence + retirement ratchets:** 23, 89 (game literals), 128 (runner rename), 168 (TERMLINK), 148.6 (zero `setInterval` in ui-core), 144.11 (no auto-cloud-push), 146.12/158.8/162.14 (zero-campaign-write batteries). Absence can only be grepped.
- **Auto-discovered cross-file sync guards** — the best statics in the file: Suite 10 (every `getElementById` in syncStateFromDom resolves in HTML), 27 (every script/link tag in SW ASSETS + on disk), 59 (every inline handler resolves to a definition, with an anti-vacuous sentinel), 49.1 (every js/css file precached, derived from disk), 184.12 (every `<details>` persistence-covered), 212.11 (every `RobcoEvents.emit` has a Diagnostic Shell trigger, with a negative proof), 220 (doc-reference integrity, mechanically derived).
- **Process/gate/config guards:** 13, 28, 30, 31, 50, 52, 57, 60, 96, 97, 98, 100-adjacent CI checks.
- **Deliberate static/behavioral pairs:** Suites 138–146 (IndexedDB P1–P8) are static *by design* — each header names its behavioral twin in `test.html` Suites 10–18, which runs the real IndexedDB in a browser at push. Converting the Node side would **duplicate** coverage, not add it. Same layering: Suite 61 vs render-check, 96.3 vs test-html-check (commit-boundary copy vs push-boundary runtime — Protocol 36a).
**Verdict:** leave all of these alone in U3, except for brittleness loosening (§5).
### 1b. CONVERT (12 suites dominant + surgical) — where green doesn't mean it works
The common shape: the suite's stated purpose is *behavior* ("the calculator computes", "the import validates", "data is archived before it's destroyed") but every assert is identifier presence, `indexOf` ordering, or the guard expression quoted verbatim — all of which stay green when the logic is inverted, unreachable, or wrong. Ranked list in §2.
### 1c. PRUNE (1 suite + ~40 asserts) — deletable with zero coverage loss
Full list with evidence in §3. Mechanical cross-check: an exact-literal duplicate scan across all suites found only **5 shared assertion literals** — so redundancy here is semantic (same invariant, different phrasing), and every prune below names its covering twin.
---
## 2. The ranked CONVERT list for U3
Ranked by (user-criticality × how false the current confidence is ÷ effort). The vm harness patterns to copy already exist in-repo: Suite 133 (autoImportState sandbox), Suite 107 (`_threatCompute`), Suite 172 (deterministic task queue), Suite 182 (fake-element drag harness), Suite 177 (renderAccount matrix), Suite 221 (per-path reconciliation).
### Tier A — do these first (S effort, user-critical, zero current behavioral coverage)
**A1. Suite 76 — autoImportState hardening F1/F2** (line ~8827) ⭐ *the single highest-value conversion*
- **Now:** the AI→durable-state import semantics proven by token presence over `indexOf`-sliced windows. A kept-token-but-inverted-branch passes everything.
- **Coverage honesty (verified against the actual test.html source):** F3 (hallucinated collectible names rejected against the registry) IS already behaviorally proven by **test.html Suite 6** at the push gate (`'NOT_A_REAL_GLOBE'` + duplicate dropped, real name kept — same for traits/skillBooks/magazines). But **F2 (explicit `null` clears an equipped slot — api-import.js:506) and F1 (status-type whitelist normalization) have NO behavioral coverage anywhere**: test.html Suite 4 only sets `equipped` on a fresh state (never proves *clearing*), and Suite 7's status tests use only valid types.
- **Behavioral:** two payloads through **Suite 133's existing harness** (it loads real state.js + reg_nv + real autoImportState; covers only malformed/hostile payloads today): a weapon equipped then `{equipped:{weapon:null}}` → slot cleared; `{status:[{type:'buff'},{type:'banana'}]}` → normalized/dropped. Optionally re-assert F3 in the same pass for commit-boundary coverage (today it's push-only).
- **Effort: S.** Bug-class newly caught: AI-driven durable-state corruption (stuck equipped item, invalid status types breaking tick-down).
- Fold in the same-harness conversion of **66.3–66.5/66.20** — the Lincoln **disposition coercion** (`'other'`→`'found'`, invalid disposition rejected) has no behavioral coverage (test.html Suite 6 covers name-filtering for other trackers, not `lincolnItems` dispositions), and 66.20 is currently satisfiable by a comment. 67's trait *filtering* is push-covered by test.html Suite 6; its remaining true gap is the **`toggleTrait` 2-cap** (a UI path, not import — execute it 3×, assert length stays 2).
**A2. Suite 114 — `recordLocationVisit` persistence** (line ~13355)
- **Now:** a tiny pure-ish state.js function guarding permanent fog-of-war save data, asserted via `toLowerCase`/`.some`/`.push` presence. An inverted dedup predicate passes every grep while corrupting `locationHistory` in saves. (test.html Suite 7 proves only that a changed `loc` lands in history — not dedup, case-insensitivity, or no-truncation.)
- **Behavioral:** vm: seed history, call with `'Goodsprings'` then `'goodsprings'` (dedup), 60 entries (no truncation), assert permanence. **Effort: S** — cheapest real-payoff conversion; also retires Suite 126's behavioral gap for free.
**A3. Suite 185.10/185.11 — `adjItemQty` / `toggleEquipItem`** (lines ~27495/27511)
- **Now:** two native WRITE paths into `state.inventory` (splice-by-index!) and `state.equipped`, grep-only. The filtered-view-index vs `_origIdx` mismatch class — the exact class Suite 221 exists to police on other paths — would pass these greps while **deleting the wrong item**.
- **Behavioral:** vm fixture inventory: qty 1 → −1 removes the row; +1 arithmetic; correct item targeted **under an active drawer filter**; equip toggle/replace semantics. **Effort: S–M.**
**A4. Surgical S-effort batch** (each ~15–30 lines using existing patterns):
- **178.12** `_confirmGameContextChange` cancel path — a cancelled cartridge tap must not reboot the terminal; grep can't prove branch reachability. Stub `confirmAction` false/true.
- **171.6** rng-locked permanence — guards a PERMANENT save lock with a reachability-blind grep.
- **162.5** `_resetTransmitUI` deterministic reset — the owner-reported perma-dim class; mock `getOverseerState` thinking vs speaking, spy the setter.
- **197.3** `item.added` AI-path dedup — same-inventory-twice through the 133 harness, assert one emit per genuinely-new name (spurious emits pollute the durable eventLog).
- **186.4** `_skillVuSet` clamp+save (150→100, −5→0, one `saveState`).
- **192.30** `_emitStatChangeIfDiffers` dedup; **179.4** `renderCartDeck` XSS escape (render with an `<img onerror>` label, assert inert); **164.14** `[BIND:]` router intercept with a transmit spy.
### Tier B — the native-tools block (M effort, the offline-first promise)
**B1. Suite 42 — Native Command Router `[SLEEP]`/`[WAIT]`** (line ~3119)
- **Now:** Protocol 24's flagship "fully usable without AI" promise proven by `indexOf` ordering (comment-spoofable) — including the shipped stale-DOM-sync bug's fix, asserted as `indexOf('loadUI') < indexOf('saveState')`. The mutation math ([SLEEP] heals HP, advances time) is never executed.
- **Behavioral:** vm-run `_routeNativeCommand('[SLEEP: 8 Hrs]')`/`_nativeWait` with fixture state + spied loadUI/saveState; assert mutation values AND actual call order. **Pre-check:** Suites 153/201/202 already vm-execute the quick-log/stat-edit grammar — confirm they don't already cover these two handlers; if partially, convert only the gap. **Effort: M.**
**B2. Suite 105 — VATS calculator** (line ~12012)
- **Now:** hit-%/AP/crit math asserted purely by identifier presence in `recomputeVATS`'s body — a sign flip, wrong clamp order, or broken interpolation ships green. Suites 107/109/110 (THREAT/BIO-SCAN/LOOT) prove the exact conversion pattern on sibling tools.
- **Behavioral:** extract (or lightly refactor out) a pure `_vatsCompute` and assert exact numbers for fixture skill/AGI/region matrices. **Effort: M–L** (DOM-entangled; the refactor is the cost).
**B3. Suite 106 — TRADE barter terminal** (line ~12191)
- **Now:** the caps economy (campaign state) mutated by doBuy/doSell, with the price formula tested only against a **test-side reimplementation** (106.4/106.5 validate the data under an *assumed* formula — the shipped `_tradeBuyPrice/_tradeSellPrice` are never called), and the documented caps-revert regression guarded only textually.
- **Behavioral:** vm-extract the price functions, assert exact prices at barter 0/50/100; optionally doBuy/doSell round-trip with a stub `#c_caps`. **Effort: M.** (Converting this makes 106.4/106.5's data halves redundant with Suite 104 — prune them then.)
**B4. Suite 151 — `_routeQuickLog` patterns** (lines ~19057–19087)
- **Now:** the quick-log grammar's regexes and state mutations guarded by regex-source-shape greps; **153.3 mocks `_routeQuickLog` instead of running it** — no test executes the patterns.
- **Behavioral:** reuse the 133/153 harness; feed `killed 3 raiders` / `+50 caps` / `arrived Novac` / `rep ncr up`; assert caps/eventLog/faction/location deltas. **Effort: M.**
### Tier C — save-pipeline round-trips (M effort, check overlap first)
**C1. Suites 4 + 5 — file export→import round-trip** (lines ~675/693)
- **Now:** the user's disaster-recovery path (exportSaveFile / handleFileUpload) guarded by identifier greps. No in-runner test proves an exported file re-imports losslessly (46.17 proves the *cloud container* round-trip; `save-survival.mjs` proves boot-path survival — neither exercises the file envelope parse/dispatch).
- **Behavioral:** one combined vm test — build the envelope with fixture globals (stub the Blob step), feed the JSON string through handleFileUpload's parse core, assert state/chat/playstyle land. **Pre-check Suite 51 + 143 for partial overlap.** **Effort: M.**
**C2. Suite 163.7/163.8/163.12 — cloud version-history ordering + per-game save filter**
- **Now:** "archive BEFORE overwrite", "purge versions BEFORE parent delete", "never hide an unattributed save" — the Protocol 34 destruction-order class — via `indexOf` and verbatim filter-expression greps.
- **Behavioral:** vm with stubbed firestore fns recording call order; `renderSavesList()` with fixture lists asserting rendered rows (incl. null-context shows). **Effort: M.**
**C3. Suite 37 — Render fan-out / `updateMath()` tail** (line ~2720)
- **Now:** the single persistence choke point for ALL manual CRUD (`updateMath()` → `saveState()`), green under wrong call *ordering* (mutate-after-save = silent stale save — the class that shipped once as the 42.10 bug).
- **Behavioral:** 3–4 representative mutators with spy render/save fns asserting call sequence and that state changed before save. **Effort: M.**
**C4. Suite 69 — game-switch clobber guard** (line ~7827) — convert the `saveState`-debounce half via Suite 51's existing state.js vm rig (`_contextSwitching=true` → no `robco_v8` write; false → write). The beforeunload half stays static + push-gate save-survival. **Effort: M.**
**C5. Suite 64 — SPECIAL commit-on-blur clamp** (line ~6991) — `_nativeSetSpecial` is the shared choke point for DOM edits, USE, and TERMINAL grammar; clamp/NaN-revert currently regex over a *concatenation of two bodies* (a call-chain break between them is invisible). vm: `{value:'14'}`→10, `'0'`→1, `''`→prior. **Effort: S–M.** (Also carries documented window-fragility — 64.1/2/8 already false-failed once per the in-suite comment.)
### Tier D — worthwhile, lower priority
- **226.11** FO3 MANIFEST detail-pane actions — greps 4 mutator names *anywhere* in ui-render-inventory.js (they already appear for inline rows); the detail wiring can be fully dead/wrong-index and stay green. vm-render the detail pane, fire actions, assert mutator+index. **M.**
- **199.1/199.5/199.6 + 196.10–12** crossing detectors + annunciator queue — once-per-transition emit logic and collapse/cap-6 mechanics, grep-only; spurious emits pollute the durable eventLog. vm with an emit recorder. **S–M.**
- **210.7 + 211.4** Diagnostic Shell filter-before-DOM-insertion — the shell's core leak-proof property; 210.6 proves the *filter*, nothing runs the mount pipeline. Extend the 211.9 synthetic-DOM harness under a stubbed prod tier, assert zero staging nodes. **M.**
- **100** staging build — execute `cf-staging-build.mjs` into a temp dir; assert the emitted `_redirects` and that the staged sw.js precache excludes `./index.html` (currently a regex matching an escaped regex literal). **M**, staging-only.
- **217.8/217.9** persistent-banner state-driven guards; **35** perf trio (saveState dirty-check / eventLog cap / search memo — the dirty-check inversion case is user-visible); **47.3** secrets-never-synced guard (M — Firebase stubs); **108** CONSULT search-merge (read-only, mitigated by 93.8); **180** tempo-dial drag math; **91** `_isDirty` (stale-panel bug is user-visible); **192.5** `_coreShouldAnimate` 4-signal gate.
**What NOT to convert:** Suites 138–146 (test.html twins), **Suite 141 included** — an early read flagged its `_migrateEventLog` [T#] split as the top conversion claiming "no behavioral twin," but verification against the actual test.html source shows **test.html Suite 13 already executes the real `migrateState` over a mixed fixture and asserts the split, manual-note preservation, idempotency (second run moves nothing), the AI re-point, AND resend dedup** — converting it in the Node runner would duplicate push-gate coverage, exactly like its 138–146 siblings. Also don't convert: Suite 61-class CSS (render-check owns pixels), auth flows (Protocol 29 — real-device only), WebAudio/wakeLock/vibrate/share/badging (115–118, 121–122 — un-mockable, greps are the sanctioned maximum), and anything in §1a.
**Verification discipline for U3 (learned in this audit):** before converting ANY suite, read the test.html twin and the sibling vm suites first — two of this audit's own first-pass rankings (141, and 76's F3 half) turned out to be push-covered on inspection. The pre-checks named per-item above (42 vs 153/201/202; 4/5 vs 51/143) are mandatory, not optional.
---
## 3. The PRUNE list (~40 asserts, each with covering evidence)
Every item names its surviving twin. Deleting all of these drops the count honestly per Protocol 2a with zero coverage loss. Grouped by confidence:
### High confidence (delete in U3)
| Test(s) | Evidence it's covered / dead |
| --- | --- |
| **Suite 2c** (line 535) — all 3 asserts | `removePerk`/`toggleCollectible` existence subsumed by Suite 37's body-level checks (2742, 2754); the `COMM-LINK COMMAND REGISTRY` literal by 32.1/32.2's data-driven registry guards. Only whole-suite prune found. |
| 2e ×2 (582–586) | Literal duplicates of Suite 11's automatic per-stateKey migration loop (926). |
| 31.1, 31.7 | Stale "(106 tests)"/"(386 tests)" label NEGs — one-time cleanup verification; live count-sync owned by Suite 28. |
| 34.1–34.3 | Dead-CSS-stays-deleted NEGs with no consumer left to regenerate the rules. |
| 56.2/56.7/56.12/56.17 | sw.js ASSETS membership strictly subsumed by Suite 49.1's derived disk scan (4454–4461). |
| 95.8, 102.6 | "Behavioral" tests that define and exercise **their own in-test mock** — no shipped-code edit can ever fail them. Real coverage: 95.1/95.2/95.9 and 102.4 respectively. (95.8 was knowingly added as Protocol-42 documentation — prune or retitle so it stops reading as shipped-code coverage.) |
| 106.22 | Byte-identical repeats of 106.16 + 106.17's regexes, 6 lines up. |
| 151.18 + 153.9 | CACHE_NAME format check duplicated 4-way (also 158.16 + Suite 19 + the pre-commit hook). Keep exactly one (Suite 19 or 158.16). 153.9's own comment admits it's superseded. |
| 152.1 | Near-tautological: its `\|\|` fallback passes for any button with the id; 152.1b immediately asserts the real content. |
| 154.34–154.37 (4) | One-time owner-audit mockup pixel verification (nib radius, ghost px offsets, `--tube-h: 112px`, corner chip). Only failure mode = a deliberate redesign that must then edit 4 tests; user-impacting geometry is owned by render-check. |
| 165.17 | Identical regex to 169.10, which 165.17's own comment calls "the dedicated regression." |
| 192.28 | Verbatim conjunct of 192.22 — same variable, same expression, same suite. |
| 189.9 | Tautological: `/status/`, `/quests/i`, function-exists. Cannot meaningfully fail; replace with a real quest-status-mapping assert or drop. |
| 66.20, 67.3 | 66.20's `/other.*found\|coerced/` is satisfiable by a comment; 67.3 (`Array.isArray` + the word `traits` anywhere in the api group) cannot meaningfully fail. Both are replaced by the A1 conversion. |
| 224.2 | Git-diffs a pinned historical commit and **auto-passes whenever git errors** — can never fail on CI shallow clones. Its own comment names 224.3d's structural parse as the permanent cover. |
| 210.6, 212.5 (keep 216.6) | All three eval the identical leak-proof predicate over the same live current registry; 216.6 is the FINAL audit and self-describes as the re-proof. Same for **210.8 vs 216.18** (keep one) and **216.19 vs 212.11** (keep 212.11 — it has the negative-proof sibling). |
| 210.14's stability clause | `x.action === x.action` — always true. Delete the clause, keep the assert. |
| 223.12 | "≤1 FO3-named CSS file" — near-unfalsifiable milestone boundary; Suite 224.1 owns the real invariant. |
| 194.20 | Asserts markup absent for a feature that was evaluated and **dropped** — verification of a decision, not a regression guard. |
| 205.19 (inlineData half) | Re-asserted verbatim by 207.3, which also supersedes its "unmodified handler" premise. |
| 196.30 (`.table-frame` row only) | Re-asserted strictly stronger by 198.12. |
### Lower confidence (verify the named twin, then shrink)
- **187.20** — subset of 181.5's computed all-boards glyph check.
- **186.9** — re-assert of 181.1's id contract; shrink to its unique `addStatusEffect()` clause.
- **176.7** (partial) — the `robco_bay_opened` clause re-asserted by 190.7; keep the unique initTabs clause.
- **71.16/71.17-first** — one-time-migration negatives; verify Suites 191/186 assert the replacements first.
- **184.6 vs 190.4** — near-identical harnesses over the same shared `_wireRadDragSurface`; keep the touch variant, drop the mouse duplicate (or vice versa).
**Net honest count drop: ~35–40 tests** (of 3,277 — about 1.2%). This is the true amount of dead weight; the suite is not padded.
---
## 4. Broken behavioral tests found (fix in U3, Protocol 42)
These aren't conversions — they're **existing behavioral tests that currently cannot fail**:
1. **Suite 84.n and 84.s** (lines ~9739, ~9825) — **verified against source**: they call `sb.doCraft(0)`/`sb.doScrap(0)` **without awaiting** and compare inventory synchronously, but `doCraft`/`doScrap` are `async` (ui-render-economy.js:290/363, first statement `await confirmAction()`) — nothing has executed by comparison time, so the two "insufficient-ingredients → no-op" asserts pass **vacuously** regardless of the logic. Fix (S): call the sync `_craftPrepare`/`_scrapPrepare` cores and assert they return the insufficient result — matching how the suite's success paths already do it.
2. **Suites 80.d / 81.d / 82.i** — their assert messages claim `lookupItemInDb('MRE') → …` but the tests **reimplement the column mapping test-side** and never call the real function; if the real mapping drifts, they stay green. Fix: feed the real fn (Suite 200's sandbox already knows how) or relabel as pure data checks.
3. **Suite 30.3** reads the *installed* `.git/hooks/pre-commit` — fails on any checkout where hooks aren't installed; retarget to the tracked `scripts/pre-commit` (which 31.10/31.11 already check).
4. Stale prose: 153.4/153.5 cite "Protocol 15 parity" (retired); the runner's final success banner still describes its 2023-era scope. Cosmetic.
---
## 5. Brittle-test flags (loosen in U3 — these break on benign refactors)
Systemic patterns, worst offenders named. None of these are wrong *today*; each is a false-failure (or worse, a silent-pass) waiting for an ordinary edit.
**5.1 Comments as load-bearing test anchors** (~15 asserts). Tests that fail if a *comment* changes: 91.6–91.8 (`// G6`, `// always`), 118.7, 119.3, 120.7, 121.5/121.7, 127.3's `WU-T3:` region anchor, 166.7/166.9 (`// FIX 2`), 194.12 (a Hz-tuning comment), 197.26, 208.9. Loosen to code-shape matches.
**5.2 Exact-whitespace / verbatim-code-line pins** (worst: 194.1's multi-line object literal incl. newlines; 156.10's 4-statement verbatim block; 120.4's `\s*\n\s*` CSS chain; 146.15; 183.3's five-properties-in-exact-order; 187.9e's `name:/karmaReq:` line-wrap ×8; 62.13/62.20/62.21's `d.open = open`-class expression pins; 53.7/53.18's exact `||`-operand order; 139.5–140's verbatim comparisons; 203.3/203.6 pinning Prettier's line-wrap; 219.1's whole function verbatim). Loosen to token/AST-ish patterns where the invariant allows.
**5.3 Fixed proximity windows** (`[\s\S]{0,N}` / `slice(idx, idx+N)`): 64.1/64.2/64.8 (already caused a documented false-fail — 64.12 was fixed, its three siblings were not), Suite 15's `{0,2000}`/`{0,5000}`, 54.14, 58's 500/2500-char windows, 165.13/170's 700-char slices, 173.7, 196.6's 1200-char window, 199.2's chained windows.
**5.4 ⚠ Silent-empty extraction anchors — the vacuous-pass hazard** (higher priority than the false-fail classes above, because these weaken silently): slices bounded by a literal that, when edited, make the guard scan `''` and **pass**: 178.14/180.8 (anchored on `rack-note" style="margin-top: …"` markup), 209's density block keyed to one token's exact value (`'--d-subtitle-mb: 4px;'`), 121.8 (sliced between two unrelated string literals), 154.17 (`'ALL SAVES'` anchor), 57.6 (extraction failure falls back to scanning the whole file), 162's CSS-comment lookahead block extractions (`(?=\/\* ── Skills Grid)`), 232.13 (quote-style change makes an ABSENCE check vacuous). U3 should give each an anti-vacuous sentinel (assert the extracted region is non-empty / of plausible size) — the pattern Suites 42.6, 59, and 62.7 already use.
**5.5 Hand-maintained lists that quietly stop ratcheting** (under-coverage, not failure): Suite 28's `GATE_SUITES` check — **CORRECTED by the second-pass verification (see Addendum): it is not merely stopped at 'Suite 111', it is fully TAUTOLOGICAL.** The check does `jsRunner.includes('Suite 22')` over `readFile('tests/robco-diagnostics.js')` — the runner's **own source**, which contains the probe strings **as the GATE_SUITES array literal itself** (lines 1928–2012). Deleting any listed suite's entire block leaves the array literal in place, so every `includes()` stays self-satisfied — the check cannot fail for ANY entry. (It was meaningful pre-U-B3, when it probed the *other* runner — the PS mirror.) Extending the list is therefore pointless; re-point it at actually-executed `header()` titles or delete it (real dropped-suite protection lives in the Protocol 2a count sync + test.html's `Suites: N` marker). Move this from "extend" to the §3 high-confidence repair/prune list. Also in this class: 134.8's 30-token device-key list; 137.10's 14-entry gatedSites; 135.16's wiring-fn list; the `=== 159` Diagnostic Shell tool count pinned in **four** suites (212.1/214.8/215.1/216.1 — centralize into one shared constant); three separate id-contract lists (181.1's 60 ids, 185.16, 189.14 — a shared `assertIdContract()` helper).
**5.6 The onclick-migration bomb:** Suite 22 (~25 asserts) plus scattered others pin `onclick="…"` literals; any future a11y-motivated migration to `addEventListener` breaks dozens of asserts at once with zero behavior change. Not a defect today — but if that refactor is ever planned, this suite needs a designed rewrite, not per-assert patching.
**5.7 Design-taste pixel pins:** Suite 158's tail (~14 asserts of exact px/rgba on the bezel), 192.34/192.35 (exact keyframe percentages/degrees/durations — already forced one rewrite on an owner taste-pass), 191's literal soup, 213.6, 226.13 (`width: 52px`, churned 34→44→52 already), 211.12 (46px pin that would fail a legitimate 48px bump). Recommend loosening to invariant form (CSS-duration-matches-JS, monotonic tier sizes, ≥ protocol floors) rather than exact literals.
**5.8 Duplicated inline harness code** (consolidate into shared helpers when U3 touches these suites anyway): six copies of the hand-rolled brace-matching extractor in Suite 46 (a `{` in a string literal desyncs it → false-green on NEG checks); three copies of the onload extractor (132/139/135); 6+ copies of the `declareFn*` helper (164/173/182/184/187/190); the same `getFactionStanding` extraction rig twice (Suite 2b at 466 + Suite 77 at 8916 — merge into one suite); 149.8 vs 62.5's duplicate eval technique.
---
## 6. Recommended U3 shape (phased, per the master plan)
1. **Phase 1 (one commit-sized pass): repairs + Tier A.** Fix the two vacuous Suite-84 asserts (§4.1) and the 210.14 clause; land A1 (Suite 76 F1/F2 + 66's disposition coercion into the 133 harness), A2 (114) — all S effort, all user-critical. Add anti-vacuous sentinels to the §5.4 list touched.
2. **Phase 2: the native-tools block** (B1 pre-check then convert, B2, B3, B4) + A3/A4 surgical batch.
3. **Phase 3: save-pipeline round-trips** (C1 after the 51/143 overlap check, C2, C3, C4, C5).
4. **Prune pass** (can ride any phase): the §3 high-confidence list in one commit, count re-synced per Protocol 2a; the lower-confidence items only after verifying their named twins.
5. **Brittleness loosening** rides opportunistically — whenever U3 edits a suite anyway — except §5.4 (silent-pass hazards) and §5.5 (Suite 28's stopped ratchet), which deserve their own small commit.
Conversions ADD tests while prunes REMOVE them; U3 should report both deltas separately so the count change is honest in both directions (Protocol 2a).
---
## 7. Honest bottom line (the four asks)
- **Bucket counts (of ~173 static-dominant suites):** **KEEP-STATIC ~160** · **CONVERT 12 whole suites** (4, 5, 37, 42, 64, 69, 76, 100, 105, 106, 108, 114) **plus surgical asserts in ~25 more** · **PRUNE 1 whole suite + ~40 scattered asserts**. (The other ~59 suites already execute real code and are mostly strong; 2 of their asserts are currently vacuous and get repaired, not converted.)
- **Single highest-value conversion to do first:** **Suite 76 — the autoImportState hardening guards (the F1/F2 halves).** It sits on the AI→durable-state path (the app's most dangerous import surface), its current greps pass with the logic inverted, the "null clears an equipped slot" and status-whitelist semantics have **no behavioral coverage anywhere** (verified — test.html covers the neighboring cases but not these), and the vm harness that can execute the real function already exists (Suite 133) — the biggest confidence gain for the smallest effort, with Suite 66's Lincoln-disposition coercion converting into the same harness in the same pass.
- **Honest prune count:** about **35–40 tests** of 3,277 (~1.2%) can be deleted with named covering evidence and zero coverage loss. The suite is not padded — that's the whole list.
- **Is "75% static" mostly legitimate or mostly false confidence?** **Mostly legitimate — roughly 92% of the static mass is exactly what Protocol 20 prescribes** (CSS/SW/security pins, data golden-masters, absence ratchets, config and doc-sync guards, and deliberate static twins of browser-side behavioral tests). The false confidence is real but concentrated in a specific, named ~8%: import semantics, save migrations, native calculators/economy, inventory write paths, and destructive-op ordering — all listed and ranked in §2 for U3 to convert. In plain terms: the gate isn't lying about most things; it's lying about a short list of important things, and we now know exactly which ones.
---
## Addendum — Independent second-pass verification (2026-07-16, same snapshot `92f614e`)
A second, fully independent analysis session re-derived this audit from scratch (own suite-boundary scan, own per-suite metrics, own suite reads — no reuse of the first pass) and then diffed its conclusions against this document. Record of what that produced:
**Mechanical numbers independently measured (all consistent with the doc's framing):**
- Runner re-run live at `92f614e`: **ALL 3277 TESTS PASSED.**
- 240 `header()` emissions → 232 canonical suites (continuation banners + the async-RESULTS tail banner account for the delta).
- ~2,704 direct `assert(` calls (the remainder of 3,277 come from `guards()` table rows and per-field loops); **4,668 `.test(` + 332 `.includes(`** pattern matches total — ≈5,000 matches backing 3,277 green ticks.
- **109 execution sites** (`require('vm')` / `new Function`) across ~60 suite blocks holding ~974 asserts (~30% of all asserts) — confirming the ~75%-static-by-suite input.
- Cross-suite exact-duplicate scan: only ~7 regex literals appear twice file-wide, most legitimately (same invariant, two data files). Independently confirms §1c: **no large dedup dividend exists.**
**Doc claims spot-verified against source (all held):**
- §4.1 — 84.n (line ~9744) and 84.s (~9825) call `sb.doCraft(0)`/`sb.doScrap(0)` un-awaited; `doCraft`/`doScrap` are `async` (ui-render-economy.js:290/363). Vacuous, confirmed.
- §3 — 210.14's `.action === .action` self-comparison confirmed at line 36307–36308 (clause always true; sibling clauses real).
- §3 — 224.2's `assert(gitErr224 !== null || …)` confirmed at ~41969: passes whenever git errors (deliberate skip-not-fail, per its comment — but it can never fail on a shallow clone, as stated).
- §3 — 106.22 re-tests 106.16/106.17's regexes, confirmed at 12396–12403.
- §1a/§2 — the test.html twins are real: test.html Suites 10–18 include **"Suite 18 — A1 Ambient Runtime (state machine + observer gating + live dial)"** and **"Suite 13 — P4 Terminal Record ([T#] migration + AI re-point)"**, both executing real code in a browser at the push gate. (The second pass had independently ranked Suite 146 as its top conversion before checking test.html — the twin check killed it, exactly as §2's "verification discipline" footnote prescribes. The discipline is load-bearing; keep it mandatory in U3.)
- §2 archetypes — Suite 106.4/106.5's test-side formula re-implementation and the Suite 42 `indexOf`-ordering proxy independently re-found and confirmed by direct reading.
**One correction contributed (folded into §5.5 above):** the Suite 28 `GATE_SUITES` check is **tautological for every entry**, not merely truncated at 'Suite 111' — it greps the runner's own source, which contains the probe strings as the array literal itself, so it cannot fail even for the suites it lists. "Extend the list" is not a fix; re-point at executed `header()` titles or prune (~1 assert + ~90 dead lines).
**Convergent bottom line (independently reached before reading this doc):** static mass mostly legitimate; false confidence real but concentrated in pure-logic subsystems (import semantics, native tool math, router/grammar, write paths); prune list small (the second pass's blind estimate was ~10–20 asserts vs this doc's better-evidenced ~35–40 — the doc's granular list stands); conversion harness patterns already in-file (133, 107/109/110). Two fully independent reads of the same runner landed on the same verdict — treat this document's §2 ranking as verified input for U3.
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).