Skip to content

Stop the app from misrepresenting NCARB results (audit Phase 0)#46

Merged
Vito-bc merged 1 commit into
mainfrom
fix/exam-model-honesty
Jul 11, 2026
Merged

Stop the app from misrepresenting NCARB results (audit Phase 0)#46
Vito-bc merged 1 commit into
mainfrom
fix/exam-model-honesty

Conversation

@Vito-bc

@Vito-bc Vito-bc commented Jul 11, 2026

Copy link
Copy Markdown
Owner

What & Why

An external audit flagged that the app asserts things about the ARE that are not true. I verified every claim against the code and against ncarb.org before touching anything — most held, one did not (see below).

These fixes are the highest trust/store risk at the lowest cost (strings + config), so they ship first, ahead of the Coach and purchases work.

The app was lying

Claim in app Reality (verified: NCARB)
"265 passing score on a 200–400 scale" Scale is 100–800, pass 550; each item = 1 point
Calculator cut scores 3 of 6 sat BELOW NCARB's real range — PcM 58 (real 59–71), PA 60 (real 65–71), PPD 63 (real 65–71). The app told candidates "Likely Pass" while they were under the true bar.
Mock Exam "matches real NCARB division weights" Real ARE = six separate exams, not one 65q mix
"PASS" / "Passing score achieved" at 70% NCARB publishes no universal raw threshold
Dashboard "42% readiness" Fabricated when Firebase was down, incl. a nonexistent "Structural Systems" section

Fixed: calculator now shows NCARB's published per-division ranges and a band (below / inside / above) instead of predicting a result → renamed Practice Score Check. Mock Exam → Multi-Division Diagnostic. PASS/FAIL → explicit practice benchmark, labelled as ours. Dashboard reports no data when it has none.

Correctness

  • 14 flashcards had mojibake math/arrows (a previous fix caught only em-dashes): CO₂ ≠ ≤ ≥ ≈ − span⁴ depth³. Repair is a strict cp1252→utf-8 round-trip — it only succeeds on genuine damage, so the legitimate × in "16×" was correctly left untouched.
  • App version was hardcoded 1.0.0 while pubspec said 1.3.0+17 → now read from package metadata, so it can't drift again.
  • README promised 1,100 questions (bank is 1,082), SM-2 flashcards (it's fresh/learning/mastered), and a light theme (app is dark-only).

Question-audit tool

The architect worklist told Maryana 692 questions was "~3–4 hours". It's ~23. That was my arithmetic bug and it set her up to fail. Fixed, and added a priority queue so she doesn't do all 692:

  • 🔴 RED 127 — needs a licensed architect (answer/explanation/citation conflict, worst-scored, duplicates)
  • 🟡 YELLOW 447 — AI proposes the fix, she only approves
  • 🟢 GREEN 118 — spot-check 10–15%

Also documented: don't rewrite a question just for being factual — the real ARE tests facts too.

RAG corpus

The 2020 NYC Energy Code was superseded by the 2025 NYCECC (enforced since 2026-03-30) — we had ingested the dead edition. Swapped in 2025 NYCECC C3/C4/C5 plus NYC's adopted ASHRAE 90.1 (which also closes a gap we thought needed a paid textbook). Corpus: 26 PDFs / 3,441 chunks. Added an edition currency section to SOURCES.md so this gets checked before each generation run.

Where the audit was wrong

It claimed the worklist "must be regenerated after dedup". Verified: 0 stale IDs — it was already post-dedup. No action taken.

Checklist

  • flutter analyze returns 0 issues
  • flutter test passes (89/89)
  • No secrets or API keys committed (.env / PDFs / backups gitignored, diff scanned)
  • Firestore rules updated if schema changed — n/a
  • README / docs updated

Not in this PR (next)

Coach (→ Claude + RAG), Android paywall (→ disable), premium-forever entitlement, npm vulns, lastActiveAt silent failure.

🤖 Generated with Claude Code

An external audit found the app asserting things about the ARE that are not
true. These are cheap to fix and carry the highest trust/store risk, so they
go first. Verified each claim against ncarb.org before changing anything.

Exam model (the app was lying):
- Score calculator claimed a "265 passing score on a 200-400 scale". NCARB
  actually scales 100-800 with 550 to pass, and does NOT publish a raw->scaled
  conversion. Worse, three of the hardcoded cut scores sat BELOW NCARB's real
  passing range (PcM 58 vs 59-71, PA 60 vs 65-71, PPD 63 vs 65-71), so the app
  told candidates "Likely Pass" while they were under the true bar. Replaced
  with NCARB's published per-division ranges and a band (below/inside/above)
  instead of a pass/fail prediction. Renamed to "Practice Score Check".
- Mock Exam claimed its 65-question mix "matched real NCARB division weights".
  The real ARE is six separate exams. Renamed to Multi-Division Diagnostic and
  documented what it actually is.
- Result screen printed PASS/FAIL and "Passing score achieved" off a flat 70%.
  NCARB publishes no such universal threshold. Now an explicit practice
  benchmark, labelled as ours.
- Dashboard fabricated "42% readiness" and a nonexistent "Structural Systems"
  weak area when Firebase was unavailable. Now reports no data, honestly.

Correctness:
- Repaired 14 flashcards whose math/arrow glyphs were mojibake (a prior fix
  only caught em-dashes): CO2, !=, <=, >=, ~=, minus, span^4, depth^3. The
  repair is a strict cp1252->utf-8 round-trip, so a legitimate 'x' in "16x"
  was correctly left alone.
- App version came from a hardcoded '1.0.0' while pubspec said 1.3.0+17. Now
  read from package metadata, so it cannot drift again.
- README promised 1,100 questions (bank has 1,082), SM-2 flashcards (it is
  fresh/learning/mastered), and a light theme (app is dark-only).

Question-audit tool:
- worklist guide told the architect 692 questions was "~3-4 hours". It is ~23.
  Fixed the arithmetic and added a priority queue so she does not have to do
  all of them: RED 127 (needs an architect), YELLOW 447 (AI proposes, she
  approves), GREEN 118 (spot-check). Also: do not rewrite a question merely for
  being factual -- the ARE tests facts too.

RAG corpus:
- The 2020 NYC Energy Code was superseded by the 2025 NYCECC, enforced since
  2026-03-30 -- we had ingested the dead edition. Swapped in 2025 NYCECC
  C3/C4/C5 and NYC's adopted ASHRAE 90.1. Corpus: 26 PDFs / 3,441 chunks.
  Added an "edition currency" section so this is checked before each run.

flutter analyze clean; 89/89 tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Vito-bc Vito-bc merged commit 08ea52b into main Jul 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant