Skip to content

feat(validator): per-repository eligibility#1293

Merged
entrius merged 2 commits into
testfrom
feat/per-repo-eligibility
May 17, 2026
Merged

feat(validator): per-repository eligibility#1293
entrius merged 2 commits into
testfrom
feat/per-repo-eligibility

Conversation

@anderdc
Copy link
Copy Markdown
Collaborator

@anderdc anderdc commented May 17, 2026

What

Eligibility moves from a single global gate per miner to an independent gate per repository. Each repo computes its own eligible/ineligible miner set from only that repo's PRs/issues, against its own thresholds — work in one repo never unlocks or penalizes another.

Changes

  • Config: RepositoryConfig gains an optional eligibility block — 12 overridable knobs (min_valid_merged_prs, min_credibility, spam thresholds, the issue-discovery equivalents). resolve_eligibility() overlays a repo's overrides onto the global default constants. The eligibility_mode bool is removed — "no gate" is now a repo with zeroed thresholds (oc-1 migrated accordingly).
  • Scoring: finalize_miner_scores groups PRs by repo and gates each repo independently; the gated/bypass split is gone. MinerEvaluation carries a per-repo RepoEvaluation map; the round-level scalars are rollups.
  • Issue discovery: gates per repo, with a new MIN_TOKEN_SCORE_FOR_VALID_ISSUE constant mirroring MIN_TOKEN_SCORE_FOR_BASE_SCORE.
  • Storage: miner_evaluations is written one row per (uid, hotkey, github_id, repository_full_name).
  • Issue bounties: payouts are no longer eligibility-gated — any registered miner who solves a bounty issue is paid.
  • Mulligan removed: credibility is now plain merged / (merged + closed).

Retuned defaults

MIN_VALID_MERGED_PRS 5→3, MIN_VALID_SOLVED_ISSUES 7→3, MIN_ISSUE_CREDIBILITY 0.80→0.70, open-PR/open-issue spam bases 10/5→2/2. MIN_CREDIBILITY stays 0.80.

Behaviour / emissions impact

This is stricter: work no longer pools across repos, so on-chain emissions reallocate the first round after deploy. Intended — see the feature plan.

Deploy order

The matching gittensor-db schema change (adds repository_full_name, 4-tuple unique constraint) must merge first — the old constraint rejects multi-repo rows. das-gittensor API changes follow. PRs linked separately.

Testing

ruff, ruff format, pyright, and pytest (795 passing) all green locally.

anderdc and others added 2 commits May 17, 2026 00:00
Eligibility is now computed per repository instead of globally. Each repo
gates and scores miners from only its own PRs/issues, against its own
optionally-overridden thresholds — work in one repo never unlocks or
penalizes another.

- RepositoryConfig gains an `eligibility` block of 12 overridable knobs;
  resolve_eligibility overlays it onto the global default constants
- finalize_miner_scores groups PRs by repo and gates each independently;
  the eligibility_mode bool and the gated/bypass split are removed
- issue discovery gates per repo, with the new per-repo
  MIN_TOKEN_SCORE_FOR_VALID_ISSUE constant
- MinerEvaluation carries a per-repo RepoEvaluation map; miner_evaluations
  is persisted one row per (uid, hotkey, github_id, repository_full_name)
- the credibility mulligan is removed; per-repo gate defaults retuned
- issue bounty payouts are no longer eligibility-gated

Requires the matching gittensor-db schema change to land first.
@entrius entrius merged commit ecf743e into test May 17, 2026
@entrius entrius deleted the feat/per-repo-eligibility branch May 17, 2026 18:42
plind-junior added a commit to plind-junior/gittensor that referenced this pull request May 21, 2026
PR entrius#1293 added a per-repo min_token_score_for_base_score eligibility override and wired it into the resolver, but mirror/scoring.py kept reading the global MIN_TOKEN_SCORE_FOR_BASE_SCORE. Issue-discovery already honored the per-repo value, so issues and PRs in the same repo were gated by different thresholds -- a silent state asymmetry.

calculate_base_score_for_pr_files now takes an optional threshold parameter and both callers (score_pr and the issue-discovery solving-PR cache miss) pass the resolved per-repo value. Regression tests cover the default plus permissive and stricter overrides.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
plind-junior added a commit to plind-junior/gittensor that referenced this pull request May 21, 2026
PR entrius#1293 added a per-repo min_token_score_for_base_score eligibility override and wired it into the resolver, but mirror/scoring.py kept reading the global MIN_TOKEN_SCORE_FOR_BASE_SCORE. Issue-discovery already honored the per-repo value, so issues and PRs in the same repo were gated by different thresholds -- a silent state asymmetry.

calculate_base_score_for_pr_files now takes an optional threshold parameter and both callers (score_pr and the issue-discovery solving-PR cache miss) pass the resolved per-repo value. Regression tests cover the default plus permissive and stricter overrides.
plind-junior added a commit to plind-junior/gittensor that referenced this pull request May 21, 2026
PR entrius#1293 added a per-repo min_token_score_for_base_score eligibility override and wired it into the resolver, but mirror/scoring.py kept reading the global MIN_TOKEN_SCORE_FOR_BASE_SCORE. Issue-discovery already honored the per-repo value, so issues and PRs in the same repo were gated by different thresholds -- a silent state asymmetry.

calculate_base_score_for_pr_files now takes an optional threshold parameter and both callers (score_pr and the issue-discovery solving-PR cache miss) pass the resolved per-repo value. Regression tests cover the default plus permissive and stricter overrides.
plind-junior added a commit to plind-junior/gittensor that referenced this pull request May 22, 2026
Collapse the three parallel per-repo config families (eligibility,
scoring, time-decay) into one spec-driven mechanism. Each family was
added separately (entrius#1293, entrius#1300) by copy-pasting the same resolve ->
coerce -> parse -> validate scaffolding.

- _FieldSpec declares each overridable field: caster, default constant,
  range bounds, and an optional note. Three spec tables drive everything.
- Generic helpers replace the duplication: _resolve_overrides (was 3
  pick-closure resolvers), _coerce_override (was 2), _parse_overrides
  (was 3 + 6 field-name tuples), _bound_desc/_validate_ranges (was 2
  validators with ~15 inline checks).
- resolve_*, _parse_*, _validate_*_configs become thin wrappers. Public
  API and dataclasses unchanged; no downstream caller touched.
- Net -134 lines in load_weights.py; a 4th override family is now a
  ~6-line spec entry instead of ~80 lines of boilerplate.

Pure refactor - no behavioral change. Adds 4 tests locking the
centralized paths (divisor note, nested time_decay range rejection,
inclusive-vs-exclusive bracket rendering). Full suite: 841 passing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Net-new functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants