test(observability): close 2 MAJOR test gaps from SKAL-2 review
F1 cache-analyzer regression guard (SC5): pin percentile (wall_time_ms_p50/p90) and time-range (oldest/newest_event_iso) — 2 of 3 'unchanged' categories were previously un-asserted on the mixed-input fixture. F2 lastMainChainModel: add direct coverage — last-wins across 2 distinct main-chain models, sidechain exclusion (even when the sidechain is the last record), and model-absent → null propagating to deriveCost refuse-to-estimate. 804 -> 807 tests (805 pass / 0 fail / 2 skipped). No test pins the test count.
This commit is contained in:
parent
7e78d076f9
commit
68c9bef38f
2 changed files with 43 additions and 0 deletions
|
|
@ -58,8 +58,14 @@ test('summarize — existing duration/event-name fields still correct on mixed i
|
|||
// Pre-existing behavior (regression guard)
|
||||
assert.equal(s.total_events, 3);
|
||||
assert.equal(s.events_with_duration, 2);
|
||||
// Percentiles: durations [100,200] → floor(2·0.5)=floor(2·0.9)=idx 1 → both 200.
|
||||
assert.equal(s.wall_time_ms_p50, 200);
|
||||
assert.equal(s.wall_time_ms_p90, 200);
|
||||
assert.equal(s.wall_time_ms_max, 200);
|
||||
assert.deepEqual(s.unique_event_names, ['main-merge-approved', 'main-merge-gate']);
|
||||
// Time range spans all ts-bearing lines (incl. the token-only record at 12:00).
|
||||
assert.equal(s.oldest_event_iso, '2026-06-26T10:00:00.000Z');
|
||||
assert.equal(s.newest_event_iso, '2026-06-26T12:00:00.000Z');
|
||||
// New behavior coexists
|
||||
assert.equal(s.total_tokens_input, 1000);
|
||||
assert.equal(s.sessions_with_tokens, 1);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import {
|
|||
deriveCost,
|
||||
buildRecord,
|
||||
upsertSessionRecord,
|
||||
lastMainChainModel,
|
||||
PRICE_TABLE,
|
||||
PRICE_TABLE_VERSION,
|
||||
} from '../../lib/stats/token-usage.mjs';
|
||||
|
|
@ -140,3 +141,39 @@ test('upsertSessionRecord — empty file → single record, trailing newline', (
|
|||
assert.ok(out.endsWith('\n'));
|
||||
assert.deepEqual(out.trim().split('\n').map(JSON.parse).length, 1);
|
||||
});
|
||||
|
||||
// ---- lastMainChainModel ----------------------------------------------------
|
||||
|
||||
test('lastMainChainModel — last main-chain model wins; sidechain excluded even when last', () => {
|
||||
// Two distinct main-chain models (opus then sonnet) → sonnet (last) wins.
|
||||
// A sidechain record sits AFTER sonnet: if exclusion broke it would win;
|
||||
// if last-wins broke, opus (first) would win. Correct answer pins both.
|
||||
const text = [
|
||||
JSON.stringify({ type: 'assistant', isSidechain: false, message: { model: 'claude-opus-4-8', usage: {} } }),
|
||||
JSON.stringify({ type: 'assistant', isSidechain: false, message: { model: 'claude-sonnet-4-6', usage: {} } }),
|
||||
JSON.stringify({ type: 'assistant', isSidechain: true, message: { model: 'claude-sidechain-ZZZ', usage: {} } }),
|
||||
JSON.stringify({ type: 'user', message: { content: 'ignored' } }),
|
||||
].join('\n');
|
||||
assert.equal(lastMainChainModel(text), 'claude-sonnet-4-6');
|
||||
});
|
||||
|
||||
test('lastMainChainModel — no main-chain model → null → deriveCost refuses to estimate', () => {
|
||||
// Only a sidechain model, a user line, and a malformed line: no main-chain model.
|
||||
const text = [
|
||||
JSON.stringify({ type: 'assistant', isSidechain: true, message: { model: 'claude-opus-4-8', usage: {} } }),
|
||||
JSON.stringify({ type: 'user', message: { content: 'hi' } }),
|
||||
'not json',
|
||||
].join('\n');
|
||||
const model = lastMainChainModel(text);
|
||||
assert.equal(model, null);
|
||||
// null model must propagate to refuse-to-estimate (honesty contract).
|
||||
const { cost_usd, is_estimate } = deriveCost({ tokens_input: 1000 }, model);
|
||||
assert.equal(cost_usd, null);
|
||||
assert.equal(is_estimate, true);
|
||||
});
|
||||
|
||||
test('lastMainChainModel — empty / nullish input → null', () => {
|
||||
assert.equal(lastMainChainModel(''), null);
|
||||
assert.equal(lastMainChainModel(null), null);
|
||||
assert.equal(lastMainChainModel(undefined), null);
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue