Skip to content

feat(calibration): config-drift section in the maintainer recap (#8214)#8257

Closed
cleanjunc wants to merge 1 commit into
JSONbored:mainfrom
cleanjunc:feat/8214-config-drift-recap-section
Closed

feat(calibration): config-drift section in the maintainer recap (#8214)#8257
cleanjunc wants to merge 1 commit into
JSONbored:mainfrom
cleanjunc:feat/8214-config-drift-recap-section

Conversation

@cleanjunc

Copy link
Copy Markdown
Contributor

Summary

Adds the config-drift section to the maintainer recap (epic #8211 track A): drift alerts are point-in-time, but the recap's calibration section is where a STANDING drift episode should be impossible to miss — today it knows nothing about drift.

  • src/services/maintainer-recap-config-drift.ts — a pure section builder mirroring buildCalibrationRecapSection (src/services/maintainer-recap-calibration.ts) exactly: a plain source struct in, a titled { title, counts, note, lines } section out, with the same private sanitizeRecapText scrub. Each drifting knob renders its direction reading (shipped → "drifted override should revert", tighter → actionable stale-config warning, looser → informational duplicate of the loosening loop — mirroring KnobDriftReport.direction's own consumer guidance at src/services/loosening-knobs.ts:143), live vs dominating value, both corpus sizes, and how long the episode has stood (fingerprint timestamp → generatedAt, with explicit unknown-age and clock-skew-clamp arms). Clean knobs collapse into one summary line. The sentinel-flag-off state renders the mandated explicit drift sentinel disabled line, so absence of data is never mistaken for absence of drift; enabled-but-no-knobs is its own distinguishable state.
  • Public-safe by construction: the per-knob projection carries aggregate numbers + knob ids only — the report's per-split BacktestComparison payloads and ruleId are structurally excluded, and an invariant test feeds a FULL KnobDriftReport (structurally compatible with the projection) and asserts none of its corpus-side content can surface.
  • Recap assembly wiring behind the existing plumbing (no new scheduling): RecapReport carries an optional configDrift section (mirroring the cohorts optional-field convention), buildMaintainerRecap builds it only when a drift source is supplied, formatMaintainerRecap renders ## Config drift with the explicit disabled fallback when no source was supplied, and runMaintainerRecap threads a source through its options for the sentinel's plumbing (calibration: nightly config-drift sentinel — cron wire + one-shot stale-config alert #8213) to hand in real reports.

Closes #8214

Scope

  • The PR title follows type(scope): short summary Conventional Commit format, for example fix(api): restore profile access checks.
  • This PR is focused and does not mix unrelated backend, UI, MCP, docs, dependency, and deploy changes.
  • This follows CONTRIBUTING.md and does not reintroduce GitHub Pages, VitePress, site/, or CNAME.
  • I linked a currently open issue this PR resolves (e.g. Closes #123) — a linked open issue is required for every contributor PR.

Validation

  • git diff --check
  • npm run actionlint
  • npm run typecheck
  • npm run test:coverage locally; codecov/patch requires ≥99% coverage of the lines AND branches you changed (aim for 100% on your diff so CI variance does not fail near the threshold). Global coverage is a non-blocking trend with a loose 90% backstop, not the gate.
  • npm run test:workers
  • npm run build:mcp
  • npm run test:mcp-pack
  • npm run ui:openapi:check
  • npm run ui:lint
  • npm run ui:typecheck
  • npm run ui:build
  • npm audit --audit-level=moderate
  • New or changed behavior has unit/integration tests for new branches, fallback paths, and sanitizer boundaries

If any required check was skipped, explain why:

  • Instead of the full unsharded test:coverage, I ran every touched suite (maintainer-recap-config-drift, maintainer-recap-format, maintainer-recap, maintainer-recap-calibration, maintainer-recap-wire — 66 tests, all green) with V8 coverage and measured the patch empirically: intersecting coverage/lcov.info DA/BRDA records (max-merged per line/arm) with git diff -U0's new-side line numbers reports 0 uncovered lines and 0 uncovered branch arms across all 27 instrumented changed lines (src/types.ts's additions are type-only). Every builder arm is exercised: disabled / no-knobs / all-clean / mixed / all-drifting, all three direction readings, unknown-age + clock-skew + sub-day + multi-day episode arms, and both formatter arms (populated section vs disabled fallback).
  • actionlint / workers / MCP / UI checks: no workflow, worker, MCP, or UI file is touched — this diff is two src/services files, a type addition, and unit tests. RecapReport is not part of the public OpenAPI surface (no route serves it), so no ui:openapi regeneration applies. Real CI re-runs the full chain regardless.

Safety

  • No secrets, wallet details, hotkeys, coldkeys, user PATs, private keys, raw trust scores, private rankings, or private maintainer evidence are exposed.
  • Public GitHub text stays sanitized, low-noise, and does not imply compensation guarantees or optimization tactics.
  • Auth, cookie, CORS, GitHub App, Cloudflare, or session changes include negative-path tests.
  • API/OpenAPI/MCP behavior is updated and tested where needed.
  • UI changes use live API data or real empty/error/loading states, not production mock/demo fallbacks.
  • Visible UI changes include a UI Evidence section below with JPG/JPEG or PNG screenshots arranged as organized, captioned, clickable thumbnails. SVG screenshots are not used as review evidence. Review-only screenshots or recordings are not committed to the repository.
  • Public docs/changelogs are updated where needed; changelogs are only edited for release-prep PRs.

UI Evidence

No visible UI, frontend, docs, or extension change — this PR touches src/services/**, src/types.ts, and test/unit/** only.

Notes

…bored#8214)

Drift alerts are point-in-time; the weekly maintainer recap is where a
standing drift episode should be impossible to miss. Add the config-drift
content slice of the recap digest (epic JSONbored#8211 track A):

- src/services/maintainer-recap-config-drift.ts: pure section builder
  mirroring buildCalibrationRecapSection — a plain source struct in
  (per-knob KnobDriftReport projections, the shape evaluateKnobDrift
  already computes), a titled section out. Renders each drifting knob
  with direction reading (shipped/tighter/looser per the report's own
  consumer guidance), live vs dominating value, both corpus sizes, and
  episode standing time from the sentinel's fingerprint timestamp;
  clean knobs collapse into one summary line. The sentinel-flag-off
  state renders an explicit 'drift sentinel disabled' line so absence
  of data is never mistaken for absence of drift. The projection
  deliberately excludes the report's per-split BacktestComparisons, so
  corpus content structurally cannot reach the digest.
- Recap assembly wiring behind the existing plumbing (no new
  scheduling): RecapReport carries an optional configDrift section,
  buildMaintainerRecap builds it only when a drift source is supplied
  (mirroring the cohorts convention), formatMaintainerRecap renders the
  section with the explicit disabled fallback when no source was
  supplied, and runMaintainerRecap threads a source through for the
  sentinel's plumbing (JSONbored#8213) to use.

Tests: every builder arm (disabled / no-knobs / all-clean / mixed /
all-drifting, all three direction readings, unknown-age + clock-skew +
sub-day + multi-day episode arms), the structural-compatibility
invariant that a FULL KnobDriftReport renders aggregates + ids only,
sanitizer scrub + line-cap, both formatter arms, and the build/run
wiring arms.
@cleanjunc
cleanjunc requested a review from JSONbored as a code owner July 23, 2026 15:22
@superagent-security

Copy link
Copy Markdown
Contributor

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

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

loopover-orb Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Caution

🛑 LoopOver review result - reject/close recommended

Review updated: 2026-07-23 15:30:45 UTC

6 files · 1 AI reviewer · 2 blockers · CI pending · dirty

🛑 Suggested Action - Reject/Close

Review summary
The AI review returned blocking findings for this change but did not include a separate narrative summary. Review the blockers below before deciding this PR.

Blockers

  • src/services/maintainer-recap-config-drift.ts duplicates the existing, more type-faithful `src/services/maintainer-recap-drift.ts` (`buildDriftRecapSection`/`DriftRecapSource`, built against the real `KnobDriftReport` type) instead of reusing or replacing it — you now have two competing config-drift section builders with different shapes, and it's unclear which one the sentinel (calibration: nightly config-drift sentinel — cron wire + one-shot stale-config alert #8213) is meant to feed; this needs a stated reason for the parallel implementation or a consolidation before merge.
Nits — 5 non-blocking
  • src/services/maintainer-recap-config-drift.ts:40 and :52 use bare magic numbers (`8214` in comments is fine, but the 240-char cap at line 52 duplicates the same literal already hardcoded in maintainer-recap.ts's `sanitizeRecapText` — consider a shared constant).
  • src/services/maintainer-recap-config-drift.ts:110 nests the `if (!source.sentinelEnabled)` early-return followed by ternary/note branching to depth 5 per the external brief; a small early-return refactor would flatten it.
  • The existing `maintainer-recap-drift.ts` renders `report.ruleId` directly into its line — if that file is ever wired instead of/alongside this one, that's a public-safety leak worth flagging separately from this PR.
  • Confirm with the epic owner whether `maintainer-recap-drift.ts` is dead code that should be deleted in this PR, or whether this new file should instead extend/reuse its `KnobDriftReport`-based projection so the sentinel (calibration: nightly config-drift sentinel — cron wire + one-shot stale-config alert #8213) has one canonical section builder to wire against.
  • Consider extracting the shared 240-char sanitizer cap into one exported constant reused by both `maintainer-recap.ts` and `maintainer-recap-config-drift.ts` to avoid drift between the two files' scrub behavior.

Why this is blocked

  • src/services/maintainer-recap-config-drift.ts duplicates the existing, more type-faithful `src/services/maintainer-recap-drift.ts` (`buildDriftRecapSection`/`DriftRecapSource`, built against the real `KnobDriftReport` type) instead of reusing or replacing it — you now have two competing config-drift section builders with different shapes, and it's unclear which one the sentinel (calibration: nightly config-drift sentinel — cron wire + one-shot stale-config alert #8213) is meant to feed; this needs a stated reason for the parallel implementation or a consolidation before merge.
  • No linked issue detected: The PR cites an issue number, but it could not be verified as a currently open issue. — If this PR is intended to solve an issue, link it explicitly in the PR body.
📋 Copy for AI agents — paste into your coding agent
Fix the following blocker(s) from this PR review:

1. src/services/maintainer-recap-config-drift.ts duplicates the existing, more type-faithful \`src/services/maintainer-recap-drift.ts\` \(\`buildDriftRecapSection\`/\`DriftRecapSource\`, built against the real \`KnobDriftReport\` type\) instead of reusing or replacing it — you now have two competing config-drift section builders with different shapes, and it's unclear which one the sentinel \(\#8213\) is meant to feed; this needs a stated reason for the parallel implementation or a consolidation before merge.

2. No linked issue detected: The PR cites an issue number, but it could not be verified as a currently open issue. — If this PR is intended to solve an issue, link it explicitly in the PR body.

Decision drivers

  • ❌ Code review — 2 blockers (1 reviewer)
  • ❌ Gate result — Blocking (Repo-configured hard blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #8214
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: 53 registered-repo PR(s), 22 merged, 36 issue(s).
Contributor context ✅ Confirmed Gittensor contributor cleanjunc; Gittensor profile; 53 PR(s), 36 issue(s).
Improvement ✅ Minor risk: clean · value: minor
Linked issue satisfaction

Addressed
The PR adds a pure buildConfigDriftRecapSection mirroring buildCalibrationRecapSection's pattern, rendering clean-knob summary lines, per-knob direction/values/corpus-sizes/episode-standing-time, and an explicit 'drift sentinel disabled' empty-state line, then wires it into RecapReport/buildMaintainerRecap/formatMaintainerRecap without new scheduling, matching the issue's requirements and delivera

Review context
  • Author: cleanjunc
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Python, TypeScript, JavaScript, Scala
  • Official Gittensor activity: 53 PR(s), 36 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Keep the PR focused and include validation evidence before maintainer review.
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 <question> answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat <question> 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 commented Jul 23, 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; No linked issue detected; AI reviewers agree on a likely critical defect: src/services/maintainer-recap-config-drift.ts duplicates the existing, more type-faithful `src/services/maintainer-recap-drift.ts` (`buildDriftRecapSection`/`DriftRecapSource`, built against the real `KnobDriftReport` type) instead of reusing or replacing it — you now have two competing config-drift section builders with different shapes, and it's unclear which one the sentinel (#8213) is meant to feed; this needs a stated reason for the parallel implementation or a consolidation before 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.

@loopover-orb loopover-orb Bot closed this Jul 23, 2026
@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.61%. Comparing base (3494297) to head (56a91c9).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8257      +/-   ##
==========================================
- Coverage   92.14%   89.61%   -2.53%     
==========================================
  Files         784      100     -684     
  Lines       78694    22798   -55896     
  Branches    23752     3899   -19853     
==========================================
- Hits        72510    20431   -52079     
+ Misses       5062     2187    -2875     
+ Partials     1122      180     -942     
Flag Coverage Δ
shard-1 53.26% <10.00%> (-5.60%) ⬇️
shard-2 86.95% <66.66%> (+33.73%) ⬆️
shard-3 32.60% <86.66%> (-15.49%) ⬇️

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

Files with missing lines Coverage Δ
src/services/maintainer-recap-config-drift.ts 100.00% <100.00%> (ø)
src/services/maintainer-recap.ts 96.92% <100.00%> (+0.14%) ⬆️
src/types.ts 100.00% <ø> (ø)

... and 685 files with indirect coverage changes

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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

calibration: config-drift section in the maintainer recap

1 participant