koala73 / koala73/worldmonitor
feat(panel): scorecard strip in ForecastPanel — show the track record with sample sizes
- Dominant language
- TypeScript
- Stars
- 86.6k
- Forks
- 13.1k
- Avg merge
- 8h 4m
- Merged PRs (30d)
- 825
Description
Part of #7066. In-product sibling of #6646. Depends on the corrected scorecard schema in #7072.
## Goal
Show the forecast track record in `ForecastPanel` with correct population, sample, uncertainty, freshness, and failure-state semantics.
## Current access contract
`get-forecast-scorecard` exists and is cache-tiered, but it is not currently an anonymous/public-shared RPC. An unauthenticated request returns 403.
For this panel issue, use the existing session-authenticated application request path. Do not widen anonymous access. #6646 owns any public-page route and must add an exact allowlisted `public=1` shared-cache shape with security tests.
## Information hierarchy
### Primary
- rolling window and generated-at time;
- published-origin Brier with n and interval, labeled "lower is better";
- matured-scored rate and resolved-within-SLA rate;
- VOID rate with count and top reasons.
### Secondary
- WM-versus-market paired difference on the matched published-origin cohort, with n and clear direction such as "WM worse by 0.032";
- calibration/reliability sparkline with empty buckets omitted;
- per-domain rows with Brier, n, interval, and insufficient-sample state.
### Required disclosure
- excluded origins and counts;
- stale/degraded status;
- projections remain unscored until #7075 lands.
Never render Brier, calibration, or market-relative skill without n. Never render an n=0 bucket as a zero outcome.
## UI states
Define and test:
- loading;
- current;
- stale but available;
- degraded/partial;
- authenticated request denied/expired;
- endpoint unavailable;
- empty/no scored sample;
- insufficient sample for a domain/bucket.
Stale and degraded values may remain visible only with a clear badge and timestamp. Do not silently present them as current.
## Accessibility and responsive behavior
- Give the sparkline an accessible text/table equivalent.
- Do not rely on color alone for better/worse or stale/degraded states.
- Preserve keyboard focus and screen-reader labels.
- Use localized user-facing strings.
- Verify the compact layout at desktop and mobile panel widths without truncating sample or status text.
## Implementation
- Reuse the panel's existing authenticated client and refresh/degrade conventions.
- Consume #7072's renamed funnel fields and interval shapes; do not locally recompute scorecard math.
- Keep the strip compact and disclose details progressively.
- Leave forecast case-file behavior unchanged unless a separate verified defect is found.
## Acceptance
- [ ] Session-authenticated scorecard data renders; the issue no longer claims anonymous access.
- [ ] Every accuracy value includes n, population, and the correct uncertainty where available.
- [ ] Coverage/yield labels use #7072 semantics, not old `publicationCoverage` wording.
- [ ] All loading/error/stale/degraded/empty/insufficient states are tested.
- [ ] Sparkline has an accessible equivalent and omits empty buckets.
- [ ] Projections are labeled unscored until #7075.
- [ ] Browser verification and screenshots cover real production-shaped data at desktop and mobile widths.
Contributor guide
Research direction
Start at ForecastPanel and its existing authenticated client, then inspect the get-forecast-scorecard response and the corrected schema from #7072. Verify the loading, stale, degraded, denied, unavailable, empty, and insufficient-sample states, including the accessible sparkline equivalent and responsive layout. Done means session-authenticated scorecard data renders with sample sizes, populations, uncertainty, status disclosures, and projection labels, with browser verification at desktop and mobile widths.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100