GitNexus/gitnexus/src
Gergő Magyar 49ffd8e316
feat(group): resolve cross-file named HTTP handlers (#2275) (#2277)
* feat(group): resolve cross-file named HTTP handlers via unique repo-wide lookup

U1 of #2275. When a provider's named handler is defined in a file other than its
route registration (e.g. router.get('/x', listUsers) with listUsers imported),
the registration file's symbols don't contain it, so resolution fell back to the
file-level boundary. Add a repo-wide name query (RESOLVE_BY_NAME_QUERY, the
label-union pattern from manifest-extractor) consulted only after the file-scoped
lookup misses, and honored ONLY when exactly one Function/Method/CodeElement
carries that name (zero/many → keep the file fallback, no wrong-symbol
attribution). Provider-only, cached by name. 4 unit tests; 743 group tests pass.

* test(bench): cross-file named handler scenario (end-to-end proof of #2275)

U2 of #2275. Adds a fifth bench scenario: a backend route whose handler
(listUsers) is imported from another file than its registration, with a frontend
consumer. Asserts the provider resolves to the handler via the repo-wide unique
name lookup (sym=listUsers, uid set) and that the cross-repo trace is symbol-
precise (no file-level fallback). verify.mjs now 12/12 on the real pipeline.

* fix(review): apply autofix feedback

ce-code-review (autofix) — no correctness/security findings; applied test-coverage
+ robustness fixes: repo-wide query throw -> empty (no exception); by-name lookup
cache fires once across same-named handlers; consumers never consult the repo-wide
lookup; same-file-wins now asserts the global path is bypassed; bench provider find
scoped by contractId; clarified the uniqueness-guard comment. 167 extractor tests.

* fix(group): tri-review fixes for cross-file handler resolution

Two-engine PR tri-review (Claude swarm+ce, Codex gpt-5.5 swarm+ce+adversarial)
on #2277. Correctness/security clean (injection refuted, bind-param). Fixes:

- Named-provider wrapper-attach (Codex swarm P1 + Claude ce-adversarial,
  cross-engine): a named handler that fails both name lookups no longer falls
  through to line-span containment, which attached the route to the enclosing
  registrar (e.g. a setupRoutes() wrapper) instead of leaving it empty.
  Containment now applies only to consumers and inline-arrow providers.
- CodeElement/ORM empty-file nodes (Claude ce-adversarial reproduced +
  ce-maintainability): RESOLVE_BY_NAME_QUERY gains 'AND n.filePath <> ""' so a
  handler name colliding with a synthetic ORM model node (orm.ts emits
  filePath:'') neither resolves to an edge-less node nor inflates the uniqueness
  count and masks the real handler; + a defensive empty-filePath guard in
  resolveSymbolByNameUnique. Added LIMIT 2 (Codex swarm P3 + ce-maintainability)
  to bound homonym materialization (count guard stays exact).
- Documented the aliased-import limitation (Codex adversarial): the route-site
  identifier is the local alias, fix deferred to #2275 import narrowing.
- README expected verdict 9/9 -> 12/12 (Codex swarm+ce P3).

Tests: +3 (wrapper-no-attach, empty-filePath reject, empty-registration-file
resolves) covering the cross-engine gaps. 170 extractor / 748 group+integration
pass; bench 12/12 end-to-end.

* feat(group): import-pinned handler resolution (fixes deferred alias case)

Resolves the tri-review's deferred item: cross-file named handlers are now pinned
to their import's target module instead of resolved by name alone, so aliases and
names that collide with a local symbol resolve correctly.

- node.ts builds a local-binding -> {declared name, module} map from the file's
  named imports; the express handler emits the DECLARED name + a handlerImport
  {name, module} (HttpDetection gains the optional field).
- resolveDetectionSymbol gains an imported-handler rung: resolveImportedSymbol
  pins to the import's target file via RESOLVE_IN_MODULE_QUERY
  (n.name= AND filePath STARTS WITH the resolved module path), unique-match
  only. An imported handler never uses file-scoped lookup (it is defined
  elsewhere); on a module miss it falls back to a unique repo-wide name match on
  the DECLARED name, then null. Relative imports only; bare/non-relative imports
  keep the repo-wide fallback. Cached by (module-prefix, name).
- Closes the Codex-adversarial alias finding: import { listUsers as handleUsers }
  + an unrelated handleUsers no longer mis-resolves — the route resolves to the
  imported listUsers in its module, and the alias is never looked up.
- Shared toResolvedSymbol helper (dedups the row->symbol + empty-filePath guard).

Tests: alias-resolves-to-declared-name + module-pin-resolves-ambiguous-name unit
tests; same-file-wins reworked to a genuinely LOCAL handler. Bench scenario 6
(aliased import with a decoy) proves it end-to-end. 172 extractor / 751
group+integration pass; bench 14/14.

* feat(group): import-pinned resolution for Python aliased handlers

Extends the JS/TS import-pinning to Python. The Python analog of express
router.get(path, handler) is Flask's imperative add_url_rule(view_func=...),
whose view is often an imported (aliased) symbol.

- New Flask add_url_rule provider pattern (path + view_func handler + methods;
  default GET, methods=[...] honored). High Flask-specificity keeps false
  positives low — unlike bare path()/Route(), which the plugin deliberately
  leaves to graph Route nodes.
- buildPythonImportMap resolves 'from .mod import name as alias' (and plain
  'from mod import name') to the declared name + raw module spec.
- resolveModuleBase generalized to two relative-import dialects: path-style
  (JS './h/users') and dotted (Python '.handlers.users', '..pkg.users' — leading
  dots are package levels). Bare/absolute imports keep the repo-wide fallback.
- Django stays graph-resolved (handlerSymbolId); FastAPI/Flask decorators stay
  same-file (decorated function). This only adds the imperative imported-view
  case Python lacked.

Tests: Flask aliased add_url_rule unit test (relative dotted module pinned, alias
never queried) + bench scenario 7 (end-to-end, 16/16). 173 extractor / 752
group+integration pass.
2026-06-23 12:12:49 +01:00
..
cli fix(lbug): stop --pdg analyze double-free (skip LadybugDB close-destructor crash) + harden connection serialization (#2264) 2026-06-21 15:25:56 +01:00
config fix(worker): analyze native worker aborts (#1833) 2026-05-26 17:28:39 +01:00
core feat(group): resolve cross-file named HTTP handlers (#2275) (#2277) 2026-06-23 12:12:49 +01:00
lib feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
mcp feat(group): cross-repo call trace using PDG (#2269) 2026-06-23 07:54:13 +01:00
server fix(lbug): stop --pdg analyze double-free (skip LadybugDB close-destructor crash) + harden connection serialization (#2264) 2026-06-21 15:25:56 +01:00
storage perf(group/http): skip source parse for graph-covered route files (#2138 Part 2) (#2265) 2026-06-23 07:22:43 +01:00
types perf(cfg): streaming/chunked PDG graph emit for full-kernel-scale repos (#2202) (#2216) 2026-06-16 05:04:10 +01:00