audit: math-fix thirteenth-pass re-verification (all gates fresh, OFFLAN-OK 21:37Z, deploy + 34/34 byte sweep, render-race cause closed)
This commit is contained in:
1 parent
c2a66a3fdb
commit
ef6962bbe9
2 files changed
+28
-1
No files matched your search
@@ -355,3 +355,30 @@ Determinism: `after12-couple-table.png` 1280×900 50,314 B md5 `cbac51ed5089…`
|
||||
Harness notes: Playwright run with `TMPDIR=/home/ubuntu/projects/retire-planner/.pwtmp` (harness TMPDIR read-only; no site impact); ssh byte-check loop uses `-n`; PNGs validated by IHDR + byte-determinism + DOM row scrapes (content evidence). `audit/math-fix/` is gitignored by design — artifacts are local evidence, referenced by path.
|
||||
|
||||
No code change required — plan executed end-to-end; fix commit `0839826` at `origin/main`; all gates fresh this pass. Final: **MATH_FIX_DONE**.
|
||||
|
||||
---
|
||||
|
||||
## Re-verification (thirteenth DSH pass, 2026-10-09 21:37 UTC, post-completion)
|
||||
|
||||
Queue gate: `git status --porcelain` empty at start (no untracked, no tracked diff), HEAD `126f90e` == `origin/main`, no job in flight → proceed (not `DSH_QUEUE_BUSY`). Fix 1–4 re-audited by direct read of the working tree (== HEAD): GIS 65+ floor — `a >= 65 ? gis(…) : 0` at the three `solve()` sites (engine.js:249/260/265) + Service Canada source-fact comment (:88–91) + merge per-partner ≥65 gates (:376–380) + `if (yr < 65) gisSum = 0;` (:382); clawback only with OAS — `oasGross > 0 ? Math.min(clawback(…), oasGross) : 0` at :248/:259 + s.3(1) ETA comment :80–83 + splitting-solver parity :366–367; mixed rows — `row.mixed` :390 + depletion guard `!row.mixed` :395 + renderer `†`/legend app.js:807–819 + legend element index.html:95 + `t.mixedNote` EN/FR i18n.js:251/512; FIRE — `fillDefaults` clamp `retireAge < age+1` :188, quiz slider `min: 40` app.js:211, `#wi-ret min="40"` index.html:86, FIRE hint EN/FR i18n.js:96/357. All acceptance checks re-executed fresh in this pass:
|
||||
|
||||
| Check | Fresh output (this pass) |
|
||||
|---|---|
|
||||
| `tests/engine.test.js` | `RESULT: 61 pass, 0 fail` (§14 T1 repro: clawback $0 @55, GIS $0 @56, OAS gross 0 @56, net OAS ≥ 0 every row, no GIS<65 anywhere; §15: 100k RRSP draw @55 → cw 0, 67y 150k draw → cw $9,150 capped at OAS gross; §16: couple GIS/clawback zero <65, net OAS ≥ 0, no growing-Total-with-Withdraw draw rows, household GIS @70, age-offset window rows 50–54, depletion guard intact, depletion never fires on a mixed row; §17: fillDefaults 52→53 & 30→40, FIRE first draw 40, rows 40–64 GIS/clawback 0, stale 52/40 state first draw 53) |
|
||||
| `tests/i18n.test.js` | `I18N-OK all i18n checks passed (50)` (incl. `t.mixedNote` EN+FR parity, `q.retire.hint` FIRE EN+FR) |
|
||||
| `tests/ui.smoke.js` | `SMOKE-OK all ui smoke checks passed (146)` (incl. † mixed-row fixture ×3 + bilingual legend under the table, control-single no †, `wi-ret min 40`, legend element present) |
|
||||
| `tests/ps-pension.test.js` / `ps-auto-service.test.js` | `70 pass, 0 fail` / `21 pass, 0 fail` (unchanged files) |
|
||||
| `passes3.js` rerun (live engine) | exit 0, `conservation: OK` ×3 → `audit/math-fix/passes3-pass13.log` (copied to `passes3-thispass.log`). PASS 1 (screenshot repro): rows 52–64 **OASnet $0 / GIS $0** (plan evidence −$3,501 @55 / $12,916 @56 / phantom $13,667/yr to 94 — all gone), first GIS row 65 (GIS $12,567, OASnet $9,150), depletion 56 honest (nest egg $170,465 vs $93k spend, finalBal $0); PASS 2 depletion 82, GIS 65+ only; PASS 3 FIRE: first draw @40 (Withdraw $62,837, CPP/OAS/GIS $0), max total $493,710 @39 = hand-math 350000×1.035¹⁰ ✓, GIS $13,667 appears at 65 |
|
||||
| `scripts/deploy.sh` | `DEPLOY-OK` (fresh this pass) |
|
||||
| Origin byte-check | cache-busted sha256 (live `retire.krisforbes.ca` vs repo) **6/6 BYTE-OK**: engine/engine.js `2101f46b28e1…`, engine/canada.js `dbd30a0e414f…`, app.js `092a35d711f0…`, i18n.js `cfc5ab0b41b2…`, index.html `28ab4f620ee8…`, style.css `2e9ba90ae919…`; full sweep local == `git cat-file origin/main:` == webroot md5: tracked **21/21 (3-way)** + `site/vision/*.jpeg` **13/13** (2-way, gitignored generated assets) = **34/34 match, 0 mismatch** (`bash .tmp/sweep13.sh`, ssh `-n`) |
|
||||
| Live recapture (`mathfix_capture.py after13` + `after`, retire.krisforbes.ca) | couple 52/52 ret 55 spend 93k CPP 60, all 40 DOM rows 55–94 parsed programmatically: **0** negative-OAS cells, **0** GIS>0 rows <65, **0** OAS≠0 rows <65, **0** growing-Total-with-Withdraw rows on consecutive ages; rows 58–64 Total $0 / OAS $0 / GIS $0, Withdraw $49K @58 then $0, Unfunded $47K–$93K (honest post-depletion drain 248K→152K→48K→0, vs the screenshot's impossible 126→141K at 3.5%); first GIS row 65; `wiRetMin: "40"`. FIRE 30/BC/ret 40: first Withdraw>0 row age **40** ($63K, OAS $0 / GIS $0), **0** pre-65 GIS/neg-OAS violations. Mobile 390: retire slider `min=40 max=72 value=40`, `sliderRight 367 ≤ vw 390` (no clip), value chip [25, 145], FIRE hint present EN, `svAfter40: "40 years"` |
|
||||
| Live mixed-window probe (re-run, `after13-mixed-*`) | couple me 52 / pt 50, `retireAge: 51` → `fillDefaults` clamps self to 53; the partner inherits the shared clamped 53 → both draw from 53 (DOM row 53 Withdraw $96K), rows 50–52 accum → **0 † rows**, `noteShown: false`, **0** GIS rows <65 — reconfirms Deviation 2 (age-axis merge + shared clamped `retireAge` ⇒ mixed draw windows are unreachable in the live couple path); the `†` suffix + bilingual legend rendering is proven by the `ui.smoke.js` `project()` fixture (3 flagged rows, EN+FR) and the engine §16 invariants |
|
||||
| Off-LAN (Midhurst `trouble@100.96.20.61`) | `OFFLAN-OK`, `"all_ok": true`, `"http_code": "200"`, `checked_at 2026-10-09T21:37:01Z` → `audit/bilingual-geo-check.json` |
|
||||
|
||||
Evidence hardening this pass: the DOM row JSONs are now swept by a parser (money cells → numbers) with a **consecutive-age** rule. The FIRE table collapses accumulation rows (30 → 35 → 40), so a naive "previous rendered row" comparison flags age 40 ($443K) against age 35 ($430K) as a growing-Total-with-Withdraw row; that pair is accum → first-draw, not a mixed window, and it is **not** flagged under the consecutive-age rule (0 violations in both scenarios).
|
||||
|
||||
Determinism: `after13-couple-table.png` 1280×900 50,314 B md5 `cbac51ed5089…` — byte-identical to the canonical renders of passes 1/8/9/10/11/12 on the FIRST attempt. The canonical `after-couple-table.png` first regenerated at the stock 900 ms settle as the known 63,753 B render-race variant (md5 `eec99021c08c…`, same size as pass 11's) with DOM row JSON **byte-identical** to `after13-couple-rows.json`; a re-shoot with a 3000 ms settle converged back to 50,314 B / `cbac51ed5089…` → the variant is chart-animation timing, not table content (pass-11 note closed with a concrete cause + remedy). `after13-mixed-rows.json` byte-identical to `after12-mixed-rows.json`. Fresh PNGs IHDR-validated: `after13-couple-table.png` / `after13-mixed-table.png` / `after-couple-table.png` / `after-fire-table.png` 1280×900, `after-fire-step-390.png` 1170×2532 @3×.
|
||||
|
||||
Harness notes: Playwright run with `TMPDIR=/home/ubuntu/projects/retire-planner/.pwtmp` (harness TMPDIR read-only; no site impact); ssh byte-check loop uses `-n`; PNGs validated by IHDR + byte-determinism + DOM row scrapes (content evidence). `audit/math-fix/` is gitignored by design — artifacts are local evidence, referenced by path.
|
||||
|
||||
No code change required — plan executed end-to-end; fix commit `0839826` at `origin/main`; all gates fresh this pass. Final: **MATH_FIX_DONE**.
|
||||
@@ -5,7 +5,7 @@
|
||||
"has_i18n_script": true,
|
||||
"i18n_js_fr_strings": true,
|
||||
"i18n_js_size": 39689,
|
||||
"checked_at": "2026-10-09T21:33:55Z",
|
||||
"checked_at": "2026-10-09T21:37:01Z",
|
||||
"vantage": "trouble@100.96.20.61 (Midhurst, off-LAN)",
|
||||
"all_ok": true
|
||||
}
|
||||
Reference in new issue
Block a user