Skip to content

Add incremental analyzer cache for large repo scans#651

Merged
kunaldhongade merged 1 commit into
mainfrom
feature/643-incremental-analysis
Jul 5, 2026
Merged

Add incremental analyzer cache for large repo scans#651
kunaldhongade merged 1 commit into
mainfrom
feature/643-incremental-analysis

Conversation

@kunaldhongade

Copy link
Copy Markdown
Member

Summary

Closes #643.

Adds a local JS/TS analyzer artifact cache under .codedecay/local/analyzer-js-cache.json so repeated analysis runs can reuse unchanged file metadata and parsed artifacts instead of reparsing every source file.

What Changed

  • Added a schema-versioned analyzer cache for file metadata, content hashes, symbols, local import specifiers, route-file markers, and last-run stats.
  • Reused cached artifacts from symbol impact analysis and reverse import graph construction.
  • Added deterministic invalidation for cache hits, stale files, content-hash validation, deleted/renamed files, and corrupted cache documents.
  • Excluded .codedecay/local and generated local artifacts from repo scanning so cache files do not become analysis inputs.
  • Exposed cache path/status in codedecay config JSON and markdown output.
  • Documented cache location and invalidation behavior.

Validation

  • npx --yes pnpm@11.8.0 run lint
  • npx --yes pnpm@11.8.0 run typecheck
  • npx --yes pnpm@11.8.0 test — 566 passed, 1 skipped
  • npx --yes pnpm@11.8.0 run build
  • npx --yes pnpm@11.8.0 eval:pr-safety -- --run-id local-pr-safety-issue-643-final — 2/2 scenarios passed
  • npx --yes pnpm@11.8.0 --filter @submuxhq/codedecay pack --dry-run
  • node packages/cli/dist/index.js --help
  • node packages/cli/dist/index.js analyze --format markdown
  • node packages/cli/dist/index.js config --format markdown

Notes

A concurrent local run of pnpm build and eval:pr-safety briefly collided while both commands cleaned dist; rerunning pnpm build alone passed.

@github-actions github-actions Bot added documentation Improvements or additions to documentation type: test Test coverage, fixtures, or verification improvements area: cli CLI package or command behavior area: analyzer-js JavaScript or TypeScript analyzer area: docs README, community files, or documentation labels Jul 5, 2026
@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

CodeDecay PR Check

Lead catch: Past regression area changed — packages/analyzer-js/src/cache/artifacts.ts:1

Untrusted memory context: past regression "Package directory with test in name misclassified as test file" may be relevant. packages/test-audit/src/index.ts was once treated as a test file because path matching used the whole path instead of segment/basename-aware test detection.

Risk: High · Merge 100/100 · Decay 39/100 · Security 0/100

Full CodeDecay report

CodeDecay Report

Overall risk: High

Score Value
Merge risk 100/100
Decay risk 39/100
Security risk 0/100
Findings Count
High 5
Medium 3
Low 11

Changed Files

  • docs/configuration.md modified (+35/-0)
  • packages/analyzer-js/src/cache/artifacts.ts added (+398/-0)
  • packages/analyzer-js/src/files/repo.ts modified (+14/-2)
  • packages/analyzer-js/src/imports/graph/collect.ts modified (+22/-21)
  • packages/analyzer-js/src/index.ts modified (+2/-0)
  • packages/analyzer-js/src/symbols/graph.ts modified (+33/-30)
  • packages/analyzer-js/test/cache.test.ts added (+181/-0)
  • packages/cli/src/commands/config.ts modified (+2/-1)
  • packages/cli/src/renderers/config.ts modified (+53/-5)
  • packages/cli/test/config.test.ts modified (+22/-2)

Likely Impacted Areas

  • Low Documentation (docs): docs/configuration.md
  • Low Source code (source): packages/analyzer-js/src/cache/artifacts.ts, packages/analyzer-js/src/files/repo.ts, packages/analyzer-js/src/imports/graph/collect.ts, packages/analyzer-js/src/index.ts, packages/analyzer-js/src/symbols/graph.ts, packages/cli/src/commands/config.ts, packages/cli/src/renderers/config.ts
  • Low Tests (test): packages/analyzer-js/test/cache.test.ts, packages/cli/test/config.test.ts

Symbol Impact Evidence

Graph artifact: .codedecay/local/symbol-impact-graph.json (791 file(s), 4393 edge(s))

  • packages/analyzer-js/src/cache/artifacts.ts#ANALYZER_CACHE_PATH -> packages/analyzer-js/src/index.ts, packages/analyzer-js/test/cache.test.ts, packages/cli/test/config.test.ts
    • Likely tests: packages/analyzer-js/test/cache.test.ts, packages/cli/test/config.test.ts
  • packages/analyzer-js/src/cache/artifacts.ts#AnalyzerCacheRunStats -> packages/analyzer-js/src/index.ts
  • packages/analyzer-js/src/cache/artifacts.ts#AnalyzerCacheSummary -> packages/analyzer-js/src/index.ts, packages/cli/src/renderers/config.ts
  • packages/analyzer-js/src/cache/artifacts.ts#getAnalyzerCacheSummary -> packages/analyzer-js/src/index.ts, packages/analyzer-js/test/cache.test.ts, packages/cli/src/commands/config.ts
    • Likely tests: packages/analyzer-js/test/cache.test.ts
  • packages/analyzer-js/src/cache/artifacts.ts#readCachedAnalyzerArtifacts -> packages/analyzer-js/src/imports/graph/collect.ts, packages/analyzer-js/src/symbols/graph.ts
  • packages/analyzer-js/src/files/repo.ts#listRepoFiles -> packages/analyzer-js/src/contract/import-boundaries.ts, packages/analyzer-js/src/imports/graph/collect.ts, packages/analyzer-js/src/index.ts, packages/analyzer-js/src/symbols/graph.ts, packages/analyzer-js/src/tests/recommendations.ts, packages/cli/src/commands/agent.ts, packages/mcp/src/handlers/analysis.ts
    • Likely tests: packages/analyzer-js/src/tests/recommendations.ts
  • packages/analyzer-js/src/imports/graph/collect.ts#buildReverseImportGraph -> packages/analyzer-js/src/imports/graph.ts, packages/analyzer-js/src/routes/analysis.ts, packages/analyzer-js/test/cache.test.ts, packages/analyzer-js/test/import-graph.test.ts
    • Likely tests: packages/analyzer-js/test/cache.test.ts, packages/analyzer-js/test/import-graph.test.ts
  • packages/analyzer-js/src/index.ts#ANALYZER_CACHE_PATH -> packages/analyzer-js/test/cache.test.ts, packages/cli/test/config.test.ts
    • Likely tests: packages/analyzer-js/test/cache.test.ts, packages/cli/test/config.test.ts
  • packages/analyzer-js/src/index.ts#AnalyzerCacheSummary -> packages/cli/src/renderers/config.ts
  • packages/analyzer-js/src/index.ts#getAnalyzerCacheSummary -> packages/analyzer-js/test/cache.test.ts, packages/cli/src/commands/config.ts
    • Likely tests: packages/analyzer-js/test/cache.test.ts
  • packages/analyzer-js/src/symbols/graph.ts#analyzeSymbolImpacts -> packages/analyzer-js/src/index.ts, packages/analyzer-js/test/cache.test.ts, packages/analyzer-js/test/symbol-graph.test.ts
    • Likely tests: packages/analyzer-js/test/cache.test.ts, packages/analyzer-js/test/symbol-graph.test.ts
  • packages/analyzer-js/src/symbols/graph.ts#SYMBOL_IMPACT_GRAPH_PATH -> packages/analyzer-js/test/symbol-graph.test.ts
    • Likely tests: packages/analyzer-js/test/symbol-graph.test.ts
  • ...and 2 more symbol impact(s)

Language And Parser Coverage

  • Source files classified: 9
  • Fully supported parser files: 9
  • Limited files: 0
  • Unsupported files: 0

Merge Risk Breakdown

  • Score: 100/100
  • Raw score before dampeners: 100/100
  • Adjusted score before severity cap: 100/100
  • Highest contributing severity: High

Top contributors:

  • +30 Past regression area changed (direct): Untrusted memory context: past regression "Package directory with test in name misclassified as test file" may be relevant. packages/test-audit/src/index.ts was once treated as a test file because path matching used the whole path instead of segment/basename-aware test detection.
  • +30 Project invariant may be impacted (direct): Untrusted memory context: invariant "No hidden cloud or model call" applies to this change. The OSS CLI must remain useful without telemetry, API keys, hosted services, required LLM calls, or CodeDecayCloud.
  • +30 Project invariant may be impacted (direct): Untrusted memory context: invariant "Commands are explicit" applies to this change. CodeDecay must not run project commands unless they are configured and safety.allowCommands is true.
  • +30 Project invariant may be impacted (direct): Untrusted memory context: invariant "Tool evidence is separate from AI suggestions" applies to this change. Reports must not present agent/model suggestions as verified evidence unless backed by deterministic checks or command output.
  • +18 Change size (structural): Changed lines amplify review cost across 10 file(s).

Decay Risk Breakdown

  • Score: 39/100
  • Raw score before dampeners: 52/100
  • Adjusted score before severity cap: 39/100
  • Highest contributing severity: High
  • Evidence mode: heuristic-only

Top contributors:

  • +18 Large test change relative to source change (heuristic): packages/analyzer-js/test/cache.test.ts adds 181 lines of tests for 524 source additions.
  • +10 High complexity in changed function (heuristic): readCachedAnalyzerArtifacts has estimated cyclomatic complexity 17.
  • +10 High complexity in changed function (heuristic): normalizeCacheFiles has estimated cyclomatic complexity 13.
  • +9 Change size (structural): Changed lines amplify review cost across 10 file(s).
  • +5 File spread (structural): Change breadth spans 10 file(s).

Dampeners:

  • -13 Heuristic-only dampener: Decay stays conservative until direct evidence exists.

Notes:

  • Heuristic-only decay is capped at 54/100 until direct evidence exists.

Security Risk Breakdown

  • Score: 0/100
  • Raw score before dampeners: 0/100
  • Adjusted score before severity cap: 0/100

Security Matcher Coverage

  • Changed source files scanned: 7
  • Security candidates found: 0
  • Skipped files: 0

Test Evidence

  • Mode: heuristic-only
  • Sources: none
  • Changed source coverage:
  • packages/analyzer-js/src/cache/artifacts.ts: not measured (no measurable changed lines)
  • packages/analyzer-js/src/files/repo.ts: not measured (no measurable changed lines)
  • packages/analyzer-js/src/imports/graph/collect.ts: not measured (no measurable changed lines)
  • packages/analyzer-js/src/index.ts: not measured (no measurable changed lines)
  • packages/analyzer-js/src/symbols/graph.ts: not measured (no measurable changed lines)
  • packages/cli/src/commands/config.ts: not measured (no measurable changed lines)
  • packages/cli/src/renderers/config.ts: not measured (no measurable changed lines)
  • Notes:
  • No runtime coverage artifact was found. Test audit remains heuristic-only.

Changed Path Test Proof

Status Count
Runtime-proven 0
Static-only 11
Weakened by mocks 0
Unproven 3
  • Static-only packages/analyzer-js/src/cache/artifacts.ts#ANALYZER_CACHE_PATH (static-reference, deterministic)
    • Evidence: Referenced by packages/analyzer-js/test/cache.test.ts, packages/cli/test/config.test.ts, but no runtime coverage artifact proves changed lines executed.
    • Static references: packages/analyzer-js/test/cache.test.ts, packages/cli/test/config.test.ts
    • Repair task: Strengthen packages/analyzer-js/test/cache.test.ts so it executes packages/analyzer-js/src/cache/artifacts.ts#ANALYZER_CACHE_PATH with assertions; static import alone is not proof.
  • Static-only packages/analyzer-js/src/cache/artifacts.ts#AnalyzerCacheRunStats (static-reference, deterministic)
    • Evidence: Referenced by packages/analyzer-js/test/cache.test.ts, but no runtime coverage artifact proves changed lines executed.
    • Static references: packages/analyzer-js/test/cache.test.ts
    • Repair task: Strengthen packages/analyzer-js/test/cache.test.ts so it executes packages/analyzer-js/src/cache/artifacts.ts#AnalyzerCacheRunStats with assertions; static import alone is not proof.
  • Static-only packages/analyzer-js/src/cache/artifacts.ts#AnalyzerCacheSummary (static-reference, deterministic)
    • Evidence: Referenced by packages/analyzer-js/test/cache.test.ts, but no runtime coverage artifact proves changed lines executed.
    • Static references: packages/analyzer-js/test/cache.test.ts
    • Repair task: Strengthen packages/analyzer-js/test/cache.test.ts so it executes packages/analyzer-js/src/cache/artifacts.ts#AnalyzerCacheSummary with assertions; static import alone is not proof.
  • Static-only packages/analyzer-js/src/cache/artifacts.ts#getAnalyzerCacheSummary (static-reference, deterministic)
    • Evidence: Referenced by packages/analyzer-js/test/cache.test.ts, but no runtime coverage artifact proves changed lines executed.
    • Static references: packages/analyzer-js/test/cache.test.ts
    • Repair task: Strengthen packages/analyzer-js/test/cache.test.ts so it executes packages/analyzer-js/src/cache/artifacts.ts#getAnalyzerCacheSummary with assertions; static import alone is not proof.
  • Static-only packages/analyzer-js/src/cache/artifacts.ts#readCachedAnalyzerArtifacts (static-reference, deterministic)
    • Evidence: Referenced by packages/analyzer-js/test/cache.test.ts, but no runtime coverage artifact proves changed lines executed.
    • Static references: packages/analyzer-js/test/cache.test.ts
    • Repair task: Strengthen packages/analyzer-js/test/cache.test.ts so it executes packages/analyzer-js/src/cache/artifacts.ts#readCachedAnalyzerArtifacts with assertions; static import alone is not proof.
  • Static-only packages/analyzer-js/src/files/repo.ts#listRepoFiles (static-reference, deterministic)
    • Evidence: Referenced by packages/analyzer-js/src/tests/recommendations.ts, packages/cli/test/config.test.ts, but no runtime coverage artifact proves changed lines executed.
    • Static references: packages/analyzer-js/src/tests/recommendations.ts, packages/cli/test/config.test.ts
    • Repair task: Strengthen packages/analyzer-js/src/tests/recommendations.ts so it executes packages/analyzer-js/src/files/repo.ts#listRepoFiles with assertions; static import alone is not proof.
  • Static-only packages/analyzer-js/src/imports/graph/collect.ts#buildReverseImportGraph (static-reference, deterministic)
    • Evidence: Referenced by packages/analyzer-js/test/cache.test.ts, packages/analyzer-js/test/import-graph.test.ts, but no runtime coverage artifact proves changed lines executed.
    • Static references: packages/analyzer-js/test/cache.test.ts, packages/analyzer-js/test/import-graph.test.ts
    • Repair task: Strengthen packages/analyzer-js/test/cache.test.ts so it executes packages/analyzer-js/src/imports/graph/collect.ts#buildReverseImportGraph with assertions; static import alone is not proof.
  • Static-only packages/analyzer-js/src/index.ts#ANALYZER_CACHE_PATH (static-reference, deterministic)
    • Evidence: Referenced by packages/analyzer-js/test/cache.test.ts, packages/cli/test/config.test.ts, but no runtime coverage artifact proves changed lines executed.
    • Static references: packages/analyzer-js/test/cache.test.ts, packages/cli/test/config.test.ts
    • Repair task: Strengthen packages/analyzer-js/test/cache.test.ts so it executes packages/analyzer-js/src/index.ts#ANALYZER_CACHE_PATH with assertions; static import alone is not proof.
  • ...and 6 more changed path proof entries

High Risk Findings

  • Project invariant may be impacted (packages/analyzer-js/src/cache/artifacts.ts:1): Untrusted memory context: invariant "No hidden cloud or model call" applies to this change. The OSS CLI must remain useful without telemetry, API keys, hosted services, required LLM calls, or CodeDecayCloud.
  • Project invariant may be impacted (packages/analyzer-js/src/cache/artifacts.ts:1): Untrusted memory context: invariant "Commands are explicit" applies to this change. CodeDecay must not run project commands unless they are configured and safety.allowCommands is true.
  • Project invariant may be impacted (docs/configuration.md:24): Untrusted memory context: invariant "Tool evidence is separate from AI suggestions" applies to this change. Reports must not present agent/model suggestions as verified evidence unless backed by deterministic checks or command output.
  • Past regression area changed (packages/analyzer-js/src/cache/artifacts.ts:1): Untrusted memory context: past regression "Package directory with test in name misclassified as test file" may be relevant. packages/test-audit/src/index.ts was once treated as a test file because path matching used the whole path instead of segment/basename-aware test detection.
  • Large test change relative to source change (packages/analyzer-js/test/cache.test.ts:1): packages/analyzer-js/test/cache.test.ts adds 181 lines of tests for 524 source additions.

Medium Risk Findings

  • High complexity in changed function (packages/analyzer-js/src/cache/artifacts.ts:84): readCachedAnalyzerArtifacts has estimated cyclomatic complexity 17.
  • High complexity in changed function (packages/analyzer-js/src/cache/artifacts.ts:277): normalizeCacheFiles has estimated cyclomatic complexity 13.
  • Project invariant may be impacted (docs/configuration.md:24): Untrusted memory context: invariant "Output must be actionable" applies to this change. Redteam reports and agent bundles should say what behavior to verify, which test proof is weak or missing, and what task a coding agent should perform.

Low Risk Findings

  • Architecture note applies (packages/cli/src/commands/config.ts:2): Untrusted architecture context: CLI is the published surface: The public npm package is @submuxhq/codedecay and the binary is codedecay. Internal workspace packages are implementation details.
  • Docs area changed (docs/configuration.md:24): docs/configuration.md touches a docs area and should be reviewed for regression impact.
  • Source area changed (packages/analyzer-js/src/cache/artifacts.ts:1): packages/analyzer-js/src/cache/artifacts.ts touches a source area and should be reviewed for regression impact.
  • Source area changed (packages/analyzer-js/src/files/repo.ts:4): packages/analyzer-js/src/files/repo.ts touches a source area and should be reviewed for regression impact.
  • Source area changed (packages/analyzer-js/src/imports/graph/collect.ts:1): packages/analyzer-js/src/imports/graph/collect.ts touches a source area and should be reviewed for regression impact.
  • Source area changed (packages/analyzer-js/src/index.ts:32): packages/analyzer-js/src/index.ts touches a source area and should be reviewed for regression impact.
  • Source area changed (packages/analyzer-js/src/symbols/graph.ts:16): packages/analyzer-js/src/symbols/graph.ts touches a source area and should be reviewed for regression impact.
  • Source area changed (packages/cli/src/commands/config.ts:2): packages/cli/src/commands/config.ts touches a source area and should be reviewed for regression impact.
  • Source area changed (packages/cli/src/renderers/config.ts:1): packages/cli/src/renderers/config.ts touches a source area and should be reviewed for regression impact.
  • Test area changed (packages/analyzer-js/test/cache.test.ts:1): packages/analyzer-js/test/cache.test.ts touches a test area and should be reviewed for regression impact.
  • Test area changed (packages/cli/test/config.test.ts:2): packages/cli/test/config.test.ts touches a test area and should be reviewed for regression impact.

Recommended Checks

  • Add an integration test that reaches packages/analyzer-js/src/index.ts#AnalyzerCacheSummary without mocking the changed boundary.
  • Add an integration test that reaches packages/cli/src/commands/config.ts#runConfigCommand without mocking the changed boundary.
  • Add an integration test that reaches packages/cli/src/renderers/config.ts#renderConfig without mocking the changed boundary.
  • Add or run tests covering packages/analyzer-js/src/cache/artifacts.ts
  • Add or run tests covering packages/analyzer-js/src/imports/graph/collect.ts
  • Flow check (CLI release smoke): Run built CLI smoke tests
  • Flow check (CLI release smoke): Run package dry-run
  • Flow check (CLI release smoke): Run published-package or tarball demo before release
  • Flow check (PR safety efficacy benchmark): Confirm edge cases and fix tasks are actionable
  • Flow check (PR safety efficacy benchmark): Confirm normal tests pass while behavior probes catch seeded regressions
  • Flow check (PR safety efficacy benchmark): Run pnpm eval:pr-safety
  • Flow check (Pull request redteam review): Check weak or missing test proof

Notes

CodeDecay is deterministic and local-first. This report was generated without telemetry, API keys, LLMs, or model calls.


Found by CodeDecay - deterministic, local-first, no telemetry.

@kunaldhongade kunaldhongade marked this pull request as ready for review July 5, 2026 15:00
@kunaldhongade kunaldhongade merged commit b700d02 into main Jul 5, 2026
8 checks passed
@kunaldhongade kunaldhongade deleted the feature/643-incremental-analysis branch July 5, 2026 15:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: analyzer-js JavaScript or TypeScript analyzer area: cli CLI package or command behavior area: docs README, community files, or documentation documentation Improvements or additions to documentation type: test Test coverage, fixtures, or verification improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make analysis incremental and viable for large monorepos

1 participant