# Red Team Audit — Energy Decision Stack v32.1

**Date:** April 2, 2026
**Scope:** Full project — HTML, JS, CSS, all docs, CSVs, cross-file consistency, claims, sourcing, code quality
**Method:** Four parallel audit passes (numerical consistency, HTML/JS code, claims & sourcing, docs consistency)

---

## Verdict

The core numbers are rock-solid. The HTML is production-ready. The issues are in **documentation gaps, sensitivity range sourcing, and discoverability** — not in the data or the code.

**0 breaking errors. 0 numerical inconsistencies. 0 broken links. 3 critical documentation gaps. 11 orphaned documents.**

---

## CRITICAL (3 issues — fix before distribution)

### C1. Missing documentation of the 76%–96% stress grid

The HTML and claims ledger cite "broad stress testing (0.5×–2× field headcount, 0.75×–1.5× field comp)" producing a 76%–96% range. But no document shows the actual calculation grid. The scoring_sensitivity_analysis.md covers *different* tests (±1 and ±2 score perturbations) yielding 87.68%–92.98%. A reader cannot trace the 76%–96% figure to its source.

**Fix:** Add a parametric stress grid table to scoring_sensitivity_analysis.md or methodology_faq.md showing the headcount/comp multiplier combinations and their outputs.

### C2. Three conflicting sensitivity ranges not reconciled

Three ranges appear across the project with no cross-reference explaining they come from different methodologies:
- 76%–96% (parametric stress grid, in HTML/claims)
- 87.68%–92.98% (scoring perturbations, in sensitivity_analysis.md)
- 88.93%–91.91% (Monte Carlo ±1, in sensitivity analysis)

A reader sees three different ranges for what appears to be the same claim.

**Fix:** Add a reconciliation table in the sensitivity analysis docs showing: test name, what it varies, range produced, and why they differ.

### C3. "Role-only range ~74%–96%" upper bound unexplained

The HTML tooltip claims "Role-only range: ~74% to ~96%." The lower bound (74.2%) matches BLS-only anchor rows, documented. The upper bound (96%) has no documented source — the role-only figure in the decomposition stress table is 89.4%, not 96%.

**Fix:** Either document the 96% derivation or correct the tooltip to match documented figures.

---

## HIGH (6 issues — fix before investor/operator meetings)

### H1. Precision inconsistency: 90.25% vs 90.3% vs ~90%

Three different numbers for the same baseline:
- HTML tooltip: "~90.3%"
- sensitivity_analysis.md: "90.25%"
- Hero display: "~90%"

No note explains which is canonical or why they differ. Investors will notice.

**Fix:** Pick one canonical figure and note the rounding convention.

### H2. Claim C25 classification: "Measured" should be "Reported"

The claim "1.7 workers nearing retirement per young entrant in nuclear" is sourced to IEA World Energy Employment 2025. IEA published it; Sunya didn't independently measure it. Per the methodology FAQ's own taxonomy, this is "Reported," not "Measured."

**Fix:** Reclassify C25 in the claims ledger and update the HTML tooltip.

### H3. Compressibility score derivation not row-level auditable

The methodology FAQ describes three derivation paths (290 rows from task_exposure_v1, 14 analyst-adjusted, 100 direct analyst judgment) but no file identifies which rows used which method. The FAQ also notes the intended formula "was not consistently applied."

**Fix:** Add a `compressibility_source` column to the CSV (or a separate lookup table) before v33.

### H4. Proprietary estimates lack specific corroboration citations

The external sources table says SemiAnalysis estimates (OpenAI 2.3 GW, xAI 1.9 GW, $10–12B/GW) are "corroborated by public reporting" but cites no specific URLs, dates, or outlets.

**Fix:** Add 1–2 specific public sources per proprietary claim, or downgrade to "Unverified proprietary estimate."

### H5. Claims ledger does not cover derivative documents

The ledger's 30 claims (C01–C30) cover only the main research artifact. Claims in deal_readiness_memo ("$50–75K diagnostic cost"), operator_memo, and other derivative docs are not tracked.

**Fix:** Either expand the ledger or add a scope note ("covers index.html claims only").

### H6. "Modeled" vs "Derivation" vs "Observation" boundaries unclear

Multiple claim types appear in HTML tooltips without consistent definitions. C19 is "Observation" but is explicitly "not an empirical measurement." The distinction between Modeled and Derivation is fuzzy.

**Fix:** Add a one-paragraph definition of each claim type to the methodology FAQ, with examples.

---

## MEDIUM (5 issues — improve before publication)

### M1. 11 orphaned documents not linked from index.html

These files exist in docs/ but are not discoverable from the main page:
1. 00_SENSITIVITY_INDEX.md
2. SENSITIVITY_ANALYSIS_README.md
3. SENSITIVITY_AT_A_GLANCE.txt
4. sensitivity_analysis_executive_summary.txt
5. scoring_sensitivity_results.json
6. synthesized_action_plan.md
7. decision_stack_next_moves_spec.md
8. demis_hassabis_brief.md
9. how_this_was_built.md
10. methodology_faq_sensitivity_paragraph.txt
11. social_launch_content.md

The most important to surface: how_this_was_built.md (transparency), synthesized_action_plan.md (v32.1 patch log), and the sensitivity analysis suite.

### M2. Sensitivity analysis documentation redundancy

00_SENSITIVITY_INDEX.md and SENSITIVITY_ANALYSIS_README.md describe the same file set in nearly identical order with identical summary tables. Should consolidate or differentiate.

### M3. Stress test methodology not shown for parametric grid

The methodology FAQ mentions the headcount/comp multipliers but doesn't show a results grid. The sensitivity_analysis.py in working/ may contain this, but it's not surfaced in a reader-friendly format.

### M4. Template density and workflow standardization columns referenced but absent

The FAQ describes these as inputs to the compressibility formula but notes they "are not present in the CSV." This is honest, but leaves the scoring methodology partly opaque.

### M5. Tier band assignment uses hash-based allocation

344 formulaic employment estimates use "tier multipliers assigned by stable hash of the role name string (hash mod 3)." This is documented but the hash function itself isn't published, making independent verification impossible.

---

## LOW (4 issues — nice to fix)

### L1. Commented-out debug logging in JS (line ~5069)

`// else{console.log('Regression check passed...')}` — harmless but untidy for production.

### L2. Font deprecation comment visible in source

Line 38: "Integral CF DEMO font removed — unlicensed for public distribution." Fine for internal tracking but visible in view-source.

### L3. Karpathy quotes lack specific timestamps

References to "YC AI Startup School (Jun 2025), No Priors podcast (Jan 2026)" have no exact quotes or transcript timestamps.

### L4. Earlier model baseline (81%) mentioned without full context

The HTML tooltip discloses the v31 score-coupled model produced ~81%. Honest, but could confuse readers who don't read the surrounding explanation.

---

## VERIFIED CLEAN

These areas passed with zero issues:

| Area | Status |
|------|--------|
| Position count: 404 = 373 + 24 + 7 | Consistent everywhere |
| Employment sources: 60 BLS + 344 formulaic | Consistent everywhere |
| Augmented rows: 304 of 404 | Consistent everywhere |
| Compensation proxies: $58K–$180K across 6 layers | Consistent everywhere |
| Exhibit count: 10 interactive exhibits | Consistent everywhere |
| Document count: 25 linked (32 in bundle) | Consistent everywhere |
| All CSV row counts correct | 404 data rows verified |
| All CSV column headers well-formed | No parsing issues |
| All scores within 0–10 range | Verified |
| All layer totals sum to 404 | Verified |
| Physical ops headcount ~29%, wage bill ~10% | Consistent everywhere |
| Total exposure-weighted wage bill ~$236B | Consistent everywhere |
| All internal anchor links valid | 10 checked, all resolve |
| All file links valid (docs/, fonts/) | All exist on disk |
| No broken external CDN dependencies | html2canvas v1.4.1, jsPDF v2.5.2 pinned |
| Meta tags / OG / Twitter cards consistent | Verified |
| Mobile responsiveness | No hardcoded breaking widths |
| Accessibility | ARIA labels, semantic HTML, keyboard nav present |
| All v32.1 fixes applied | 6/6 confirmed |
| No [TBD], [TODO], FIXME placeholders found | Clean |
| No stale references to superseded/ files | Clean |
| No typos or grammatical errors detected | Clean |

---

## PRIORITY ACTION LIST

| Priority | Action | Effort |
|----------|--------|--------|
| **Now** | Document the parametric stress grid (C1) | 2 hrs |
| **Now** | Add sensitivity range reconciliation table (C2) | 1 hr |
| **Now** | Fix or document role-only 96% upper bound (C3) | 30 min |
| **Now** | Pick canonical baseline figure and note rounding (H1) | 15 min |
| **This week** | Reclassify C25 from Measured to Reported (H2) | 15 min |
| **This week** | Add claim-type definitions to methodology FAQ (H6) | 30 min |
| **This week** | Add scope note to claims ledger (H5) | 15 min |
| **This week** | Link orphaned docs from Research Room (M1) | 1 hr |
| **v33** | Add compressibility_source column to CSV (H3) | 1 day |
| **v33** | Add specific corroboration URLs for proprietary claims (H4) | 2 hrs |
| **v33** | Consolidate sensitivity index docs (M2) | 30 min |
| **v33** | Publish hash function for tier assignment (M5) | 30 min |
