Skip to content

ci(bot): pin coverage threshold floor before phase-2 cleanup - #835

Merged
LucasSantana-Dev merged 1 commit into
release/v2.10.0from
ci/bot-coverage-threshold
May 9, 2026
Merged

LucasSantana-Dev merged 1 commit into
release/v2.10.0from
ci/bot-coverage-threshold

Conversation

@LucasSantana-Dev

@LucasSantana-Dev LucasSantana-Dev commented May 9, 2026 •

Copy link
Copy Markdown
Owner

What

Adds coverageThreshold to packages/bot/jest.config.cjs so the bot
suite's coverage gate becomes binding before phase-2 test cleanup
begins.

Why

After PR #821 landed, the bot suite has 2,848 tests / 39k LOC and
no coverage threshold configured. Per the canonical /test-cleanup
skill, deletions must run against a configured floor — otherwise pruning
is blind to coverage and a regression slips silently into CI.

This PR is intentionally tiny so the gate exists in CI before the
larger phase-2 deletion PR is opened.

Numbers

Metric Current Floor Headroom
Statements 67.03 % 65 % 2.03
Branches 63.47 % 60 % 3.47
Functions 63.89 % 60 % 3.89
Lines 68.15 % 65 % 3.15

The floor is the round-down of post-#821 baseline. The plan is to
tighten 2-3 % per cleanup phase as the suite shrinks toward proportional
size (target ~1,500 tests for a 39k LOC full-stack-tier bot).

Test posture

  • 2,848 / 2,848 tests pass on release/v2.10.0 post-merge.
  • Coverage run with new threshold: PASS.
  • No source changes — this is a CI-policy patch only.

Related

  • Plan: .agents/plans/test-cleanup-phase2.md
  • Follow-up: test/suite-redesign-phase2 will start the actual cleanup
    pass after this lands.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Tests
    • Established minimum code coverage thresholds to maintain and improve baseline code quality standards.

Review Change Stack

Lock the bot package's coverage gate at the round-down of the post-#821
baseline so subsequent test-cleanup work has a tripwire. Numbers are
chosen to be binding without forcing emergency repair on day 1; tighten
2-3 % per phase as the suite shrinks toward proportional size.

Current vs floor:
  Statements 67.03 % (>= 65)
  Branches   63.47 % (>= 60)
  Functions  63.89 % (>= 60)
  Lines      68.15 % (>= 65)

Refs .agents/plans/test-cleanup-phase2.md
@vercel

vercel Bot commented May 9, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lucky Ready Ready Preview, Comment May 9, 2026 1:31pm

Request Review

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LucasSantana-Dev has reached the 50-review limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@coderabbitai

coderabbitai Bot commented May 9, 2026 •

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1ece5c1b-5072-4638-a8bc-9d229558163e

📥 Commits

Reviewing files that changed from the base of the PR and between d51a9f9 and bf7a2f1.

📒 Files selected for processing (1)
  • packages/bot/jest.config.cjs
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: AI Code Review
  • GitHub Check: Security
  • GitHub Check: Quality Gates
  • GitHub Check: SonarCloud Scan
🔇 Additional comments (1)
packages/bot/jest.config.cjs (1)

14-25: LGTM! Excellent baseline establishment.

The coverage threshold configuration is well-structured and follows best practices. The conservative floor values with 2-3% headroom provide a binding safety net without creating immediate CI friction, and the clear documentation referencing the post-#821 baseline and cleanup plan makes the intent transparent.


📝 Walkthrough

Walkthrough

This PR updates the Jest configuration for the bot package to enforce minimum code coverage thresholds. A coverageThreshold block is added to jest.config.cjs specifying global minimums of 65% for statements and lines, and 60% for branches and functions, based on a pinned baseline intended for future tightening.

Changes

Jest Coverage Configuration

Layer / File(s) Summary
Coverage Threshold Configuration
packages/bot/jest.config.cjs
Jest coverageThreshold.global is added with minimum coverage requirements for statements/lines (65%) and branches/functions (60%), backed by a pinned baseline comment.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: pinning a coverage threshold floor in the bot Jest configuration before phase-2 cleanup, which is the primary objective of the PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/bot-coverage-threshold

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented May 9, 2026

Copy link
Copy Markdown

Failed to generate code suggestions for PR

@LucasSantana-Dev
LucasSantana-Dev enabled auto-merge (squash) May 9, 2026 13:33
@sonarqubecloud

sonarqubecloud Bot commented May 9, 2026

Copy link
Copy Markdown

@LucasSantana-Dev
LucasSantana-Dev merged commit 1778d14 into release/v2.10.0 May 9, 2026
17 checks passed
LucasSantana-Dev added a commit that referenced this pull request May 10, 2026
…e/v2.10.0 merge

Merge from release/v2.10.0 brought in PR #835 (test phase-2) which
included new tests using the legacy 'reason: string' shape. Update
to the new {source, signals} basis API:

- autoplayAudit.spec.ts: createScoredTrack helper uses basis; setFinalSelected
  + emit tests pass basis instead of reason; expected reason becomes
  serializeBasis output ('spotify rec • preferred artist', 'last.fm similar').
- pipeline.integration.spec.ts: upsertScoredCandidate calls use {source, signals}.
- lastFmSeeder.spec.ts / candidateFallback.spec.ts: calculateRecommendationScore
  mock returns {score, signals} (no reason).
- queueManipulation.spec.ts: ScoredTrack literals use basis.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
LucasSantana-Dev added a commit that referenced this pull request May 10, 2026
…ionBasis (#830)

* refactor(autoplay): introduce RecommendationBasis type and serializeBasis

* refactor(autoplay): fix RecommendationSignal to match candidateScorer signal strings

* refactor(autoplay): candidateScorer returns signals array instead of reason string

* refactor(autoplay): collectors assign RecommendationSource to upsertScoredCandidate

* fix(tsconfig): update ignoreDeprecations from 6.0 to 5.0 for TypeScript 5.9 compatibility

* refactor(autoplay): serialize basis at display/persistence boundaries

- diversitySelector.ts: change markAsAutoplayTrack to use serializeBasis(candidate.basis)
- replenisher.ts: change debug log to use serializeBasis(s.basis) for display
- candidateFallback.ts: remove reason mutation in enrichWithAudioFeatures (signal already captured by scoreCalculation)
- candidateCollector.spec.ts: update tests to use new { score, source, signals } signature for upsertScoredCandidate

All TypeScript errors resolved for modified files. No behavior changes, only API boundary updates.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor(autoplay): complete recommendation basis migration - tests + cleanup

* refactor(autoplay): fix stale comment in serializeBasis

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(tsconfig): revert ignoreDeprecations back to 6.0

The project requires TypeScript ^6.0.3 per packages/shared/package.json.
The per-package tsc (6.0.3) requires "ignoreDeprecations": "6.0" to
silence the node10/baseUrl deprecation warnings. The earlier change to
"5.0" was based on running root-level tsc (5.9.3) which is not the
build tool for these packages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(tsconfig): bump ignoreDeprecations to 6.0 for frontend and backend

baseUrl is deprecated in TypeScript 7.0 and requires ignoreDeprecations: "6.0"
to silence the TS5101 error that was breaking the type check CI step.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(test): update 3 specs for RecommendationBasis refactor

- candidateFallback.spec.ts: createScoredTrack uses basis instead of
  reason; remove stale reason assertion (genre penalty only changes score)
- lastFmSeeder.spec.ts: mock ./candidateCollector for shouldInclude/
  upsertScored (moved from queueManipulation in this PR)
- replenisher.spec.ts: mockScoredTracks and candidateMap use basis to
  prevent serializeBasis(undefined) swallowing the telemetry log

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(autoplay): restore genre family drift signal tracking in enrichWithAudioFeatures

The penalty was applied to score but the signal was not pushed to
basis.signals after the RecommendationBasis refactor. Matches the
threshold used in candidateScorer.ts (familyPenalty <= -0.3).

Also restores the spec assertion to verify the signal is tracked.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(test): update lastFmSeeder spec assertions for RecommendationBasis refactor

Replace stale reason string checks with source field assertions after
upsertScoredCandidate signature changed from {score, reason} to
{score, source, signals}.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(test): update remaining lastFmSeeder reason assertions to source checks

Two more stale `reason` references (skips-disliked and vc-member tests)
updated to use source === 'lastfm-genre-fallback'.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(autoplay): address code review feedback on PR #830

- diversitySelector.ts: Use 'import type' for RecommendationBasis to follow project convention and avoid issues with strict module settings
- candidateCollector.ts: Add explanatory note to hard-reject debug logs about why signals are empty, improving debuggability

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: revert ignoreDeprecations to 5.0 and clean up spotifyRecommender

- Revert tsconfig ignoreDeprecations from 6.0 to 5.0 across all packages
  Root TypeScript is 5.9.3 and does not understand 6.0, causing TS5103 errors
  Per-package TypeScript 6.0.3 installation would be needed for 6.0 to work
- Clean up duplicate and stale code fragments in spotifyRecommender.ts
  from previous incomplete merge conflict resolution

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(tsconfig): restore ignoreDeprecations 6.0 for per-package TS 6.0.3

CI build failed with TS5107/TS5101 because previous revert dropped
ignoreDeprecations back to '5.0', but the per-package TypeScript is
6.0.3 and rejects '5.0'. Root tsconfig stays on '5.0' (root TS is 5.9.3).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(autoplay): replace stale t.reason with serializeBasis(t.basis) in autoplayAudit

setFinalSelected still referenced ScoredTrack.reason after the
RecommendationBasis refactor removed it. Wire serializeBasis the
same way diversitySelector.markAsAutoplayTrack does.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(autoplay): align specs with RecommendationBasis API after release/v2.10.0 merge

Merge from release/v2.10.0 brought in PR #835 (test phase-2) which
included new tests using the legacy 'reason: string' shape. Update
to the new {source, signals} basis API:

- autoplayAudit.spec.ts: createScoredTrack helper uses basis; setFinalSelected
  + emit tests pass basis instead of reason; expected reason becomes
  serializeBasis output ('spotify rec • preferred artist', 'last.fm similar').
- pipeline.integration.spec.ts: upsertScoredCandidate calls use {source, signals}.
- lastFmSeeder.spec.ts / candidateFallback.spec.ts: calculateRecommendationScore
  mock returns {score, signals} (no reason).
- queueManipulation.spec.ts: ScoredTrack literals use basis.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(autoplay): dedupe 'genre family drift' signal push in enrichWithAudioFeatures

Address CodeRabbit feedback on PR #830. Although serializeBasis dedupes
via Array.from(new Set), the in-memory ScoredTrack.basis.signals[] could
accumulate duplicates if the same track flows through enrichment twice.
Guard with .includes() before push.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
LucasSantana-Dev added a commit that referenced this pull request May 13, 2026
Lock the bot package's coverage gate at the round-down of the post-#821
baseline so subsequent test-cleanup work has a tripwire. Numbers are
chosen to be binding without forcing emergency repair on day 1; tighten
2-3 % per phase as the suite shrinks toward proportional size.

Current vs floor:
  Statements 67.03 % (>= 65)
  Branches   63.47 % (>= 60)
  Functions  63.89 % (>= 60)
  Lines      68.15 % (>= 65)

Refs .agents/plans/test-cleanup-phase2.md
LucasSantana-Dev added a commit that referenced this pull request May 13, 2026
…ionBasis (#830)

* refactor(autoplay): introduce RecommendationBasis type and serializeBasis

* refactor(autoplay): fix RecommendationSignal to match candidateScorer signal strings

* refactor(autoplay): candidateScorer returns signals array instead of reason string

* refactor(autoplay): collectors assign RecommendationSource to upsertScoredCandidate

* fix(tsconfig): update ignoreDeprecations from 6.0 to 5.0 for TypeScript 5.9 compatibility

* refactor(autoplay): serialize basis at display/persistence boundaries

- diversitySelector.ts: change markAsAutoplayTrack to use serializeBasis(candidate.basis)
- replenisher.ts: change debug log to use serializeBasis(s.basis) for display
- candidateFallback.ts: remove reason mutation in enrichWithAudioFeatures (signal already captured by scoreCalculation)
- candidateCollector.spec.ts: update tests to use new { score, source, signals } signature for upsertScoredCandidate

All TypeScript errors resolved for modified files. No behavior changes, only API boundary updates.

* refactor(autoplay): complete recommendation basis migration - tests + cleanup

* refactor(autoplay): fix stale comment in serializeBasis

* fix(tsconfig): revert ignoreDeprecations back to 6.0

The project requires TypeScript ^6.0.3 per packages/shared/package.json.
The per-package tsc (6.0.3) requires "ignoreDeprecations": "6.0" to
silence the node10/baseUrl deprecation warnings. The earlier change to
"5.0" was based on running root-level tsc (5.9.3) which is not the
build tool for these packages.

* fix(tsconfig): bump ignoreDeprecations to 6.0 for frontend and backend

baseUrl is deprecated in TypeScript 7.0 and requires ignoreDeprecations: "6.0"
to silence the TS5101 error that was breaking the type check CI step.

* fix(test): update 3 specs for RecommendationBasis refactor

- candidateFallback.spec.ts: createScoredTrack uses basis instead of
  reason; remove stale reason assertion (genre penalty only changes score)
- lastFmSeeder.spec.ts: mock ./candidateCollector for shouldInclude/
  upsertScored (moved from queueManipulation in this PR)
- replenisher.spec.ts: mockScoredTracks and candidateMap use basis to
  prevent serializeBasis(undefined) swallowing the telemetry log

* fix(autoplay): restore genre family drift signal tracking in enrichWithAudioFeatures

The penalty was applied to score but the signal was not pushed to
basis.signals after the RecommendationBasis refactor. Matches the
threshold used in candidateScorer.ts (familyPenalty <= -0.3).

Also restores the spec assertion to verify the signal is tracked.

* fix(test): update lastFmSeeder spec assertions for RecommendationBasis refactor

Replace stale reason string checks with source field assertions after
upsertScoredCandidate signature changed from {score, reason} to
{score, source, signals}.

* fix(test): update remaining lastFmSeeder reason assertions to source checks

Two more stale `reason` references (skips-disliked and vc-member tests)
updated to use source === 'lastfm-genre-fallback'.

* fix(autoplay): address code review feedback on PR #830

- diversitySelector.ts: Use 'import type' for RecommendationBasis to follow project convention and avoid issues with strict module settings
- candidateCollector.ts: Add explanatory note to hard-reject debug logs about why signals are empty, improving debuggability

* fix: revert ignoreDeprecations to 5.0 and clean up spotifyRecommender

- Revert tsconfig ignoreDeprecations from 6.0 to 5.0 across all packages
  Root TypeScript is 5.9.3 and does not understand 6.0, causing TS5103 errors
  Per-package TypeScript 6.0.3 installation would be needed for 6.0 to work
- Clean up duplicate and stale code fragments in spotifyRecommender.ts
  from previous incomplete merge conflict resolution

* fix(tsconfig): restore ignoreDeprecations 6.0 for per-package TS 6.0.3

CI build failed with TS5107/TS5101 because previous revert dropped
ignoreDeprecations back to '5.0', but the per-package TypeScript is
6.0.3 and rejects '5.0'. Root tsconfig stays on '5.0' (root TS is 5.9.3).

* fix(autoplay): replace stale t.reason with serializeBasis(t.basis) in autoplayAudit

setFinalSelected still referenced ScoredTrack.reason after the
RecommendationBasis refactor removed it. Wire serializeBasis the
same way diversitySelector.markAsAutoplayTrack does.

* test(autoplay): align specs with RecommendationBasis API after release/v2.10.0 merge

Merge from release/v2.10.0 brought in PR #835 (test phase-2) which
included new tests using the legacy 'reason: string' shape. Update
to the new {source, signals} basis API:

- autoplayAudit.spec.ts: createScoredTrack helper uses basis; setFinalSelected
  + emit tests pass basis instead of reason; expected reason becomes
  serializeBasis output ('spotify rec • preferred artist', 'last.fm similar').
- pipeline.integration.spec.ts: upsertScoredCandidate calls use {source, signals}.
- lastFmSeeder.spec.ts / candidateFallback.spec.ts: calculateRecommendationScore
  mock returns {score, signals} (no reason).
- queueManipulation.spec.ts: ScoredTrack literals use basis.

* fix(autoplay): dedupe 'genre family drift' signal push in enrichWithAudioFeatures

Address CodeRabbit feedback on PR #830. Although serializeBasis dedupes
via Array.from(new Set), the in-memory ScoredTrack.basis.signals[] could
accumulate duplicates if the same track flows through enrichment twice.
Guard with .includes() before push.

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
LucasSantana-Dev added a commit that referenced this pull request May 13, 2026
Promote [Unreleased] entries into the v2.10.0 section, bump root + workspace
versions from 2.9.0 to 2.10.0, and update the lockfile.

Release highlights:
- Spotify 429 retry hardening (#808)
- Last.fm canonical metadata + multi-artist scrobble fix (#821)
- Autoplay Spanish-gospel-block + sertanejo prioritization series
  (#817-#820, #827, #829, #830)
- Review-tools revamp: Claude review + Danger + chilled CodeRabbit
  via org-level reusable workflows (#838)
- Coverage threshold pinned for phase-2 test cleanup (#835)
- CI extended to release/** branches (#816)
@LucasSantana-Dev
LucasSantana-Dev deleted the ci/bot-coverage-threshold branch May 23, 2026 02:21

This branch was successfully deployed

1 active deployment
Preview — bf7a2f15 Deployed May 9, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant