test(retention): cover pruneExpiredRecords's two defensive ?? 0 arms - #8489
test(retention): cover pruneExpiredRecords's two defensive ?? 0 arms#8489kai392 wants to merge 1 commit into
Conversation
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
The dry-run `row?.n ?? 0` and delete-loop `result.meta?.changes ?? 0` guards had no direct coverage, unlike the identical pattern on the sibling dedupeSignalSnapshots, whose arms are already tested in this file. Test-only: pruneExpiredRecords's logic is unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Caution 🛑 LoopOver review result - fixes requiredReview updated: 2026-07-24 15:39:37 UTC
Review summary Nits — 3 non-blocking
CI checks failing
Decision drivers
Context & advisory signals — never blocks the verdict
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://loopover.ai/docs/loopover-commands 🧪 Experimental — new and may change. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.
|
|
LoopOver is closing this pull request on the maintainer's behalf (CI is failing (validate, validate-tests-merge)). This is an automated maintenance action — to pursue this change, please open a new pull request with the issues resolved. Closed PRs may be analyzed later to improve review accuracy, but they are not automatically reopened or re-reviewed. |
Fixes #8370
Root cause
pruneExpiredRecordsinsrc/db/retention.tshas two defensive?? 0guards against a D1 driver returning an unexpected shape:deleted: Number(row?.n ?? 0)const changes = Number(result.meta?.changes ?? 0)Neither had direct coverage. The identical pattern on this file's sibling
dedupeSignalSnapshotsis already tested, so this was a gap in one of two twins rather than an untested idea.Fix approach
Test-only —
pruneExpiredRecords's logic is untouched, per the issue's explicit scope.Four tests mirroring
dedupeSignalSnapshots's existing approach: a hand-builtenv.DBwhoseprepare().bind()returns the degenerate shape, and a single-rulepolicyso exactly one table is walked. Each arm gets both of its failure shapes, because they reach the fallback differently:row?.n ?? 0first()→undefined(no row)first()→{ n: null }meta?.changes ?? 0run()→{}(no meta)run()→{ meta: { changes: null } }The split matters: the optional-chain and the
??are separate branches, and only the absent shape exercises the optional-chain arm. The null-valued cases also assertNumber.isNaN(...) === false, which is the guard's actual purpose —Number(null)is0butNumber(undefined)isNaN, so an unguarded read would putNaNinto the returneddeletedcount.Impact / risks
src/**lines in the diff, so this carries no Codecov patch percentage; the coverage it adds to the two existing branches is the whole deliverable.Validation
row?.n ?? 0) and line 88 (meta?.changes ?? 0) each report both branch paths taken. Measured with the other 18 tests in the file skipped, so the coverage comes from these four tests directly rather than incidentally from the D1-backed tests.npm run typecheck— clean;oxlint— clean.main(9b9924b3).One note for the reviewer: 16 pre-existing tests in this file fail on my local win32 checkout with
ERR_SQLITE_ERROR: column index out of rangefrom thetest/helpers/d1.tsshim. That count is identical on unmodifiedmain— I verified by stashing this change — and my four tests use plain mocks with no D1 involvement, so they pass regardless. Flagging it only so the local-vs-CI difference isn't mistaken for something this PR introduced.