feat(notifications): idempotent per-period recap claim + generation audit trail - #4459
Conversation
…udit trail Adds a per-UTC-date claim (migration 0129, mirroring claimRegateFanoutSlot's atomic conditional-UPDATE pattern) so a retried cron tick or redelivered queue message never re-scans repos or re-sends the maintainer recap digest for a period already sent. Also records a maintainer_recap_generated audit event once the report is built, giving operators a ledger trail independent of the per-channel delivery-outcome event.
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4459 +/- ##
=======================================
Coverage 94.01% 94.01%
=======================================
Files 418 418
Lines 37417 37427 +10
Branches 13677 13678 +1
=======================================
+ Hits 35178 35188 +10
Misses 1583 1583
Partials 656 656
🚀 New features to boost your workflow:
|
|
Warning 🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨 ⏸️ Gittensory review result - manual review recommendedReview updated: 2026-07-09 20:04:13 UTC
⏸️ Suggested Action - Manual Review
Review summary Nits — 1 non-blocking
Linked issue satisfactionPartially addressed Review context
Contributor next steps
Signal definitions
🟩 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 Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
|
Gittensory is closing this pull request on the maintainer's behalf (conflicts with the base branch — resolve and open a fresh PR). 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. |
Summary
claimMaintainerRecapPeriod(src/db/repositories.ts) performs an atomic conditionalUPDATEon theglobal_agent_controlssingleton, mirroring the exact proven patternclaimRegateFanoutSlotalready uses for the re-gate sweep's own fan-out dedup (migration 0063) — D1 serializes writes, so only the first invocation for a given period (YYYY-MM-DD, UTC) matches the "unset or a different period" predicate; a retry for the same period gets 0 changes and short-circuits before any repo scan or Discord send. Fail-open on a driver error, matchingclaimRegateFanoutSlot's own philosophy (a DB hiccup must never silently stop the digest from ever sending).migrations/0129_maintainer_recap_claim.sql(ALTER TABLE global_agent_controls ADD COLUMN last_recap_period_key TEXT— nullable, no default, backward-compatible).isRecapEnabled— was already completed in feat(notifications): schedule the maintainer recap job on a configurable cadence #4418 (thegenerate-maintainer-recapjob type + case already exist). This PR adds only the missing idempotency piece.maintainer_recap_generatedaudit event once the report is built, mirroringgenerateWeeklyValueReport's ownrecordAuditEventcall (weekly-value-report.ts:72). Metadata:cadence(resolved the same wayshouldFireMaintainerRecapdoes — a present config-as-code override wins, else the env knob),windowDays,repoCount,sectionCount,channelsAttempted.deliverRecapToDiscord's own existingmaintainer_recap_notification.discordaudit event. This PR adds only the missing generation-level event.Scope
type(scope): short summaryConventional Commit format.runMaintainerRecapJoborchestrator, both "Part of Maintainer review recap digest (Discord / Slack) #1963") rather than splitting into two PRs that would each touch the exact same lines.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Closes #2249,Closes #2251.Validation
git diff --checknpm run actionlintnpm run db:migrations:check— contiguous, next free 0130npm run db:schema-drift:check—global_agent_controlsstays raw-SQL-only (allowlisted), no Drizzle driftnpm run typechecknpm run test:coveragelocally — 100% branch coverage on every changed line, verified directly againstlcov.infofor every touched file (src/db/repositories.ts,src/review/maintainer-recap-wire.ts,src/queue/processors.ts)npm run test:workersnpm run build:mcpnpm run test:mcp-packnpm run ui:openapi:checknpm run ui:lintnpm run ui:typechecknpm run ui:buildnpm audit --audit-level=moderate— 0 vulnerabilitiesnpm run test:cigreen (652 test files / 12,769 tests)Test coverage added:
test/unit/db-parsers.test.ts:claimMaintainerRecapPeriod— first claim for a period wins, a retry for the same period loses, a different period wins again; fails open (returnstrue) on a DB error.test/unit/maintainer-recap-wire.test.ts: a retried tick within the same UTC date is a no-op (no repo scan, no second Discord post — verified via the stubbed fetch call count); a tick on a different UTC date gets its own fresh claim and sends again; themaintainer_recap_generatedaudit event's full metadata shape on success; a present manifest cadence override is reflected in the audit metadata over the env value.Safety
UI Evidencesection. (N/A — no visible UI changes; backend-only.)UI Evidence
N/A — backend-only change (D1 migration + queue orchestrator), no UI surface touched.
Notes