Skip to content

fix(signals): dedupe overlapping label sources in contributor dominantLabels - #418

Merged
JSONbored merged 2 commits into
JSONbored:mainfrom
galuis116:fix/dominant-labels-dedupe-sources
Jun 5, 2026
Merged

fix(signals): dedupe overlapping label sources in contributor dominantLabels#418
JSONbored merged 2 commits into
JSONbored:mainfrom
galuis116:fix/dominant-labels-dedupe-sources

Conversation

@galuis116

Copy link
Copy Markdown
Contributor

Summary

Both contributor-profile builders computed registeredRepoActivity.dominantLabels by concatenating labels from two overlapping views of the same activity and frequency-ranking the combined list with topItems(..., 8):

  • cached authored PR/issue records, and
  • the contributor's pre-aggregated repoStats.dominantLabels (built during backfill) for the same repos.

So for any repo the contributor has both cached records and a stat row in — the normal case — that repo's labels were counted twice. Every other field in the same function already reconciles these two sources as overlapping: reposTouched uses new Set([...]) (dedupe), unlinkedOpenPullRequests uses Math.max(...), statPullRequests/statMergedPullRequests use the stats only. dominantLabels was the lone outlier that summed them. Closes #417.

This is scoring, not just display: dominantLabels becomes labelHistory (decision-pack.ts, buildContributorOpportunities) and drives labelFit (+5 per matching label in opportunity scores and repo-decision reasoning). Because labelHistory is the top-8 set, double-counting shifts which labels survive the cutoff — a low-frequency repo-dominant label can displace a higher-effort single-source label, perturbing the rankings surfaced to miners.

Scope

  • src/signals/engine.ts:
    • buildContributorProfile — only fold repoStats.dominantLabels for repos that have no cached authored records (cachedLabelRepos guard).
    • buildGittensorContributorProfile — only fold repoStats.dominantLabels for repos not present in snapshot.repositories.
    • Both preserve complementary coverage (stats still fill in repos the cached/snapshot data does not have) while removing the overlap double-count, consistent with how the sibling fields reconcile the same sources.
  • test/unit/signals-coverage.test.ts — fail-on-revert: a stat-only-label for a repo that already has cached records must not appear in dominantLabels (old code included it), while an uncached-label for a repo with no cached records still contributes.

Validation

  • npx tsc --noEmit — clean.
  • npx vitest run (full suite) — 1132 passed, 1 skipped; no other assertions affected.
  • Branch coverage 97.04% (above the 97% gate); engine.ts 98.05% branch (the new filter branches in both builders are covered).

Safety

  • Behavior is unchanged for contributors whose cached records and repoStats cover disjoint repos (the common-repo overlap is exactly what was being double-counted). No public schema/API surface change; dominantLabels keeps its type and topItems(..., 8) shape.
  • Purely a deduplication of an already-computed overlap; stat-derived labels for repos without cached records are still included.

Notes

The fix mirrors the existing reposTouched (dedupe) / unlinkedOpenPullRequests (max) treatment of the same two sources, so the whole function now reconciles cached records and repoStats consistently.

@ghost

ghost commented Jun 5, 2026

Copy link
Copy Markdown

Note

Gittensory Gate skipped

PR closed before full evaluation. No late first comment was created.

Signal Result Evidence Action
Gate result ⚠️ Skipped #418 is no longer open. No action.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

@github-actions github-actions Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jun 5, 2026

@JSONbored JSONbored left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@galuis116 this is ready from my side.

A few notes:

  • This fixes the double-counting path without dropping complementary stat-only repo labels.
  • The regression covers both cached-record overlap and uncached stat contribution.
  • Non-Gittensory checks are green, and I do not have code changes to request.

@dosubot dosubot Bot added the lgtm label Jun 5, 2026
@JSONbored
JSONbored merged commit 1ea1372 into JSONbored:main Jun 5, 2026
6 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in gittensory - v1 roadmap Jun 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier.

Projects

No open projects
Status: Done

2 participants