- Shipped
- August 12, 2026 at 5:44 PM UTC
- Author
- kamo
- Commit
- 4d8e9dc
The masthead percentage mixed units and could only flatter. `complete` summed org-wide ASSIGNMENT counts while `open` counted MEMBER-DOMAINS off memberRows, capped at 2 per member: a 50-person org with 800 completed assignments and 20 members carrying open work reported ~98% where the honest figure is 80%, and it is the one org-wide number on the page plus the meter under it. Both sides now come from the per-member rollups, so both are assignment counts read at one instant. Extracted as assignmentCompliance() in app/lib/hrOverview.ts, because vitest here collects only .test.ts and a rule left in a .tsx is a rule with no test. `overdue` is deliberately not added: it is a subset of `open`. A failed fetch still rendered every section's EMPTY state. One thin red banner does not undo "Overdue 0", "Every package is executed." and "Nobody has an outstanding HR obligation." underneath it — a reader can act on those. The failure flags are threaded into all four sections and each renders its own failed state, reusing hr.overview.loadFailed and hr.overview.retry. No key was invented: messages/ is populated at build time from a separate repo and next-intl throws on a key missing from en.json. Where rows survive from the other summary, the notice sits above them rather than replacing them, so a partial list is never passed off as the whole workforce. The pillars carry no retry button — the card is an anchor and a nested button swallows the click. The matrix and the rail rendered whenever ANY section was visible, so a member holding only MANAGE_RESOURCES was told "Nobody has an outstanding HR obligation" about data they cannot see. Each is now gated on the domains that feed it. Dropped the &member= ledger param. /hr/attendance, /hr/legal-compliance and /hr/training read searchParams.get('sub') and nothing else, so it filtered nothing, dangled bare when the id was null, and survived every later sub-tab switch through **************** A link promising a filter it does not apply is worse than a plain link. Rendered the pillar content that was already being computed and shipped: average score, legal drafts and active packages, published courses, failed final. And removed the hint that rendered the bare string "Active packages" under the executed count with no number, reading as a figure that failed to load. averageScore null renders an em dash, never a count-up to 0.