Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions gittensor/validator/oss_contributions/mirror/scoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
- ``edited_after_merge`` is NOT a PR-level gate — it gates only the issue
bonus multiplier in ``_is_valid_linked_issue``, matching legacy
``is_valid_issue``.
- Mirror's ``actor_association`` per label lets ``_resolve_maintainer_set_label``
require maintainer-applied labels; legacy can't do this and accepts any-applier.
- Mirror's ``actor_association`` per label lets ``_resolve_trusted_scoring_label``
require maintainer-applied labels unless a repo opts into its trusted label pipeline.
"""

import os
Expand Down Expand Up @@ -351,7 +351,7 @@ def _calculate_pr_multipliers(scored: ScoredMirrorPR, repo_config: RepositoryCon

scored.repo_weight_multiplier = resolve_repo_weight(repo_config)

chosen_label = _resolve_maintainer_set_label(pr)
chosen_label = _resolve_trusted_scoring_label(pr, repo_config)
scored.label = chosen_label
scored.label_multiplier = LABEL_MULTIPLIERS.get(chosen_label, 1.0) if chosen_label else 1.0

Expand All @@ -372,21 +372,22 @@ def _calculate_pr_multipliers(scored: ScoredMirrorPR, repo_config: RepositoryCon
scored.review_quality_multiplier = 1.0


def _resolve_maintainer_set_label(pr: MirrorPullRequest) -> Optional[str]:
"""Pick the highest-multiplier currently-applied label that was set by a maintainer.
def _resolve_trusted_scoring_label(pr: MirrorPullRequest, repo_config: RepositoryConfig) -> Optional[str]:
"""Pick the highest-multiplier currently-applied scoring label from a trusted actor.

Mirror gives us actor attribution per label, so we can directly require the
label to have been applied by an OWNER/MEMBER/COLLABORATOR. Labels with null
actor_association (backfilled events) are ignored to be conservative.
By default, mirror labels must come from OWNER/MEMBER/COLLABORATOR actors.
Repos with trusted_label_pipeline=True may use bot/App labelers whose mirror
events have null actor_association, so any scoring label on those repos counts.
"""
trust_any_actor = repo_config.trusted_label_pipeline
candidates = [
label
for label in pr.labels
if label.actor_association in MAINTAINER_ASSOCIATIONS and (label.name or '').lower() in LABEL_MULTIPLIERS
if (label.name or '').lower() in LABEL_MULTIPLIERS
and (trust_any_actor or label.actor_association in MAINTAINER_ASSOCIATIONS)
]
if not candidates:
return None
# Highest multiplier wins; tie-broken by label name for deterministic output
best = max(candidates, key=lambda label: (LABEL_MULTIPLIERS[label.name.lower()], label.name.lower()))
return best.name.lower()

Expand Down
39 changes: 32 additions & 7 deletions gittensor/validator/utils/load_weights.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,37 @@ class RepositoryConfig:
mirror_enabled: When True, fetch this repo's data from the das-github-mirror
service instead of via per-miner PATs. Defaults to False so existing
entries keep their current PAT-based behavior.
trusted_label_pipeline: When True, mirror scoring trusts scoring labels
regardless of actor association. Defaults to False so community repos
keep the maintainer-association gate.

"""

weight: float
inactive_at: Optional[str] = None
additional_acceptable_branches: Optional[List[str]] = None
mirror_enabled: bool = False
trusted_label_pipeline: bool = False

@classmethod
def from_metadata(cls, metadata: dict) -> 'RepositoryConfig':
"""Parse a master_repositories.json entry into a typed config."""
if not isinstance(metadata, dict):
raise TypeError(f'repository metadata must be dict, got {type(metadata)}')
return cls(
weight=float(metadata.get('weight', DEFAULT_REPO_WEIGHT)),
inactive_at=metadata.get('inactive_at'),
additional_acceptable_branches=metadata.get('additional_acceptable_branches'),
mirror_enabled=_metadata_bool(metadata, 'mirror_enabled'),
trusted_label_pipeline=_metadata_bool(metadata, 'trusted_label_pipeline'),
)


def _metadata_bool(metadata: dict, key: str) -> bool:
value = metadata.get(key, False)
if isinstance(value, bool):
return value
raise TypeError(f'{key} must be bool, got {type(value)}')


def resolve_repo_weight(repo_config: Optional[RepositoryConfig]) -> float:
Expand Down Expand Up @@ -117,17 +141,18 @@ def load_master_repo_weights() -> Dict[str, RepositoryConfig]:
normalized_data: Dict[str, RepositoryConfig] = {}
for repo_name, metadata in data.items():
try:
config = RepositoryConfig(
weight=float(metadata.get('weight', 0.01)),
inactive_at=metadata.get('inactive_at'),
additional_acceptable_branches=metadata.get('additional_acceptable_branches'),
mirror_enabled=bool(metadata.get('mirror_enabled', False)),
)
config = RepositoryConfig.from_metadata(metadata)
normalized_data[repo_name.lower()] = config
except (ValueError, TypeError) as e:
bt.logging.warning(f'Could not parse config for {repo_name}: {e}, using defaults')
# Create config with defaults if parsing fails
normalized_data[repo_name.lower()] = RepositoryConfig(weight=float(metadata.get('weight', 0.01)))
weight = DEFAULT_REPO_WEIGHT
if isinstance(metadata, dict):
try:
weight = float(metadata.get('weight', DEFAULT_REPO_WEIGHT))
except (ValueError, TypeError):
pass
normalized_data[repo_name.lower()] = RepositoryConfig(weight=weight)

bt.logging.debug(f'Successfully loaded {len(normalized_data)} repository entries from {weights_file}')
return normalized_data
Expand Down
17 changes: 13 additions & 4 deletions gittensor/validator/weights/master_repositories.json
Original file line number Diff line number Diff line change
Expand Up @@ -205,19 +205,28 @@
},
"entrius/allways": {
"weight": 1.0,
"mirror_enabled": true
"mirror_enabled": true,
"trusted_label_pipeline": true
},
"entrius/allways-ui": {
"weight": 0.5,
"mirror_enabled": true
"mirror_enabled": true,
"trusted_label_pipeline": true
},
"entrius/das-github-mirror": {
"weight": 0.2,
"mirror_enabled": true,
"trusted_label_pipeline": true
},
"entrius/gittensor": {
"weight": 1.0,
"mirror_enabled": true
"mirror_enabled": true,
"trusted_label_pipeline": true
},
"entrius/gittensor-ui": {
"weight": 0.5,
"mirror_enabled": true
"mirror_enabled": true,
"trusted_label_pipeline": true
},
"espressif/arduino-esp32": {
"weight": 0.1444
Expand Down
85 changes: 62 additions & 23 deletions tests/validator/oss_contributions/mirror/test_scoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
_should_skip_merged_mirror_pr = scoring_module._should_skip_merged_mirror_pr
_convert_mirror_files = adapters_module.mirror_files_to_legacy
_calculate_pr_multipliers = scoring_module._calculate_pr_multipliers
_resolve_maintainer_set_label = scoring_module._resolve_maintainer_set_label
_resolve_trusted_scoring_label = scoring_module._resolve_trusted_scoring_label
_calculate_issue_multiplier = scoring_module._calculate_issue_multiplier
_is_valid_linked_issue = scoring_module._is_valid_linked_issue
score_mirror_pr = scoring_module.score_mirror_pr
Expand Down Expand Up @@ -100,11 +100,16 @@ def _pr(
)


def _config(weight: float = 0.5, additional_branches: list | None = None) -> RepositoryConfig:
def _config(
weight: float = 0.5,
additional_branches: list | None = None,
trusted_label_pipeline: bool = False,
) -> RepositoryConfig:
return RepositoryConfig(
weight=weight,
mirror_enabled=True,
additional_acceptable_branches=additional_branches,
trusted_label_pipeline=trusted_label_pipeline,
)


Expand Down Expand Up @@ -408,35 +413,41 @@ def test_renamed_file_carries_previous_filename(self):
class TestLabelResolution:
def test_no_labels_returns_none(self):
scored = ScoredMirrorPR(pr=_pr(labels=[]))
assert _resolve_maintainer_set_label(scored.pr) is None
assert _resolve_trusted_scoring_label(scored.pr, _config()) is None

def test_non_scoring_labels_ignored(self):
# 'enhancement' is in LABEL_MULTIPLIERS, 'random' typically isn't
labels = [
{'name': 'random', 'actor_github_id': '1', 'actor_association': 'OWNER'},
]
scored = ScoredMirrorPR(pr=_pr(labels=labels))
assert _resolve_maintainer_set_label(scored.pr) is None

def test_non_maintainer_label_ignored(self):
from gittensor.constants import LABEL_MULTIPLIERS

scoring_label = next(iter(LABEL_MULTIPLIERS.keys()))
labels = [
{'name': scoring_label, 'actor_github_id': '1', 'actor_association': 'CONTRIBUTOR'},
]
assert _resolve_trusted_scoring_label(scored.pr, _config()) is None

@pytest.mark.parametrize(
'actor_association,resolves',
[
('OWNER', True),
('MEMBER', True),
('COLLABORATOR', True),
('CONTRIBUTOR', False),
('NONE', False),
(None, False),
],
)
def test_untrusted_repo_requires_maintainer_actor(self, actor_association, resolves):
labels = [{'name': 'feature', 'actor_github_id': '1', 'actor_association': actor_association}]
scored = ScoredMirrorPR(pr=_pr(labels=labels))
assert _resolve_maintainer_set_label(scored.pr) is None
expected = 'feature' if resolves else None
assert _resolve_trusted_scoring_label(scored.pr, _config(trusted_label_pipeline=False)) == expected

def test_null_actor_association_ignored(self):
from gittensor.constants import LABEL_MULTIPLIERS

scoring_label = next(iter(LABEL_MULTIPLIERS.keys()))
labels = [
{'name': scoring_label, 'actor_github_id': None, 'actor_association': None},
]
@pytest.mark.parametrize(
'actor_association',
['OWNER', 'MEMBER', 'COLLABORATOR', 'CONTRIBUTOR', 'NONE', None],
)
def test_trusted_repo_accepts_any_scoring_label_actor(self, actor_association):
labels = [{'name': 'feature', 'actor_github_id': '1', 'actor_association': actor_association}]
scored = ScoredMirrorPR(pr=_pr(labels=labels))
assert _resolve_maintainer_set_label(scored.pr) is None
assert _resolve_trusted_scoring_label(scored.pr, _config(trusted_label_pipeline=True)) == 'feature'

def test_maintainer_set_scoring_label_returned(self):
from gittensor.constants import LABEL_MULTIPLIERS
Expand All @@ -446,7 +457,7 @@ def test_maintainer_set_scoring_label_returned(self):
{'name': scoring_label, 'actor_github_id': '1', 'actor_association': 'COLLABORATOR'},
]
scored = ScoredMirrorPR(pr=_pr(labels=labels))
assert _resolve_maintainer_set_label(scored.pr) == scoring_label.lower()
assert _resolve_trusted_scoring_label(scored.pr, _config()) == scoring_label.lower()

def test_highest_multiplier_wins(self):
from gittensor.constants import LABEL_MULTIPLIERS
Expand All @@ -462,7 +473,7 @@ def test_highest_multiplier_wins(self):
{'name': b, 'actor_github_id': '1', 'actor_association': 'OWNER'},
]
scored = ScoredMirrorPR(pr=_pr(labels=labels))
chosen = _resolve_maintainer_set_label(scored.pr)
chosen = _resolve_trusted_scoring_label(scored.pr, _config())
# Whichever label has the higher LABEL_MULTIPLIERS value should win
expected = max([a, b], key=lambda n: (LABEL_MULTIPLIERS[n], n)).lower()
assert chosen == expected
Expand Down Expand Up @@ -688,3 +699,31 @@ def test_open_pr_only_neutral_multipliers(self):
assert scored.time_decay_multiplier == 1.0
assert scored.credibility_multiplier == 1.0
assert scored.review_quality_multiplier == 1.0

def test_bot_applied_refactor_label_scores_on_trusted_repo(self):
labels = [{'name': 'refactor', 'actor_github_id': '1', 'actor_association': None}]
scored = ScoredMirrorPR(pr=_pr(labels=labels))

_calculate_pr_multipliers(scored, _config(trusted_label_pipeline=True))

assert scored.label == 'refactor'
assert scored.label_multiplier == 0.5

def test_bot_applied_label_stays_neutral_on_untrusted_repo(self):
labels = [{'name': 'feature', 'actor_github_id': '1', 'actor_association': None}]
scored = ScoredMirrorPR(pr=_pr(labels=labels))

_calculate_pr_multipliers(scored, _config(trusted_label_pipeline=False))

assert scored.label is None
assert scored.label_multiplier == 1.0

@pytest.mark.parametrize('trusted_label_pipeline', [False, True])
def test_maintainer_applied_label_scores_on_all_repos(self, trusted_label_pipeline):
labels = [{'name': 'feature', 'actor_github_id': '1', 'actor_association': 'OWNER'}]
scored = ScoredMirrorPR(pr=_pr(labels=labels))

_calculate_pr_multipliers(scored, _config(trusted_label_pipeline=trusted_label_pipeline))

assert scored.label == 'feature'
assert scored.label_multiplier == 1.5
64 changes: 63 additions & 1 deletion tests/validator/test_load_weights.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,24 @@ def test_mirror_enabled_field_present_on_live_configs(self):
f'{repo_name} mirror_enabled should be bool, got {type(config.mirror_enabled)}'
)

def test_trusted_label_pipeline_field_present_on_live_configs(self):
"""Live master_repositories.json entries load with a bool trusted_label_pipeline."""
repos = load_master_repo_weights()
for repo_name, config in repos.items():
assert isinstance(config.trusted_label_pipeline, bool), (
f'{repo_name} trusted_label_pipeline should be bool, got {type(config.trusted_label_pipeline)}'
)

def test_entrius_repos_enable_trusted_label_pipeline(self):
repos = load_master_repo_weights()
entrius_repos = {name: config for name, config in repos.items() if name.startswith('entrius/')}
assert entrius_repos, 'expected entrius/* entries in master_repositories.json'
for repo_name, config in entrius_repos.items():
assert config.trusted_label_pipeline is True, f'{repo_name} must trust its label pipeline'


class TestRepositoryConfigMirrorFlag:
"""Dataclass-level tests for the mirror_enabled field + its JSON parsing."""
"""Dataclass-level tests for mirror/trusted-label flags + JSON parsing."""

def test_mirror_enabled_default_false(self):
"""RepositoryConfig constructor defaults mirror_enabled to False."""
Expand All @@ -136,6 +151,14 @@ def test_mirror_enabled_explicit_true(self):
config = RepositoryConfig(weight=0.5, mirror_enabled=True)
assert config.mirror_enabled is True

def test_trusted_label_pipeline_default_false(self):
config = RepositoryConfig(weight=0.5)
assert config.trusted_label_pipeline is False

def test_trusted_label_pipeline_explicit_true(self):
config = RepositoryConfig(weight=0.5, trusted_label_pipeline=True)
assert config.trusted_label_pipeline is True

def test_loader_parses_mirror_enabled_true(self, tmp_path, monkeypatch):
"""load_master_repo_weights() parses mirror_enabled:true from JSON."""
import json
Expand All @@ -160,6 +183,45 @@ def test_loader_parses_mirror_enabled_true(self, tmp_path, monkeypatch):
assert repos['foo/legacy-repo'].mirror_enabled is False
assert repos['foo/explicit-off'].mirror_enabled is False

def test_loader_parses_trusted_label_pipeline_true(self, tmp_path, monkeypatch):
import json

from gittensor.validator.utils import load_weights as lw

fake_weights_dir = tmp_path
(fake_weights_dir / 'master_repositories.json').write_text(
json.dumps(
{
'foo/trusted-repo': {'weight': 0.5, 'trusted_label_pipeline': True},
'foo/untrusted-repo': {'weight': 0.3},
'foo/explicit-off': {'weight': 0.2, 'trusted_label_pipeline': False},
}
)
)
monkeypatch.setattr(lw, '_get_weights_dir', lambda: fake_weights_dir)

repos = lw.load_master_repo_weights()

assert repos['foo/trusted-repo'].trusted_label_pipeline is True
assert repos['foo/untrusted-repo'].trusted_label_pipeline is False
assert repos['foo/explicit-off'].trusted_label_pipeline is False

def test_string_bool_does_not_enable_trusted_label_pipeline(self, tmp_path, monkeypatch):
"""Pin _metadata_bool strictness: a JSON typo like "false" must not enable trust."""
import json

from gittensor.validator.utils import load_weights as lw

fake_weights_dir = tmp_path
(fake_weights_dir / 'master_repositories.json').write_text(
json.dumps({'foo/bad-bool': {'weight': 0.5, 'trusted_label_pipeline': 'false'}})
)
monkeypatch.setattr(lw, '_get_weights_dir', lambda: fake_weights_dir)

repos = lw.load_master_repo_weights()

assert repos['foo/bad-bool'].trusted_label_pipeline is False


class TestBannedOrganizations:
"""Tests ensuring banned organizations are not active in the repository list.
Expand Down
Loading