feat: resolve ES/TS package specifiers for IMPORTS edges (#180)#184
feat: resolve ES/TS package specifiers for IMPORTS edges (#180)#184dLo999 wants to merge 1 commit intoDeusData:mainfrom
Conversation
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
dLo999
left a comment
There was a problem hiding this comment.
Review Summary
Adds ES/TS package specifier resolution via a package map built from package.json files. New pass_pkgmap.c (build/free/resolve), pkg_map field on ctx, 6 call sites updated, 20 new tests. Enables real IMPORTS edges for JS/TS monorepo package imports.
Findings
Reviewer flagged two "critical" issues that are false positives:
- [resolved] pass_pkgmap.c:305 —
cbm_ht_get_key()was flagged as missing, but it exists athash_table.h:49/hash_table.c:173. Build confirms zero link errors. The duplicate package handling pattern is correct. - [resolved] pass_pkgmap.c:294-307 — Memory management concern depends on above function existing, which it does.
Remaining valid observations (all consistent with existing codebase patterns):
- [nit] pass_pkgmap.c:283 — No NULL check after strdup for pkg_dir. Matches existing pattern (pipeline code doesn't check strdup returns — OOM at this point is unrecoverable).
- [nit] pass_pkgmap.c:370 — Fixed-size 1024/2048 buffers for paths. Same pattern as all other pipeline pass files.
- [nit] pass_pkgmap.c:318 — Stack max 512 for directory traversal. Extreme repos might hit this, but 512 levels is well beyond practical monorepo depth.
CI Status
No CI on fork branch. Local: 2761 tests pass (20 new + 2741 existing), 0 regressions. Behavioral verification confirms IMPORTS edges now appear for cross-package imports.
Verdict
APPROVE — Both critical findings are false positives (function exists in foundation layer). Implementation follows architect's design, matches existing codebase patterns, and is comprehensively tested.
Closes #180
Summary
Adds ES/TS package specifier resolution so that
import { foo } from '@myorg/storage-utils'produces real IMPORTS edges. Previously,fqn_module()treated npm package specifiers as file paths, producing QNs that matched no graph nodes — result: zero IMPORTS edges for all package imports.How it works
Package map build (new Phase 1.5 in
pipeline_run()): Walks the repo forpackage.jsonfiles, parsesname+ entry point (exports["."]→main→src/index.tsfallback). Builds aCBMHashTablemapping package names to resolved module QNs.cbm_pipeline_resolve_module(ctx, module_path): New wrapper called instead offqn_module()at IMPORTS-edge creation sites. If the specifier is a package reference and found in the map, returns the mapped QN. Handles subpath imports (@myorg/pkg/utils) by resolving relative to the package directory. Falls through tofqn_module()for relative paths and unknown packages.Zero behavior change for non-JS repos: When no
package.jsonfiles exist,pkg_mapis NULL and all resolution falls through tofqn_module(). 0ms overhead.Changes
src/pipeline/pass_pkgmap.c(new) — package map build, free, and resolve functionssrc/pipeline/pipeline_internal.h—pkg_mapfield on ctx,cbm_pkg_entry_tstruct, prototypessrc/pipeline/pipeline.c— Phase 1.5 build step, ctx initialization, cleanupsrc/pipeline/pass_definitions.c:297—resolve_module()instead offqn_module()src/pipeline/pass_calls.c:91— samesrc/pipeline/pass_usages.c:96— samesrc/pipeline/pass_semantic.c:81— samesrc/pipeline/pass_parallel.c:647— same (incbm_build_registry_from_cache)Makefile.cbm— addedpass_pkgmap.candtest_pkgmap.ctests/test_pkgmap.c(new) — 20 unit testsTest results
Build: Compiles cleanly on macOS (Apple Clang, arm64) with
-Wall -Wextra -WerrorTest suite: 2761 passed, 0 failed (was 2741 — 20 new pkgmap tests)
Behavioral verification (monorepo matching issue scenario):
Created pnpm-like monorepo:
MATCH (a)-[r:IMPORTS]->(b) RETURN a, bapps/server/src/__file__→packages/storage-utils/src/indexMATCH (a)-[r:CALLS]->(b) RETURN a, bpkg_mapphase timingEdge cases tested (unit tests):
./utils→ falls through@test/utils→ exact match@test/utils/helpers→ resolves relative to pkg dirreact→ falls through"name"→ skippedexports["."]["import"]conditional → resolvedpackage.jsonin repo → NULL map, 0msScope boundary (not addressed)
./utils) — already works@/components) — separate issuenode_modules/) — outside project graph by designGenerated with agent-team via /issue