Skip to content

feat(ship): observe-a-run V-3 (part) — cost column on Home recent-runs - #459

Open
sarath-soman wants to merge 1 commit into
mainfrom
feat/v3-home-cost
Open

feat(ship): observe-a-run V-3 (part) — cost column on Home recent-runs#459
sarath-soman wants to merge 1 commit into
mainfrom
feat/v3-home-cost

Conversation

@sarath-soman

Copy link
Copy Markdown
Contributor

Summary

Partial discharge of lambda-brahman/ship#20. Adds the Cost column to Home's recent-runs table per design.md sub-flow 1 ("History zone: columns include cost · run-id · rerun").

Server (`src/lib/run-dir.ts`):

  • New `sumCostFromTelemetry(runDir)` sums per-stage `cost_usd` from `telemetry.json`. Returns null when missing/empty/unparseable — null is "no signal", distinct from a real zero-cost run.
  • `scanRuns` sets `RunSummary.cost_usd` when defined.
  • `RunSummary` (and `web/types.ts` mirror) gains `cost_usd?: number`.

Client (`src/web/pages/Home.tsx`):

  • New `Cost` column between `Duration` and `Run ID`.
  • `formatCost(c)` → `$X.YZ` (2 dp) or `—` when undefined/non-finite.
  • `data-testid="cost-cell"` for follow-up integration tests.
  • `colSpan` bumped 7 → 8 on conflict/error banner rows.

Tests (4 new in `src/lib/run-dir.test.ts`):

  • claim 1 — multi-stage telemetry sums correctly (1.5 + 6.25 + 0.8 = 8.55)
  • claim 2 — missing `telemetry.json` leaves field absent
  • claim 3 — empty / malformed-only file leaves field absent
  • claim 4 — non-numeric rows ignored; valid rows still summed

What this is NOT

V-3 has three surfaces; this PR closes one. Out of scope here:

lambda-brahman/ship#20 stays open after this lands; close it only when all three surfaces ship.

Test plan

Rebased onto current main (includes #457, #458).

🤖 Generated with Claude Code

Per V-3 acceptance ("per-run cost is visible") and design.md sub-flow 1
("History zone: columns include cost · run-id · rerun. Cost column is new
(V-3)").

Server side (`src/lib/run-dir.ts`):
- New `sumCostFromTelemetry(runDir)` helper sums per-stage `cost_usd` from
  `telemetry.json`. Returns `null` when the file is missing, empty, or has
  no rows with a numeric cost — null is "no signal" (distinct from a real
  zero-cost run).
- `scanRuns` calls it once per run and sets `RunSummary.cost_usd` when
  defined. No change for runs without telemetry (field stays absent).
- `RunSummary` (and wire-shape mirror in `src/web/types.ts`) gains a new
  optional `cost_usd?: number` field.

Client side (`src/web/pages/Home.tsx`):
- New `Cost` column in the recent-runs table, between `Duration` and `Run ID`.
- `formatCost(c)` → `$X.YZ` (2 decimals) or `—` when undefined / non-finite.
- `data-testid="cost-cell"` on the latest-run cost cell for click-through tests
  in follow-up PRs.
- `colSpan` on conflict/error banner rows bumped 7 → 8.

Tests: 4 new in `src/lib/run-dir.test.ts` (claim 1 — multi-stage sums; 2 —
missing telemetry leaves field absent; 3 — empty/malformed file leaves field
absent; 4 — non-numeric cost rows ignored, valid rows still summed).

Partial discharge of #430 — surfaces per-run cost on Home (one of the three
surfaces design.md specs). OutcomeHeader aggregate (depends on V-2 #453) and
UnifiedTimeline per-phase cost (depends on U-1 #432) remain.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant