Context
src/db/retention.ts's pruneExpiredRecords has two defensive ?? 0 fallback arms guarding against
D1 driver anomalies:
- Line 75:
results.push({ ..., deleted: Number(row?.n ?? 0) }); (dry-run count path)
- Line 85:
const changes = Number(result.meta?.changes ?? 0); (actual delete-loop path)
Neither arm has any direct test coverage in test/unit/retention.test.ts today.
The exact same defensive pattern exists on this file's sibling function, dedupeSignalSnapshots
(lines 151 and 161), and that sibling's two equivalent ?? 0 arms do have dedicated tests —
test/unit/retention.test.ts lines 236-264, explicitly titled around a "defensive ?? 0 arm" mocking
env.DB to return a row/meta shape that triggers the fallback.
This repo's Codecov patch gate is 99%+ of changed lines and branches — these two untested nullish-
coalescing branches in pruneExpiredRecords are exactly the kind of gap the gate is meant to catch,
and the fix pattern is already fully precedented in the same file for the sibling function.
Requirements
- Add tests for
pruneExpiredRecords's two ?? 0 fallback arms (lines 75 and 85), following the
exact same mocking approach dedupeSignalSnapshots's existing tests (lines 236-264) already use for
the identical pattern — mock env.DB to return a row/meta shape where the relevant field is
missing/null/undefined, and assert the function falls back to 0 rather than throwing or producing
NaN.
- Do not modify
pruneExpiredRecords's actual logic — this issue is scoped to adding missing test
coverage for existing, already-correct defensive code.
Deliverables
Test Coverage Requirements
This repo's Codecov patch gate is 99%+ of changed lines and branches (src/** is covered). Since this
issue is pure test-addition (no production code changes), the deliverable is the coverage: both
previously-uncovered ?? 0 branches in pruneExpiredRecords must show as covered after this PR.
Expected Outcome
pruneExpiredRecords's two defensive fallback arms have the same direct test coverage its sibling
dedupeSignalSnapshots already has for the identical pattern, closing a Codecov branch gap with no
production-code risk.
Links & Resources
src/db/retention.ts:75,85 — the two branches to cover
src/db/retention.ts:151,161 — dedupeSignalSnapshots's identical pattern
test/unit/retention.test.ts:236-264 — the existing tests to mirror
Context
src/db/retention.ts'spruneExpiredRecordshas two defensive?? 0fallback arms guarding againstD1 driver anomalies:
results.push({ ..., deleted: Number(row?.n ?? 0) });(dry-run count path)const changes = Number(result.meta?.changes ?? 0);(actual delete-loop path)Neither arm has any direct test coverage in
test/unit/retention.test.tstoday.The exact same defensive pattern exists on this file's sibling function,
dedupeSignalSnapshots(lines 151 and 161), and that sibling's two equivalent
?? 0arms do have dedicated tests —test/unit/retention.test.tslines 236-264, explicitly titled around a "defensive?? 0arm" mockingenv.DBto return a row/meta shape that triggers the fallback.This repo's Codecov patch gate is 99%+ of changed lines and branches — these two untested nullish-
coalescing branches in
pruneExpiredRecordsare exactly the kind of gap the gate is meant to catch,and the fix pattern is already fully precedented in the same file for the sibling function.
Requirements
pruneExpiredRecords's two?? 0fallback arms (lines 75 and 85), following theexact same mocking approach
dedupeSignalSnapshots's existing tests (lines 236-264) already use forthe identical pattern — mock
env.DBto return a row/metashape where the relevant field ismissing/null/undefined, and assert the function falls back to
0rather than throwing or producingNaN.pruneExpiredRecords's actual logic — this issue is scoped to adding missing testcoverage for existing, already-correct defensive code.
Deliverables
test/unit/retention.test.tscoveringpruneExpiredRecords's dry-runrow?.n ?? 0fallback (line 75), mirroringdedupeSignalSnapshots's existing equivalent test.pruneExpiredRecords's delete-loopresult.meta?.changes ?? 0fallback (line 85), mirroring
dedupeSignalSnapshots's existing equivalent test.Test Coverage Requirements
This repo's Codecov patch gate is 99%+ of changed lines and branches (
src/**is covered). Since thisissue is pure test-addition (no production code changes), the deliverable is the coverage: both
previously-uncovered
?? 0branches inpruneExpiredRecordsmust show as covered after this PR.Expected Outcome
pruneExpiredRecords's two defensive fallback arms have the same direct test coverage its siblingdedupeSignalSnapshotsalready has for the identical pattern, closing a Codecov branch gap with noproduction-code risk.
Links & Resources
src/db/retention.ts:75,85— the two branches to coversrc/db/retention.ts:151,161—dedupeSignalSnapshots's identical patterntest/unit/retention.test.ts:236-264— the existing tests to mirror