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:

In src/lib/currency.test.ts:

  1. Extend the ./currency import to include formatOptionalUsdPlainFourDecimals alongside formatUsd and normalizeCurrencyForDisplay.
  2. 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.

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).

git add src/lib/currency.test.ts
git commit -m "test: add formatOptionalUsdPlainFourDecimals cases (red)"

Task 2: Implement formatter in currency.ts

Files:

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)}`;
}

Run:

npx vitest run src/lib/currency.test.ts

Expected: PASS (all tests in file).

git add src/lib/currency.ts
git commit -m "feat: formatOptionalUsdPlainFourDecimals for task costs"

Task 3: TaskRoutingScorecardTable uses shared helper

Files:

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)

Run:

npx vitest run src/components/TaskRoutingScorecardTable.test.tsx src/lib/currency.test.ts

Expected: PASS.

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:

Add with other @/lib imports:

import { formatOptionalUsdPlainFourDecimals } from "@/lib/currency";

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),

Run:

npm run test

Expected: PASS.

git add src/pages/TaskDetail.tsx
git commit -m "refactor: task overview cost uses four-decimal USD helper"

Task 5: Final verification

Run:

rg "1000\)\.toFixed\(3\)\}m|cost < 0\.001" src/components/TaskRoutingScorecardTable.tsx src/pages/TaskDetail.tsx

Expected: no matches.

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:

  1. Subagent-driven (recommended) — Fresh subagent per task, review between tasks. Required sub-skill: superpowers:subagent-driven-development.

  2. Inline execution — Run tasks in this session with checkpoints. Required sub-skill: superpowers:executing-plans.

Which approach do you want?