Skip to content

feat(core)!: replace saturating score curve with a monotonic one#19

Open
PunGrumpy wants to merge 3 commits into
advisor/006-realistic-negative-test-casesfrom
advisor/008-score-curve
Open

feat(core)!: replace saturating score curve with a monotonic one#19
PunGrumpy wants to merge 3 commits into
advisor/006-realistic-negative-test-casesfrom
advisor/008-score-curve

Conversation

@PunGrumpy

Copy link
Copy Markdown
Owner

What

Replaces the saturating score formula with a monotonic, asymptotic curve, and versions the JSON report. Implements plan 008. Depends on 002 (CLI tests) and 006 (hardened rule suite — so a score move is attributable to the curve, not a rule regression).

Why

The score was 100 − penalty floored at 0 (weights: error 10, warning 4, info 1). Any project with ~10 errors or ~25 warnings scored exactly 0 and stayed there, no matter how much worse (or better) it got. That defeats the entire skill regression workflow ("re-scan, confirm the score didn't drop") — a repo at 0 never moves, so a new Dockerfile with 30 violations still reads 0 and the check green-lights it.

The new curve

score = round(100 · e^(−penalty / K)), K = 70, same severity weights (10/4/1). Approaches 0 without ever saturating, so it stays strictly monotonic and responsive across the whole range.

penalty old new
0 100 100
4 (one warning) 96 94
10 (one error) 90 87
25 75 70
50 50 49
100 (~10 errors) 0 24
200 0 6
400 0 0

K=70 keeps a single warning at 94 (comfortably inside "Excellent" ≥90) while errors and repeated warnings still erode the score. Rationale is documented in a comment in scoring.ts and in the README's new "How the score works" section.

Scope discipline

  • Only the formula changed. The label block and its 90/75/50 thresholds are byte-identical (verified in the diff) — this PR changes the number, not the presentation.
  • Severity weights unchanged; rules/** untouched; the score < 50 CLI gate left as-is.

Report versioning

The JSON report now carries schemaVersion: 2 (REPORT_SCHEMA_VERSION exported from packages/core/src/report.ts) so machine consumers can tell old scores from new. This updates plan 002's strict Object.keys assertion to include the new key (the assertion working as designed).

Tests

New packages/core/test/scoring.test.ts (first tests this module has had): empty→100, per-severity weights, strict monotonicity at 10/20/40 errors (the core regression), fixing an issue always raises the score, integer/range invariants across a wide sweep, label boundaries. Characterization commit 3d0b933 pins the old behavior in git history before the change.

  • scoring 11/0 · core 58 pass / 2 todo / 0 fail · cli 12/0 · typecheck 0 · ultracite 0 · fixtures/clean --score → 99.

Changeset

@docker-doctor/cli minor (pre-1.0: minor signals breaking). Score values shift; existing badges will show different numbers; label thresholds unchanged.

Stacking & merge note

Base is advisor/006-realistic-negative-test-cases (PR #18#16#15#14). Auto-retargets to main once that chain merges.

⚠️ Merge-order note: PR #17 (plan 007) also edits packages/core/src/scoring.ts — it refactors the label block into a SCORE_BUCKETS table, while this PR changes the formula line just above it. The edits are in adjacent-but-distinct regions; whichever of #17 / this PR merges second will need a small conflict resolution in scoring.ts (keep this PR's formula line + K comment and #17's SCORE_BUCKETS label block).

🤖 Generated with Claude Code

BREAKING CHANGE: score = round(100 * e^(-penalty / 70)) replaces
`max(0, 100 - penalty)`. The old formula saturated at 0 once penalty
reached ~100 (e.g. ~10 errors), making the score inert on messy repos
and defeating score-regression checks. The new curve approaches but
never reaches 0, staying strictly monotonic across the whole range.
Per-severity weights (error 10, warning 4, info 1) and label
thresholds/strings (90/75/50) are unchanged. The JSON report gains a
`schemaVersion` field to make future score/shape changes detectable.
@vercel

vercel Bot commented Jul 23, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
docker-doctor Ready Ready Preview, Comment Jul 23, 2026 2:58am

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.

1 participant