Skip to content

fix(status): recommend a re-index when package.json alone adds or drops a framework - #3005

Open
inth3shadows wants to merge 2 commits into
colbymchenry:mainfrom
inth3shadows:fix/framework-hint-resolver-only
Open

inth3shadows wants to merge 2 commits into
colbymchenry:mainfrom
inth3shadows:fix/framework-hint-resolver-only

Conversation

@inth3shadows

@inth3shadows inth3shadows commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #3007.

codegraph status now recommends a re-index when a framework comes or goes through package.json alone, with no source file changed.

The bug

#2941 (the #2516 fix, unreleased) has a sync detect frameworks again when what detection read changed. It records the difference from the last full index, and status recommends a re-index. But a sync detects again only when it extracts a file:

// src/extraction/index.ts
const detectedFrameworks = filesToIndex.length === 0 ? undefined : this.refreshFrameworkDetection(...)

So adding express or @sveltejs/kit to package.json with no source file edited records nothing. Status stays silent while the files indexed before the edit lack the framework:

  • an unchanged Express app's routes stay missing;
  • an unchanged +layout.svelte's goto('/login') stays unlinked.

Repro (Express): index with {"dependencies":{}} and an app.get('/hello', …) server, add express to package.json, run codegraph sync, then codegraph status --json. Before: frameworksChangedSinceIndex: null, reindexRecommended: false. With this change: { added: ['express'] }, true.

I found it with a differential harness that replays a repo's git history and compares each sync against a fresh index. It came up on a SvelteKit app.

The fix

The status hint gets a second source:

  • A full index also stamps the resolver's framework set (resolver_frameworks_at_index).
  • getFrameworkChangesSinceIndex() merges what syncs recorded, as before, with a comparison of that stamp against the set the resolver detects now. The resolver already detects on every open (createResolver → initialize), so status pays nothing extra.

Since status is a fresh process, it sees a manifest-only change whether or not a sync ran.

Known limits

  • A long-running process (the MCP server's watcher) still doesn't pick up the framework. After a manifest-only edit, that process's resolver keeps the old set until a source file is extracted, because the gate above skips detection. This PR only fixes what status reports. Removing the gate would fix the process too, but every no-op sync would then pay a detection, which fix(sync): a long-running session picks up a framework added while it runs #2941 measured at about 300 ms on excalidraw for a full one. I'll open that separately so you can weigh the cost.
  • Indexes built before this change have no resolver_frameworks_at_index. The new half of the hint starts after their next full index.

Tests

__tests__/framework-hint-resolver-only.test.ts has 4 cases:

  • SvelteKit added, then status, then a re-index clears it and links the goto;
  • SvelteKit removed;
  • Express added with no source change;
  • an unchanged project stays silent.

On main: 3 failed, 1 passed (the silent case). With this change: 4/4. sync-framework-detection.test.ts: 8/8. tsc --noEmit is clean. Full suite: Tests 8768 passed | 417 skipped, 0 failed.

False positives (a hint right after a full index):

  • 25 framework fixtures, each checked through index, reopen, sync and a read-only open: none. They cover Next, Express, Nest, Laravel, Django, Flask, React Native, Expo, UIKit/SwiftUI, Nuxt, SvelteKit, Rails, Spring, gin, ASP.NET, Astro, Angular, Drupal, TanStack, Play, COBOL/CICS and an empty project.
  • 11 real repositories: none.

…ps a framework

A sync detects frameworks again only when it extracts a file, so adding
express or @sveltejs/kit to package.json with no source file edited recorded
nothing, and status stayed silent while the files indexed before it lacked the
framework's routes and links. The full index now stamps the resolver's
framework set, and status compares it with the set the resolver detects on
open.
… the changelog note into its unreleased entry
inth3shadows added a commit to inth3shadows/codegraph that referenced this pull request Oct 29, 2026
inth3shadows added a commit to inth3shadows/codegraph that referenced this pull request Oct 29, 2026

This branch has not been deployed

No deployments
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.

codegraph status stays silent when package.json alone adds or drops a framework

1 participant