diff --git a/app/renderer/App.test.tsx b/app/renderer/App.test.tsx index 2832cb4d..d29b4c43 100644 --- a/app/renderer/App.test.tsx +++ b/app/renderer/App.test.tsx @@ -139,6 +139,11 @@ function installDefaultMocks() { healthScore: 100, healthGrade: 'A', findingCount: 0, periodCostUSD: 0, sessions: 0, calls: 0, potentialSavingsTokens: 0, potentialSavingsCostUSD: 0, potentialSavingsPercent: 0, costRateUSD: 0, measuredSavingsUSD: 0, + byClass: { + fix: { tokensSaved: 0, savingsUSD: 0, count: 0 }, + nudge: { tokensSaved: 0, savingsUSD: 0, count: 0 }, + keep: { tokensSaved: 0, savingsUSD: 0, count: 0 }, + }, }, findings: [], }) diff --git a/app/renderer/lib/types.ts b/app/renderer/lib/types.ts index d1f61a79..8cc1fd0a 100644 --- a/app/renderer/lib/types.ts +++ b/app/renderer/lib/types.ts @@ -423,6 +423,7 @@ export type OptimizeJsonReport = { potentialSavingsPercent: number | null costRateUSD: number measuredSavingsUSD: number + byClass: Record } findings: Array<{ id: string diff --git a/app/renderer/sections/Optimize.test.tsx b/app/renderer/sections/Optimize.test.tsx index 03b922b5..a01ed0e7 100644 --- a/app/renderer/sections/Optimize.test.tsx +++ b/app/renderer/sections/Optimize.test.tsx @@ -49,6 +49,11 @@ function makeOptimizeReport(): OptimizeJsonReport { sessions: 88, calls: 1220, potentialSavingsTokens: 184_000, potentialSavingsCostUSD: 94.4, potentialSavingsPercent: 15.4, costRateUSD: 0.0005, measuredSavingsUSD: 27.8, + byClass: { + fix: { tokensSaved: 18_200, savingsUSD: 9.1, count: 1 }, + nudge: { tokensSaved: 17_400, savingsUSD: 8.7, count: 1 }, + keep: { tokensSaved: 4_800, savingsUSD: 2.4, count: 1 }, + }, }, findings: [ { @@ -129,7 +134,11 @@ describe('Optimize', () => { await screen.findByText('Opus is doing your small talk') const groups = document.querySelectorAll('.opt-group') - expect([...groups].map(g => g.textContent)).toEqual(['Fix now (apply-able)', 'Habits', 'FYI']) + expect([...groups].map(g => g.textContent)).toEqual([ + 'Fix now (apply-able) · 18.2K tokens · $9.10 · 1 finding', + 'Habits · 17.4K tokens · $8.70 · 1 finding', + 'FYI · 4.8K tokens · $2.40 · 1 finding', + ]) }) it('renders tabs and actionable Waste findings with impact, savings, explanation, and copy-paste fix', async () => { diff --git a/app/renderer/sections/Optimize.tsx b/app/renderer/sections/Optimize.tsx index e0a6b347..0d6ea911 100644 --- a/app/renderer/sections/Optimize.tsx +++ b/app/renderer/sections/Optimize.tsx @@ -101,7 +101,7 @@ function WasteRows({ report }: { report: Polled }) {
{report.data.summary.findingCount.toLocaleString('en-US')} findings · {formatUsd(report.data.summary.potentialSavingsCostUSD)} potential · health {report.data.summary.healthScore}/100
- + ) } @@ -124,7 +124,7 @@ function actionText(fix: WasteAction): string { return fix.type === 'file-content' ? fix.content : fix.text } -function ActionableFindingRows({ findings }: { findings: OptimizeFinding[] }) { +function ActionableFindingRows({ findings, byClass }: { findings: OptimizeFinding[]; byClass: OptimizeJsonReport['summary']['byClass'] }) { const [expandedId, setExpandedId] = useState(null) const [copiedId, setCopiedId] = useState(null) @@ -145,7 +145,11 @@ function ActionableFindingRows({ findings }: { findings: OptimizeFinding[] }) { const showHeader = finding.class !== findings[i - 1]?.class return ( - {showHeader &&
{CLASS_HEADERS[finding.class]}
} + {showHeader && ( +
+ {CLASS_HEADERS[finding.class]} · {formatCompact(byClass[finding.class].tokensSaved)} tokens · {formatUsd(byClass[finding.class].savingsUSD)} · {byClass[finding.class].count} {byClass[finding.class].count === 1 ? 'finding' : 'findings'} +
+ )}