SkillNote 0.5.4 — /analytics crash hotfix
·
24 commits
to master
since this release
[0.5.4] - 2026-05-15
Hotfix release for a post-0.5.3 /analytics page crash. Single bug, plus an audit pass to verify no related null-safety issues lurking elsewhere.
Fixed
/analyticspage no longer crashes the Chrome renderer withTypeError: Cannot read properties of undefined (reading 'toFixed'). Root cause was a three-way contract mismatch in the Top Skills table: the backend (app/api/analytics.py) returnssuccess_rateasfloat | None, but the frontend type (src/lib/api/analytics.ts) declared it ascompletion_rate: number(wrong name, non-null), and the page (src/app/(app)/analytics/page.tsx:1254-1265) reads.completion_rate(alwaysundefined) and called.toFixed(0)inside arating_count > 0gate. As soon as any skill hadrating_count: 1withsuccess_rate: null(e.g. one rating but no completed-outcome runs yet), the page entered the conditional and threw. Fixed by:- Renaming the frontend type field to
success_rate: number | nullwith a doc comment. - Updating the three page references and changing the gate from
rating_count > 0to the actually-meaningfulsuccess_rate != null.
- Renaming the frontend type field to
- MOST CALLED card in the analytics summary row no longer overflows its container when the most-called skill has a long slug (e.g.
superpowers:brainstorming). String values now render at 15px monospace withbreak-wordsplus zero-width-space soft-break hints after:-/_so the browser breaks at natural slug separators (yieldssuperpowers:/brainstormingrather thansuperpowers:bra/instorming). Numeric values still render at the existing 22px tabular display.
Tests
- New regression test
e2e/r7-workflow-bugs.spec.ts → "Top Skills row with rating_count > 0 and success_rate null renders an em-dash, not a crash". Mocks the exact production crash payload ({ slug, call_count: 1, avg_rating: 3.0, rating_count: 1, success_rate: null }), asserts the page renders the em-dash fallback, and listens onpageerrorto catch any futuretoFixedregression. The previous Top Skills e2e test only exercised rows withrating_count: 0(which short-circuits the buggy branch), which is why the suite missed this in 0.5.3. - Existing analytics mock updated to use the correct API field name (
success_rate) instead of the legacycompletion_rate, so future tests stay aligned with the real backend shape.
Internal
- Audit of similar patterns. Swept all
.toFixed/.toLocaleStringcall sites insrc/. All other ratings call sites (skill-card.tsx,skill-list-item.tsx,skill-detail.tsx,SkillViewTab.tsx) were already properly null-guarded.SkillHistoryTab.tsx:33declaresversionRating?.avg_rating: number(non-null) but the backend's GROUP BY-with-AVG SQL guarantees that field is never null for the rows it returns; documented as a latent risk to tighten in a follow-up but not a current crash.