fix(notifications): wire the calibration/gate-outcomes/per-repo builders into the recap digest#8511
Conversation
…the digest The three section builders shipped fully implemented and unit-tested but were never composed into the delivered digest, and formatMaintainerRecap's per-repo body was a second, drifted inline copy of buildPerRepoRecapSection. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
runMaintainerRecap now assembles formatMaintainerRecap's options key-by-key, so the routingShadow present/absent arms are both changed lines. JSONbored#8229 shipped that path with no test producing a decision, and none covering the fail-safe null return. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
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 #8511 +/- ##
===========================================
+ Coverage 78.52% 89.61% +11.08%
===========================================
Files 791 98 -693
Lines 79348 22783 -56565
Branches 23969 3893 -20076
===========================================
- Hits 62307 20416 -41891
+ Misses 13869 2187 -11682
+ Partials 3172 180 -2992
Flags with carried forward coverage won't be shown. Click here to find out more.
|
|
Tip ✅ LoopOver review result - approve/merge recommendedReview updated: 2026-07-24 17:31:12 UTC
Review summary Nits — 3 non-blocking
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.
|
Fixes #8372
Re-file of #8465, which the bot closed for a base-branch conflict while it sat green —
#8229's routing-shadow work landed onformatMaintainerRecapin the meantime. This branch is cut from currentmain(4bfb322f) with that change merged in properly, not worked around.Root cause
buildCalibrationRecapSection,buildGateOutcomesRecapSection, andbuildPerRepoRecapSectionshipped fully implemented and unit-tested, but nothing in production called them —formatMaintainerRecapimported none of the three. The same "built, tested, never called" shape as #6636.formatMaintainerRecapinstead carried its own inline per-repo map — a second implementation that had drifted from the dedicated builder: no sorting, no cap, no "(+N more)" remainder, so a maintainer watching many repos got an unbounded, arbitrarily-ordered block.Separately,
runMaintainerRecaphad no way to pass a drift projection through, leavingformatMaintainerRecap'sconfigDriftoption (#8214) unreachable from the orchestrator.Fix approach
## Per-repokeeps its header and renders the builder's.linesthrough the existingrecapSectionLines/redactRecapLinepath; the inline map is deleted.## Calibrationand## Gate outcomesare unconditional rather than flag-gated — both builders read onlyreport.totals/report.windowDays, which everyRecapReportalways carries, so there is nothing to opt into.configDrift?: DriftRecapSectiontorunMaintainerRecap's options and forward it. Deliberately not sourced here — reading the sentinel state is its own data-sourcing concern. Plumbing only, so the section stays absent until a caller passes one.Merging with #8229. That change added a
routingShadowoption resolved on the same call. Rather than pick a side,runMaintainerRecapnow assembles the options object key-by-key:exactOptionalPropertyTypesforbids passing either key an explicitundefined, and the two are independent — a single ternary can't express all four combinations.Every added line goes through the existing redaction path; no new text reaches a channel unredacted.
Impact
## Per-repoempty state is now the builder's ownNo repo activity in the last N day(s)., and rows adoptrepo: reviewed N, merged N, closed N. The gate/override/reversal counts those rows carried are unchanged in## Totalsand now broken out by## Gate outcomes. Both tests gained assertions rather than losing them.Coverage note worth a reviewer's eye
Rewriting the options assembly made #8229's
routingShadowarms changed lines, so they now need coverage that never existed. I added both:reviewer_routing_shadowaudit row and asserts the section rendersenvthat throws only on the routing query, assertingloadRoutingRecapSection's fail-safenullleaves the rest of the digest intactChasing this corrected a misreading on my part:
loadRoutingRecapSectionreturns a section even with zero decisions, so the truthy arm was always taken; the genuinely uncovered path was the error return.Validation
npm run typecheck— clean;oxlintcleanmaintainer-recap*suites. The one failure (maintainer-recap-wire.test.ts, thealready_sent_this_perioddedup case) is identical on unmodified4bfb322f— I verified by checking out cleanupstream/mainand re-running. Not introduced here.src/services/maintainer-recap.ts: zero uncovered lines; the only uncovered branches (131, 136) are pre-existing and outside every hunk in this diffgit diff --check upstream/main HEAD— clean