Skip to content

feat: combined weighted Health Report (#10) - #40

Merged
oekazuma merged 12 commits into
mainfrom
feat/health-report
Jun 23, 2026
Merged

oekazuma merged 12 commits into
mainfrom
feat/health-report

Conversation

@oekazuma

@oekazuma oekazuma commented Jun 23, 2026 •

Copy link
Copy Markdown
Owner

The differentiated 1.0 capstone: synthesize the per-category scores (SEO, Performance, Accessibility) into one weighted Health score, surfaced across reporters and the MCP analyze tool. This is svelte-vitals' own synthesis — not something official Svelte tooling provides.

What's new

  • computeHealth(results, config) (core) — weighted average over the present categories from scoresByCategory, equal weights by default (config.weights?.[cat] ?? 1), re-normalized over present categories; 100 when none are present.
  • Config.weights — optional per-category weights (programmatic for now; a CLI/config-file surface is a follow-up).
  • Console / agent — a Health: N/100 headline above the per-category scores.
  • --min-health <0-100> — optional CI gate: exit 1 when Health is below the threshold, OR-ed with the unchanged severity-based exit (--fail-on). No behavior change when omitted.
  • MCP analyze surfaces score (= Health) + weights for free (it returns the JSON report unchanged).

Breaking change (JSON report)

For the 1.0 lead-in, the JSON report's top-level score is now the combined Health score (it was the SEO score), the top-level scoreModel is removed, and a weights field is added. Per-category scores remain under categories (e.g. categories.seo.score / categories.seo.scoreModel). Called out in the changeset.

Roadmap

Moves the Health Report to Shipped and records that the Upgrade/deprecation category was dropped (covered by official Svelte tooling — the compiler, the Svelte MCP, and sv migrate). Remaining toward 1.0: rule-reference docs (fix the svelte-vitals.dev/rules/… links) and a config file.

Validation

  • pnpm -r test — 262 passed (core 96, vite 31, cli 126, mcp 9)
  • pnpm -r typecheck, pnpm build, pnpm lint, publint + attw (esm-only) — green

Notes for reviewers

  • Built subagent-driven: 5 tasks (each spec+quality reviewed) + a whole-branch review (verdict: ready to merge).
  • Known follow-up (roadmap C): validate non-negative weights when --weights/config-file lands; computeHealth documents the assumption.

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced Health Report: a combined weighted score aggregating SEO, Performance, and Accessibility with equal default weights, displayed in all reporters and MCP output.
    • Added --min-health <0-100> CLI option for health-based CI gating.
    • Configuration now supports customizable per-category weights.
  • Breaking Changes

    • JSON report: top-level score now represents Health (previously SEO score).
    • JSON report: removed top-level scoreModel; added new weights field.

oekazuma and others added 8 commits June 23, 2026 09:35
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…el (#10)

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

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

coderabbitai Bot commented Jun 23, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@oekazuma, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 13 minutes and 51 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e5c3a4fd-f803-4cbf-87b1-5117d0602bd8

📥 Commits

Reviewing files that changed from the base of the PR and between 4b99de6 and 127ca56.

📒 Files selected for processing (8)
  • docs/superpowers/plans/2026-06-23-health-report.md
  • docs/superpowers/specs/2026-06-23-health-report-design.md
  • packages/cli/src/bin.ts
  • packages/cli/src/index.ts
  • packages/cli/test/run.test.ts
  • packages/core/src/reporter/console.ts
  • packages/core/src/scoring/score.ts
  • packages/core/test/health.test.ts
📝 Walkthrough

Walkthrough

Adds a combined weighted Health score (SEO + Performance + Accessibility, equal default weights) via a new computeHealth function and Config.weights option. The JSON report's top-level score becomes Health, scoreModel is removed, and weights is added. Console and agent reporters gain a Health: N/100 headline, and the CLI gains a --min-health <0-100> exit-code gate.

Changes

Health Report Feature

Layer / File(s) Summary
Config.weights type and computeHealth implementation
packages/core/src/types.ts, packages/core/src/scoring/score.ts, packages/core/src/index.ts, packages/core/test/health.test.ts
Config gains weights?: Partial<Record<Category, number>>. HealthResult interface and computeHealth function are added to score.ts and re-exported from the core package. Four unit tests cover equal weighting, weight overrides, absent-category re-normalization, and empty-results fallback to 100.
JSON reporter schema reshape
packages/core/src/reporter/json.ts, packages/core/test/json-report.test.ts, packages/mcp/test/analyze-tool.test.ts
JsonReport removes top-level scoreModel, adds weights, and repurposes score as the combined Health value. buildJsonReport is rewired to use a single computeHealth call. Tests assert the new shape and verify MCP analyze output includes weights.
Console and agent reporter Health headline
packages/core/src/reporter/console.ts, packages/core/src/reporter/agent.ts, packages/core/test/console-report.test.ts, packages/core/test/agent-report.test.ts
Both reporters call computeHealth and prepend a Health: N/100 line to their output. Tests assert the headline appears above per-category score lines.
CLI --min-health gate
packages/cli/src/bin.ts, packages/cli/src/index.ts, packages/cli/test/run.test.ts
bin.ts adds --min-health help text, mri string option parsing, and validation (0–100). RunOptions gains minHealth?: number. run() exit code now also fails when computed health is below minHealth. Two end-to-end tests cover the gate tripping at 100 and passing at 0.
Spec, plan, changeset, and README
docs/superpowers/specs/..., docs/superpowers/plans/..., .changeset/health-report.md, README.md
Design spec and implementation plan documents are added. Changeset marks minor releases and documents the JSON breaking change. README roadmap adds Health Report to "Shipped" and reframes "Upcoming" as "Toward 1.0".

Sequence Diagram(s)

sequenceDiagram
  participant User as CLI User
  participant bin as bin.ts
  participant run as run() in index.ts
  participant computeHealth as computeHealth
  participant reporters as Console/Agent/JSON reporters

  User->>bin: svelte-vitals --min-health 80
  bin->>bin: parse & validate min-health (0–100)
  bin->>run: run({ ...options, minHealth: 80 })
  run->>reporters: formatConsoleReport / formatAgentReport / buildJsonReport
  reporters->>computeHealth: computeHealth(results, config)
  computeHealth-->>reporters: { health, categories, weights }
  reporters-->>run: formatted output with Health: N/100
  run->>computeHealth: computeHealth(results, config) for gate check
  computeHealth-->>run: { health: 72 }
  run->>run: health(72) < minHealth(80) → exit code 1
  run-->>User: exit 1
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • oekazuma/svelte-vitals#28: Introduced the MCP analyze tool whose structured JSON output shape is directly affected by this PR's score/weights changes and requires the added weights assertion.
  • oekazuma/svelte-vitals#36: Established scoresByCategory and the per-Result.category multi-category plumbing that computeHealth now builds on to derive the weighted Health aggregate.

Poem

🐇 A score for all three, not just one domain,
SEO, perf, a11y — balanced and plain.
computeHealth weighs them with equal delight,
JSON reshaped, scoreModel takes flight.
--min-health now guards the CI gate with care,
One Health to rule them all — how fair! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: combined weighted Health Report (#10)' accurately and concisely summarizes the primary change: introduction of a combined Health Report feature that synthesizes per-category scores into a single weighted score.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/health-report

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.

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/cli/src/bin.ts`:
- Around line 55-63: The validation logic for the minHealth parameter currently
logs an error message and continues execution when invalid input is provided,
which silently ignores the invalid --min-health argument and can lead to
false-green CI runs. In the else block where the validation fails for the
minHealthRaw value (checking if it is finite and between 0-100), replace the
console.error statement with a call to process.exit(1) to immediately terminate
the process with an error status when invalid --min-health input is detected.

In `@packages/cli/src/index.ts`:
- Around line 161-163: The opts.minHealth parameter is used directly in the
failByHealth condition without validation, which allows invalid values like NaN,
negative numbers, or values greater than 100 to bypass or force the health gate
unexpectedly. Add validation logic for opts.minHealth before it is used in the
comparison on line 162 to ensure that if minHealth is provided, it is a valid
number within an acceptable range (typically 0-100 for health percentages).
Either throw an error or provide a clear validation message when invalid values
are detected in the RunOptions object.

In `@packages/core/src/scoring/score.ts`:
- Around line 113-121: The weight values retrieved from config.weights in the
loop iterating over categories are not validated, allowing negative or
non-finite weights to be assigned to the weights object. This can produce
invalid Health values outside the 0-100 range. Add validation when assigning the
weight value `w` to the weights object to ensure it is non-negative and finite;
if the weight fails validation, treat it as the default value of 1. This will
preserve the Health contract and ensure the fallback to 100 when total weight is
non-positive works correctly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c26b66bf-8d6d-484b-8584-dafd4a5cbbdf

📥 Commits

Reviewing files that changed from the base of the PR and between a1fc649 and 4b99de6.

📒 Files selected for processing (18)
  • .changeset/health-report.md
  • README.md
  • docs/superpowers/plans/2026-06-23-health-report.md
  • docs/superpowers/specs/2026-06-23-health-report-design.md
  • packages/cli/src/bin.ts
  • packages/cli/src/index.ts
  • packages/cli/test/run.test.ts
  • packages/core/src/index.ts
  • packages/core/src/reporter/agent.ts
  • packages/core/src/reporter/console.ts
  • packages/core/src/reporter/json.ts
  • packages/core/src/scoring/score.ts
  • packages/core/src/types.ts
  • packages/core/test/agent-report.test.ts
  • packages/core/test/console-report.test.ts
  • packages/core/test/health.test.ts
  • packages/core/test/json-report.test.ts
  • packages/mcp/test/analyze-tool.test.ts

Comment thread packages/cli/src/bin.ts
Comment thread packages/cli/src/index.ts
Comment thread packages/core/src/scoring/score.ts Outdated
…hts (#10)

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a combined weighted Health score (derived from per-category scores) and surfaces it consistently across the JSON report, console/agent reporters, the MCP analyze tool, and CI gating via a new --min-health option.

Changes:

  • Introduces computeHealth(results, config) and Config.weights in @svelte-vitals/core, and exports them as public API.
  • Reshapes the JSON report so top-level score is now Health, adds top-level weights, and removes top-level scoreModel (per-category scoreModel remains).
  • Updates reporters + CLI: console/agent show a Health: N/100 headline; CLI adds --min-health gate and validation; tests/docs/changeset updated accordingly.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
README.md Documents Health Report as shipped and updates the roadmap toward 1.0.
packages/mcp/test/analyze-tool.test.ts Asserts MCP analyze structured output includes weights.
packages/core/test/json-report.test.ts Updates JSON report shape assertions + verifies score/weights match computeHealth.
packages/core/test/health.test.ts Adds unit tests for computeHealth behavior and weight validation.
packages/core/test/console-report.test.ts Verifies console reporter includes Health headline.
packages/core/test/agent-report.test.ts Verifies agent reporter includes Health headline.
packages/core/src/types.ts Adds Config.weights type.
packages/core/src/scoring/score.ts Implements HealthResult + computeHealth.
packages/core/src/reporter/json.ts Makes JSON top-level score = Health, adds weights, removes top-level scoreModel.
packages/core/src/reporter/console.ts Adds Health headline to console report.
packages/core/src/reporter/agent.ts Adds Health headline to agent report.
packages/core/src/index.ts Exports computeHealth/HealthResult.
packages/cli/test/run.test.ts Adds CLI tests for minHealth validation + gating behavior.
packages/cli/src/index.ts Adds RunOptions.minHealth, validates it, and applies the Health gate in exit logic.
packages/cli/src/bin.ts Adds --min-health parsing/validation and help text.
docs/superpowers/specs/2026-06-23-health-report-design.md Adds Health design/spec; currently needs alignment with implemented --min-health invalid-input behavior.
docs/superpowers/plans/2026-06-23-health-report.md Adds implementation plan; currently needs alignment with implemented --min-health invalid-input behavior.
.changeset/health-report.md Declares release notes + JSON breaking change for score/weights/scoreModel.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/core/src/reporter/console.ts
Comment thread packages/core/src/reporter/console.ts Outdated
Comment thread docs/superpowers/specs/2026-06-23-health-report-design.md Outdated
Comment thread docs/superpowers/specs/2026-06-23-health-report-design.md Outdated
Comment thread docs/superpowers/plans/2026-06-23-health-report.md
oekazuma and others added 2 commits June 23, 2026 10:23
… --min-health docs to exit-2 (#10)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ix (#10)

Present categories with weights summing to 0 now throw a RangeError instead
of silently returning Health 100, which could mask findings and let a
--min-health gate pass. Also drop the redundant `svelte-vitals:` prefix from
computeHealth's RangeError messages so it isn't doubled when surfaced through
the CLI's error-wrapping catch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants