2026 04 13 Task Cost Four Decimals
Task / scorecard cost: four decimal USD (no millidollars) — Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Replace millidollar cost display with a shared plain $ + four-decimal formatter for the routing scorecard and task detail overview.
Architecture: Add formatOptionalUsdPlainFourDecimals in src/lib/currency.ts (null → em dash, else `${cost.toFixed(4)}`). Remove duplicate local formatCost from TaskRoutingScorecardTable.tsx and TaskDetail.tsx; import the shared helper. No API or billing changes.
Tech Stack: React, TypeScript, Vite, Vitest
Spec: docs/superpowers/specs/2026-04-13-task-cost-display-four-decimals-design.md
File map
| File | Role |
|---|---|
src/lib/currency.ts |
New exported formatter |
src/lib/currency.test.ts |
Vitest coverage for formatter |
src/components/TaskRoutingScorecardTable.tsx |
Drop local formatCost; import helper for cost column |
src/pages/TaskDetail.tsx |
Drop local formatCost; import helper for overview rollup |
Task 1: Failing tests for formatOptionalUsdPlainFourDecimals
Files:
-
Modify:
src/lib/currency.test.ts -
[ ] Step 1: Add tests and import (function does not exist yet)
In src/lib/currency.test.ts:
- Extend the
./currencyimport to includeformatOptionalUsdPlainFourDecimalsalongsideformatUsdandnormalizeCurrencyForDisplay. - Insert this block immediately after the import line and before the existing
describe("normalizeCurrencyForDisplay", ...):
describe("formatOptionalUsdPlainFourDecimals", () => {
it("returns em dash for null", () => {
expect(formatOptionalUsdPlainFourDecimals(null)).toBe("\u2014");
});
it("formats with four decimal places using Number#toFixed(4)", () => {
expect(formatOptionalUsdPlainFourDecimals(0.01234)).toBe("$0.0123");
expect(formatOptionalUsdPlainFourDecimals(0.00005)).toBe("$0.0001");
expect(formatOptionalUsdPlainFourDecimals(0.0000007)).toBe("$0.0000");
});
});
Do not remove or reorder the existing normalizeCurrencyForDisplay and formatUsd tests.
- [ ] Step 2: Run tests and confirm failure
Run:
cd /Users/kodart/Projects/ai-route-hub && npx vitest run src/lib/currency.test.ts
Expected: FAIL (TypeScript or runtime: formatOptionalUsdPlainFourDecimals is not exported / not a function).
- [ ] Step 3: Commit
git add src/lib/currency.test.ts
git commit -m "test: add formatOptionalUsdPlainFourDecimals cases (red)"
Task 2: Implement formatter in currency.ts
Files:
-
Modify:
src/lib/currency.ts -
[ ] Step 1: Export the helper
Append after formatUsd (end of file is fine):
/** Plain USD for task/scorecard costs: `
2026 04 13 Task Cost Four Decimals — MultiRoute Docs
+ four decimals; `null` → em dash (U+2014). */
export function formatOptionalUsdPlainFourDecimals(cost: number | null): string {
if (cost === null) return "\u2014";
return `${cost.toFixed(4)}`;
}
- [ ] Step 2: Run currency tests
Run:
npx vitest run src/lib/currency.test.ts
Expected: PASS (all tests in file).
- [ ] Step 3: Commit
git add src/lib/currency.ts
git commit -m "feat: formatOptionalUsdPlainFourDecimals for task costs"
Task 3: TaskRoutingScorecardTable uses shared helper
Files:
-
Modify:
src/components/TaskRoutingScorecardTable.tsx -
[ ] Step 1: Import helper and remove local
formatCost
Add import (group with other @/lib imports):
import { formatOptionalUsdPlainFourDecimals } from "@/lib/currency";
Delete the entire formatCost function (the block):
function formatCost(cost: number | null): string {
if (cost === null) return "—";
if (cost < 0.001) return `${(cost * 1000).toFixed(3)}m`;
return `${cost.toFixed(4)}`;
}
Replace the cost cell expression formatCost(c.cost_usd_avg) with:
formatOptionalUsdPlainFourDecimals(c.cost_usd_avg)
- [ ] Step 2: Run tests
Run:
npx vitest run src/components/TaskRoutingScorecardTable.test.tsx src/lib/currency.test.ts
Expected: PASS.
- [ ] Step 3: Commit
git add src/components/TaskRoutingScorecardTable.tsx
git commit -m "refactor: scorecard cost uses plain four-decimal USD helper"
Task 4: TaskDetail uses shared helper
Files:
-
Modify:
src/pages/TaskDetail.tsx -
[ ] Step 1: Import helper
Add with other @/lib imports:
import { formatOptionalUsdPlainFourDecimals } from "@/lib/currency";
- [ ] Step 2: Remove local
formatCostand simplify rollup
Delete:
function formatCost(cost: number | null): string {
if (cost === null) return "—";
if (cost < 0.001) return `${(cost * 1000).toFixed(3)}m`;
return `${cost.toFixed(4)}`;
}
Find the overview stat that currently reads like:
overviewRollups.cost != null ? formatCost(overviewRollups.cost) : "—",
Replace with:
formatOptionalUsdPlainFourDecimals(overviewRollups.cost),
- [ ] Step 3: Run lint (if used) and full test suite
Run:
npm run test
Expected: PASS.
- [ ] Step 4: Commit
git add src/pages/TaskDetail.tsx
git commit -m "refactor: task overview cost uses four-decimal USD helper"
Task 5: Final verification
- [ ] Step 1: Confirm no remaining millidollar branch
Run:
rg "1000\)\.toFixed\(3\)\}m|cost < 0\.001" src/components/TaskRoutingScorecardTable.tsx src/pages/TaskDetail.tsx
Expected: no matches.
- [ ] Step 2: Optional manual check
Open a task with routing scorecard data; confirm cost column shows $0.xxxx only (no m suffix).
Plan self-review
| Spec item | Task |
|---|---|
No millidollars; four decimal plain $ |
Tasks 2–4 |
null → em dash |
Tasks 1–2, usage in 3–4 |
Shared helper in currency.ts |
Tasks 1–2 |
| Scorecard + overview scope | Tasks 3–4 |
Tests in currency.test.ts |
Task 1–2 |
| Out of scope (Tasks, billing) | Not touched |
No placeholder steps; all code blocks are complete.
Plan complete and saved to docs/superpowers/plans/2026-04-13-task-cost-four-decimals.md.
Execution options:
-
Subagent-driven (recommended) — Fresh subagent per task, review between tasks. Required sub-skill: superpowers:subagent-driven-development.
-
Inline execution — Run tasks in this session with checkpoints. Required sub-skill: superpowers:executing-plans.
Which approach do you want?