Conversation
loadTsConfigs() gated on the literal filename "tsconfig.json", so a JavaScript-only project that declares its aliases in jsconfig.json got no aliases at all. `create-next-app` writes jsconfig.json when you decline TypeScript, with the identical compilerOptions.paths, so every `@/...` import in such a project silently resolved to nothing and the graph lost its app -> lib edges. The alias machinery (matchTsAlias/applyTsAlias) was already correct; only the discovery filter was wrong. Accept both basenames. When one directory holds both, tsconfig.json wins: a project carrying both is a TypeScript project whose jsconfig is vestigial. The reads run in parallel, so the winner is tracked explicitly rather than left to whichever promise settles last -- otherwise the same repo could produce different graphs run to run. Warning text and the resolver-config-parse failure message now name the file actually read instead of always saying "tsconfig.json". Existing tests assert on failure `path` and `stage`, not that message, so they are unaffected. Measured on a real JS-only Next.js app (161 files): resolved import edges 54 -> 196, files with resolved imports 42 -> 85. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Independent confirmation from a second JS-only Next.js App Router project:
Spot checks against
I also applied the one-line filename change on its own before finding this PR. It produced a byte-identical import map on this project, which is expected since there is no Tests on this branch: +1 for merging. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
loadTsConfigs()discovers alias configs by matching the literal filename:JavaScript-only projects declare the very same
compilerOptions.pathsinjsconfig.json— it is whatcreate-next-appwrites when you declineTypeScript. Those projects therefore get no aliases at all, so every
@/...import resolves to nothing and the knowledge graph loses itsapp/→lib/edges.The failure is quiet, which is the worst part: nothing errors, no warning is
emitted, and the dashboard renders a confident graph in which the application
layer and the library layer look almost disconnected. For a codebase whose
whole architecture is "pure logic in
lib/, thin shell inapp/", that isthe single most misleading thing the graph could say.
The alias machinery itself (
matchTsAlias/applyTsAlias) was alreadycorrect — only the discovery filter was wrong.
The fix
Accept both basenames. When one directory holds both,
tsconfig.jsonwins: aproject carrying both is a TypeScript project whose
jsconfig.jsonisvestigial.
The reads go through
readFilesParallel, so the winner is tracked explicitly(
wonBy) rather than left to whichever promise settles last — otherwise thesame repository could produce a different graph run to run.
Warning text and the
resolver-config-parsefailure message now name the fileactually read, instead of always saying "tsconfig.json". Existing tests assert
on failure
pathandstagerather than that message, so they are unaffected(checked
test_extract_import_mapandtest_prepare_incremental).Impact
Measured on a real JS-only Next.js app (161 files, App Router + Supabase):
Corroborating detail: in that run the file-analyzer agents had independently
hand-rolled
depends_onedges to paper over the missing imports. After thefix, 74 of those 87 edges landed on exactly the pairs the resolver now
recovers deterministically.
Tests
Two added to
tests/skill/understand/test_extract_import_map.test.mjs:resolves jsconfig.json paths aliases in a JS-only project— verified tofail without this change and pass with it.
prefers tsconfig.json over jsconfig.json when a directory holds both—guards the precedence rule against parallel-read nondeterminism. This one
passes either way by construction (with no jsconfig support the jsconfig-only
alias is ignored anyway); it exists to protect the new
wonBylogic.test_extract_import_map+test_prepare_incremental: 135 passed.pnpm lintclean.🤖 Generated with Claude Code