Stop the app from misrepresenting NCARB results (audit Phase 0)#46
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
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
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.1.0.0while pubspec said1.3.0+17→ now read from package metadata, so it can't drift again.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:
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 analyzereturns 0 issuesflutter testpasses (89/89)Not in this PR (next)
Coach (→ Claude + RAG), Android paywall (→ disable), premium-forever entitlement, npm vulns,
lastActiveAtsilent failure.🤖 Generated with Claude Code