Skip to content

feat(scoring): surface the saturated base-score value in the score breakdown#2356

Merged
JSONbored merged 6 commits into
JSONbored:mainfrom
RenzoMXD:feat/scoring-base-score-breakdown
Jul 1, 2026
Merged

feat(scoring): surface the saturated base-score value in the score breakdown#2356
JSONbored merged 6 commits into
JSONbored:mainfrom
RenzoMXD:feat/scoring-base-score-breakdown

Conversation

@RenzoMXD

@RenzoMXD RenzoMXD commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

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:

  • baseScoreBreakdown() function — 3 bands: blocked (gate), neutral (sub-cap), full (saturated)
  • baseScoreCap field on ScorePreviewResult.scoreEstimate (computed in scoring core)
  • BASE_SCORE_SATURATION_RATIO=0.95 for saturation detection (dynamic, per-model cap)
  • LeverageScore 75 when gate-blocked (ties with densityBreakdown for tie disclosure)
  • 5 test cases: blocked, neutral+bonus, neutral+no-bonus, saturated, + regression with alt constants

Review fixes applied (2 commits):

  1. e83f718: Named constant, fixture fix, split tests, bump blocked LS to 75
  2. a298b98: baseScoreCap field on ScorePreviewResult — saturation derived from model cap, not hardcoded 29.5

Files changed:

  • src/scoring/preview.ts — baseScoreCap typed + computed in scoring core
  • src/services/score-breakdown.ts — baseScoreBreakdown + BASE_SCORE_SATURATION_RATIO
  • test/unit/score-breakdown.test.ts — 5 new test cases + fixture fix

Validation:

  • npx vitest run test/unit/score-breakdown.test.ts → 19/19 pass
  • npm run typecheck → clean
  • CI: validate OK codecov/patch OK validate-code OK

…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).
@RenzoMXD RenzoMXD requested a review from JSONbored as a code owner July 1, 2026 11:18
@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Jul 1, 2026
@superagent-security superagent-security Bot removed the size:M This PR changes 30-99 lines, ignoring generated files. label Jul 1, 2026
@gittensory-orb

gittensory-orb Bot commented Jul 1, 2026

Copy link
Copy Markdown

Warning

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

⏸️ Gittensory review result - manual review recommended

Review updated: 2026-07-01 19:01:55 UTC

3 files · 1 AI reviewer · no blockers · readiness 48/100 · CI green · clean

⏸️ Suggested Action - Manual Review

  • Touches a guarded path — held for manual review

Review summary
The change adds a baseScore breakdown component and carries a model-derived baseScoreCap through the preview result so the UI can distinguish blocked, sub-cap, saturated, and fixed-override cases. The cap calculation is correctly tied to the active scoring model instead of a hardcoded threshold, and the new tests exercise the key visible branches in the breakdown. I do not see a reachable correctness break in the provided diff; the most notable cleanup is test-comment accuracy around the saturation-model case.

Nits — 5 non-blocking
  • nit: test/unit/score-breakdown.test.ts:621 has a misleading comment saying a value around 29.2 is below 28.5, while the actual test inputs use sourceTokenScore 100 and totalTokenScore 0 for the sub-cap case; fix the comment so it matches the exercised scenario.
  • src/services/score-breakdown.ts:39 consider trimming the long formula comment or moving the derivation detail beside computeScoreCore in src/scoring/preview.ts, since that is now the source of truth for baseScoreCap.
  • test/unit/score-breakdown.test.ts:621 update the saturation-model test comment to describe the actual sourceTokenScore 100 / totalTokenScore 0 sub-cap input, then keep the sourceTokenScore 400 full-bonus case as the saturated branch.
  • Readiness score is below the configured threshold — Use the readiness panel as advisory maintainer context; the score does not block this PR.
  • 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 ⚠️ Missing No linked issue or no-issue rationale found.
Related work ⚠️ 3 scoped overlaps Top overlaps are listed below; lower-confidence bulk is hidden.
Change scope ❌ 8/20 High review scope from cached public metadata (size label size:M; 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: 62 registered-repo PR(s), 31 merged, 7 issue(s).
Contributor context ✅ Confirmed Gittensor contributor RenzoMXD; Gittensor profile; 62 PR(s), 7 issue(s).
Gate result ⚠️ Not blocking Advisory; not blocking this PR.
Review context
Contributor next steps
  • Explain no-issue PR.
  • Review top overlaps.
  • Add a concise scope and risk note.
  • Await review-lane availability.
  • Triage stale or unlinked PRs.
  • Refresh registry data or choose a registered active repo.
  • Link the issue being solved, or explicitly explain why this is a no-issue PR.
  • Check active issues and PRs before submitting.
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

@gittensory-orb gittensory-orb Bot added gittensor Gittensor contributor context gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 1.25x multiplier. labels Jul 1, 2026
- 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
@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Jul 1, 2026
@codecov

codecov Bot commented Jul 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.62%. Comparing base (fa09b39) to head (bb1b63c).
⚠️ Report is 55 commits behind head on main.

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           
Files with missing lines Coverage Δ
src/scoring/preview.ts 99.09% <100.00%> (+<0.01%) ⬆️
src/services/score-breakdown.ts 99.11% <100.00%> (+0.13%) ⬆️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

… 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
@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:M This PR changes 30-99 lines, ignoring generated files. labels Jul 1, 2026
- Add baseScoreCap > 0 guard before saturation ratio division
- Fix test comment: 993 is the 95% threshold value, not 'full bonus'
@RenzoMXD RenzoMXD force-pushed the feat/scoring-base-score-breakdown branch from 5777cc1 to 35a7131 Compare July 1, 2026 15:45
@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. size:L This PR changes 100-499 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. size:M This PR changes 30-99 lines, ignoring generated files. labels Jul 1, 2026
@RenzoMXD RenzoMXD force-pushed the feat/scoring-base-score-breakdown branch from c24bc29 to 4e496ca Compare July 1, 2026 16:03
@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. size:L This PR changes 100-499 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. size:M This PR changes 30-99 lines, ignoring generated files. labels Jul 1, 2026
- fixedBaseScore override → baseScoreCap undefined, copy says 'fixed base score override'
- pending_saturation_model → cap = MERGED_PR_BASE_SCORE + MAX_CONTRIBUTION_BONUS
@RenzoMXD RenzoMXD force-pushed the feat/scoring-base-score-breakdown branch from e3a5358 to bb1b63c Compare July 1, 2026 16:17
@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Jul 1, 2026
@dosubot dosubot Bot added the lgtm Approved by a maintainer. label Jul 1, 2026
@JSONbored JSONbored merged commit 6fa9637 into JSONbored:main Jul 1, 2026
9 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in gittensory - v1 roadmap Jul 1, 2026
@RenzoMXD RenzoMXD deleted the feat/scoring-base-score-breakdown branch July 2, 2026 13:23
@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:feature Gittensor-scored feature linked to a feature issue — scores a 1.25x multiplier. gittensor Gittensor contributor context lgtm Approved by a maintainer. size:M This PR changes 30-99 lines, ignoring generated files.

Projects

No open projects
Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants