Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to `omnidash` are documented here.

This project follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## v1.1.6 (2026-10-08)

### Features
- The Overview shows Baseline spend: the served `counterfactual_usd` of metering-summary.v1's all-time
row, the figure `onex metering --json` reports, beside the baseline model and pricing manifest it is
priced at. With no baseline resolved it shows Baseline unresolved, never $0 (OMN-20752)

## v1.1.5 (2026-10-08)

### Fixes
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "omnidash",
"version": "1.1.5",
"version": "1.1.6",
"description": "Composable widget dashboard for real-time observability — Vite + React with per-widget 2D and 3D variants.",
"main": "index.js",
"homepage": "https://github.com/OmniNode-ai/omnidash#readme",
Expand Down
106 changes: 106 additions & 0 deletions src/pages/LocalDashboardPage.omn20752.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// @vitest-environment jsdom
// OMN-20752: the Overview shows Baseline spend, the served counterfactual_usd of metering-summary.v1's all-time row --
// the figure `onex metering --json` reports as counterfactual_usd -- and a typed state, never $0, when no baseline
// resolved.
//
// Failure modes, each with a test below:
// B1 a served all-time row with a known counterfactual renders that amount on a Baseline spend card;
// B2 a row whose baseline_state is unresolved renders Baseline unresolved, never $0, whether the row leaves
// counterfactual_usd null or serves it as 0;
// B3 the card names the same row's baseline model and pricing manifest, and says the figure is modelled;
// B4 no served row at all is a typed not-measured state, never a number;
// B5 only the all-time row is read: a day row's counterfactual is not the headline (the control for B1).
import { act, render, screen } from '@testing-library/react';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

const METERING = 'onex.snapshot.projection.metering-summary.v1';

const harness = vi.hoisted(() => ({
reachable: new Set<string>(),
answer: (_topic: string): Promise<unknown[]> => Promise.resolve([]),
}));

vi.mock('@/data-source', () => ({
createSnapshotSource: () => ({
async *readAll() { yield []; },
readSnapshot: async (topic: string) => {
const rows = await harness.answer(topic);
return { rows, rowCount: rows.length, dataFreshness: 'fresh', latestEventAt: null, readAt: new Date().toISOString() };
},
}),
}));
vi.mock('@/data-source/data-source-override', () => ({ resolveEffectiveDataSource: () => ({ mode: 'http' }) }));
vi.mock('@/data-source/exposure-census', () => ({
fetchExposureCensus: async () => ({
rows: [...harness.reachable].map((topic) => ({ topic, reachability: 'reachable' })),
}),
}));

import { LocalDashboardPage } from './LocalDashboardPage';

// The all-time row the OMN-20223 walk read on 2026-10-08: 23 runs, `onex metering --json` counterfactual_usd 0.015292.
const allRow = (fields: Record<string, unknown>) => ({
window_kind: 'all', window_start: '', as_of: '2026-10-08T18:40:44Z', baseline_model: 'claude-sonnet-5-5',
pricing_manifest_version: '3', baseline_state: 'resolved', runs_total: 23, runs_measured: 23,
runs_unknown_tokens: 0, runs_unknown_spend: 0, tokens_in: 5756, tokens_out: 378, spend_usd: 0,
counterfactual_usd: 0.015292, savings_usd: 0.015292, savings_per_measured_run_usd: 0.000665, ...fields,
});

async function baselineCard(rows: unknown[]): Promise<HTMLElement> {
harness.reachable = new Set([METERING]);
harness.answer = (topic) => Promise.resolve(topic === METERING ? rows : []);
render(<LocalDashboardPage pageName="overview" />);
await act(async () => { await vi.advanceTimersByTimeAsync(0); });
const card = screen.getByRole('heading', { name: 'Baseline spend' }).closest('article');
if (card === null) throw new Error('no Baseline spend card on the Overview');
return card as HTMLElement;
}

const figure = (card: HTMLElement) => card.querySelector('.local-dashboard-metric')?.textContent ?? '';

describe('OMN-20752 Baseline spend on the Overview', () => {
beforeEach(() => {
vi.useFakeTimers({ toFake: ['setInterval', 'clearInterval', 'setTimeout', 'clearTimeout', 'Date'] });
vi.setSystemTime(new Date('2026-10-08T18:45:00Z'));
});
afterEach(() => { vi.useRealTimers(); });

it('B1: renders the served counterfactual_usd of the all-time row', async () => {
const card = await baselineCard([allRow({})]);
expect(figure(card)).toBe('$0.0153');
});

it('B1: a different served counterfactual renders that amount, not a constant', async () => {
const card = await baselineCard([allRow({ counterfactual_usd: 12.5, savings_usd: 12.5 })]);
expect(figure(card)).toBe('$12.5000');
});

for (const counterfactual of [null, 0]) {
it(`B2: an unresolved baseline is Baseline unresolved, never $0 (counterfactual_usd ${String(counterfactual)})`, async () => {
const card = await baselineCard([allRow({
baseline_state: 'unresolved', baseline_model: null, counterfactual_usd: counterfactual, savings_usd: null,
})]);
expect(figure(card)).toBe('Baseline unresolved');
expect(card.textContent ?? '').not.toMatch(/\$\s*0/);
});
}

it("B3: names the row's baseline model and pricing manifest, and says the figure is modelled", async () => {
const card = await baselineCard([allRow({})]);
expect(card.textContent).toContain('Baseline claude-sonnet-5-5');
expect(card.textContent).toContain('pricing manifest v3');
expect(card.textContent).toContain('Modelled');
});

it('B4: no served row is a typed not-measured state, never a number', async () => {
const card = await baselineCard([]);
expect(figure(card)).toMatch(/^Not measured/);
expect(figure(card)).not.toMatch(/\d/);
});

it("B5: a day row's counterfactual is not the headline", async () => {
const day = { ...allRow({ counterfactual_usd: 99 }), window_kind: 'day', window_start: '2026-10-08' };
const card = await baselineCard([day, allRow({})]);
expect(figure(card)).toBe('$0.0153');
});
});
30 changes: 30 additions & 0 deletions src/pages/local/overview.contracts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,36 @@
"no-data"
]
},
{
"component_id": "overview-baseline-spend",
"component_kind": "metric_card",
"title": "Baseline spend",
"contract_version": {
"major": 1,
"minor": 0,
"patch": 0
},
"data_bindings": [
{
"binding_id": "overview-baseline-spend-metering",
"projection_topic": "onex.snapshot.projection.metering-summary.v1",
"ordering_authority_field": "as_of",
"ordering_direction": "descending",
"required_fields": [
"window_kind",
"as_of",
"baseline_model",
"pricing_manifest_version",
"baseline_state",
"counterfactual_usd"
]
}
],
"supported_empty_state_reasons": [
"missing-field",
"no-data"
]
},
{
"component_id": "overview-quality",
"component_kind": "table",
Expand Down
18 changes: 18 additions & 0 deletions src/pages/local/overview.page.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,24 @@
"precision": 6
}
},
{
"widget_id": "6f1d2c8e-4b7a-5e39-9c0d-20752a1c0c01",
"title": "Baseline spend",
"row": 8,
"col": 8,
"width": 4,
"height": 2,
"data_source": "overview-baseline-spend",
"config": {
"config_kind": "metric_card",
"widget_type": "metric_card",
"metric_key": "counterfactual_usd",
"label": "Baseline spend",
"unit": "USD",
"format": "currency",
"precision": 4
}
},
{
"widget_id": "d4da9a48-f797-4b1d-b622-41f028a67e04",
"title": "Quality",
Expand Down
2 changes: 2 additions & 0 deletions src/pages/local/pages.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,8 @@ describe('local pages against the captured lab catalogue', () => {
'spend_usd', 'savings_usd', 'runs_measured', 'tokens_in_and_out',
// OMN-20009: the served run-locally share and the served saving per measured run.
'by_tier.local_call_share', 'savings_per_measured_run_usd',
// OMN-20752: Baseline spend, the same all-time row's served counterfactual_usd.
'counterfactual_usd',
// OMN-20226: compression and cache hit rate, each a served metering-summary.v1 column, Not measured until produced.
'compression_ratio', 'cache_hit_rate',
]);
Expand Down
Loading