🤖 feat: merge Costs + Stats into unified Stats tab with sub-tabs - #2729
Conversation
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 12cf75a7c1
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f5d8ab8f94
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review Fixed the migration issue: |
|
@codex review The migration issue raised was already addressed in the latest commit — |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1258f21cf1
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ce28f53186
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review Addressed both P1 and P2 feedback:
|
|
@codex review Resolved the new P1 thread — the empty tabset guard was already implemented in the latest commit. |
|
Codex Review: Didn't find any major issues. Already looking forward to the next diff. ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
|
@codex review Fixed E2E test failures — all specs referencing the old "Costs" tab name have been updated to "Stats". Also adjusted split layout tab count expectation (4 → 3) since the standalone stats tab no longer exists. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9631afbfad
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review Addressed the P2 feedback: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f12ecb7c6b
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review Addressed the archive cleanup issue: |
|
Codex Review: Didn't find any major issues. Already looking forward to the next diff. ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
|
@codex review Fixed the unit test failure for |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8b4fc81f50
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review Added ErrorBoundary back around StatsContainer — restores the fault isolation the old standalone StatsTab panel had. Also fixed the archive workspace unit test. |
|
Codex Review: Didn't find any major issues. 🎉 ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
Restructure the bottom panel tabs: - Rename top-level 'Costs' tab to 'Stats' (internal key remains 'costs') - Add sub-tabs inside Stats: Cost (always shown), Timing (feature-flagged), Models (feature-flagged) - Remove standalone 'Stats' top-level tab (absorbed into sub-tabs) - The statsTab feature flag now controls Timing/Models sub-tab visibility New files: - StatsContainer.tsx: Sub-tab container with ToggleGroup switching Refactored: - StatsTab.tsx: Extract useStatsData hook, TimingPanel, ModelBreakdownPanel - TabLabels.tsx: Merge CostsTabLabel + StatsTabLabel into unified StatsTabLabel - registry.ts: Remove 'stats' entry, rename costs name to 'Stats' - RightSidebar.tsx: Use StatsContainer, remove statsTabEnabled prop/effect - Migration: Clean up persisted 'stats' tabs from layouts
- Remove test expecting standalone 'stats' tab (absorbed into 'costs') - Add assertion that no standalone stats tab exists - Update renderReviewPanel selectTab types to remove 'stats'
Move stats tab migration to parseRightSidebarLayoutState's pre-parse step (stripLegacyStatsTab) so it runs before isTabType validation. This preserves user's custom sidebar configuration instead of resetting to defaults when persisted layouts contain the old 'stats' tab. Add 3 tests verifying the migration handles simple, activeTab fallback, and split layout scenarios.
- Change tab name matchers from /costs/ to /stats/ in play functions - Set statsContainer:subTab to 'cost' in cost-focused stories to ensure the Cost sub-tab is active (prevents timing sub-tab leaking from earlier stories via shared localStorage)
…ybook test
P1: stripLegacyStatsTab now ensures at least one tab remains when
a tabset only contained 'stats' (falls back to ['costs']).
P2: resolvePresetTab maps legacy 'stats' → 'costs' so older layout
presets resolve correctly. resolvePresetNodeToLayout deduplicates
tabs to prevent double 'costs' entries.
Storybook: StatsTabStreaming play function uses getByTestId instead
of getByText(/timing/i) to avoid ambiguity with the sub-tab toggle
button.
All E2E specs (sidebarDragDrop, review, reviewRefresh, terminal) referenced the old 'Costs' tab name. Updated to 'Stats' and adjusted split layout tab count (4 → 3) since standalone stats tab no longer exists.
When the persisted activeTab was 'stats' and tabs were reordered
(e.g., ['review', 'costs', 'stats']), prefer mapping to 'costs'
(semantic replacement) rather than the first tab ('review').
Added test for reordered layout case.
archiveWorkspace used isRightSidebarLayoutState directly on raw persisted data. Layouts with legacy 'stats' tabs would fail validation, skipping terminal tab cleanup on archive. Now uses parseRightSidebarLayoutState which runs stripLegacyStatsTab first.
parseRightSidebarLayoutState auto-injects 'explorer' when missing, so the test layout and expectations needed updating.
Restores the ErrorBoundary that the old standalone StatsTab panel had. Prevents TimingPanel/ModelBreakdownPanel errors from unmounting the entire sidebar.
ebff9b0 to
e16eb4b
Compare
…orts (coder#4472) ## Summary Deletes browser production code that only tests still called, and moves the tests that guarded live behavior onto the live code path. Part of the test-audit follow-up campaign (frontend area, WS7). ## What was removed | Removed | Why it was dead | What happened to its tests | | --- | --- | --- | | `StatsTab` component + its test-only `_snapshot`/`_clearStats` props and `useStatsData` overrides | No production caller since coder#2729 moved the Stats tab to `StatsContainer` (`TimingPanel` + `ModelBreakdownPanel`) | `StatsTab.clear.test.tsx` replaced by `TimingPanel.clear.test.tsx`, which drives the live path: real `WorkspaceStore` stats subscription + `APIProvider` client whose `workspace.stats.clear` rejects | | `compareRecords`, `compareArrays` (`useStableReference.ts`) | Only `compareMaps` is used (`App.tsx`) | 12 comparator tests deleted; stale "tested manually via useUnreadTracking…" comments fixed | | `closeSplit` (`rightSidebarLayout.ts`) | Never called in production since coder#1340 | Test deleted | | `isActionableTaskExecutionStatus` | Last caller removed in coder#4341 | No tests | | `shouldRefreshInlineSkillSuggestions` | coder#4013 made inline suggestions synchronously derived, so there is no refresh gate | Tests deleted | | `getAnthropicThinkingDisableReason` + `hasAnthropicThinkingSignature` | coder#1450 stopped disabling Anthropic thinking | Tests deleted; the one transform test that used it as an oracle now asserts the preserved signature directly | | `useProjectGitStatuses` (`GitStatusStore.ts`) | No production caller | None in CI | | `buildReviewDiffPathFilter`, `normalizeReviewPanelAssistedHunks` (test-only wrappers in `ReviewPanel.tsx`) | Production calls `buildReviewDiffPathFilterSpecs` / `getReviewPanelPathContext` + `normalizeAssistedReviewHunks` directly | Tests retargeted to those production functions (`getReviewPanelPathContext` is now exported) | | `computeTaskAwaitPollGroupInfos` (test-only wrapper) | ChatPane calls `computeOperationalBundleInfos({ taskAwaitPollsOnly })` | Tests use a local fixture helper around the production function | | 2 `/fork` cases in `parser.test.ts` | Same contract and name as `fork.test.ts` | Deleted | Retained on purpose (test reset seams, not dead code): `__resetForTests` (highlight worker), `resetAiSelectionIntentForTests`, `overlayWorkspaceStoreRaw` (test-support module). ## Validation - Sweep: every `export` under `src/browser` (excluding stories) checked for non-test references across `src/`, `tests/`, `vscode/`, `scripts/`, `.storybook/`; orphan-module sweep found only the two HTML entry points. - `TimingPanel.clear.test.tsx` fails when `handleClearStats` stops setting the error (mutation check). - `bun test` on RightSidebar, hooks/useStableReference, utils/{messages,agentSkills,ui,rightSidebarLayout}, stores/GitStatusStore: 1141 pass. - `make static-check` green. LOC: production +11 / −585; tests +134 / −355. --- _Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `high` • Cost: `$4.21`_ <!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=high costs=4.21 -->
Summary
Merge the standalone "Costs" and "Stats" top-level tabs into a single unified "Stats" tab with sub-tabs (Cost, Timing, Models).
Background
Previously the right sidebar had separate "Costs" and "Stats" tabs. The Stats tab was feature-flagged and duplicated some navigation patterns. This consolidates them into a single top-level "Stats" tab with a ToggleGroup for switching between sub-views.
Implementation
"costs"to avoid persisted layout migrations. Only the display name changes to "Stats".StatsContainer.tsx): UsesToggleGroupwith "Cost", "Timing", and "Models" options. Timing/Models only appear when thestatsTabfeature flag is enabled.TimingPanelandModelBreakdownPanelextracted fromStatsTab.tsxvia shareduseStatsDatahook.CostsTabLabel+StatsTabLabelinto one component showing both cost and duration badges.stripLegacyStatsTabruns as a pre-parse step inparseRightSidebarLayoutState, stripping"stats"from persisted layouts beforeisTabTypevalidation. This preserves user layout configuration during upgrade.Generated with
mux• Model:anthropic:claude-opus-4-6• Thinking:xhigh• Cost:$6.61