Skip to content

fix: honour the canonical-pin grace window in eval.verify (honest training PRs are auto-closed as eval:REJECT) - #232

Merged
ai-hpc merged 1 commit into
gittensor-model-hub:mainfrom
kai392:fix/critical-issue-canonical-pin-grace
Jul 25, 2026
Merged

fix: honour the canonical-pin grace window in eval.verify (honest training PRs are auto-closed as eval:REJECT)#232
ai-hpc merged 1 commit into
gittensor-model-hub:mainfrom
kai392:fix/critical-issue-canonical-pin-grace

Conversation

@kai392

@kai392 kai392 commented Jul 24, 2026

Copy link
Copy Markdown

SparkDistill contribution

Track

Select the one track this PR belongs to.

  • Dataset track submission
  • Training/evaluation improvement

Neither box applies: this is a bug fix to the training-track gate itself, not a
submission. Per CONTRIBUTING.md this is a non-quality PR and scores 0 — it is
filed because the bug auto-closes other people's honest submissions.

Summary

Closes #231. Restores the canonical-pin grace window from #121 (issue #118) on the
one code path that still ignored it.

Root cause

#121 added a merge-base→HEAD grace window so a training-track PR is not rejected
when a dataset-track merge advances datasets/canonical.json mid-training. The
window reaches two of the three mix_manifest.sft_sha256 checks:

check window applied
validate_pr_body_canonical_pin
verify_remote_proof_bundle
check_canonical_dataset_claim inside eval.verify.verify_submission

gate_training_pr computes acceptable_sft_shas, but verify_remote_proof_bundle_scores
never received it, so _download_and_verify_bundle called
verify_submission(bundle_dir, frontier, attestation=attestation) — and verify_submission
had no such parameter. check_canonical_dataset_claim then fell back to
allowed = {canonical_sft_sha256()}: the single pin at the checked-out tree, which
training_track.yml checks out from pull_request.base.ref (live main).

Reproduction with a bundle pinned to the merge-base sha and a window of {base, head}:

stage 1  verify_remote_proof_bundle       -> []            # accepted
stage 2  verify_remote_proof_bundle_scores -> eval:REJECT
         'eval.verify canonical_dataset_failed: bundle mix_manifest.sft_sha256 does not
          match an accepted canonical pin (allowed 1 pin(s) for this PR window)'

The error text reports allowed 1 pin(s) — proof the grace set never arrived.

eval:REJECT is in _AUTO_CLOSE_EVAL_LABELS, and training_track.yml runs the gate
with --close-on-reject, so the honest PR is closed automatically.

Fix approach

Thread the already-computed window down the call chain, nothing more:

gate_training_prverify_remote_proof_bundle_scores_download_and_verify_bundle
verify_submissioncheck_canonical_dataset_claim (which already accepts
acceptable_sft_shas).

record_merged_ledger_entry shares _download_and_verify_bundle, so it gains a
merge_base_ref argument and computes the same window via the existing
_canonical_sft_sha256s_for_pr_window helper; training_track_ledger.yml passes
pull_request.base.sha. Without this, the pin can advance again between the gate job
and the ledger job, recording eval:REJECT for an already-merged run and skipping its
runs/frontiers.json update — which would then mis-tier every later submission.

Impact

  • Honest training-track PRs are no longer auto-closed when a dataset-track PR merges
    during their train→eval cycle. This is what the PR template already promises:
    "any pin from merge-base through HEAD is accepted".
  • Miner credibility (merged/(merged+closed), which gates eligibility at 80% and
    multiplies earned score) is no longer damaged by an automated wrong-close.
  • The merged ledger and frontiers.json stay correct for runs that were merge-eligible
    at gate time.

Risk and tradeoffs

  • Backward compatible. acceptable_sft_shas and merge_base_ref both default to
    None, which preserves today's strict behaviour. The standalone
    python -m eval.verify validator path is unchanged and still requires the pin at
    datasets/canonical.json.
  • No security loosening. The accepted set is bounded by the PR's own
    merge-base→HEAD history of datasets/canonical.json; a miner cannot inject an
    arbitrary sha, and any pin outside the window is still canonical_dataset_failed
    (covered by a test). The gate and the verify stage now agree on one set instead of
    silently disagreeing.
  • No new dependencies; no behaviour change for dataset-track PRs.

Tests

Three regression tests in tests/test_training_track_pin_grace.py (the file #121 added):
verify_submission accepts a merge-base pin, still rejects a pin outside the window,
and verify_remote_proof_bundle_scores no longer tiers a base-pin bundle eval:REJECT.
All three fail on main and pass with this change.

pytest tests/ -q       269 passed, 8 skipped, 1 pre-existing env failure
                       (test_aggregate_and_publish_mining_dataset needs a SparkProof checkout)
pyright eval/verify.py eval/training_track_gate.py eval/record_training_ledger.py
                       0 errors, 0 warnings

One existing test fake (fake_verify_submission) gained **kwargs to accept the new
keyword argument.

The pin-grace window from gittensor-model-hub#121 (issue gittensor-model-hub#118) reached only
validate_pr_body_canonical_pin and verify_remote_proof_bundle. The third
check — check_canonical_dataset_claim inside eval.verify.verify_submission,
reached via verify_remote_proof_bundle_scores — still compared the bundle's
mix_manifest.sft_sha256 against the single pin at the checked-out tree
(live main). An honest training-track PR whose pin advanced mid-training
passed stage 1 and was then rejected as eval:REJECT, which
training_track.yml auto-closes.

Thread the window gate_training_pr already computes down through
verify_remote_proof_bundle_scores -> _download_and_verify_bundle ->
verify_submission, and give record_merged_ledger_entry the PR's
merge_base_ref so the merge-time ledger path computes the same window
(otherwise a merged run can be logged eval:REJECT and skip its
frontiers.json update).

The new parameter defaults to None, so the standalone `python -m eval.verify`
validator path keeps requiring the pin at datasets/canonical.json.

Closes gittensor-model-hub#231
@ai-hpc
ai-hpc merged commit f73ad53 into gittensor-model-hub:main Jul 25, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Canonical-pin grace window is dropped in eval.verify, so honest training PRs are auto-closed as eval:REJECT

2 participants