Skip to content

feat(benchmark): maintainer action-space schema and proposal validator (#9260) - #9595

Merged
JSONbored merged 3 commits into
mainfrom
feat/benchmark-action-space-9260
Jul 28, 2026
Merged

feat(benchmark): maintainer action-space schema and proposal validator (#9260)#9595
JSONbored merged 3 commits into
mainfrom
feat/benchmark-action-space-9260

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

What

The frozen-repo benchmark harness's task format (#9216 requirement 1), fixed as validated types. Without a closed, validated action space two agents' outputs are not comparable and the scorer has nothing stable to score against — so:

  • Closed action setmerge | close | request_changes | label | hold. Closed, not extensible-by-string: an unrecognized action is a validation error, never a silently-ignored or zero-scored entry.
  • Typed per-action parameters, enforced by a per-kind key allowlist, so a parameter that does not apply to the chosen action fails loudly (labels: unexpected key for action "merge") rather than being dropped into an answer the scorer would grade differently than the agent intended. close carries a reason class (not free text — realized history grades the class); request_changes carries a bounded non-blank concern; label carries a bounded, duplicate-free, non-blank set; merge/hold carry nothing.
  • Abstention is first-class — declining a work unit is a recorded prediction feeding Spec: validator-facing eval interface — what SN74 consumes from LoopOver as the objective eval provider #9215's coverage metric, not a wrong answer, so a precise-but-narrow agent stays distinguishable from a broad-but-noisy one. An abstention carrying an action is contradictory and rejected.
  • The horizon lives on the task, not the proposal (BenchmarkTask.horizonDays, fixed per benchmark), so an agent cannot pick a horizon that flatters its answer; horizonDays on a proposal is an unexpected key. A proposal echoes benchmarkId + snapshotRef + workUnitId, so a submission cannot be replayed against a different snapshot or benchmark.
  • Both validators are pure and never throw, return {valid: true, …} | {valid: false, errors} with one error per failing field path, and reject unknown keys — the same contract as validateAttestationEnvelope, which they deliberately mirror. Exported from the engine barrel so a candidate agent author validates locally against the exact code the harness runs.

Tests (10 node:test cases, 100% of branches)

Every action kind with exactly its own parameters plus abstention round-trips; the closed-set rejection; the inapplicable-parameter rejection for three action kinds; close reason-class bounds; request_changes blank/oversize/missing; the eight label rejection paths named by index (including duplicates); prediction-shape rejections; the full proposal envelope (version, stray keys, identity bounds, subject shape); a multi-defect proposal reporting one error per path rather than only the first; and the task validator's own envelope/horizon/frozenAt rejection table.

Closes #9260 — first of the #9216 benchmark chain, now unblocked by #9215's closed spec.

@loopover-orb

loopover-orb Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Warning

⏸️ LoopOver review result - manual review recommended

Review updated: 2026-07-28 22:37:09 UTC

13 files · 1 AI reviewer · 1 blocker · CI green · clean

⏸️ Suggested Action - Manual Review

Review summary
The diff bundles two unrelated features: the benchmark action-space schema/validator this PR is titled and scoped for (#9260, packages/loopover-engine/src/calibration/benchmark-proposal.ts — a well-structured, thoroughly-tested pure validator mirroring validateAttestationEnvelope's contract) and a completely separate Bittensor on-chain ledger-anchoring report pipeline (#9277) with new API routes, auth allowlist entries, a DB migration, an env var, and doc updates. The benchmark validator code itself is solid — closed action set, per-action key allowlists, first-class abstention, horizon pinned to the task not the proposal, one error per field path — and its test suite exercises the real rejection/acceptance paths without fabricated coverage. The bittensor report-ingestion code also looks correct (signature verification against published keys, live-row seq/hash binding, honest failed-report logging) but has no business being in a PR whose title and description are exclusively about #9260.

Blockers

Nits — 5 non-blocking
  • migrations/0201_ledger_anchor_bittensor.sql uses `INSERT INTO decision_ledger_anchors_new SELECT * FROM decision_ledger_anchors` — I can't see the pre-migration column order in this diff, so confirm the old table's column order exactly matches the new CREATE TABLE's order before merging (a `SELECT *` mismatch silently misaligns columns rather than erroring).
  • packages/loopover-engine/src/calibration/benchmark-proposal.ts:124 nests to depth 5 in validateAction's per-kind branches — consider extracting the close/request_changes/label checks into their own small validators for readability, though it's not incorrect as written.
  • The two undetailed FAILED checks (validate-tests, validate) can't be diagnosed from what's given — the branch is 1 commit behind the default branch, which is a plausible cause; worth rebasing before merge to rule that out rather than assuming it's this diff's own defect.
  • Split the Bittensor anchoring work (src/review/ledger-anchor-bittensor.ts, its routes, migration, auth entries, docs, and tests) into a separate PR tied to ledger: Bittensor on-chain commitment backend — optional, Gittensor/SN74-audience corroboration #9277 so benchmark: maintainer action-space schema + proposal validator #9260's benchmark validator can be reviewed and merged on its own.
  • PR author also opened the linked issue — Link an issue that was opened by a different contributor, or provide a rationale for why this self-authored issue represents genuine discovery work.

Concerns raised — review before merging

📋 Copy for AI agents — paste into your coding agent
Fix the following blocker(s) from this PR review:

1. This PR is titled/scoped as \#9260's benchmark validator but bundles an entirely unrelated feature \(\#9277's Bittensor ledger-anchoring report pipeline: src/review/ledger-anchor-bittensor.ts, two new API routes in src/api/routes.ts, two new unauthenticated-route entries in src/auth/route-auth.ts, migrations/0201\_ledger\_anchor\_bittensor.sql, LOOPOVER\_LEDGER\_ANCHOR\_REPORT\_TOKEN in src/env.d.ts, and a docs rewrite\) with no issue explicitly authorizing that work be shipped in this PR — split it into its own PR against \#9277 so each can be reviewed and reverted independently.

Decision drivers

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

Addressed
The diff adds packages/loopover-engine/src/calibration/benchmark-proposal.ts with a closed BenchmarkActionKind type, per-action key allowlists enforcing unexpected-parameter rejection, a BenchmarkTask type carrying horizonDays (not the proposal), a first-class abstain/act BenchmarkPrediction, and validateBenchmarkProposal/validateBenchmarkTask mirroring validateAttestationEnvelope's pure never-thr

Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is registered but has no active allocation in the current snapshot.
  • Public profile languages: not available
  • Official Gittensor activity: 14 PR(s), 310 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Treat this as maintainer-lane context rather than normal contributor-lane activity.
  • Then work through the remaining 1 step in the Signals table above.
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.

Decision record
  • action: hold · clause: ai_consensus_defect
  • config: ded8c7fce4061ae913c4bf3e225575c5c6431598b6e29da1128f20e269cc12e6 · pack: oss-anti-slop · ci: passed
  • model: claude-code · prompt: 3a2749341e077d28ff813dfc0ef8ce749853e15baba4f1283e0edd9221a1316f · confidence: 0.9
  • record: 1072802d282197118bf0456160b57a5b40f378fc564563bbaca90c8b44c5cd0e (schema v5, head 0519426)
Visual preview
Route Viewport Before (production) After (this PR's preview) Diff
/ desktop before /
before /
after /
after /
/ mobile before / (mobile)
before / (mobile)
after / (mobile)
after / (mobile)

Click any thumbnail to open the full-size screenshot. Before = production · After = this PR's preview deploy.

Scroll preview
Route Before (production) After (this PR's preview)
/ before / (scroll)
before / (scroll)
after / (scroll)
after / (scroll)

A short scroll-through clip (desktop) — click either thumbnail to open the full animation. Evidence for scroll-linked behavior a single screenshot can't show.

🟩 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

@superagent-security

Copy link
Copy Markdown
Contributor

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

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 28, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
loopover-ui 0519426 Commit Preview URL

Branch Preview URL
Jul 28 2026, 09:57 PM

@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

Bundle Report

Changes will increase total bundle size by 6.38kB (0.08%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
loopover-ui 7.79MB 6.38kB (0.08%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: loopover-ui

Assets Changed:

Asset Name Size Change Total Size Change (%)
assets/add-scalar-classes-D8Dj7YyG.js (New) 2.16MB 2.16MB 100.0% 🚀
assets/tanstack-vendor-DgX5HYmn.js (New) 912.86kB 912.86kB 100.0% 🚀
openapi.json 1.83kB 712.86kB 0.26%
assets/docs.fumadocs-spike-api-reference-DHZ63mnT.js (New) 443.45kB 443.45kB 100.0% 🚀
assets/AgentScalarChatInterface.vue-D0XRxWXc.js (New) 201.7kB 201.7kB 100.0% 🚀
assets/modal-CKVqXj52.js (New) 184.5kB 184.5kB 100.0% 🚀
assets/client-BiUgLQNF.js (New) 151.47kB 151.47kB 100.0% 🚀
assets/maintainer-panel-BE-s2qKp.js (New) 78.99kB 78.99kB 100.0% 🚀
assets/what-you-can-verify-WYKa_oSR.js (New) 54.1kB 54.1kB 100.0% 🚀
assets/routes-BIIqSisu.js (New) 35.96kB 35.96kB 100.0% 🚀
assets/owner-panel-BIwdq47g.js (New) 27.92kB 27.92kB 100.0% 🚀
assets/app-Bn5KjUMo.js (New) 25.78kB 25.78kB 100.0% 🚀
assets/ui-vendor-BqoXHLzp.js (New) 24.57kB 24.57kB 100.0% 🚀
assets/miner-panel-hgWaNYQQ.js (New) 20.24kB 20.24kB 100.0% 🚀
assets/app.runs-6vZbrege.js (New) 20.22kB 20.22kB 100.0% 🚀
assets/api._op-DVwCRakh.js (New) 17.57kB 17.57kB 100.0% 🚀
assets/self-hosting-docs-audit-HktHL1uq.js (New) 16.6kB 16.6kB 100.0% 🚀
assets/docs._slug-C_m8qXeX.js (New) 15.52kB 15.52kB 100.0% 🚀
assets/playground-panel-B49R_Yi7.js (New) 14.42kB 14.42kB 100.0% 🚀
assets/fairness-VY1DclTZ.js (New) 10.73kB 10.73kB 100.0% 🚀
assets/app.audit-CaFm8Eqs.js (New) 10.08kB 10.08kB 100.0% 🚀
assets/app.config-generator-i6cjBVeu.js (New) 10.06kB 10.06kB 100.0% 🚀
assets/maintainers-DsDK-yPw.js (New) 8.06kB 8.06kB 100.0% 🚀
assets/miners-BMvDsqDe.js (New) 7.91kB 7.91kB 100.0% 🚀
assets/agents-Q1yFlaDD.js (New) 7.74kB 7.74kB 100.0% 🚀
assets/commands-panel-D-8wPXGb.js (New) 6.65kB 6.65kB 100.0% 🚀
assets/maintainer-workflow-CQG8L7mN.js (New) 6.52kB 6.52kB 100.0% 🚀
assets/digest-panel-DuUBSq1O.js (New) 6.15kB 6.15kB 100.0% 🚀
assets/repos._owner._repo.quality-F3oREzhU.js (New) 6.14kB 6.14kB 100.0% 🚀
assets/docs-nav-uW4i6eVC.js (New) 6.01kB 6.01kB 100.0% 🚀
assets/docs.index-Mag_9Ek5.js (New) 5.95kB 5.95kB 100.0% 🚀
assets/api.index-B0sE4AFV.js (New) 4.7kB 4.7kB 100.0% 🚀
assets/docs-DSuqq3FI.js (New) 2.7kB 2.7kB 100.0% 🚀
assets/api-LvGaCYkk.js (New) 2.69kB 2.69kB 100.0% 🚀
assets/docs-page-CsRVj76t.js (New) 2.1kB 2.1kB 100.0% 🚀
assets/table-sKqhVkg8.js (New) 1.75kB 1.75kB 100.0% 🚀
assets/app.workbench-D8wd2Gd0.js (New) 1.58kB 1.58kB 100.0% 🚀
assets/tabs-BylaM85l.js (New) 1.39kB 1.39kB 100.0% 🚀
assets/app.repos-XkgUdRhW.js (New) 1.07kB 1.07kB 100.0% 🚀
assets/input-BfvmcGjW.js (New) 796 bytes 796 bytes 100.0% 🚀
assets/file-cog-DxfkU_Qm.js (New) 758 bytes 758 bytes 100.0% 🚀
assets/app.maintainer-nUgZiMyM.js (New) 502 bytes 502 bytes 100.0% 🚀
assets/app.owner-H7TNH-hk.js (New) 474 bytes 474 bytes 100.0% 🚀
assets/app.commands-Co1kG67d.js (New) 455 bytes 455 bytes 100.0% 🚀
assets/app.playground-BkgwmzcP.js (New) 442 bytes 442 bytes 100.0% 🚀
assets/index-CnL2s3_D.js (New) 438 bytes 438 bytes 100.0% 🚀
assets/app.digest-DwIhNDUN.js (New) 430 bytes 430 bytes 100.0% 🚀
assets/eye-off-DX6rI0lD.js (New) 430 bytes 430 bytes 100.0% 🚀
assets/app.miner-_EzNdLDQ.js (New) 422 bytes 422 bytes 100.0% 🚀
assets/key-round-DaONLAkf.js (New) 355 bytes 355 bytes 100.0% 🚀
assets/bot-CsaaI2U2.js (New) 328 bytes 328 bytes 100.0% 🚀
assets/trash-2-CzgYtdg9.js (New) 328 bytes 328 bytes 100.0% 🚀
assets/save-DbIfNLkM.js (New) 327 bytes 327 bytes 100.0% 🚀
assets/git-pull-request-arrow-D2fv1DMg.js (New) 321 bytes 321 bytes 100.0% 🚀
assets/list-checks-1EbutALM.js (New) 279 bytes 279 bytes 100.0% 🚀
assets/compass-CQgBrikq.js (New) 251 bytes 251 bytes 100.0% 🚀
assets/history-vw6Aln5Z.js (New) 237 bytes 237 bytes 100.0% 🚀
assets/message-square-DMcaexhm.js (New) 233 bytes 233 bytes 100.0% 🚀
assets/lock-Ba4wK6Uv.js (New) 206 bytes 206 bytes 100.0% 🚀
assets/rotate-cw-lpWDG7jF.js (New) 201 bytes 201 bytes 100.0% 🚀
assets/play-CrO53Kph.js (New) 190 bytes 190 bytes 100.0% 🚀
assets/circle-check-CFE2hDxO.js (New) 178 bytes 178 bytes 100.0% 🚀
assets/search-DjH7H0qh.js (New) 174 bytes 174 bytes 100.0% 🚀
assets/add-scalar-classes-ClD5uxs8.js (Deleted) -2.16MB 0 bytes -100.0% 🗑️
assets/tanstack-vendor-DQgq5OSM.js (Deleted) -911.49kB 0 bytes -100.0% 🗑️
assets/docs.fumadocs-spike-api-reference-C0UJXd3W.js (Deleted) -443.45kB 0 bytes -100.0% 🗑️
assets/AgentScalarChatInterface.vue-BAkmyz2N.js (Deleted) -201.7kB 0 bytes -100.0% 🗑️
assets/modal-Cm8Tzpcj.js (Deleted) -184.5kB 0 bytes -100.0% 🗑️
assets/client-HY28ZfK6.js (Deleted) -151.47kB 0 bytes -100.0% 🗑️
assets/maintainer-panel-CV5l0RVc.js (Deleted) -78.99kB 0 bytes -100.0% 🗑️
assets/what-you-can-verify-CiXBz4TS.js (Deleted) -50.92kB 0 bytes -100.0% 🗑️
assets/routes-C5VVDu7X.js (Deleted) -35.96kB 0 bytes -100.0% 🗑️
assets/owner-panel-Deyi_wiR.js (Deleted) -27.92kB 0 bytes -100.0% 🗑️
assets/app-D_Dv4YdD.js (Deleted) -25.78kB 0 bytes -100.0% 🗑️
assets/ui-vendor-Dy1Rnzlr.js (Deleted) -24.57kB 0 bytes -100.0% 🗑️
assets/miner-panel-DH5NnRmi.js (Deleted) -20.24kB 0 bytes -100.0% 🗑️
assets/app.runs-7TMmwQ1m.js (Deleted) -20.22kB 0 bytes -100.0% 🗑️
assets/api._op-DwYtF28W.js (Deleted) -17.57kB 0 bytes -100.0% 🗑️
assets/self-hosting-docs-audit-D8C_veIb.js (Deleted) -16.6kB 0 bytes -100.0% 🗑️
assets/docs._slug-BOpUB7AR.js (Deleted) -15.52kB 0 bytes -100.0% 🗑️
assets/playground-panel-D6GGRjRp.js (Deleted) -14.42kB 0 bytes -100.0% 🗑️
assets/fairness-CvTa_YZi.js (Deleted) -10.73kB 0 bytes -100.0% 🗑️
assets/app.audit-CbteU9si.js (Deleted) -10.08kB 0 bytes -100.0% 🗑️
assets/app.config-generator-CXwnYcT2.js (Deleted) -10.06kB 0 bytes -100.0% 🗑️
assets/maintainers-1i1i4UQZ.js (Deleted) -8.06kB 0 bytes -100.0% 🗑️
assets/miners-DOe2OszS.js (Deleted) -7.91kB 0 bytes -100.0% 🗑️
assets/agents-CociCkFx.js (Deleted) -7.74kB 0 bytes -100.0% 🗑️
assets/commands-panel-BVNwV8Zt.js (Deleted) -6.65kB 0 bytes -100.0% 🗑️
assets/maintainer-workflow-BVxUEli6.js (Deleted) -6.52kB 0 bytes -100.0% 🗑️
assets/digest-panel-CAeX5F4v.js (Deleted) -6.15kB 0 bytes -100.0% 🗑️
assets/repos._owner._repo.quality-DMePUsr5.js (Deleted) -6.14kB 0 bytes -100.0% 🗑️
assets/docs-nav-DuX9s4h9.js (Deleted) -6.01kB 0 bytes -100.0% 🗑️
assets/docs.index-QjQzfLqm.js (Deleted) -5.95kB 0 bytes -100.0% 🗑️
assets/api.index-YGOgpX7S.js (Deleted) -4.7kB 0 bytes -100.0% 🗑️
assets/docs-Br-kvME0.js (Deleted) -2.7kB 0 bytes -100.0% 🗑️
assets/api-CD9duIYi.js (Deleted) -2.69kB 0 bytes -100.0% 🗑️
assets/docs-page-1ySSUtgu.js (Deleted) -2.1kB 0 bytes -100.0% 🗑️
assets/table-B0UxI15m.js (Deleted) -1.75kB 0 bytes -100.0% 🗑️
assets/app.workbench-CCsr-6Fs.js (Deleted) -1.58kB 0 bytes -100.0% 🗑️
assets/tabs-C7b_HP1D.js (Deleted) -1.39kB 0 bytes -100.0% 🗑️
assets/app.repos-CxnF3aN5.js (Deleted) -1.07kB 0 bytes -100.0% 🗑️
assets/input-BJ_EdN8j.js (Deleted) -796 bytes 0 bytes -100.0% 🗑️
assets/file-cog-NbCElz_t.js (Deleted) -758 bytes 0 bytes -100.0% 🗑️
assets/app.maintainer-BCNJz3OU.js (Deleted) -502 bytes 0 bytes -100.0% 🗑️
assets/app.owner-DVviUgkt.js (Deleted) -474 bytes 0 bytes -100.0% 🗑️
assets/app.commands-BaIBn7R3.js (Deleted) -455 bytes 0 bytes -100.0% 🗑️
assets/app.playground-o5tpA7_S.js (Deleted) -442 bytes 0 bytes -100.0% 🗑️
assets/index-DQw8M9V1.js (Deleted) -438 bytes 0 bytes -100.0% 🗑️
assets/app.digest-7t-KH7QG.js (Deleted) -430 bytes 0 bytes -100.0% 🗑️
assets/eye-off-MH_rerEw.js (Deleted) -430 bytes 0 bytes -100.0% 🗑️
assets/app.miner-w3nx_ZmL.js (Deleted) -422 bytes 0 bytes -100.0% 🗑️
assets/key-round-DvM_GmWd.js (Deleted) -355 bytes 0 bytes -100.0% 🗑️
assets/bot-D6NNYx_T.js (Deleted) -328 bytes 0 bytes -100.0% 🗑️
assets/trash-2-DwuO4vEd.js (Deleted) -328 bytes 0 bytes -100.0% 🗑️
assets/save-CZpxL0JA.js (Deleted) -327 bytes 0 bytes -100.0% 🗑️
assets/git-pull-request-arrow-DP-sV9U1.js (Deleted) -321 bytes 0 bytes -100.0% 🗑️
assets/list-checks-EOxf8X2i.js (Deleted) -279 bytes 0 bytes -100.0% 🗑️
assets/compass-DDiQU4UF.js (Deleted) -251 bytes 0 bytes -100.0% 🗑️
assets/history-C9TsYZ8e.js (Deleted) -237 bytes 0 bytes -100.0% 🗑️
assets/message-square-BZCF6OHX.js (Deleted) -233 bytes 0 bytes -100.0% 🗑️
assets/lock-DrZR2-DH.js (Deleted) -206 bytes 0 bytes -100.0% 🗑️
assets/rotate-cw-DZOb_f-N.js (Deleted) -201 bytes 0 bytes -100.0% 🗑️
assets/play-B__w4wlD.js (Deleted) -190 bytes 0 bytes -100.0% 🗑️
assets/circle-check-Z6QeTmNw.js (Deleted) -178 bytes 0 bytes -100.0% 🗑️
assets/search-DYcunweo.js (Deleted) -174 bytes 0 bytes -100.0% 🗑️

@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.87%. Comparing base (26071f1) to head (0519426).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9595      +/-   ##
==========================================
+ Coverage   89.85%   89.87%   +0.02%     
==========================================
  Files         880      882       +2     
  Lines      111175   111488     +313     
  Branches    26473    26561      +88     
==========================================
+ Hits        99891   100204     +313     
  Misses       9992     9992              
  Partials     1292     1292              
Flag Coverage Δ
backend 95.50% <50.58%> (-0.13%) ⬇️
engine 66.16% <100.00%> (+0.23%) ⬆️

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

Files with missing lines Coverage Δ
...pover-engine/src/calibration/benchmark-proposal.ts 100.00% <100.00%> (ø)
packages/loopover-engine/src/index.ts 100.00% <100.00%> (ø)
src/api/routes.ts 95.62% <100.00%> (+0.03%) ⬆️
src/auth/route-auth.ts 100.00% <100.00%> (ø)
src/openapi/spec.ts 99.30% <100.00%> (+<0.01%) ⬆️
src/review/ledger-anchor-bittensor.ts 100.00% <100.00%> (ø)
src/review/ledger-anchor-persistence.ts 100.00% <ø> (ø)

…the off-Worker submitter (#9277)

The fourth, optional, Gittensor/SN74-audience anchoring backend. The
on-chain SUBMISSION never runs in this Worker: a process on the
operator's own node infrastructure (where its dedicated anchor-only
hotkey lives as an operational secret, never in this repo) fetches the
signed checkpoint, commits sha256(signingInput) via the commitments
pallet's set_commitment(netuid, Data::Sha256), and reports the outcome
back. This lands the validation boundary that report crosses:

- GET /v1/public/decision-ledger/anchor-payload: the current tip's
  freshly signed checkpoint + the exact signingInput bytes to hash.
  Unauthenticated (it is the same payload Rekor/git already publish
  externally); no-store, since 'at' is minted per call.
- POST /v1/decision-ledger/anchor-attempts: bearer-gated
  (LOOPOVER_LEDGER_ANCHOR_REPORT_TOKEN, fails closed unset -- the
  isAuthorizedIngest posture). Authentication alone cannot forge
  corroboration: an ok report must verify against a PUBLISHED anchor
  key AND its (seq, rowHash) must match the LIVE chain row; a failed
  report records without those checks, because a broken submitter is
  exactly what the public attempt log exists to make visible.
- decision_ledger_anchors backend CHECK widened to 'bittensor'
  (migration 0201 rebuild); the public listing filter follows. Rows are
  byte-identical in shape to Rekor/git attempts.
- backendRef carries the FULL historical-retrieval reference
  {netuid, blockNumber, blockHash, hotkey}: CommitmentOf is overwritten
  in place on-chain, so a verifier reads archive state at that block,
  never current chain state -- now documented step-by-step in
  what-you-can-verify.mdx, still clearly scoped as optional
  corroboration outside the default two-backend claim.

Closes #9277
…backend filter

The route/spec ratchet caught both new routes as undescribed -- correctly:
they exist in createApp() with no OpenAPI operation, which is exactly what
that check is for.

- GET /v1/public/decision-ledger/anchor-payload: the signed checkpoint an
  off-Worker submitter commits, with the 404 arms (signing unconfigured,
  empty ledger) described as the honest degrades they are.
- POST /v1/decision-ledger/anchor-attempts: the report ingest, with every
  refusal documented -- notably the 401 covering an unconfigured token
  (fails closed) and the 422 naming all four unverifiable outcomes, since
  those are what a submitter integrates against.
- The anchors listing's `backend` filter gains 'bittensor', matching the
  widened CHECK constraint.
#9260)

The frozen-repo benchmark's task format, fixed as validated types so two
agents' outputs are comparable and the scorer downstream can assume
well-formed input.

- CLOSED action set (merge | close | request_changes | label | hold):
  an unrecognized action is a validation ERROR, never a silently-ignored
  or zero-scored entry.
- Typed per-action parameters, enforced by a per-kind key allowlist, so
  a parameter that does not apply to the chosen action fails loudly
  ('labels: unexpected key for action "merge"') rather than being
  dropped into an answer the scorer grades differently than intended.
  close carries a reason CLASS (not free text, because realized history
  grades the class); request_changes carries a bounded concern; label
  carries a bounded, duplicate-free set; merge/hold carry nothing.
- Abstention is FIRST-CLASS: declining a work unit is a recorded
  prediction feeding #9215's coverage metric, not a wrong answer, so a
  precise-but-narrow agent stays distinguishable from a broad-but-noisy
  one. An abstention carrying an action is contradictory and rejected.
- The prediction horizon lives on the TASK, never the proposal, so an
  agent cannot pick a horizon that flatters its answer; a proposal
  echoes benchmarkId + snapshotRef + workUnitId so a submission cannot
  be replayed against a different snapshot.
- Both validators are pure, never throw for ordinarily-invalid input,
  return one error per failing field path, and reject unknown keys --
  the same contract as validateAttestationEnvelope, which they mirror
  deliberately. Exported from the engine barrel so a candidate agent
  author can validate locally against the exact code the harness runs.

Closes #9260
@JSONbored
JSONbored force-pushed the feat/benchmark-action-space-9260 branch from 701257f to 0519426 Compare July 28, 2026 21:54
@JSONbored
JSONbored merged commit b543e1e into main Jul 28, 2026
11 checks passed
@JSONbored
JSONbored deleted the feat/benchmark-action-space-9260 branch July 28, 2026 22:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

manual-review Gittensor contributor context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

benchmark: maintainer action-space schema + proposal validator

1 participant