Skip to content

feature(web): cache proposals UI#138

Merged
jamby77 merged 4 commits into
feature/cache-apply-logic-and-approval-apifrom
feature/cache-proposals-ui
Apr 29, 2026
Merged

feature(web): cache proposals UI#138
jamby77 merged 4 commits into
feature/cache-apply-logic-and-approval-apifrom
feature/cache-proposals-ui

Conversation

@jamby77

@jamby77 jamby77 commented Apr 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add the Cache Proposals tab to Monitor (route /cache-proposals) with Pending and History sub-views.
  • Pending view: cards render the 4 (cache_type, proposal_type) variants — semantic threshold adjust, agent tool TTL adjust, semantic invalidate, agent invalidate. Approve is optimistic ("Applying…"), Reject opens an inline reason input, Edit swaps the proposed value for an inline numeric input that posts via /edit-and-approve. Edit is hidden on invalidate cards. estimated_affected > 10000 triggers a warn visual.
  • History view: table with status + cache_name filters, source column, clickable rows opening a detail panel with reasoning, payload, apply result, and full audit trail.
  • Unread indicator: sidebar badge on the Cache Proposals nav item, cleared when the user opens the Pending tab. Persisted in localStorage.
  • New helpers: lib/formatters.ts (formatTtlSeconds, formatTimeAgo, formatExpiresIn).
  • Component tests (Vitest + RTL) cover all 4 card variants, edit hidden on invalidate, warn visual at >10000, optimistic Applying state, reject flow with/without reason, edit-and-approve, and direct approve.

Stacked on #137 — merge after the apply-dispatcher PR lands.

Closes the UI portion of issue-179753285 (Days 7–9). Spec: docs/plans/specs/spec-cache-proposals-ui.md.

Test plan

  • pnpm --filter @betterdb/web test — all web tests pass (175 tests, 27 files).
  • pnpm --filter @betterdb/web build — typecheck + Vite build clean.
  • Manual: visit /cache-proposals, verify all 4 card variants render correctly, approve/reject/edit flows POST to the right endpoint, history filters work, detail panel opens with audit trail, unread badge clears on tab visit.
  • Verify no hard-coded hex colours — all status colours use var(--chart-*) / shadcn theme variables.

Note

Medium Risk
Medium risk because it introduces new approve/reject/edit-and-approve mutation flows that trigger operational changes via new API endpoints, plus polling/unread state persisted in localStorage.

Overview
Introduces a new /cache-proposals page with Pending and History views for reviewing agent-submitted cache proposals.

Pending proposals render as actionable cards (approve, reject with optional reason, and edit+approve for supported proposal types) with basic validation and “high impact” highlighting; history adds filtering and a row-click detail sheet that shows payload, apply result, and audit events.

Adds a cacheProposalsApi client plus React Query hooks (including pending polling and query invalidation) and a sidebar unread badge backed by localStorage, along with new time/TTL formatting utilities and targeted component/unit tests.

Reviewed by Cursor Bugbot for commit 1bef37b. Bugbot is set up for automated code reviews on this repo. Configure here.

Add /cache-proposals route with Pending and History tabs. Pending cards
render four (cache_type, proposal_type) variants with approve, reject,
and edit-and-approve flows. Edit hidden on invalidate cards. History
table filters by status/cache_name and opens a detail panel with full
reasoning, payload, and audit trail. Sidebar shows an unread badge for
new pending proposals.
Comment thread apps/web/src/hooks/useCacheProposals.ts
Comment thread apps/web/src/pages/CacheProposals.tsx
Comment thread apps/web/src/hooks/useCacheProposals.ts Outdated
Use a module-level subscription store with useSyncExternalStore so the
sidebar badge clears when CacheProposals.markAllRead() runs. Wraps
markAllRead in useCallback to avoid firing the page-level effect every
render. Drops the unused cacheProposalQueryKeys export.
Comment thread apps/web/src/components/pages/cache-proposals/HistoryTable.tsx
Comment thread apps/web/src/hooks/useCacheProposals.ts Outdated
- proposalSource now reads proposed_by only (was falling through to
  reviewed_by, mislabelling UI-proposed/MCP-reviewed entries as 'mcp').
- Track unread by last-seen timestamp instead of id, so when the
  marker proposal is approved/rejected/expired it doesn't inflate the
  unread count to all remaining (already-seen) pending proposals.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 88beada. Configure here.

Comment thread apps/web/src/hooks/useCacheProposals.ts
…sion

Math.max guards setLastSeenAt so a markAllRead call where the newest
pending proposal has a smaller timestamp (e.g. the previous newest was
approved by another user) cannot move the marker backward and resurrect
already-seen proposals as unread.
@jamby77
jamby77 merged commit 6901271 into feature/cache-apply-logic-and-approval-api Apr 29, 2026
2 checks passed
@jamby77
jamby77 deleted the feature/cache-proposals-ui branch April 29, 2026 06:23
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 29, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant