Skip to content

fix(core): harden the dead-code cache key against version and input-list drift#1056

Merged
rayhanadev merged 1 commit into
mainfrom
ray/perf-dead-code-cache-key-hardening
Jul 4, 2026
Merged

fix(core): harden the dead-code cache key against version and input-list drift#1056
rayhanadev merged 1 commit into
mainfrom
ray/perf-dead-code-cache-key-hardening

Conversation

@rayhanadev

@rayhanadev rayhanadev commented Jul 4, 2026

Copy link
Copy Markdown
Member

Why

Follow-up to #1053, addressing both review findings:

  • Devin (fingerprint drift): the cache key's extension and manifest lists were hand-copied from deslop-js's behavior — a silent under-invalidation risk if the analyzer's inputs widen. Making it concrete: the copies were already missing two inputs deslop reads today (ng-package.json, whose lib.entryFile feeds Angular entry discovery, and pnpm-workspace.yml).
  • Cursor Bugbot (missing version key): cached entries hold diagnostics after checkDeadCode's post-processing (message text, toolchain-dependency filtering), so upgrading react-doctor with an unchanged tree could replay stale-shaped findings.

What changed

  • deslop-js (in-monorepo) now exports its canonical input lists via a new dependency-free deslop-js/analyzed-inputs subpath: DEFAULT_EXTENSIONS (already the single source its walk uses) and ANALYZED_MANIFEST_FILENAMES (assembled from constants its own readers now consume — the workspace/lockfile/monorepo-marker lists were consolidated into constants.ts so the export can't drift from usage either). A dedicated entry matters: deslop's root export top-level-imports typescript/oxc-parser/oxc-resolver, which the in-process cache module must never load (verified: 162-byte entry, stays external in core's and the CLI's bundles).
  • The core cache module imports those lists and deletes its copies, keeping only two documented core-side extras (knip.json, read core-side for entry/ignore patterns; deno.lock as an extra installed-metadata proxy).
  • CORE_PACKAGE_VERSION (build-time-injected from core's package.json, mirroring the CLI's VERSION mechanism; verified inlined as 0.6.3 in both dists) joins the cache key.
  • DEAD_CODE_CACHE_SCHEMA_VERSION deliberately not bumped — it stays reserved for cache-format changes; both drift classes are now closed structurally.

Test plan

  • packages/core: 1162 passed (baseline 1158; +4 — core-version key sensitivity, per-extension and per-manifest fingerprint loops over the imported lists, and a reviewed-set snapshot so a widened deslop list lands as a conscious choice). deslop-js suite (node --import tsx --test): 489 passed, before and after. Root typecheck + lint + vp fmt clean.
  • Functional sanity: a cache stored by an origin/main build is missed by this build (version-keyed re-store confirmed via key + mtime), and a fresh store→hit round-trip replays the fixture's unused-file finding exactly.

🤖 Generated with Claude Code


Note

Low Risk
Changes are limited to cache key composition and a dependency-free deslop subpath export; behavior on cache miss is unchanged and tests cover invalidation paths.

Overview
Hardens whole-project dead-code cache invalidation so stale diagnostics are not replayed after react-doctor or deslop upgrades, or when analyzer input coverage grows.

The cache key now includes CORE_PACKAGE_VERSION (inlined at core build time), because stored entries reflect core post-processing (messages, toolchain filtering), not raw deslop output. DEAD_CODE_CACHE_SCHEMA_VERSION is unchanged — reserved for on-disk format changes only.

Fingerprint extension and manifest name sets are no longer duplicated in core: they come from a new lightweight deslop-js/analyzed-inputs export (DEFAULT_EXTENSIONS, ANALYZED_MANIFEST_FILENAMES), built from the same constants.ts lists deslop readers use. Core still fingerprints knip.json and deno.lock on its side. In deslop-js, workspace/lockfile/monorepo marker lists were centralized in constants.ts (closing prior gaps such as ng-package.json and pnpm-workspace.yml in the old copy).

Tests add core-version key sensitivity, loops over imported extension/manifest sets, and snapshot assertions so widening deslop inputs is an explicit review step.

Reviewed by Cursor Bugbot for commit 00e045f. Bugbot is set up for automated code reviews on this repo. Configure here.

…ist drift

Addresses the two review findings on #1053: the fingerprint's extension and
manifest lists are now imported from a new dependency-free
deslop-js/analyzed-inputs subpath (single source of truth with the analyzer's
own readers — the hand-copies were already missing ng-package.json and
pnpm-workspace.yml), and the core package version joins the key so an
upgrade invalidates post-processed cached diagnostics.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 4, 2026 01:51

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@pkg-pr-new

pkg-pr-new Bot commented Jul 4, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/eslint-plugin-react-doctor@1056
npm i https://pkg.pr.new/oxlint-plugin-react-doctor@1056
npm i https://pkg.pr.new/react-doctor@1056

commit: 00e045f

@rayhanadev rayhanadev merged commit 20d81f6 into main Jul 4, 2026
24 of 26 checks passed
@github-actions github-actions Bot mentioned this pull request Jul 4, 2026
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