fix(notifications): humanize JSON bodies, collapse stale bursts, Natural Light restyle #5462
ccantynzAI Reviewcommented 24d ago
AI Triage
(no summary)
Priority: medium Risk area: mixed
Suggested labels: (no label suggestions) Suggested reviewers: (no reviewer suggestions)
Suggestions only — nothing has been applied. The PR author stays in control.
gluecron[bot]🤖 botAI Reviewcommented 24d ago
AI review unavailable
The platform's AI balance is exhausted, so AI generation is temporarily unavailable. Nothing was lost. You can queue this as a repair for the internal agent from the repository's Health page, or try again once the balance is restored. The PR is otherwise unchanged.
Cross-repo impact
See what breaks downstream if this PR merges.
⮌ Merged
This pull request was merged into main.
c comment · e edit title · m merge · a approve · r request changes · ? shortcuts
Part of the design-sweep for the visual-audit ledger — refs #211. NOTIFICATIONS slice. All fixes are render-time; stored notification rows are never mutated.
Defect 1 — raw JSON blob rendered as a notification body (BROKEN)
Before: the top notification printed its stored JSON payload verbatim — braces, keys and all — as the row body. After:
humanizeNotificationBody()(newsrc/lib/notification-render.ts) detects a body that parses as JSON at render time and shows itsmessage/title/summaryfield, or akey: valuedigest of primitive fields ("repo name: gluecron · pr number: 42"). An empty{}/[]hides the body entirely. Plain prose passes through untouched, including brace-leading text that isn't JSON. Raw braces never reach the user.Defect 2 — ~200 identical ungrouped "PR #xxxx has gone quiet" rows
Before: every stale-sweep run wrote one notification per stale PR, and the inbox showed them as ~200 identical rows (capped at 50 by the query, so even the count was a lie). After:
collapseNotificationRows()groups adjacent runs of the same kind + repo (kindspr_stale,issue_stale) into one row — "234 PRs have gone quiet in owner/repo" — following the burst-collapse precedent insrc/lib/recent-activity.ts. The group row has a "Show all N"<details>expander (first 20 members inline with per-item mark-read, then a link to the full list) plus a "View pull requests" link to the repo's filtered view. Fetch limit raised to 500 so the group count is honest; the page still displays at most 50 grouped rows.Defect 3 — list styling to the Natural Light standard
Before: the old dark "2026 hero" treatment — animated blur orb, gradient headline text, glow shadows, gradient AI badge, a literal "purple-tinted" AI-row wash, and hardcoded dark-theme colors (
#60a5fa,#fbbf24,#34d399,rgba(255,255,255,…)). After:.hlth-*idiom fromsrc/routes/health.tsx— panel card (--bg-elevated+ 1px--border,--r-lg), hairline--border-subtleseparators, hover--bg-hover, a solidvar(--accent)unread bar, token-only icon tints (--blue/--amber/--green/--accent), quiet outline AI badge and mark-all button, and an honest empty state ("No notifications" / "No unread notifications" — no fake liveness). No purple, no gradients, no hardcoded hex.Also found while in here
n.repoOwner/n.repoName, which the bareselect()never populated. The query now joinsrepositories+users, so the link is real (and powers the group headline)./notifications/:id/delete— which had no handler anywhere; every dismiss was a 404. Added the row-scoped delete handler in the same idiom as:id/read.Tests
src/__tests__/notification-render.test.ts(16 tests, pure module — no db mocks): JSON humanization incl. the never-raw-braces invariant, burst collapsing incl. repo boundaries and non-collapsible kinds, group phrasing.bunx tsc --noEmit -p .— clean.bun test src/__tests__ --test-name-pattern "notif"— 30 pass / 0 fail.🤖 Generated with Claude Code