feat(scoring): surface the saturated base-score value in the score breakdown#2356
Conversation
…eakdown explainScoreBreakdown explained every multiplier on scoreEstimate that scales the score (density, contribution bonus, label, issue, credibility, review-penalty, review-collateral, open-PR pressure, open-issue spam, the merged-PR history floor from JSONbored#1801, the issue-discovery validity floor from JSONbored#1984, and the time-decay floor from JSONbored#1877) but silently omitted the **baseScore** itself — the saturated-value foundation `25 × (1 - exp(-src_tok / SRC_TOK_SATURATION_SCALE=58)) + min(total_token_score / CONTRIBUTION_SCORE_FOR_FULL_BONUS=1500, 1) × MAX_CONTRIBUTION_BONUS=5` (capped at 30) that flows into estimatedMergedScore before any multiplier applies. A contributor could see their `densityMultiplier` was healthy but had no surface for the actual cap contribution or the contribution-bonus adder. Add a `baseScoreBreakdown` sibling of `densityBreakdown` (which already uses `baseTokenGatePassed` as a gate trigger) that: - returns `blocked` when `baseTokenGatePassed` is false (the change does not yet meet the minimum meaningful source-change threshold), - returns `full` when baseScore is saturated near the 30-point cap and names whether the contribution bonus is contributing, - returns `neutral` when baseScore is mid-curve, with a copy that names BOTH the baseScore and the contributionBonus dimensions explicitly (avoids the §7 Tier A rule 3 collapse-copy nit — the production copy always iterates on observed values for both axes, no "no source contribution observed" single-clause ever produced). Purely additive explanation projection; no scoring behavior change. Wiring: - src/services/score-breakdown.ts: add `baseScoreBreakdown`, insert at index 0 of the components projection (foundation before density / contributionBonus), under the `leverageScore` convention that keeps `densityMultiplier` as the canonical top lever when both are blocked (baseScore blocked = 70, below densityMultiplier's 75). - test/unit/score-breakdown.test.ts: include the new `baseScore` component in the top-level `arrayContaining` regression list, and add a focused test covering the blocked / neutral-with-bonus / saturated branches (avoids the §7 Tier A rule 5 missing-both-branches test gap). Verified locally: - `git diff --check` clean. - `npm run typecheck` clean. - `npm run actionlint` clean. - `npm run db:migrations:check` — 90 migrations OK, contiguous 0001..0087. - `npm run build:mcp` clean. - `npx vitest run test/unit/score-breakdown.test.ts --coverage --coverage.include='src/services/score-breakdown.ts'` — **15/15 tests pass**; 100% statements; 100% lines; 3 uncovered branches in pre-existing code (issueMultiplierBreakdown:240 + 2 in pre-existing reviewCollateralBreakdown), not touched by this change. Diff stat: `src/services/score-breakdown.ts` +34 lines, `test/unit/score-breakdown.test.ts` +60 lines, total +94 lines (`size:S` territory; orb counts src files primarily per §7 Tier A rule 1).
|
Warning 🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨 ⏸️ Gittensory review result - manual review recommendedReview updated: 2026-07-01 19:01:55 UTC
⏸️ Suggested Action - Manual Review
Review summary Nits — 5 non-blocking
Review context
Contributor next steps
Signal definitions
🟩 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.
|
- Fix test fixture MAX_CONTRIBUTION_BONUS from 25 to 5 (match production) - Replace hardcoded '30-point cap' with generic 'score cap' text - Extract BASE_SCORE_SATURATION_DISPLAY_THRESHOLD (29.5) as named constant - Bump baseScore blocked leverageScore from 70 to 75 (match density gate block) - Split 3-branch test into separate focused it() blocks - Add test for hasBonus=false + gate-passed branch
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2356 +/- ##
=======================================
Coverage 95.61% 95.62%
=======================================
Files 218 218
Lines 24315 24333 +18
Branches 8818 8829 +11
=======================================
+ Hits 23250 23268 +18
Misses 436 436
Partials 629 629
🚀 New features to boost your workflow:
|
… not hardcoded threshold Hardcoding BASE_SCORE_SATURATION_DISPLAY_THRESHOLD=29.5 meant any preview using different MERGED_PR_BASE_SCORE or MAX_CONTRIBUTION_BONUS constants would mislabel saturated vs sub-cap. - Add baseScoreCap to ScorePreviewResult.scoreEstimate (computed alongside baseScore in the scoring core, which has the snapshot constants) - Replace hardcoded 29.5 with BASE_SCORE_SATURATION_RATIO=0.95 applied to baseScore / baseScoreCap — always relative to the active model's cap - baseScoreCap is undefined when fixedBaseScore is in effect - Add regression test with MERGED_PR_BASE_SCORE=50, MAX_CONTRIBUTION_BONUS=10 proving the threshold adapts to non-default constants
- Add baseScoreCap > 0 guard before saturation ratio division - Fix test comment: 993 is the 95% threshold value, not 'full bonus'
5777cc1 to
35a7131
Compare
c24bc29 to
4e496ca
Compare
- fixedBaseScore override → baseScoreCap undefined, copy says 'fixed base score override' - pending_saturation_model → cap = MERGED_PR_BASE_SCORE + MAX_CONTRIBUTION_BONUS
e3a5358 to
bb1b63c
Compare
Summary
Adds a baseScore component to the score breakdown so miners see the saturated base-score value alongside the existing density/contribution multipliers.
What changed:
Review fixes applied (2 commits):
Files changed:
Validation: