Skip to content

fix(notifications): wire the calibration/gate-outcomes/per-repo builders into the recap digest#8465

Closed
kai392 wants to merge 1 commit into
JSONbored:mainfrom
kai392:fix/critical-issue-recap-sections-wiring
Closed

fix(notifications): wire the calibration/gate-outcomes/per-repo builders into the recap digest#8465
kai392 wants to merge 1 commit into
JSONbored:mainfrom
kai392:fix/critical-issue-recap-sections-wiring

Conversation

@kai392

@kai392 kai392 commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Fixes #8372

Root cause

buildCalibrationRecapSection, buildGateOutcomesRecapSection, and buildPerRepoRecapSection all shipped fully implemented and unit-tested, but nothing in production ever called them — formatMaintainerRecap imported none of the three. The same "built, tested, never called" shape as #6636.

formatMaintainerRecap instead carried its own inline per-repo map, a second implementation that had drifted from the dedicated builder: it did not sort, did not cap the list, and had no "(+N more)" remainder line, so a maintainer watching many repos got an unbounded, arbitrarily-ordered block.

Separately, runMaintainerRecap had no way to pass a drift projection through to formatMaintainerRecap, whose configDrift option (#8214) was therefore unreachable from the orchestrator.

Fix approach

  • Compose all three builders in formatMaintainerRecap. ## Per-repo keeps its header and renders the builder's .lines through the existing recapSectionLines/redactRecapLine path; the inline map is deleted.
  • ## Calibration and ## Gate outcomes are appended unconditionally rather than behind an options flag — both builders read only report.totals/report.windowDays, which every RecapReport always carries, so there is nothing for a caller to opt into.
  • Add configDrift?: DriftRecapSection to runMaintainerRecap's options and forward it. Deliberately not sourced here: reading the knob-loosening sentinel state is its own data-sourcing concern. This is plumbing only, so the section stays absent until a caller passes one and every existing digest is byte-identical.

Every added line goes through the existing redaction path — no new text reaches a channel unredacted.

Impact

  • Risk of regression is confined to the digest's rendered text; no data sourcing, delivery, or schema changes.

  • Two existing assertions describe output this issue asks to change, so I updated them rather than the source:

    • the ## Per-repo empty state is now the builder's own No repo activity in the last N day(s)., so the generic _No repositories…_ fallback no longer fires (the section is never empty);
    • per-repo rows adopt the builder's repo: reviewed N, merged N, closed N format. The gate/override/reversal counts the old inline row carried are unchanged in ## Totals and are now broken out per-dimension by ## Gate outcomes.

    Both tests gained assertions rather than losing them — the new section headers are asserted, and a new test covers the configDrift present arm end-to-end (returned string and delivered payload).

Risks

  • Digest layout changes for maintainers: two new sections, and per-repo rows are now sorted, capped, and reformatted. That is the issue's stated intent, and the capping is a strict improvement for many-repo accounts.
  • The configDrift forwarding is inert until a caller supplies a projection, so it cannot regress current output.

Validation

  • npm run typecheck — clean
  • 46/46 across all six maintainer-recap* suites, on a branch rebased onto current main (ac97dee9)
  • lcov scoped to src/services/maintainer-recap.ts: zero uncovered lines; the only uncovered branches (129, 134) are pre-existing and outside every hunk in this diff
  • oxlint clean on all three changed files

@kai392
kai392 requested a review from JSONbored as a code owner July 24, 2026 14:13
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

…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>
@codecov

codecov Bot commented Jul 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.60%. Comparing base (6c25eb6) to head (be60692).
⚠️ Report is 18 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8465      +/-   ##
==========================================
+ Coverage   79.69%   89.60%   +9.90%     
==========================================
  Files         791       98     -693     
  Lines       79319    22772   -56547     
  Branches    23954     3890   -20064     
==========================================
- Hits        63216    20405   -42811     
+ Misses      13298     2187   -11111     
+ Partials     2805      180    -2625     
Flag Coverage Δ
shard-1 72.72% <80.00%> (?)
shard-2 95.45% <100.00%> (+44.34%) ⬆️
shard-3 4.54% <0.00%> (-48.88%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/services/maintainer-recap.ts 96.96% <100.00%> (+0.09%) ⬆️

... and 693 files with indirect coverage changes

@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 24, 2026
@loopover-orb

loopover-orb Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Warning

⏸️ LoopOver review result - manual review recommended

Review updated: 2026-07-24 15:48:43 UTC

3 files · 1 AI reviewer · no blockers · CI green · dirty

⏸️ Suggested Action - Manual Review

Review summary
This PR wires three previously-orphaned recap-section builders (calibration, gate-outcomes, per-repo) into formatMaintainerRecap, replacing an inline per-repo map that lacked sorting/capping, and threads a configDrift option through runMaintainerRecap to the formatter. The change is well-scoped plumbing matching its stated intent, updates the two existing assertions whose expected output legitimately changes, and adds a real end-to-end test asserting the drift section reaches the actual delivered fetch payload, not just the returned string. All new content is routed through the existing redactRecapLine path per the diff, consistent with the stated no-new-unredacted-text claim.

Nits — 4 non-blocking
  • formatMaintainerRecap now unconditionally appends Calibration and Gate outcomes sections with no options flag to suppress them (src/services/maintainer-recap.ts formatMaintainerRecap) — reasonable given both builders only read always-present totals/windowDays, but worth a one-line confirmation in review that no caller relies on the old shorter digest shape.
  • The two call-arm workaround for configDrift (src/services/maintainer-recap.ts runMaintainerRecap) to dodge exactOptionalPropertyTypes is a bit verbose; a small local `options.configDrift ? { configDrift: options.configDrift } : {}` spread into a single call would read the same but the comment explaining why not is a reasonable trade-off as-is.
  • Consider whether the PR's issue linkage (fix(notifications): wire the maintainer-recap's calibration/gate-outcomes/per-repo section builders into the actual digest output #8372) should also be referenced in the CI/PR title metadata if not already enforced — not visible in this diff but worth confirming per repo convention.
  • No changes needed to maintainer-recap-wire.ts since it only calls runMaintainerRecap without configDrift, consistent with the 'plumbing-only, no data-sourcing' design goal stated in the description.

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #8372
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 135 registered-repo PR(s), 68 merged, 10 issue(s).
Contributor context ✅ Confirmed Gittensor contributor kai392; Gittensor profile; 135 PR(s), 10 issue(s).
Improvement ✅ Minor risk: clean · value: minor
Linked issue satisfaction

Addressed
The diff wires buildPerRepoRecapSection, buildCalibrationRecapSection, and buildGateOutcomesRecapSection into formatMaintainerRecap in the required order, and adds a configDrift option to runMaintainerRecap that forwards to formatMaintainerRecap as specified, matching all five numbered requirements including the code comment noting the wire.ts caller doesn't yet supply drift data.

Review context
  • Author: kai392
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: not available
  • Official Gittensor activity: 135 PR(s), 10 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Triage stale or unlinked PRs.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask 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.

  • @loopover ask &lt;question&gt; answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat &lt;question&gt; answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

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.

  • Re-run LoopOver review

@loopover-orb loopover-orb Bot added the manual-review Gittensor contributor context label Jul 24, 2026
@loopover-orb

loopover-orb Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

LoopOver 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. manual-review Gittensor contributor context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(notifications): wire the maintainer-recap's calibration/gate-outcomes/per-repo section builders into the actual digest output

2 participants