← back to Desktop Dotbar
dotbar/jev: isolate tests from real cost ledger + reconcile paidCallsToday to the enforced count
a32c6bfcc24b90e625cec634fe3eae7a2150fe38 · 2026-09-23 12:53:47 -0700 · Steve Abrams
Verification caught two defects in the count-cap change:
- Tests exercising the paid-log path called the real defaultLogSpend -> cost-tracker
log.js -> the REAL ~/.claude/cost-ledger.jsonl, writing phantom typesafe_jev rows
on every `npm test` (no money spent — mock transport — but polluting prod data and
pre-consuming the live caps). Fix: every paid-firing test now injects a mock logSpend
via the opts DI seam. Proven: full suite writes 0 rows to the real ledger (line count
unchanged across a run). The 7 rows already written were backed up and removed (rest
byte-identical).
- /api/jev showed paidCallsToday:0 while the ledger held 7 rows — the displayed stat
(a per-refresh snapshot, only set when armed) diverged from the value the cap enforces
(countPaidCallsToday). Fix: getStats() now derives paidCallsToday LIVE from the same
ledger (shared defaultReadLedger), so displayed == enforced regardless of paidEnabled;
a fail-closed read surfaces as null. Added an observability regression test.
13/13 pass. Bar re-verified: paidEnabled:false, paidCalls:0, paidCallsToday:0, $0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M jev-dots.jsM test/jev-dots.test.js
Diff
commit a32c6bfcc24b90e625cec634fe3eae7a2150fe38
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed Sep 23 12:53:47 2026 -0700
dotbar/jev: isolate tests from real cost ledger + reconcile paidCallsToday to the enforced count
Verification caught two defects in the count-cap change:
- Tests exercising the paid-log path called the real defaultLogSpend -> cost-tracker
log.js -> the REAL ~/.claude/cost-ledger.jsonl, writing phantom typesafe_jev rows
on every `npm test` (no money spent — mock transport — but polluting prod data and
pre-consuming the live caps). Fix: every paid-firing test now injects a mock logSpend
via the opts DI seam. Proven: full suite writes 0 rows to the real ledger (line count
unchanged across a run). The 7 rows already written were backed up and removed (rest
byte-identical).
- /api/jev showed paidCallsToday:0 while the ledger held 7 rows — the displayed stat
(a per-refresh snapshot, only set when armed) diverged from the value the cap enforces
(countPaidCallsToday). Fix: getStats() now derives paidCallsToday LIVE from the same
ledger (shared defaultReadLedger), so displayed == enforced regardless of paidEnabled;
a fail-closed read surfaces as null. Added an observability regression test.
13/13 pass. Bar re-verified: paidEnabled:false, paidCalls:0, paidCallsToday:0, $0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
jev-dots.js | 19 +++++++++++++++----
test/jev-dots.test.js | 14 ++++++++++++--
2 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/jev-dots.js b/jev-dots.js
index 2b4f2c8..3485960 100644
--- a/jev-dots.js
+++ b/jev-dots.js
@@ -62,7 +62,7 @@ const stats = {
capUsd: CONFIG.capUsd,
maxPaidCallsPerDay: CONFIG.maxPaidCalls,
lastSpendUsd: 0,
- paidCallsToday: 0, // today's paid-call count read from the ledger (last refresh)
+ paidCallsToday: 0, // shape default only — getStats() overrides with the LIVE ledger count (== what the cap enforces)
updated: 0,
};
@@ -180,6 +180,12 @@ function countPaidCallsToday(readLedger) {
}
}
+// Shared default ledger reader — the SAME source the count-cap enforces on, so the
+// displayed paidCallsToday (getStats) and the enforced value (classifyDots) can't diverge.
+function defaultReadLedger() {
+ try { return fs.readFileSync(CONFIG.ledgerPath, 'utf8'); } catch { return ''; }
+}
+
function logPaidCall(logSpend) {
// Log every paid call to the cost ledger via cost-tracker's log.js. Best-effort:
// a logging failure must never crash a refresh (but is counted).
@@ -260,7 +266,7 @@ async function classifyDots(rows, opts = {}) {
const paidEnabled = opts.paidEnabled !== undefined ? opts.paidEnabled : CONFIG.paidEnabled;
const capUsd = opts.capUsd !== undefined ? opts.capUsd : CONFIG.capUsd;
const maxPaidCallsPerDay = opts.maxPaidCallsPerDay !== undefined ? opts.maxPaidCallsPerDay : CONFIG.maxPaidCalls;
- const readLedger = opts.readLedger || (() => { try { return fs.readFileSync(CONFIG.ledgerPath, 'utf8'); } catch { return ''; } });
+ const readLedger = opts.readLedger || defaultReadLedger;
const paidTransport = opts.paidTransport || typeSafeClassify;
const logSpend = opts.logSpend || defaultLogSpend;
@@ -285,7 +291,6 @@ async function classifyDots(rows, opts = {}) {
spend = spendTodayUsd(readLedger);
stats.lastSpendUsd = Number.isFinite(spend) ? spend : stats.lastSpendUsd;
paidCount = countPaidCallsToday(readLedger);
- stats.paidCallsToday = Number.isFinite(paidCount) ? paidCount : stats.paidCallsToday;
}
for (const m of misses) {
@@ -325,7 +330,13 @@ async function classifyDots(rows, opts = {}) {
return out;
}
-function getStats() { return { ...stats, cacheSize: cache.size }; }
+function getStats(readLedger = defaultReadLedger) {
+ // paidCallsToday is computed LIVE from the same ledger the count-cap enforces on,
+ // so what /api/jev shows == what the cap actually counts (no per-process drift).
+ // A fail-closed read (Infinity) surfaces as null = "unreadable -> cap treats as at-cap".
+ const n = countPaidCallsToday(readLedger);
+ return { ...stats, paidCallsToday: Number.isFinite(n) ? n : null, cacheSize: cache.size };
+}
function _resetForTest() { cache.clear(); for (const k of Object.keys(stats)) if (typeof stats[k] === 'number') stats[k] = 0; }
module.exports = { classifyDots, classifyBuiltin, extractState, stateHash, spendTodayUsd, countPaidCallsToday, getStats, LABELS, _resetForTest };
diff --git a/test/jev-dots.test.js b/test/jev-dots.test.js
index 10af344..bcb9b1c 100644
--- a/test/jev-dots.test.js
+++ b/test/jev-dots.test.js
@@ -104,9 +104,10 @@ test('COUNT-CAP fail-closed: count >= cap -> paid transport is NEVER called, fal
const spyTransport = async () => { paidAttempts++; return { color: 'green', source: 'typesafe', confidence: 0.9 }; };
// capUsd high so the DOLLAR cap can't be the blocker; count cap of 3 with 3 rows already logged.
const map = await jev.classifyDots([row('a', 'purple', 'gated · 1'), row('b', 'green', 'working')], {
- paidEnabled: true, capUsd: 100, maxPaidCallsPerDay: 3, readLedger: () => nPaidLines(3), paidTransport: spyTransport,
+ paidEnabled: true, capUsd: 100, maxPaidCallsPerDay: 3, readLedger: () => nPaidLines(3),
+ paidTransport: spyTransport, logSpend: () => {},
});
- const s = jev.getStats();
+ const s = jev.getStats(() => nPaidLines(3)); // same source the cap read -> displayed == enforced
assert.equal(paidAttempts, 0, 'no paid attempt once the call-count cap is reached');
assert.ok(s.countCapBlocked >= 2, 'count-cap block counted for each miss');
assert.equal(s.capBlocked, 0, 'the $ cap was NOT the binding limit here');
@@ -123,6 +124,7 @@ test('COUNT-CAP boundary + burst: one call under cap fires, then the reserve blo
const map = await jev.classifyDots([row('a', 'yellow', 'needs direction'), row('b', 'purple', 'gated · 1')], {
paidEnabled: true, capUsd: 100, maxPaidCallsPerDay: 2, readLedger: () => nPaidLines(1),
paidTransport: async () => { paidAttempts++; return { color: 'green', source: 'typesafe', confidence: 0.9 }; },
+ logSpend: () => {}, // MOCK — never touch the real cost ledger from a test
});
const s = jev.getStats();
assert.equal(paidAttempts, 1, 'exactly one paid call fires before the reserve hits the cap');
@@ -154,6 +156,14 @@ test('paid used when armed + under BOTH caps + transport ok, and logs the spend'
assert.equal(map.get('a').source, 'typesafe');
});
+test('observability: getStats().paidCallsToday == the ledger count the cap enforces (no drift)', () => {
+ jev._resetForTest();
+ // Displayed stat is derived from the SAME ledger source the count-cap reads.
+ assert.equal(jev.getStats(() => nPaidLines(4)).paidCallsToday, 4, 'shows the true ledger count');
+ assert.equal(jev.getStats(() => '').paidCallsToday, 0, 'empty ledger -> 0');
+ assert.equal(jev.getStats(() => { throw new Error('x'); }).paidCallsToday, null, 'unreadable -> null (cap treats as at-cap)');
+});
+
test('classifyDots never throws on junk rows', async () => {
jev._resetForTest();
const map = await jev.classifyDots([null, {}, row('a', 'green', 'x'), { tty: '', color: 'green' }]);
← 1ab5eb8 dotbar/jev: price-independent daily call-COUNT cap as the re
·
back to Desktop Dotbar
·
auto-data-snapshot: 2026-09-23T13:13:50 (1 data files) — sta 60473d3 →