Skip to content

Coverage floors, budget/persistence tests, and a paid-response loss fix - #188

Merged
anantham merged 5 commits into
mainfrom
claude/coverage-ratchet
Sep 24, 2026
Merged

anantham merged 5 commits into
mainfrom
claude/coverage-ratchet

Conversation

@anantham

Copy link
Copy Markdown
Owner

Owner-approved coverage work: lock in today's coverage level, then test the code where a bug costs money or data.

Changes

1. Whole-surface coverage floors (CORE-013 amendment)

  • verify:coverage-policy now sums coverage/coverage-final.json with istanbul-lib-coverage, the library behind Vitest's own summary; its totals match the All files row exactly. It fails when a global floor is missed.
  • Vitest thresholds still take only per-file entries, because perFile: true would apply a global floor to every file. The guard in vitest.config.ts that rejected positive global floors is removed.
  • Floors: lines 60, statements 59, functions 59, branches 47, from the measured baseline rounded down. Recorded in docs/infrastructure/COVERAGE-BASELINE.md and a CORE-013 amendment.
  • Validator tests cover pass, miss, an empty total, an unknown metric and an out-of-range value.

2. Fix: a failed OpenRouter price lookup discarded paid translations

  • calculateCost runs after a paid call and documents that it must not throw. For an uncached OpenRouter model, though, a failed catalog refresh propagated.
  • The unguarded translation paths (the OpenAI/OpenRouter adapter, Gemini translate and claudeService) then dropped the finished translation. The failure now falls through to the existing $0 post-hoc path.
  • The regression test failed before the fix.

3. Tests where the risk is

  • tests/services/ai/cost.test.ts runs the real hasKnownPricing budget-gate logic, which other suites only mock. It fails closed on missing or non-numeric prices and on a failed refresh, and accepts free models. It also covers OpenRouter refresh-once and date-suffix fallback.
  • tests/services/db/translationOps.integration.test.ts runs TranslationOps → facade → repository → fake IndexedDB. It checks that:
    • no API key reaches a persisted settingsSnapshot (verified by mutation: the test fails if narrowing is removed);
    • each retranslation gets the next version, with exactly one active;
    • active switching and deletion work;
    • the stableId:// fallback keeps a translation whose URL cannot be resolved.
  • The existing date-suffix cost test never exercised the fallback (its model had its own dated entry); it now does.
  • Deleted the unused promisifyCursor, batchOperation and debugTransaction from txn.ts. promisifyCursor also awaited before cursor.continue(), which lets IndexedDB auto-commit the transaction.
  • Per-file floors: services/ai/cost.ts L95/F100 (was 68% lines, now 100%), services/db/core/txn.ts L95/F100 (21% → 100%) and services/db/operations/translations.ts L75/F100 (22% → 78%).

Verification

Run on this branch after merging current main (#186 and #187), in a Node 22 container:

  • tsc: pass
  • eslint: 0 errors
  • vite build: pass
  • verify:integrity: pass
  • vitest --coverage: 9,597 passed, 1 failed. The failure is the known Node-22-only indrasNetImageProvider.test.ts case, which passes on Node 24 per the De-sprawl: retire Sutta Studio shims, single Gemini SDK, delete dead code #186 review.
  • Coverage: lines 61.05, statements 59.50, functions 59.58, branches 47.92. There are no threshold errors, and the validator passes all floors.

Audit HIGH 2 (commit-time write durability) and MEDIUM 9 (export API-key leak) were already fixed and tested; this PR doesn't touch them.

🤖 Generated with Claude Code

https://claude.ai/code/session_011d1MbSabs9nA9d9w8pxP1W


Generated by Claude Code

verify:coverage-policy now sums the measured coverage-final.json with
istanbul-lib-coverage (the library behind Vitest's summary; totals match the
'All files' row) and fails when any global floor is missed. Vitest thresholds
still take only per-file entries, since perFile:true would apply a global
floor to every file.

Floors are the measured main baseline rounded down: lines 60, statements 58,
functions 59, branches 47. Recorded in COVERAGE-BASELINE.md and a CORE-013
amendment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011d1MbSabs9nA9d9w8pxP1W
…up fails

calculateCost runs after a paid call and documents that it must not throw,
but an uncached OpenRouter model triggered a catalog refresh whose failure
propagated. The unguarded translation paths (OpenAI/OpenRouter adapter,
Gemini translate, claudeService) then dropped the finished translation. The
lookup failure now falls through to the existing $0 post-hoc path.

Adds tests for the real hasKnownPricing budget-gate logic (other suites only
mock it) and makes the date-suffix test hit the fallback: its old model had
its own dated entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011d1MbSabs9nA9d9w8pxP1W
promisifyCursor, batchOperation and debugTransaction had no callers.
promisifyCursor was also unsafe: it awaited the processor before
cursor.continue(), which lets IndexedDB auto-commit the transaction.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011d1MbSabs9nA9d9w8pxP1W
Other suites mock TranslationOps, the single translation write path. The new
suite runs ops -> facade -> repository -> IndexedDB and locks in: no API key
ever reaches a persisted settingsSnapshot, retranslations get the next
version with exactly one active, active switching, deletion, and the
stableId:// fallback that keeps a translation whose URL cannot be resolved.

Per-file floors: cost.ts L95/F100, txn.ts L95/F100,
operations/translations.ts L75/F100. Global statements floor 58 -> 59.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011d1MbSabs9nA9d9w8pxP1W
@vercel

vercel Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
lexicon-forge Ready Ready Preview Sep 24, 2026 6:56pm UTC

@anantham
anantham merged commit 1ce6d55 into main Sep 24, 2026
7 checks passed

This branch was successfully deployed

1 active deployment
Preview — 629f7934 Deployed Sep 24, 2026 by vercel[bot]
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.

2 participants