feat(ui): add AMS-vs-human contributor-mix maintainer dashboard panel#6590
Conversation
Adds a maintainer-only panel comparing identifiable AMS miners against a repo's other contributors on acceptance rate, review-cycle count, time-to-merge, and PR volume, per JSONbored#6210's decided design. Membership ("has AMS track-record data") is resolved via the existing ORB/AMS reputation bridge's pull path (fetchAmsTrackRecord); the per-repo metrics reuse submitter-reputation.ts's existing review_targets classification via a new grouped-by-submitter aggregate query. Live lookups are capped at the repo's 25 most active submitters (AMS_MINER_COHORT_CHECK_CAP) to bound per-dashboard-load network fan-out -- every unchecked submitter defaults to the human cohort rather than being assumed AMS, and the response discloses checkedSubmitterCount/totalSubmitterCount so a caller never reads a capped result as exhaustive. New GET /v1/repos/:owner/:repo/ams-miner-cohort route, maintainer-gated identically to the existing maintainer-noise route. present: false (never an error) when the AMS bridge is off, unconfigured, or the repo has no submitter activity in the window -- the panel's required empty state. Closes JSONbored#6488
|
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 #6590 +/- ##
=======================================
Coverage 93.64% 93.64%
=======================================
Files 678 679 +1
Lines 67964 68011 +47
Branches 18678 18687 +9
=======================================
+ Hits 63642 63689 +47
Misses 3347 3347
Partials 975 975
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-16 16:30:06 UTC
Review summary Nits — 5 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. Visual preview
Click any thumbnail to open the full-size screenshot. Before = production · After = this PR's preview deploy. 🟩 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.
|



Summary
Per #6210's decided design: a maintainer-only dashboard panel comparing identifiable AMS miners
against a repo's other contributors on acceptance rate, review-cycle count, time-to-merge, and PR
volume.
src/review/ams-miner-cohort.ts, new): classifies a repo's recent submitters into anAMS cohort vs. a human cohort and computes the four required metrics per cohort. Membership ("has
AMS track-record data") reuses the existing ORB/AMS reputation bridge's pull path
(
fetchAmsTrackRecord, Implement upgrade-only ORB/AMS reputation bridge (pull, GitHub-login-keyed) #6485); the metrics reusesubmitter-reputation.ts's existingreview_targetsoutcome classification via a newlistSubmitterCohortRowsgrouped-by-submitteraggregate query, rather than re-deriving anything.
(there's no cached "is this an AMS miner" flag anywhere). To bound per-dashboard-load network
fan-out, only the repo's
AMS_MINER_COHORT_CHECK_CAP(25) most active submitters get a live check;every unchecked submitter defaults to the human cohort (never assumed AMS — same conservative-default
discipline as the bridge's own upgrade-only rule). The response discloses
checkedSubmitterCount/totalSubmitterCountso a caller never reads a capped result as exhaustive.GET /v1/repos/:owner/:repo/ams-miner-cohort, maintainer-gated identically to theexisting
maintainer-noiseroute (requireRepoMaintainer).present: false(never a 404/error)when the AMS bridge is off, unconfigured, or the repo has no submitter activity in the window — the
panel's required empty state.
AmsMinerCohortCardinapps/loopover-ui/src/components/site/app-panels/, wired intomaintainer-panel.tsxnext toActivationPreview. Self-contained repo picker + self-fetch, mirroringActivationPreview's exact shape (this repo's established precedent for a maintainer-panel card thatneeds its own single-repo data, distinct from the multi-repo
qualityDashboardaggregate).AmsMinerCohortComparisonschema, registered the same wayMaintainerNoiseReportis (schema only, no
registerPath— matches the maintainer-only, non-MCP-facing route convention).No wallet/hotkey/reward/trust-score wording anywhere in the panel or backend, matching this repo's
existing constraints for private-only surfaces.
Test plan
test/unit/ams-miner-cohort.test.ts(new): purecomputeCohortMetrics/splitCohortRowscases(empty cohort, multi-submitter aggregation,
nullacceptanceRate/avgTimeToMergeMs never fabricated),plus the full
buildAmsMinerCohortComparisonorchestrator (bridge off, no endpoint, empty-window,AMS/human classification via a mocked bridge fetch, a fail-safe null lookup never counting as AMS, the
AMS_MINER_COHORT_CHECK_CAPregression, and a customwindowDaysthreading through) — 14/14 passingtest/unit/submitter-reputation.test.ts: addedlistSubmitterCohortRowsD1 fail-safe tests(binding shape, default window, throw →
[], malformed result →[]) — 51/51 passingtest/integration/api.test.ts: added the new route's 401/200 +present: falseempty-state case— 142/142 passing across the full integration suite
apps/loopover-ui/.../ams-miner-cohort-card.test.tsx(new, 8 tests) +maintainer-panel.test.tsxregression (7/7) — both passing
src/**files(
ams-miner-cohort.ts,submitter-reputation.ts) via scopedvitest --coverage, and zero uncoveredlines/branches on the new route's changed lines in
routes.tsvia direct lcovDA:/BRDA:inspection (one line needed a
v8 ignore next, matching the exact, already-established precedent at3 other
requireRepoMaintainercall sites in this same file — unauthenticated requests are rejectedby the auth middleware before the handler runs, so that in-handler branch is genuinely unreachable)
npm run build --workspace @loopover/engine,npm run ui:lint,npm run ui:typecheck,npm run ui:openapi+ui:openapi:check+ui:openapi:settings-parity,npm run docs:drift-check,npm run manifest:drift-check,npm run engine-parity:drift-check,git diff --check,npm run actionlint— all cleannpm audit --audit-level=moderate— 0 vulnerabilitiesnpm run typecheckOOMs in this sandbox regardless of diff content (pre-existing environmentlimitation, unrelated to this change); substituted the scoped engine build plus careful manual
line-by-line type review of every changed
src/**fileCloses #6488