Release v12.2.0
Letter-only grading for package vibrancy across the report and detail views, plus a new "true footprint" view that links shared dependency size into per-package cost.
Added
- Quick fixes (Batch 12): Added 10 new quick fixes (9 new producers, 1 reuse) for previously fix-less rules:
avoid_redundant_positional_field_name(record_pattern) — deletes the redundant$Nname from a positional record field.prefer_wildcard_pattern(record_pattern) — replaces an unused pattern variable name (unused,ignore, …) with_.prefer_wildcard_for_unused_param(naming_style) — renames an unused positional parameter to the_wildcard.avoid_non_null_assertion(type_safety) — reuses the existingRemoveNullAssertionFixto strip the!operator.prefer_const_constructor_declarations(class_constructor) — insertsconstbefore a generative constructor.prefer_const_constructors_in_immutables(class_constructor) — insertsconston the first non-const generative constructor in an @immutable / Widget class.prefer_final_fieldsandprefer_final_fields_always(class_constructor) — addsfinalto a mutable instance field (replacing a leadingvarwhen present).avoid_double_and_int_checks(control_flow) — rewritesx is int || x is double/&&to the equivalentx is numcheck.deprecated_new_in_comment_reference(documentation) — strips the deprecatednewkeyword from[new Foo]doc references.
- Rule:
prefer_type_sync_over_is_link_sync(WARNING, Recommended tier) — flags staticFileSystemEntity.isLinkSync(path)calls, which returnfalseunconditionally on Windows per documenteddart:iobehavior and silently break cross-platform symbolic-link checks. Suggests the portable replacementFileSystemEntity.typeSync(path, followLinks: false) == FileSystemEntityType.link. Plan #79. - Rule:
avoid_removed_js_number_to_dart(WARNING, Recommended tier) — flags the removedJSNumber.toDartgetter fromdart:js_interop(Dart SDK 3.2). Surfaces a more actionable migration message than the analyzer default, directing developers to the type-explicittoDartDouble(floating-point) ortoDartInt(integer) getters. No auto-fix because the numeric target type is a semantic choice. Plan #90. - Extension: Footprint-mode toggle (Own / + Unique / + All) in the vibrancy report toolbar — switches what the Size column shows: the package's own archive (default), own + transitives used only by this dep (the size you'd save by removing it), or own + all transitives including ones shared with other direct deps. Sorting by Size respects the active mode.
- Extension: "True Footprint" row in the package detail panel — for any direct dep with transitives, surfaces the breakdown as
unique · +shared = totalwith a tooltip explaining how much disappears if you remove the dep vs. how much stays pulled in by other deps. Lets you spot cases likecrop_your_imagewhere the bulk of the size comes from a sharedimagetransitive. - Extension:
TransitiveInfo.uniqueTransitiveSizeBytesandsharedTransitiveSizeBytesfields, computed inenrichTransitiveInfofrom the per-package archive sizes already gathered during scan. - Extension: Re-export awareness throughout the vibrancy report. Each
PackageUsagenow carries anisExport: booleanflag. The Single-use summary card excludes packages whose only reference is aexport 'package:...'directive (they're public-API surface, not removable). The detail panel tags individual re-export lines with a "re-export" badge and a "public API surface" header note. The report row's References cell shows a "↪" badge after the count and prepends a warning to its tooltip when re-exported, and the muted single-use styling no longer applies to re-exports.hasActiveReExport()helper exposed alongsideactiveFileUsages(). - Extension: Startup-scan skip-gate. The package vibrancy scan that runs on every VS Code restart now persists a fingerprint of the last successful scan (sha256 of pubspec.lock + scoring weights/allowlist/repo-overrides/publisher-trust-bonus, plus the result snapshot). On the next startup, when the lock file and scan-config inputs are unchanged AND the prior scan finished within the configured skip window, results are silently rehydrated and the progress notification is suppressed. Falls back to a normal scan on any cache miss, schema mismatch, malformed blob, or clock skew.
- Extension: New setting
saropaLints.packageVibrancy.startupScanSkipTtlMinutes(default 60, min 0, max 10080 = one week). Skip-window for the startup scan in minutes. Set to0to always run the startup scan and disable skipping entirely. - Extension: New setting
saropaLints.packageVibrancy.showStartupScanSkipStatusBar(default false). When the startup scan is skipped, briefly show a status bar item (✓ Vibrancy: cached (Nm)) so users notice the skip; clicking it triggers a fresh scan. Off by default — silent rehydrate is the point. - Extension: Existing
saropaLints.packageVibrancy.cacheTtlHourssetting (declared but previously unused) is now wired toCacheServiceso the per-package pub.dev/GitHub response cache TTL honors the user's configured value (default 24 hours). - Extension: Clear Cache command (
saropaLints.packageVibrancy.clearCache) now also clears the persisted last-scan fingerprint so the next startup performs a fresh scan instead of silently rehydrating stale cached results.
Fixed
- Extension: Vibrancy report column headers no longer wrap to two lines when many optional columns are visible. Headers, right-aligned numeric cells, and the footprint-mode toggle buttons now use
white-space: nowrapso each value stays on a single line. - Extension: Vibrancy report version-age suffix no longer shows
(new)for packages published within the last month. The label was misleading (a recently published version of a mature package isn't "new") and didn't carry useful information, so the suffix is now omitted entirely under one month.
Changed
- Extension: Vibrancy report Category column now shows the letter grade badge only — the category label ("Vibrant", "Stable", etc.) and the dimmed
(n/10)suffix were removed. Full label and score breakdown remain available via the hover tooltip. - Extension: Report summary filter cards (Vibrant/Stable/Outdated/Abandoned/End-of-Life) now display the grade letter (A/B/C/E/F) as their label. The full category name moved to a
titletooltip on each card. - Extension: Report average-score summary card renamed to "Project Package Grade" and now shows a single letter derived from the average vibrancy score, replacing the old
n/10value. - Extension: Radial gauge in the report header now displays the project package grade letter instead of the
n//10stack. Tooltip label updated to "Project Package Grade". - Extension: Sidebar detail view header replaced the
n/10score pill plus standalone category-badge with a single letter pill. Category name is surfaced via the pill'stitletooltip. - Extension: Package detail panel header badge (top-right) now shows the letter grade only; the
n/10score and inline category label were dropped (label moved to the title tooltip). - Extension: Expanded row "Health Score" detail card dropped the redundant "Overall" numeric row — the aggregate is already shown as the letter badge in the card header; the factor rows (Resolution Velocity, Engagement Level, Popularity, Publisher Trust) remain.
- Extension: Health breakdown tooltip (shown on hover over a row's grade cell) now leads with "Grade: X" instead of "Vibrancy Score: n/10". Factor rows unchanged.
- Extension: CodeLens titles changed from "emoji n/10 Label" to "emoji X" (letter). The
indicatorStyle: textvariant now shows only the text indicator since a letter next to the text label was redundant;indicatorStyle: noneshows the letter alone. - Extension: pubspec hover tooltips show "X Category" (letter + label) in place of "n/10 Category". Alternatives list shows "(X)" per alt (letter derived from the alt's score via
scoreToGrade). - Extension: Diagnostic messages trail with "(X)" (grade letter) instead of "(n/10)". Applies to Review/Monitor/Deprecated verbs and to blocker annotations.
- Extension: Vibrancy tree view blocker row switched from "score (category)" to a single letter grade. Alternatives group shows "(X)" per suggestion.
- Extension: Package comparison view row renamed "Vibrancy Score" → "Vibrancy Grade"; cell displays the letter derived from the 0-100 score (ranking still uses the numeric score so ordering stays precise).
- Extension: Markdown report export renamed the "Score" column to "Grade" and displays the letter. The JSON sibling preserves the numeric
health.scorefield unchanged so downstream automation keeps working. - Extension: Budget-exceeded message for the
minAverageVibrancyrule now reads "Project Package Grade X is below minimum Y" instead of showingn/10actual vs limit. - Extension: DetailLogger output channel prints "name — X (Category)" and "Blocker grade: X" instead of
n/10forms. - Extension: New
scoreToGrade(score)helper incategory-dictionary.ts, re-exported fromstatus-classifier, providing a single source of truth for score-to-letter thresholds used by the gauge, summary card, alternatives, comparison view, and budget messages.