Skip to content

Cost basis on the remaining Usage cards, the Overview hero chip and Sessions transcript cost chips - #6000

Merged
vivekchand merged 7 commits into
mainfrom
feat/cost-basis-remaining-5937
Sep 15, 2026
Merged

vivekchand merged 7 commits into
mainfrom
feat/cost-basis-remaining-5937

Conversation

@vivekchand

@vivekchand vivekchand commented Sep 15, 2026 •

Copy link
Copy Markdown
Owner

Closes the remaining scope of #5937 that #5975 (released in 0.12.877) left open: the audit on 2026-09-14 found several Usage cards, the Overview hero cost chip and the Sessions transcript per-turn and per-tool chips still printing dollar amounts with no financial basis.

Factory requirement: REQ-OBS-CEA-025, extended with AC-OBS-CEA-025.8, .9 and .10 (non-goals and in-flight banner updated): https://factory.8090.ai/project/b415065f-ab2f-4f53-8864-0c009fd098cb/requirements/950d4687-45cc-45a8-9d58-0c0d82fd5d9b

What is now labelled

Every figure is usage value at published rates (published_rate), or unknown where nothing could be read. None claims contract or actual spend. Counterfactuals (projected savings, the month-end forecast, the same tokens on another model) carry the arithmetic basis estimated beside it.

Overview

  • Hero cost chip: it now prints the Spending tile's own number and provenance entry through the shared component, with the badge beside it. It no longer reads the tile's text back off the page.
  • Runtime-scoped Spending tile: it called an fmtCost that does not exist in that scope. The ReferenceError was swallowed, so the tile kept node-wide figures while the hero showed the runtime's. This is the "hero figure differs from the tile" noted on Cost figures: label vendor-reported vs contract vs estimated everywhere; split actual spend from API-equivalent #5937. The tile, its badge and the hero now share one entry, which also carries the financial basis.

Usage

  • Where the money goes: a caption carries the totals and the category-split badges (SVG text cannot hold a badge). Every label goes through cmProv.text, and the table cells through the shared figure.
  • Cards and tables through the shared figure: Cost Forecast, Cache Re-read Tax, cache hit rate, cache performance, savings ideas, routing advisor, compression potential, Cost By Plugin / Skill legend, Cost Comparison, Spend Optimization, Skill Cost Leaderboard and Cost by Team.
  • Cost Comparison: "Your actual spend (30 days)" now reads "Your usage value at published rates (30 days)" (AC-OBS-CEA-025.9).
  • Skill Cost Leaderboard: the local API sends total_cost_usd / avg_cost_usd, but the renderer read total_cost / avg_cost (the hosted synthesiser's shape), so every local row printed $0.00. It now reads both shapes.

Sessions

  • Transcript payloads (/api/transcript/<id>, /api/transcript-page/<id>) carry a messages[].cost_usd entry.
  • The per-turn and per-tool chips render through the shared figure with the basis in their hover text.
  • The transcript header shows the badge once rather than once per chip, which keeps the keyboard stops down.

Server side and cloud parity (FLYWHEEL §0a)

  • clawmetry/cost_basis_surfaces.py (new) holds the entries for every surface above, in one place.
  • clawmetry/efficiency.py and clawmetry/spend_flow.py stamp them inside the engines. /api/efficiency, /api/spend-flow, every byRuntime scope and the hosted snapshot's efficiency and spendFlow slices therefore carry identical entries. The cloud interceptor's per-runtime copy of spendFlow keeps them too.
  • routes/usage.py stamps the forecast, cost comparison, cache trends, spend optimization, cache risk, compression, by-plugin, skill attribution and by-team payloads, on both the DuckDB and the legacy paths. The hosted forecast, costComparison, cacheTrends and spendOptimization snapshot slices reuse those builders.
  • routes/sessions.py stamps the transcript dict. The hosted snapshot's transcripts slice reuses it, and cm-cloud-transcript returns that object whole.
  • provenance.js adds cmCostFigure: the shared figure for a cost whose basis may not have arrived. It badges when an entry exists and never invents one.

Guards

  • tests/test_provenance_render_coverage.py
    • Whole-file unbadged ceiling: 62 -> 43.
    • New per-tab ratchet, discovered from the tab templates rather than a hand-kept list: a function belongs to a tab when it touches an id in templates/tabs/<tab>.html, plus its helpers three calls deep, and local money formatters are discovered by shape. Ceilings: overview 24, usage 0, transcripts 5.
    • The named surfaces must route every figure through the shared component.
    • Discovery must reach them, so the ratchet cannot pass vacuously.
  • tests/test_cost_basis_remaining_surfaces.py (15 tests, added to CI's provenance step)
    • Payloads: efficiency and spend-flow scopes, the Usage card routes, and the hosted snapshot usage and transcripts slices.
    • Shipped renderers under node: hero chip, spend flow, comparison, plugin legend, skills, team and cache risk, transcript chips.
    • A class guard: no function may call a formatter that only another function defines.
  • Proved against origin/main: with the fix's code absent, 20 of 21 tests in the two files fail. The one pass is the pre-existing ceiling-padding test.
  • AC-OBS-CEA-025.8 to .10 are mirrored into docs/acceptance_criteria.json with no duplicate ids. docs/ac_coverage_baseline.json and docs/MODULE_MAP.md are regenerated.

Verified

  • pytest passes for the four provenance and cost-basis files (79 tests), plus 195 tests across the efficiency, spend flow, cache trends, compression, transcript, usage and cost optimizer suites.
  • Checks: node --check, module map --check, AC traceability, and ruff clean on the new files. Ruff counts on the changed route files are unchanged from main.
  • Headless browser against a scratch install:
    • Setup: scratch HOME, random port, seeded DuckDB, local_only. The dashboard's spawned daemon was pointed at the worktree code.
    • Usage: forecast, cache performance, plugin legend, cost comparison, efficiency and routing advisor showed "published rates" badges.
    • Transcript: the header badge rendered, and turn chips carried the basis in their hover text.
    • Overview, node-wide and ?runtime=claude_code: the Spending tile and hero chip printed the same figure with the same entry, with no page errors. The scoped tile now renders; before, it failed silently.
    • The scratch page's own initial load timed out (the cold-load problem fix(dashboard): first load no longer times out its own startup requests (#5935) #5957 fixes), so the Overview renderers were driven with the live payloads.
  • tests/test_usage_forecast_local_store_v3.py: 3 tests fail identically on a clean origin/main checkout (a 6/7 daily rate near midnight). This predates this change.

Overlap with other PRs (all merged, resolved on this branch)

Rebased linearly onto main, no merge commits. Resolved semantically:

Not in this change

  • Other Overview and Sessions panels. Run and cohort comparison, anomaly panel, waste summary, loop sources, similar runs and the orchestration panel stay unlabelled; their payloads carry no basis yet. The per-tab ceilings hold them and can only fall.
  • Hosted synthesiser. The hosted dashboard synthesises Cost By Plugin / Skill and the Skill Cost Leaderboard in the browser (cm-tokens-synth in clawmetry-cloud), so those two cards show figures with no badge on hosted until the cloud side adds entries.
  • Cloud pin. Hosted billingCoverage, brain and cost-breakdown pass-through remains as listed on Cost figures: label vendor-reported vs contract vs estimated everywhere; split actual spend from API-equivalent #5937, and the new snapshot entries reach hosted with the next cloud pin.
  • Other bases. Contract and actual spend, and the cache and window reconciliation audit, are out of scope.
  • CHANGELOG. No CHANGELOG entry here; it is carried by the release PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Jm9d7s4fN55hN3YzQo75o9

@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

html += '<td style="padding:6px 8px;font-size:13px;text-align:right;color:var(--text-muted);">' + escHtml(String(row.invocations == null ? '' : row.invocations)) + '</td>';
html += '<td style="padding:6px 8px;font-size:13px;text-align:right;">' + window.cmCostFigure(num(row, 'avg_cost_usd', 'avg_cost'), avgEntry, { noBadge: true, label: 'Average cost per invocation' }) + '</td>';
html += '<td style="padding:6px 8px;font-size:13px;text-align:right;font-weight:600;color:var(--text-accent);">' + window.cmCostFigure(num(row, 'total_cost_usd', 'total_cost'), totalEntry, { noBadge: true, label: 'Total cost' }) + '</td>';
html += '<td style="padding:6px 8px;font-size:12px;text-align:right;"><a href="' + escHtml(row.clawhub_url) + '" target="_blank" style="color:#4caf50;text-decoration:none;">ClawHub ↗</a></td>';
@github-actions

github-actions Bot commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Visual diff

Bot run failed before producing screenshots. Check the workflow logs.

This check is non-blocking.

@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

1 similar comment
@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

@vivekchand
vivekchand force-pushed the feat/cost-basis-remaining-5937 branch from acde63e to cce43ce Compare September 15, 2026 01:30
@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

1 similar comment
@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

@vivekchand
vivekchand force-pushed the feat/cost-basis-remaining-5937 branch from b7358eb to 42bf4c0 Compare September 15, 2026 03:56
@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

1 similar comment
@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

@vivekchand
vivekchand force-pushed the feat/cost-basis-remaining-5937 branch from 445e37c to 5ef325f Compare September 15, 2026 07:37
@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

@vivekchand
vivekchand force-pushed the feat/cost-basis-remaining-5937 branch from 5ef325f to e72c609 Compare September 15, 2026 12:22
@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

2 similar comments
@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

vivekchand and others added 7 commits September 15, 2026 15:14
…ranscript chips

Refs #5937 (REQ-OBS-CEA-025, AC-OBS-CEA-025.8 to .10).

- clawmetry/cost_basis_surfaces.py: one place for the financial-basis
  entries of every remaining cost surface.
- efficiency.py / spend_flow.py stamp them inside the engines, so the
  local routes and the hosted snapshot slices carry identical entries.
- routes/usage.py: forecast, cost comparison, cache trends, cache risk,
  compression, by-plugin, skill attribution, by-team, spend optimization.
- routes/sessions.py: transcript and transcript-page payloads label
  messages[].cost_usd; the snapshot transcripts slice reuses the dict.
- app.js: those cards, the Overview hero chip and the transcript turn and
  tool chips render through provenance.js (new cmCostFigure).
- Fixes found on the way: the runtime-scoped Spending tile called an
  undefined fmtCost (tile stayed node-wide, hero showed the runtime), and
  the Skill Cost Leaderboard read avg_cost/total_cost while the local API
  sends *_usd, printing $0.00 on every row. "Your actual spend" is now
  "usage value at published rates".
- Guards: per-tab unbadged-render ratchet discovered from the tab
  templates (overview 24, usage 0, transcripts 5); line ceiling 62 -> 43;
  tests/test_cost_basis_remaining_surfaces.py (payloads, snapshot slices,
  shipped renderers under node).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm9d7s4fN55hN3YzQo75o9
…0.00 total

Refs #5937.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm9d7s4fN55hN3YzQo75o9
…e the other paths

The previous commit labelled it unknown, which stamp() nulls, and
test_api TestSkillCosts (a numeric total_cost) failed on all three OSes.
With no skill reads found, a total of 0 over zero skills is exact.

Refs #5937.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm9d7s4fN55hN3YzQo75o9
…ted after rebase

uses document.createElement); the node harness now provides both.
docs/MODULE_MAP.md regenerated on the rebased tree.

Refs #5937.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm9d7s4fN55hN3YzQo75o9
…a known number

tests/test_live_session_truth.py (MOAT Verifier) pins that 'free' is
computed only after the cost value is known and that the cost chip is
pushed only when known. The refactor had folded both into
_cmHeroCostChip; they are restored in place with the same meaning
(value, not tile text), and the chip keeps its basis badge.

Refs #5937.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm9d7s4fN55hN3YzQo75o9
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012gURwssjXXXdN4ftTqnycU
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R2qvyzQXsAhnjfrCt4izc8
@vivekchand
vivekchand force-pushed the feat/cost-basis-remaining-5937 branch from a13ef74 to 5e0e879 Compare September 15, 2026 15:14
@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

@vivekchand
vivekchand merged commit 1672394 into main Sep 15, 2026
44 of 46 checks passed
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.

3 participants