Skip to content

fix(decision): match label history against config labels case-insensitively#2580

Merged
JSONbored merged 1 commit into
JSONbored:mainfrom
glorydavid03023:fix/decision-pack-label-case
Jul 2, 2026
Merged

fix(decision): match label history against config labels case-insensitively#2580
JSONbored merged 1 commit into
JSONbored:mainfrom
glorydavid03023:fix/decision-pack-label-case

Conversation

@glorydavid03023

Copy link
Copy Markdown
Contributor

Summary

buildContributorDecisionPack built its label-history Set straight from registeredRepoActivity.dominantLabels (raw GitHub casing) and looked up config labels with a raw .has(label):

// src/services/decision-pack.ts
const labelHistory = new Set(args.profile.registeredRepoActivity?.dominantLabels ?? []); // not lowercased
// ...
Object.keys(args.repo.registryConfig?.labelMultipliers ?? {}).filter((label) => labelHistory.has(label)) // raw

The canonical sibling — the opportunity engine — lowercases both sides (src/signals/engine.ts:1385 builds new Set(dominantLabels.map((l) => l.toLowerCase())), queried labelHistory.has(label.toLowerCase())), and this same function's languageSet is already case-insensitive (:618 build + :772 toLowerCase() lookup). Labels were the local outlier: a mixed-case dominant label (e.g. "Good first issue") never overlapped a differently-cased config label (e.g. "good first issue"), so it was silently dropped from the decision-pack's user-facing label-overlap copy ("Label overlap with your history: …", "target labels: …").

Fix: lowercase both the built Set and the config-key lookup, so label overlap is case-insensitive — matching the engine and the languageSet handling.

dominantLabels ["Good first issue"] + config { "good first issue": 1.5 }
// before: labelFit []          (dropped)
// after:  labelFit ["good first issue"]

No issue because issue creation is restricted on this repo for outside accounts; this aligns a duplicated case-insensitive-label-overlap concept with its canonical sibling.

Scope

  • Conventional Commit title; focused; follows CONTRIBUTING; small self-evident fix (no linked issue).

Validation

  • git diff --check
  • npm run typecheck
  • npm run test:coverage (scoped: test/unit/decision-pack.test.ts — 45 pass; both changed lines and their branches are exercised by the added mixed-case regression plus the existing empty/absent cases)
  • npm run test:workers
  • npm run build:mcp
  • npm run test:mcp-pack
  • npm run ui:openapi:check
  • npm run ui:lint
  • npm run ui:typecheck
  • npm run ui:build
  • npm audit --audit-level=moderate
  • New or changed behavior has unit/integration tests for new branches, fallback paths, and sanitizer boundaries

If any required check was skipped, explain why:

  • Backend-only change confined to src/services/decision-pack.ts. typecheck clean; decision-pack.test.ts passes (45), including the added regression that pins case-insensitive label overlap end-to-end (mixed-case dominant label) and on the lookup side (mixed-case config key). I did not run the full UI/workers/MCP steps (unrelated to this diff), and the local Windows tree has pre-existing unrelated failures (CRLF, missing CLI binaries, Node 24 vs pinned 22). CI runs the full matrix on a clean checkout.

Safety

  • No secrets/wallets/hotkeys/trust/reward/private terms exposed.
  • Public GitHub text stays sanitized and low-noise.
  • Auth/cookie/CORS/session negative-path tests. — N/A: no such changes.
  • API/OpenAPI/MCP behavior updated/tested where needed. (No such surface changed; internal decision-pack copy only.)
  • UI changes use live API data. — N/A: no UI change.
  • UI Evidence. — N/A: no visible UI change.
  • Docs/changelog updated where needed. (None needed.)

Notes

  • The engine (signals/engine.ts) already lowercases label history for its opportunity labelFit; this brings the decision-pack path to the same case-insensitive behavior, so the two surfaces agree.
  • No UI Evidence section: there is no visible UI, frontend, docs, or extension change.

…tively

buildContributorDecisionPack built its label-history Set straight from
registeredRepoActivity.dominantLabels (raw GitHub casing) and looked up config
labels with a raw `.has(label)`. The opportunity engine (signals/engine.ts)
lowercases both sides, and this file's own languageSet is already
case-insensitive, so labels were the local outlier: a mixed-case dominant label
(e.g. "Good first issue") never overlapped a differently-cased config label
(e.g. "good first issue"), silently dropping it from the decision-pack
label-overlap copy.

Lowercase both the built Set and the config-key lookup so label overlap is
case-insensitive, matching the engine and the languageSet handling. Adds a
regression test covering a mixed-case dominant label end-to-end and a mixed-case
config key on the lookup side.

No issue because issue creation is restricted on this repo; this aligns a
duplicated case-insensitive-label-overlap concept with its canonical sibling,
no schema or API change.
@dosubot dosubot Bot added the size:XS label Jul 2, 2026
@loopover-orb

loopover-orb Bot commented Jul 2, 2026

Copy link
Copy Markdown

Warning

🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨

⏸️ Gittensory review result - manual review recommended

Review updated: 2026-07-02 11:03:42 UTC

2 files · 1 AI reviewer · no blockers · readiness 80/100 · CI green · clean

⏸️ Suggested Action - Manual Review

  • Touches a guarded path — held for manual review

Review summary
This change correctly normalizes label history and config-label lookup to lower case in the decision-pack path, bringing label overlap behavior in line with the existing case-insensitive language matching. The output still preserves the config key casing in labelFit, so user-facing copy remains tied to repository configuration while matching mixed-case history. The added regression exercises both the Set construction path and the lookup-side path, and I do not see a reachable break in the visible diff.

Nits — 1 non-blocking
  • Touches a guarded path — held for manual review — A maintainer must review and merge this change.
Signal Result Evidence
Code review ✅ No blockers 1 reviewer
Linked issue ✅ No-issue rationale PR body explains why no issue is linked.
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 (size label size:XS; no linked issue context).
Validation posture ❌ 5/25 Preflight is holding this PR: the review lane is unavailable, so it is not ready for automated review.
Contributor workload ✅ 10/10 Author activity: 213 registered-repo PR(s), 142 merged, 9 issue(s).
Contributor context ✅ Confirmed Gittensor contributor glorydavid03023; Gittensor profile; 213 PR(s), 9 issue(s).
Gate result ⚠️ Not blocking Advisory; not blocking this PR.
Review context
  • Author: glorydavid03023
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository registration is not available in the local Gittensory cache.
  • Public profile languages: not available
  • Official Gittensor activity: 213 PR(s), 9 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Await review-lane availability.
  • Refresh registry data or choose a registered active repo.
  • Link the issue being solved, or explicitly explain why this is a no-issue PR.
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.

🟩 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 Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

@loopover-orb loopover-orb Bot added gittensor gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. labels Jul 2, 2026
@codecov

codecov Bot commented Jul 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.98%. Comparing base (1092bf3) to head (e817ae2).
⚠️ Report is 19 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2580      +/-   ##
==========================================
- Coverage   95.98%   95.98%   -0.01%     
==========================================
  Files         229      229              
  Lines       25814    25810       -4     
  Branches     9391     9388       -3     
==========================================
- Hits        24778    24774       -4     
  Misses        425      425              
  Partials      611      611              
Files with missing lines Coverage Δ
src/services/decision-pack.ts 97.31% <100.00%> (ø)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@dosubot dosubot Bot added the lgtm label Jul 2, 2026
@JSONbored
JSONbored merged commit 2ca1fb6 into JSONbored:main Jul 2, 2026
9 checks passed
@github-actions github-actions Bot mentioned this pull request Jul 2, 2026
12 tasks
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

None yet

Development

Successfully merging this pull request may close these issues.

2 participants