The page added in #2462 lived at `/{slug}/dashboard` and was titled
"Dashboard", which collides with the conventional meaning ("personal
landing surface") and doesn't tell new users what the page is for. Its
actual contents — token spend, cost, run time, task counts — map cleanly
onto the OpenAI / Anthropic / Vercel "Usage" surface, so rename to that.
Renames (user-visible)
- Route: `/{slug}/dashboard` → `/{slug}/usage` (web App Router + desktop
memory router)
- Sidebar entry: label "Dashboard" / "看板" → "Usage" / "用量", icon
LayoutDashboard → BarChart3 (page header icon swapped in sync)
- Page title in en/zh-Hans
- Reserved-slugs: add `usage` to workspace route segments group;
`dashboard` stays reserved in the marketing group (back-compat against
workspace slug collisions + keeps the name free for a future Home page)
- i18n namespace `dashboard` → `usage` across resources-types.ts,
locales/index.ts, and the moved JSON files
- WORKSPACE_ROUTE_SEGMENTS in editor link-handler
- paths.workspace(slug).dashboard() → .usage(), with matching test
expectation updates
Per-agent leaderboard polish (`packages/views/dashboard/components/
dashboard-page.tsx`)
- Card title "Cost & run time by agent" → "Leaderboard" with a 4-way
Segmented control: Tokens / Cost / Time / Tasks
- Active metric drives row order, progress-bar width, and the
emphasised column header / cell — keeping ranking, visual quantity,
and column emphasis in lockstep so users always see what's being
measured
- Default sort = Tokens (most universally meaningful; Cost still one
click away)
- Project filter dropdown:
- Show ProjectIcon next to the selected project + each list item;
FolderKanban as the "All projects" fallback (matches ProjectPicker
language)
- alignItemWithTrigger={false} so "All projects" doesn't get pushed
above the trigger and clipped when the header sits at the top of
the viewport (was the root cause of "can't re-select All projects"
once a project was selected)
- max-h-72 to cap the dropdown when workspaces accrue many projects;
matches the runtime-detail Select precedent
- Folder name `packages/views/dashboard/*` and `DashboardPage`
component name intentionally left in place — user-visible rename
only, no broad code refactor.
Old `/dashboard` routes are not redirected because the page only landed
in #2462 (a few days ago); no real users, external links, or
desktop-tab persistence have settled on it yet.
Reserved workspace slugs lived in two parallel files (`workspace_reserved_slugs.go`
and `packages/core/paths/reserved-slugs.ts`) with no parity check. Adding or
renaming a global route on one side without the other would slip through CI
and surface only when a real user hit the collision.
Collapse the two lists into one source: `server/internal/handler/reserved_slugs.json`.
Go embeds the JSON via `//go:embed` and parses it at package init; the TS file
is regenerated by `scripts/generate-reserved-slugs.mjs` (run via
`pnpm generate:reserved-slugs`). CI re-runs the generator and `git diff
--exit-code`s the TS output, so a stale TS file cannot land. The slug set is
unchanged (87 entries, byte-equivalent slug literals).
Update CLAUDE.md to describe the new "edit JSON, run generator" workflow.
Co-authored-by: multica-agent <github@multica.ai>