Skip to content

feat(stats): public proof-of-power — lifetime PRs-handled + accuracy counter on homepage hero #1059

Description

@JSONbored

Part of #1058 · Advances #1022 (ops/stats/self-improve) · Depends on #1011 (unified engine) and #1025 (historical backfill)

Why

Every PR gittensory handles is proof the system works — and we've already handled 1000+ across the repos we run. We have the data (review_targets, review_audit, gate_outcomes) but no public exposure. Surface it on the homepage hero, above the fold, as a live counter: an onboarding asset and a credibility signal for a technical audience. Lead with both volume and accuracy.

This issue also owns the shared pr_outcome ground-truth plumbing that the close-the-loop epic's accuracy/trust and feedback-loop children depend on (see deliverable 1).

Data sources (already exist — no new capture needed for volume)

  • Lifetime handled: COUNT(*) FROM review_targets per project (migrations/0050)
  • Outcome split (merged / closed / held / manual): review_targets.verdict + status
  • Slop & gate blocks: gate_outcomes.blocker_codes_json, overridden (migrations/0041)
  • Human-reversal rate: review_audit WHERE event_type LIKE 'reversal_%' (migrations/0049)
  • Existing aggregation logic (currently bearer-gated, to be reused): src/review/stats.ts (computeStats), src/review/ops.ts (computeCalibration)

Requirements

  1. The lifetime number must reflect the true total, including PRs handled by reviewbot pre-convergence — not just post-cutover gittensory-native records.
  2. Accuracy must be defined honestly and defensibly (reversal-grounded: a decision is "correct" unless a human later overrides/reverts it). The definition must be documented publicly.
  3. The public endpoint must be cheap to serve (cached, O(1)) and expose no sensitive data — aggregates only, no PR content, actor logins, scores, or rewards.
  4. The hero counter must match the existing design system and reuse existing patterns (no new realtime infra).

Deliverables

  • pr_outcome ground-truth plumbing — write a pr_outcome event to review_audit on pull_request.closed / merged (event type exists; review_targets.terminal_at is the hook). Enables real accuracy = agree(verdict, outcome) / decided. (Shared foundation for the epic.)
  • Historical backfill — coordinate with State + audit migration (decision-cache/approvedSha/reputation/tunables/review_audit) before cutover #1025 (state/audit migration) to import reviewbot's lifetime handled-PR records into review_targets / review_audit so the counter shows the true 1000+. Blocker for an honest lifetime number.
  • Rollup table pr_handling_stats(date, project, handled, merged, closed, held, blocked, reversed, accuracy) refreshed by the existing */30 cron (wrangler.jsonc).
  • Public endpoint GET /v1/public/stats (Hono, no auth, Cache-Control: public, max-age=60, stale-while-revalidate=300) in src/api/routes.ts; regenerate OpenAPI via npm run ui:openapi (src/openapi/spec.ts).
  • Hero band component — new RealtimeStatsCounter in apps/gittensory-ui/src/components/site/, placed between <Hero/> and <MetaStrip/> in apps/gittensory-ui/src/routes/index.tsx. Reuse the Stat primitive, the useApiStatus 60s polling pattern (lib/api/status.ts / GithubStatsChip), and the motion count-up. Four stats: PRs handled · auto-merged · decision accuracy · slop blocked, with a "Live · updated Ns ago" freshness line.
  • /stats detail page (optional follow-up) — per-repo breakdown + trend, and the public accuracy-definition writeup.

Acceptance criteria

  • Homepage hero shows four live stats above the fold, polling every 60s, matching the design system in light + dark mode.
  • GET /v1/public/stats returns cached aggregates with no auth and no sensitive fields; OpenAPI updated.
  • The lifetime "PRs handled" figure includes reviewbot history (post-State + audit migration (decision-cache/approvedSha/reputation/tunables/review_audit) before cutover #1025) and reconciles with review_targets + backfilled records.
  • Accuracy is reversal-grounded and the definition is documented.
  • No raw scores / rewards / hotkeys / wallet data anywhere in the payload or UI.

Out of scope

  • WebSockets / SSE — 60s polling is sufficient and matches existing site behavior.
  • Per-contributor leaderboards (future, privacy-reviewed).

Labels: roadmap, maintainer-only, visual · Assignee: @JSONbored

Metadata

Metadata

Assignees

Labels

maintainer-onlyOwner-only work — yields no Gittensor points.roadmapOn the Wave-2 agent-layer roadmap board (project 9)visualUI/web visual work — owner-led, NOT for Gittensor contributors (extensions excepted)

Projects

Status
Done

Relationships

None yet

Development

No branches or pull requests

Issue actions