mirror of
https://github.com/dtzp555-max/olp.git
synced 2026-07-19 09:45:07 +00:00
feat: D82 — dashboard UI Claude.ai-style (Phase 5) (#54)
* feat: D82 — dashboard UI Claude.ai-style per-provider rows (Phase 5)
Implements ADR 0012 D82: restructures dashboard.html to render
quota_v2 data (produced by D81 / PR #53) in a Claude.ai-style
per-provider row layout. Closes v1.x roadmap #8.
## What changed
### dashboard.html (A–G)
A. New "Plan Usage" section at top (full-width, above the 2-col grid):
- Per-provider rows rendered from `data.quota_v2`
- Each row: provider badge (colored chip), status dot + chip
(live/stale/unavailable), schema version tag
- Two utilization bars (5h + 7d) with:
- Rounded gradient bar (green <50% / amber 50-80% / red >80%)
- Label "Current 5-hour session: 49%" / "Weekly all-models: 31%"
- Right-side reset countdown (see B)
- Bottom chips: representative-claim badge (purple), overage chip
(amber/green), fallback-percentage chip, last-fresh "Updated N
min ago" tag; stale rows show amber ⚠ stale data chip with tooltip
- Unavailable rows: provider badge + reason text only; no bars
B. formatResetCountdown(epochSeconds):
- < 1 hour: "Resets in 23 min"
- 1–24 hours: "Resets in 12hr 30min"
- < 7 days: "Resets Sun 9:00 PM" (weekday + 12h time)
- >= 7 days: "Resets May 31 9:00 PM" (month day + time)
- past: "Resetting now…"
Uses toLocaleString('en-US', { hour12: true }).
C. 60s auto-refresh (quota_v2 only) with visibilityState guard:
- Separate timer (quotaRefreshTimer); does NOT replace the 30s poll
- Pauses on 'hidden'; resumes + immediate re-fetch on 'visible'
- Other 3 panels (24h, 30d, top fallback) keep 30s cadence unchanged
D. Manual refresh button (↻ Refresh) in Plan Usage header:
- 2-second spam guard (button disables post-click)
- Spinning ⟳ icon during fetch
- Re-enables after fetch completes (success or error)
E. Graceful quota_v2 / legacy quota fallback:
- If data.quota_v2 is present and non-empty → render Plan Usage rows;
hide legacy "Quota (per provider)" panel
- If data.quota_v2 is absent/empty → show note in Plan Usage area;
surface legacy data.quota in the original table panel
- Guards operator running an older OLP build (pre-D81)
F. Visual polish: rounded bars, gradient fills, airy whitespace, mobile-
responsive (bars reflow on narrow viewports via flex-wrap). Color
palette: #10b981 (green), #f59e0b (amber), #ef4444 (red) matching
Tailwind emerald/amber/red-500 per spec.
G. Other 3 panels (24h, 30d, top fallback) and their 30s poll cadence
are IDENTICAL to D51. Only the Quota panel restructures.
### docs/v1x-roadmap.md (H)
Marks entry #8 as "✅ CLOSED (D82, v0.5.0)". Adds closure status,
PR ref, and a brief note inside the entry body. Updates reading-order
header paragraph to include #8 in the closed list.
## Authority + citations
- ADR 0012 D82 — Claude.ai-style restructure D-day spec
(docs/adr/0012-phase-5-charter-quota-probes-dashboard.md § D-day table)
- D81 PR #53 — quota_v2 shape producer (commit 5288493);
ProviderQuotaEntry shape per ADR 0008 Amendment 1 § 3
- Maintainer reference 2026-05-26 — claude.ai/settings/usage screenshot;
"Resets in 1hr 6min" / "Resets Sun 9:00 PM" string format
- v1.x roadmap #8 — closed by this commit
(docs/v1x-roadmap.md #8 — Dashboard enrichment)
## Test impact
npm test: 727 pass / 0 fail (unchanged). dashboard.html is frontend-only;
D83 ships Suite 38/39 (probe unit tests + dashboard smoke tests).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(dashboard): D82 reviewer Nit #4 — gate overage chip on real status
When entry.overage = { status: null, disabled_reason: null } (audit-query's
default shape when the provider doesn't supply overage info), the chip rendered
as amber "Overage: —" which falsely suggests a warning state.
Now: chip only renders when entry.overage.status is truthy (i.e., Anthropic
actually returned an overage-status header). Truly-missing overage info shows
no chip at all, matching the maintainer's intent.
Identified by D82 fresh-context reviewer (PR #54 thread) as the only
maintainer-visible nit worth folding in pre-merge. 1-line change. All 727
tests continue to pass.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: dtzp555 <dtzp555@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+3
-2
@@ -8,7 +8,7 @@
|
||||
3. **Where** does the work live in the tree today (file + anchor).
|
||||
4. **When** does it need to land (trigger: load profile, security event, governance amendment).
|
||||
|
||||
**Reading order for a v1.x sprint kickoff.** As of 2026-05-25, #1 (streaming SF, D57+D58) and #2 (multi-key auth, Phase 2) are CLOSED, and #4 and #7 closed in D56. Remaining v1.x scope: #3 (soft trigger reactivation), #5 (provider cacheKeyFields mask), #6 (streaming SPAWN_FAILED salvage — unbundled from #1 at #1 close). All three remaining items have explicit "trigger to start" gates that have not fired.
|
||||
**Reading order for a v1.x sprint kickoff.** As of 2026-05-26, #1 (streaming SF, D57+D58), #2 (multi-key auth, Phase 2), #4 and #7 (closed in D56), and #8 (dashboard enrichment, D82 Phase 5) are CLOSED. Remaining v1.x scope: #3 (soft trigger reactivation), #5 (provider cacheKeyFields mask), #6 (streaming SPAWN_FAILED salvage — unbundled from #1 at #1 close). All three remaining items have explicit "trigger to start" gates that have not fired.
|
||||
|
||||
---
|
||||
|
||||
@@ -88,8 +88,9 @@
|
||||
- **Tracking.** Not a GitHub issue. Tracked here.
|
||||
- **Trigger to start.** First report of streaming-path SPAWN_FAILED mid-stream where partial-chunk salvage would have helped a downstream caller. Practically unlikely at family scale.
|
||||
|
||||
## #8 — Dashboard enrichment: per-provider subscription quota + reset times + 1-min refresh + manual refresh (D78 follow-up)
|
||||
## #8 — Dashboard enrichment: per-provider subscription quota + reset times + 1-min refresh + manual refresh (D78 follow-up) — ✅ **CLOSED (D82, v0.5.0)**
|
||||
|
||||
- **Status.** Closed at D82 (Phase 5). `dashboard.html` restructured to Claude.ai-style per-provider rows rendering `quota_v2`. Closed by PR on branch `d82-dashboard-ui-claude-ai-style`; ships with v0.5.0. 60s quota auto-refresh + manual refresh button + visibilityState guard implemented. Graceful fallback to legacy `quota` field when server runs a pre-D81 build.
|
||||
- **What.** Phase 3 dashboard (D51 `dashboard.html`, v0.3.0) shows: per-provider quota (currently always "n/a — no quota api"), last-24h request count + cache hit + fallback rate, 30d request-count sparkline, top fallback chains. **Maintainer request 2026-05-26 post-D78**: extend to show what each enabled provider's subscription is actually consuming, with reset times visible, refresh once per minute (current 30s is OK but maintainer specified 1min target), and a manual refresh button. Reference design: Claude.ai's own `claude.ai/settings/usage` page — current session bar with "Resets in 1hr 6min", weekly all-models bar with "Resets Sun 9:00 PM", per-model bar (Sonnet only), additional features (routine runs), usage credits + monthly spend limit + auto-reload toggle.
|
||||
- **Why deferred.** v0.3.0/v0.4.x ships the dashboard frame but `provider.quotaStatus()` returns `null` in all three v0.1 plugins (anthropic / openai / mistral). The ratifying spec in ADR 0004 Amendment 2 punts `quotaStatus()` to v1.x ("soft trigger reactivation") — this dashboard ask is the **operator-facing reason** that work would land.
|
||||
- **What this requires.** Per-provider plugin work + dashboard.html UI work + audit-query.mjs aggregation:
|
||||
|
||||
Reference in New Issue
Block a user