Coverage floors, budget/persistence tests, and a paid-response loss fix - #188
Merged
Merged
Conversation
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
# Conflicts: # docs/WORKLOG.md
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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-policynow sumscoverage/coverage-final.jsonwithistanbul-lib-coverage, the library behind Vitest's own summary; its totals match theAll filesrow exactly. It fails when a global floor is missed.thresholdsstill take only per-file entries, becauseperFile: truewould apply a global floor to every file. The guard invitest.config.tsthat rejected positive global floors is removed.docs/infrastructure/COVERAGE-BASELINE.mdand a CORE-013 amendment.2. Fix: a failed OpenRouter price lookup discarded paid translations
calculateCostruns after a paid call and documents that it must not throw. For an uncached OpenRouter model, though, a failed catalog refresh propagated.claudeService) then dropped the finished translation. The failure now falls through to the existing $0 post-hoc path.3. Tests where the risk is
tests/services/ai/cost.test.tsruns the realhasKnownPricingbudget-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.tsrunsTranslationOps→ facade → repository → fake IndexedDB. It checks that:settingsSnapshot(verified by mutation: the test fails if narrowing is removed);stableId://fallback keeps a translation whose URL cannot be resolved.promisifyCursor,batchOperationanddebugTransactionfromtxn.ts.promisifyCursoralso awaited beforecursor.continue(), which lets IndexedDB auto-commit the transaction.services/ai/cost.tsL95/F100 (was 68% lines, now 100%),services/db/core/txn.tsL95/F100 (21% → 100%) andservices/db/operations/translations.tsL75/F100 (22% → 78%).Verification
Run on this branch after merging current
main(#186 and #187), in a Node 22 container:tsc: passeslint: 0 errorsvite build: passverify:integrity: passvitest --coverage: 9,597 passed, 1 failed. The failure is the known Node-22-onlyindrasNetImageProvider.test.tscase, which passes on Node 24 per the De-sprawl: retire Sutta Studio shims, single Gemini SDK, delete dead code #186 review.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