mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-28 06:22:22 +00:00
168 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
36141609a1 |
fix(scope): fail closed on namespace factory returns the lookup cannot prove
Review follow-up for the namespace factory return lookup (#3498). Each case below either resolved to the wrong class or crashed; each now types the receiver correctly or records a receiver-unresolved drop. - Disk mode: the namespace-name set walked `scopeTree.byId`, which throws after the out-of-core seal, so an inline-only `rp.make().m()` partition aborted analyze under GITNEXUS_DISK_SCOPE_INDEX=1. It is now built from the finalized `scopes.imports` edges, resolved namespace edges only. This also removes the run-to-run edge/drop drift the lazy build caused. - Hoisted method returns: TS and Dart hoist a method's return annotation to the module under the method name, and Go binds receiver methods at package scope, so `m.create()` could take `WidgetFactory.create(): Widget`. The return binding must now start where a module-local `Function` of that name is declared. - `import pkg.sub` binds `pkg` but targets `pkg/sub.py`; such an edge only counts when its target file is the module the local name binds. - A dotted return (`-> models.Order`) is not followed further: the next step would read `models` in the caller's namespace map, not the producer's. - Zig: the `const x = rp.make()` binding decided namespace-vs-file-struct from the filename's case and lost `list.push`-style edges on lowercase file-structs. That binding form is reverted; the inline form is unaffected. - Shared-position drops: a site's identity is now `receiver.member`, so `rp.untyped().untyped()` records its outer drop while a call and its own callee read still count once. Tests: temp-repo regression rows for each case in the TypeScript, Go and Python suites, a lowercase file-struct row in Zig, an awaited Dart row (an awaited Future is not unwrapped yet, so it records a drop), and data-driven unit cases for recordSiteMember. Corpus A/B against origin/main: identical CALLS/ACCESSES edges outside the new fixtures; the drop set outside them is unchanged from the previous head. Receiver bench: +1 call drop (the awaited Dart row). Dart scope-capture fingerprint moves for the same fixture row only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
555051c842
|
test(bench): rebaseline captures and receiver counts for Dart and Zig
- receiver-resolution: the Dart fixture's untyped factory adds one call drop (151 -> 152); every typed form in the Dart and Zig fixtures resolves. - scope-capture (dart): two existing dart-method-enrichment locals initialized by `obj.method()` / `Type.method()` gain a call-derived binding, plus the new fixture's captures. A full lang-resolution A/B emits the identical edges outside the new fixtures. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
cddbe135c0
|
fix(scope): follow namespace factory return types and record untyped drops
`import mod as rp; x = rp.make(); x.m()` lost the receiver type even when `make` is declared `-> C`: `x` was bound to the raw dotted name `rp.make`, and nothing followed a dotted name to a function's return type. The inline `rp.make().m()` failed the same way in the compound resolver, which read `ns.f()` only as a construction. Resolve `ns.f` to `f`'s return annotation when `ns` is a namespace import, the fact `propagateImportedReturnTypes` already mirrors for a named import. The post-finalize chain follow uses it for bindings and the compound resolver for inline calls. Only sites that emitted nothing change: the full lang-resolution corpus emits the identical 2,838 CALLS/ACCESSES edges. Record the drops that left `impact` at "exact": - a plain receiver bound to a namespace function with no usable return type (`x = ns.untyped()`); - an outer call whose `file:line:col` key a resolved inner site already claimed (`ns.untyped().m()`, `s.repo.Delete(id)`). Only a duplicate capture of the same member hides a drop now. Receiver baseline: call drops 128 -> 151, reads 44 -> 48, ten shape-arm cells INVISIBLE-GAP -> VISIBLE-GAP; every new drop has no CALLS edge to its member (BASELINE.md lists them). The python.factory-qualified accuracy gap is removed; the python-scope fingerprint and capture golden gain the new fixture only. Fixes #3498 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
9df1e98350
|
fix(routes): scope inline Express handlers and report api_impact lower bound (#3643)
* fix(routes): scope inline Express handlers and report api_impact lower bound Inline Express handlers are anonymous Function nodes named by position, but the route facts only recorded a handler name for bare identifiers. Routes with inline handlers therefore had no handlerSymbolId: every route in a file got the union of its handlers' response keys and every flow starting there. Record the positional name for inline handlers, read response keys from the resolved handler when a file registers several routes, and let processes link exactly by handlerSymbolId as they already do for named handlers. Count, per route, the files that pass its URL to a callee not proven to be a fetch wrapper (excluding proven consumers and the route's own file). The count is stored as Route.unverifiedConsumers; api_impact reports epistemic: 'lower-bound' with that count when it is non-zero. Older indexes without the column fall back to the previous query. Closes #3488 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(routes): match unverified consumers once per URL Memoize route matching per distinct fetch URL, skip the proven-consumer scan when no unproven call matches a route, and build the Route query's optional columns from a list instead of two booleans. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(group): keep inline handlers attributed to their registrar Inline Express handlers now carry their positional Function name in the route facts so ingestion can resolve a handlerSymbolId. Group HTTP contracts read the same facts, but that name is a graph identity rather than a symbol name the contract lookup can match, so the provider lost its enclosing-registrar attribution. Ignore the name for inline handlers there. Rebaseline the two bench guards the branch moved: - emit-persistence: route.csv gains the header-only unverifiedConsumers field; stripping it restores the prior fingerprint exactly. - receiver-resolution: the new fixture's req.query.path read on an untyped inline-handler parameter adds one receiver-unresolved read (191 -> 192). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> |
||
|
|
faa453c528
|
fix: reduce MCP token overhead and correct cost comparisons (#3645)
Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> |
||
|
|
01af833875
|
fix(scope): preserve lexical bindings in HTTP wrapper detection (#3632)
* docs(scope): clarify lexical binding ownership and wrapper provenance Checkpoint for #3630. Publishing the implemented source, regression tests, and benchmark harness as a draft PR; full-suite and final scaling validation remain in progress. * fix(scope): publish #3630 docs/plans * fix(scope): publish #3630 gitnexus/bench/lexical-binding-provenance * fix(scope): publish #3630 gitnexus/bench/lexical-binding-provenance/fixtures * fix(scope): publish #3630 gitnexus/bench/lexical-binding-provenance/results * fix(scope): publish #3630 gitnexus/src/core/ingestion * fix(scope): publish #3630 gitnexus/src/core/ingestion/languages/typescript * fix(scope): publish #3630 gitnexus/src/core/ingestion/languages * fix(scope): publish #3630 gitnexus/src/core/ingestion/pipeline-phases * fix(scope): publish #3630 gitnexus/src/core/ingestion/route-extractors * fix(scope): publish #3630 gitnexus/src/core/ingestion/workers * fix(scope): publish #3630 gitnexus/test/fixtures/lang-resolution/fetch-wrapper-target-identity/lib * fix(scope): publish #3630 gitnexus/test/fixtures/lang-resolution/fetch-wrapper-target-identity * fix(scope): publish #3630 gitnexus/test/fixtures/lang-resolution/fetch-wrapper-target-identity/packages/http * fix(scope): publish #3630 gitnexus/test/fixtures/lang-resolution/fetch-wrapper-target-identity/packages/http/src * fix(scope): publish #3630 gitnexus/test/fixtures/lang-resolution/fetch-wrapper-target-identity/server * fix(scope): publish #3630 gitnexus/test/fixtures/lang-resolution/fetch-wrapper-target-identity/web * fix(scope): publish #3630 gitnexus/test/integration/resolvers * fix(scope): publish #3630 gitnexus/test/unit * fix(scope): publish #3630 gitnexus/test/unit/group * fix(scope): publish #3630 gitnexus/test/unit/scope-resolution * fix(scope): publish #3630 gitnexus/test/unit/scope-resolution/typescript * fix(scope): publish #3630 gitnexus-shared/src/scope-resolution * fix(scope): treat wrapped assignment targets as writes `(app) = new Map()`, `(app as T) = x` and `app! = x` assign the same binding as `app = x`, but route-fact invalidation and the shared pattern walker stopped at the wrapper, so Express provenance survived the write and produced a false route. Recurse through parenthesized, as/satisfies and non-null targets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(routes): resolve wrappers through overloads, declarator lists and barrels Three wrapper shapes lost their identity: - Bodyless overload signatures were indexed as separate definitions sharing the implementation's binding, so the binding looked ambiguous and both local and imported calls were rejected. Signatures now declare no callable. - Facts for `const base = 0, request = (url) => fetch(url)` followed the first declarator. The captured name now selects its own declarator. - An import resolved to a workspace barrel stopped at index.ts. Workers now record named, star and imported-then-exported re-exports, and resolution follows them to the declaring module: local and named exports shadow `export *`, star exports never carry `default`, and conflicting star exports block the name. No repository-wide name fallback is restored. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(scope): assert closure ownership against the declaration The closure-write assertion compared one lookup with itself, which also passes when both are undefined. Compare it with the outer declaration and the shadowing parameter, and keep the memoization check explicit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(routes): share lexical helpers and release per-file HTTP contexts - Share binding keys, parameter patterns and transparent expression wrappers from lexical-bindings instead of four local copies; drop the unused moduleStem export; name the inferred-source predicates in lookup. - Key the per-file HTTP context by its tree rather than its ParsedFile. Workers retain ParsedFiles for the whole chunk, which kept every file's AST and traversal maps alive until the chunk flushed. - Index re-exports by name, memoize barrel walks per starting export, and keep facts without import targets as-is instead of copying them. - Move TS-only wrapper cases into the TS describe.each instead of branching inside the per-language loop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(routes): keep wrapper identity for HOCs, CommonJS, object keys and fetch packages Four definition shapes that main linked by name lost their wrapper identity: - `const load = useCallback((url) => fetch(url))` and curried HOCs produced no facts because definition lookup stopped at the call; it now follows the callable argument, as the structural definition capture does. - `module.exports = { request }`, `exports.x = …` and `module.exports.x = …` were not exports, so destructured `require` callers missed the wrapper. CommonJS export assignments are recorded when `module`/`exports` are the unshadowed globals, including functions defined inline in the export object. - An object-literal key or method name was resolved as a lexical binding and collided with a same-named module wrapper. Only binding identifiers now name a definition's binding. - `import fetch from 'node-fetch'` no longer counted as fetch. Imports of known fetch implementations (node-fetch, cross-fetch, isomorphic-fetch, the fetch member of undici and whatwg-fetch) are fetch evidence again; parameters and other local names still are not. Reference identifiers are also resolved only when their name is bound to a callable or class region; other identifiers cannot add a reachability edge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(routes): drive the forwarding fallback case from data and cover re-export merges Replace the boolean-switched forwarding fallback case with table rows instead of branching inside the test, and assert that barrel re-export facts survive worker sub-batch merges. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(bench): reject stale or dirty call-graph exports The committed comparison named a candidate revision that is not on this branch, and nothing stopped it. Comparison now requires both exports to come from clean checkouts and the candidate export to come from the checkout running the comparison. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(bench): regenerate the call-graph comparison on the reviewed head Clean baseline |
||
|
|
0e7b3d6fad
|
fix(mcp): report cross-function explain lines 1-based (#3635)
* fix(mcp): report cross-function explain lines 1-based The interprocedural branch of explain passed the endpoints' and hops' graph startLine through unchanged. Those are 0-based (tree-sitter rows), so every cross-function source, sink and hop sat one line above the function's declaration in an editor, while the intra-procedural findings of the same response were already 1-based. source.line, sink.line and hops[].line now go through toDisplayLine like context, query and impact (#2377), and the response note says these are declaration lines. The interproc integration block asserts the exact fixture lines: handle on line 7 of source.ts, runIt on line 6 of sink.ts. Fixes #3491 * fix(review): remove repaired accuracy allowance --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> |
||
|
|
47d63a0601
|
chore(vendor): update tree-sitter-dart to 1.0.0-g0038280 (#3633)
* chore(vendor): update tree-sitter-dart to 1.0.0-g0038280 * chore(vendor): rebuild native prebuilds (tree-sitter-dart) Built by https://github.com/abhigyanpatwari/GitNexus/actions/runs/39212887661 * fix(dart): use native extension type parsing The upgraded grammar parses extension types directly. The compatibility rewrite loses generic extension bodies and implements clauses, so capture the native nodes and register their member ownership instead. Refresh the Dart capture fingerprint after comparing the old grammar and emitter over the same fixture corpus. Keep the scaling budget unchanged. Refs #3633 * chore(vendor): rebuild native prebuilds (tree-sitter-dart) Built by https://github.com/abhigyanpatwari/GitNexus/actions/runs/39239767139 * fix: repair Dart parity and checkpoint regressions Remove Dart from the preprocessing fixture inventory after retiring its hook. Use the parsed body boundary when reading extension-type heritage so named-record representations retain their implements clauses. Seed the WAL recovery fixture with the normal checkpoint threshold, then force one-byte checkpoints only for the deliberately blocked write. Require an actual error exit instead of accepting a subprocess timeout. Refs #3633 * chore(vendor): rebuild native prebuilds (tree-sitter-dart) Built by https://github.com/abhigyanpatwari/GitNexus/actions/runs/39248441688 --------- Co-authored-by: gitnexus-release-bot[bot] <gitnexus-release-bot[bot]@users.noreply.github.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> |
||
|
|
565e50276d
|
fix(routes): resolve Express registrations made through helper parameters (#3629)
* fix(routes): resolve Express registrations made through helper parameters (#3487) #3603 made Express receivers provenance-proven, which removed the receiver- name false positives but also every registration on a function parameter: a parameter has no binding value, so `app.get(...)` inside a helper never resolved. On GitNexus's own server that dropped `* /api/mcp` (`mountMCPEndpoints(app, ...)`) and `GET /` (`registerWebUI(app, ...)`), and the two SSE progress routes registered by `mountSSEProgress(app, '/api/.../progress', jobs)` were never found at all (#3487, item a). Named function values in the route facts now carry an identity and the binding id of each parameter (a TypeScript `this` parameter takes no position, and a parameter written anywhere in the body, nested closures included, takes none either). Calls to plain functions and to namespace or default import members are recorded as invocations, keeping only the arguments that can carry an allocation or a literal path; arguments after a spread have no position. The resolver resolves a registration whose receiver, literal path or mounted child is a parameter through each call site of its function, once per site and in the helper's file. This is one hop only: a site argument that is itself a parameter does not resolve. When no call site is recorded, the call is evaluated as written, so an unknown mount path still suppresses its child router instead of exposing its paths at the root. Only calls whose callee is named like a function that registers on its parameters are evaluated, which keeps resolution at its previous cost on repositories with many helper calls. A function value's invalidation key now includes its identity, so a property write on one function (`Button.displayName = ...`) no longer disables every other. The group layer shares the resolver, so it gets the same routes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(routes): forward mounted-child parameters and aliased helper imports Review follow-ups for the helper-parameter forwarding: - A helper that forwards only its mounted router (`function mountChild(child) { app.use('/api', child) }`) was never resolved, because the forwarded function was chosen from the receiver and path alone. Any parameter among the receiver and arguments now selects it, as long as all come from one function. - A helper called through an aliased import (`{ mountSSEProgress as mountProgress }`) was filtered out before its call sites were recorded, since the filter compared only the local name. It now also accepts the imported name. - A write to a same-named local declared in a nested block (`{ let app; app = other; }`) discarded the outer parameter. A write to a binding that a nested block, function or catch clause declares no longer counts. - The fixture's `registerWebUI` uses its static directory. The release tool-accuracy gate now passes `routes.helper-registration`, so its known-gap allowance is removed. Its expected file moves from the caller (`api.ts`) to the helper (`progress.ts`): an Express route belongs to the file of its `app.get` call, which is also where its handler and response keys are, as for every directly registered route. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(routes): treat destructuring reassignment as a parameter write `[app] = [other]` reassigns `app`, but the write check compared the whole target text (`[app]`) with the parameter name, so the parameter stayed forwardable and later registrations used the call-site argument. A destructuring target now writes each name it binds; a member target still writes only a property. Also drops an unused local flagged by CodeQL. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(routes): follow helpers exported under another name `export { mountRoutes as setup }` records the export as a binding, so the call-site filter knew the helper only as `mountRoutes` and skipped callers importing `setup`. An export of a binding to a named function now adds its exported name too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> |
||
|
|
aa33a6e94c
|
fix(routes): link base-URL fetch calls made through wrapper chains (#3628)
* fix(routes): link base-URL fetch calls made through wrapper chains (#3488) GitNexus's own web client calls `fetchWithTimeout(`${_backendUrl}/api/repos`)`, which reaches fetch through `resilientFetch` and a local `fetchImpl` alias. `api_impact` found none of those consumers, for three independent reasons: - normalizeFetchURL rejected any URL that did not start with `/`, so a leading base-URL binding dropped the call. It now strips a leading `${...}` run followed by `/`, with the same rules as the group layer's consumer normalizer (#3111); the helper moves to route-path.ts so both layers share it. A path whose every segment is a param (`${base}/${id}`, `${base}/${id}.json`) is rejected, since it would match every route of that depth. Interpolations are collapsed brace-balanced before the query split, so `${repo ? `?repo=${repo}` : ''}` no longer ends the path, and one glued to the last static segment is treated as a query or suffix. - The wrapper call collector required a `/`-leading literal, so the same template never became a wrapper candidate. - Wrapper detection only looked five AST levels deep for a call to an identifier named `fetch`. Arrow-const wrappers sit deeper than that, and `resilientFetch` calls an alias of `globalThis.fetch`. Detection now walks the whole definition and accepts `globalThis`/`window`/`self.fetch` and aliases whose value names fetch (through `??`, `||`, `?:`), read from the AST rather than the text. It records whether the first parameter reaches fetch's URL argument and which callees receive that parameter. The routes phase closes the wrapper set over that forwarding: `fetchWithTimeout` is a wrapper because it forwards its URL to `resilientFetch`. A callee declared in the caller's file or imported from a relative module must carry a URL in exactly that module; a package-imported name is followed only when every recorded function of that name carries one. A fetch caller whose first parameter is not the URL (`track(event)`) or a same-named function elsewhere (an IPC `request(channel)`) lends nothing. When `[param]` matches several sibling routes (`/api/analyze/upload` and `/api/analyze/:jobId`), the fetch now links to the route whose segments match by kind instead of the first one registered. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(routes): match wrapper calls by declaring module and decline ambiguous fetch matches Review follow-ups for #3488: - A propagated wrapper's name went into a repo-wide set, so a literal call to an unrelated same-named function in another module was taken as a fetch. Wrapper call candidates now carry the module declaring a bare callee when the file declares or imports it relatively, and must reach a wrapper defined in exactly that module. Package and member callees keep the name match. - An alias declared in a nested helper (`const fetchImpl = globalThis.fetch`) marked an outer call to a same-named parameter as a fetch. An alias now counts only where its declaring function encloses the call. - A first parameter redeclared inside the function (`{ const url = ...; fetch(url) }`) was taken as the URL. A shadowed parameter is no longer followed. - A fetch whose `[param]` ties between sibling static routes (`/api/kinds/foo`, `/api/kinds/bar`) linked to the first registered one. A tie now links none. - The fixture's `resilientFetch` returns the last response instead of rejecting with `undefined`, and its client encodes the repo query value. The release tool-accuracy gate now passes `api.template-wrapper`, so its known-gap allowance is removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(routes): keep call-site wrapper names and ignore helpers that never run - A wrapper call through a renamed relative import (`import { request as send }`) stored the exported name, so a configured `fetchWrappers` entry naming the call-site `send` no longer matched. The call keeps its call-site name and carries the declared name separately for the module lookup. - A nested helper bound to a local that is never referenced again (`const later = () => resilientFetch(url)`) made its enclosing function forward its URL. Calls inside such a helper are ignored; a helper that is called or passed on, such as a retry callback, still counts. - The fixture's `resilientFetch` no longer retries after a timeout or abort. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(routes): let a nested parameter shadow a fetch alias A function parameter between a fetch alias and a call shadows the alias there (`function send(fetchImpl) { return fetchImpl(event) }` beside an outer `const fetchImpl = globalThis.fetch`), so that call no longer marks the enclosing function as a fetch wrapper. The fixture's retry helper also stops returning a stale 5xx response after a later attempt throws. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(routes): drop fetch aliases whose name is redeclared with another value A block that redeclares an alias name with a non-fetch value (`{ const fetchImpl = other; fetchImpl('/x') }`) let the inner call read as a fetch. A name declared anywhere in the function with a value that does not name fetch is no longer an alias, which covers every block-scoped shadow without lexical scope tracking. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(routes): ignore uncalled nested declarations and shadowed global objects - An uncalled nested `function helper() { fetch('/x') }` made its enclosing function a fetch wrapper. Nested function declarations that are never referenced are now ignored, as unused function-valued locals already were. - `window.fetch(url)` through a parameter or local named `window` (or `self`, `globalThis`) was read as the platform fetch. Such a root is now that value's method. A bare `fetch` parameter is still taken as fetch, since injecting a fetch implementation is the common reason for it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(bench): refresh the receiver-resolution baseline for the fetch fixture The new `fetch-base-url-wrapper` fixture in `test/fixtures/lang-resolution` adds one unresolved TypeScript chain-field call to the committed check corpus (127 to 128 call drops). Regenerated with `measure.mjs --update-baseline` after a fresh build and cleared parse caches; no other counter moved. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> |
||
|
|
702c917377
|
fix(python): retain nullable factory receiver types (#3595)
* fix(python): retain nullable factory receiver types * test(accuracy): remove repaired Python gap allowances * test(bench): refresh Python capture fingerprint * fix(python): type `None or call()` assignments like `call() or None` `None or make_user()` always evaluates to the call, but only the `call() or None` order matched, so the variable lost the factory's return type. Add the mirrored boolean pattern, matching the two conditional-expression orders the PR already supports. Fixture gains `none_or` (resolves to User.save) and `none_and` (stays unresolved: `None and x` is always None). The capture golden changes only for the edited fixture, and the python-scope baseline is re-recorded (`measure.mjs --check` passes, scaling 1.021). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
18128f9347
|
test(embeddings): cover CodeEmbedding scans after delete and re-create (#3569, #3474) (#3623)
LadybugDB 0.18.3 (shipped in 1.6.12 and 1.6.13-rc.57) misreads string
columns after a selective write. The CodeEmbedding table is affected by
the embedding writeback's own statements, without any COPY: after
per-node DELETE + CREATE and a checkpoint, 3,936 of 8,192 tuples scan
wrong and the {nodeId} lookup misses a retained row. On a released
build this makes unchanged nodes look new (re-embedding) and puts blank
or truncated ids into the CodeEmbedding key ("duplicated primary key").
The 0.21.1 engine on main fixes it.
- reproduce-search.cjs gains an `embedding` scenario using the
production CREATE / DELETE-by-nodeId statements; it fails on 0.18.3
and passes on 0.21.1. The vitest wrapper runs it with the other
scenarios; per-scenario expectations are now data, not branches.
- incremental-method-integrity runs both analyses with a deterministic
loopback embedding endpoint and asserts that only the edited file is
re-embedded and every other CodeEmbedding row (4,096+) is unchanged
from a cold reader.
Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
||
|
|
bd20dde825
|
fix(taint): report inline and factory handler flows (#3612)
* fix(taint): cover inline and returned handlers (U8) Join expression-handler CFG summaries to distinct graph functions without changing existing anonymous-owner identities. Keep named function expressions private to their lexical scope. Related: #3489 * fix(ci): encode inline handler taint paths (U8) Use codec-safe generated display names while preserving positional function identity. Verify persisted hop continuity and remove the repaired inline-flow accuracy allowance. * fix: keep anonymous names unbound (U8) * test: pin inline callback captures (U8) * ci: run inline taint guard (U8) * test: align inline handler contracts (U8) Pin callback-owned call edges while preserving nested callable IDs and module-level HOC attribution. Assert repaired inline flows and the retained captured-closure limitation. * ci: run native inline proofs on all OSes (U8) Register real-worker identity/CFG and persisted explain cases on the existing Windows/macOS matrix. Charge explicit scheduling estimates without changing watchdogs or runtime behavior. * test(taint): reject all enclosing factory sources --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> |
||
|
|
30676685e0
|
fix(rename): apply the exact reviewed edit plan (#3617)
* fix(rename): bind apply to reviewed plans (U7) Retain exact semantic edits behind single-use preview tokens and reject source, target, inventory and graph drift before application. Preserve explicit partial-write accounting and keep large unedited sources covered with hashes instead of retained text. Refs #2973 * fix(rename): cover unindexed sources (U7) Address PR #3617 review by binding every supported source to streamed byte hashes and canonical targets, including tracked and untracked files absent from the graph. Keep the exact reviewed edits and bound evidence memory. Use conventional even-sample medians and extend the existing CI benchmark to capture and validate unindexed sources without relaxing timing gates. Note: pre-existing packed Tree-sitter GLIBCXX_3.4.31 host failure in parse-cache-identity-package.test.ts is not addressed by this PR. * fix(rename): preserve lazy startup (U7) Keep language providers off the MCP startup path; load their existing classification only when rename inventory is requested. The existing 12 startup closure checks now pass. Address PR #3617 review by including token validation in reviewed apply timing and growing indexed evidence before preview, preserving the 20MiB controls under a 256MiB native pool. Migrate dispatch and retention tests to the preview token contract, keeping write-failure oracles. Note: pre-existing auto-sync /tmp fixture security and installed ARM64 grammar-header failures remain outside this PR; the packed Tree-sitter GLIBCXX_3.4.31 host failure also reproduces on unchanged main. * test(rename): always remove apply fixture (U7) Own the temporary directory from creation in an outer finally so setup and preview assertions cannot bypass cleanup. Keep spy restoration in its inner finally and preserve all write-failure assertions. Address PR #3617 cleanup feedback. * fix(rename): retain targets and config evidence * test(rename): verify approved physical output * test(rename): cover native filesystem matrix * test(rename): align preview contract fixtures --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> |
||
|
|
f43834e814
|
fix(indexing): converge coverage around directory symlinks (#3616)
* fix(indexing): converge coverage around directory symlinks (U5) * style(bench): format symlink baseline (U4) * ci: run directory symlink coverage benchmark --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> |
||
|
|
9b04fbe627
|
fix(embeddings): budget generated inputs and isolate rejections (#3615)
* fix(embeddings): budget generated inputs and isolate rejections (U4) * test(embeddings): require pending retry request * fix(embeddings): preserve Unicode in context * ci: run generated embedding input budget guard * test(embeddings): run input isolation on native OSes * fix: retain container identity after long prefixes * test: distinguish generated input cases --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> |
||
|
|
e6ae04ed84
|
fix(embeddings): reject corrupt identities before mutation (#3614)
* fix(embeddings): reject corrupt identities before mutation (U2) * fix(embeddings): preserve exact Unicode keys (U2) * fix(storage): validate identities before opening CSVs * fix(embeddings): validate caches before mutation * ci: gate native embedding identity benchmark * test(embeddings): run identity proofs on native OSes * docs: describe CSV identity validation pass --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> |
||
|
|
c8629f1b6c
|
fix(storage): preserve published graph on rebuild failure (#3613)
* fix(storage): preserve published graph on rebuild failure (U1) * test(storage): strengthen publication review coverage (U1) * test(storage): align publication evidence (U1) * fix(storage): retain completed recovery archives * fix(storage): preserve quarantines before cache reads * ci: run staged publication benchmark guard * fix(ci): declare WAL replay probe determinism Document that the bounded recovery read drains and discards its rows. Only WAL replay success is observed; row identity and query behavior are unchanged. The existing 21 query-determinism checks pass. * test(storage): cover publication across platforms * test(ci): exclude POSIX suite from Windows estimates * test: allow native publication retry to finish * test: verify Windows incremental recovery --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> |
||
|
|
22a7608b7c
|
feat(cache): derive parser and PDG cache identities automatically (#3606) | ||
|
|
cae60c2bd4
|
fix(mcp): reject corrupt query identities and refresh index metadata (#3571)
Some checks are pending
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
Publish / Classify release event (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (push) Blocked by required conditions
Publish / ci (push) Blocked by required conditions
Publish / Publish to npm (push) Blocked by required conditions
Publish / Build & Push RC Docker images (push) Blocked by required conditions
Trivy Image Scan / Trivy (gitnexus-cli) (push) Waiting to run
Scorecard / Scorecard analysis (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-web) (push) Waiting to run
* fix(mcp): reject corrupt query identities and refresh index metadata * fix(mcp): preserve reader and search integrity Keep replaced readers unknown until matching metadata is published. Defer shared-handle refresh until other consumers release the old graph to avoid rebuilding connections against the same stale generation. Propagate identity corruption after both hybrid search lanes settle, so the sibling cannot query after its database session is released. Select the regressions for the OS matrix and retain Python coverage without optional Swift grammars. Validation: 393 focused tests, nine native generation tests and ten race executions across five fresh processes pass. Build and source/test typechecks pass. The early full run passed 26,096 tests and failed eight: seven reproduce on baseline; the mixed-source publication case passes in clean reruns. Windows/macOS native execution remains for CI. Graph analysis maps all edited production symbols; coverage remains partial for the anonymous FTS test callback, manually reviewed. Refs #3571 * fix(lbug): bump @ladybugdb/core to 0.21.2 to stop doubled rows after delete and re-copy LadybugDB 0.21.0 and 0.21.1 return every row of a table that spans more than one native vector twice once the incremental writeback has DETACH DELETEd it and a COPY into an earlier table has run. NodeGroup::scan let a morsel that ended before the group's first live row wrap an unsigned subtraction and rescan to the end of the group (LadybugDB #1085, fixed in 0.21.2). No primary key error fires. The identity guard from #3442 stops the run with "unexpected or duplicate ID", so a Swift edit that pulls every importer into the write set failed on repos with more than 2048 structs. Only unreleased main was affected: 1.6.12 ships 0.18.3. Pin 0.21.2 in package.json, update the six @ladybugdb/core entries in the lockfile, and move coreVersion in the vendored FTS manifest. The FTS extension stays at 0.21.0 because no v0.21.1 or v0.21.2 artifact is published; the pairing assertion and its unit tests pass. Add a regression to the delete-nodes-for-files suite: 2049 structs with CONTAINS edges are loaded, every file is deleted, the graph is loaded again, and each id and edge must appear exactly once. Verification (Linux, Node 22.18): - lbug-delete-nodes-for-files: 11/11 on 0.21.2. With the 0.21.1 native packages swapped in, the new test fails with 4098 rows instead of 2049. - Reporter recipe end to end on the built CLI: incremental analyze exits 0 with no duplicate ids on a Swift-heavy fixture and on a 70-file Python fixture, with and without FTS. On 0.21.1 the Swift fixture exits 1. - A 0.21.1-written database opens and reads under 0.21.2. - prettier, eslint and typecheck:tests are clean on the changed files. - The full lbug-db project had not finished when this was committed. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * test(fts): say what the Windows warm-session branch covers On Windows the repair step calls poolClose, which removes the pool entry before the in-place writer opens. The step therefore checks the backend's cached capability state, not a live pool connection. The comment now says so instead of implying the pool stays warm. No behavior change. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * revert: take the @ladybugdb/core 0.21.2 bump out of this PR Reverts |
||
|
|
8fa8e64388
|
fix(rename): extend safe refactoring and flow coverage across languages (#3557) | ||
|
|
191a954bf6
|
fix(python): resolve calls through module-returning accessors (#3542)
Some checks failed
Trivy Image Scan / Trivy (gitnexus-cli) (push) Has been cancelled
Trivy Image Scan / Trivy (gitnexus-web) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Gitleaks / gitleaks (push) Has been cancelled
Publish / Classify release event (push) Has been cancelled
Scorecard / Scorecard analysis (push) Has been cancelled
Publish / RC guard (marker + release-PR skip) (push) Has been cancelled
Publish / ci (push) Has been cancelled
Publish / Publish to npm (push) Has been cancelled
Publish / Build & Push RC Docker images (push) Has been cancelled
* test(accuracy): retire repaired Python accessor gaps * fix(python): connect module accessor resolution * fix(python): resolve calls through module-returning accessors Bind `_pc().target()` and `m = _pc(); m.target()` to the module's function when a local accessor returns an imported module, and count capped-out dropped names in the impact lower bound. Closes #3497 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor(python): share module-accessor position key (#3542) - Reuse the capture-side positionKey in the receiver namespace resolver instead of a second line:col helper plus an inline template. - Note why the synthetic { moduleScope, scopes: [] } input is sufficient for createNamespaceTargetCache (sealed disk-backed ParsedFile shape). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor(python): reuse subtype-dispatch positionKey (#3542) - Export the existing line:col positionKey from subtype-dispatch instead of defining an identical copy in module-accessors, so both Python capture side channels key positions through one helper. - Apply prettier to the Function-scope indexing line. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(ci): unique test titles and rebaseline Python benches (#3542) - impact-epistemic-lower-bound: `%j` rendered null, NaN and Infinity all as `null`, so the test-completeness audit rejected the duplicate identities. Use `%s` so every parameterized case has a distinct title. - python-scope: capture fingerprint changes with the new module-accessor capture facts (golden captures were already updated). - receiver-resolution: +4 Python call drops (125 -> 129). The two-step `x = f(); x.m()` form is now counted as an unresolved call instead of vanishing: fastapi-depends `router.get/post` (unknown, x3) and python-method-chain-binding `user.get_city()` (in-program; `User` has no `get_city`, so the site is genuinely unresolvable). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
999cc9f913
|
fix(deps): upgrade native tree-sitter to 0.25.1 (#3531)
* fix(deps): upgrade native tree-sitter to 0.25.1 * fix(tree-sitter): preserve sync loading and update verified capture baselines Route C# scope queries through the synchronous native grammar loader so the compiled analyze module remains require-compatible on Node 22.18. Refresh only the audited empty-Python-module and renamed-PHP-fixture captures, and pin the runtime assertion to 0.25.1. Validated 479 targeted tests, all 16 scope-capture benchmark cases, Python capture/import guards, compiled C# worker parsing, build, typecheck and formatting. Performance budgets are unchanged. * fix(tree-sitter): refresh upstream vendors and preserve parser semantics * fix(ci): refresh prebuilds and support Windows ARM Refresh macOS, Linux ARM, and Windows x64 grammar binaries from the successful native CI builds. Pin node-gyp 12.4.0 so the Windows ARM jobs recognize Visual Studio 2026. Use local Git filtering for E2E to avoid PR-files API timeouts on generated parser diffs. Validation: 143 focused tests, Actionlint, and all 16 scope-capture benchmark checks passed. Full npm test run started; native database suites still running. * fix(ci): refresh Windows ARM grammar prebuilds Import all seven Windows ARM grammar artifacts from successful native build run 37965761760. Artifact filenames and SHA-256 hashes verified; all 42 native build jobs passed. Validation: 31 prebuild coverage tests passed. * fix(bench): stabilize scope capture timing guard Warm each input size seven times and use 21 median samples while retaining isolated timing blocks. Yield between languages so native finalizers release allocations outside the measured sections. Keep all fixture sizes, fingerprints, scaling formulas, and budgets unchanged. Validation: all 16 language guards passed with a 2 GB heap limit (1.38 deep-chain ratio; 1518 MB peak RSS). Linear and quadratic controls passed their expected guard outcomes. Formatting and graph change analysis passed. Full npm test is running without failures so far. * fix(parser): reduce TypeScript capture traversal cost * fix(test): await parser worker readiness before teardown * fix(parser): load C# synchronously in workers * fix(grpc): resolve native proto detections against their own file With the native proto grammar active, sibling .proto files that declare the same short service name under different packages tied in the directory-based resolveProtoConflict heuristic and both providers were dropped. A proto-origin detection already knows its defining file, so use that file's entry before falling back to the heuristic. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * ci(packaging): assert native grammars load from the installed tarball The packaged-install smoke only ran `gitnexus --version`, so a grammar that failed to load from the published package (bundled runtime, patched peer manifests, vendored prebuilds, C# sync loader, Protobuf wrapper) would ship silently; the dev-tree ABI smoke also accepts vendored grammars that report unavailable. Parse a sample for every registered grammar plus the native Protobuf plugin from the installed package, on the main thread and in a worker thread. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * ci(tree-sitter): track compatibility workarounds instead of 0.25 readiness The daily readiness report still targeted tree-sitter@0.25.0, so after the upgrade it would keep reporting "Blocked" and never close its tracking issue. Repurpose it to track what we carry for the bundled runtime: derive the target from the package.json pin, list each pack-time peer patch from prepare-tree-sitter-bundle.cjs with its drop condition (bump, wait for an upstream release, transitive, or intentionally pinned), and reword the buckets. The workflow adopts the issue opened under the old title. Also update the grammar-update-monitor header and auto-PR text, which still described the 0.21.1 runtime and a tree-sitter-c hold. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(dart): assert both nested labels target the loop; fix Zig call-shape doc The nested-label CFG test only jumped to `outer` and checked reachability, which still passes when a jump is retargeted to the inner loop (its exit reaches the outer header). Jump to both labels and assert the exact `continue` edges; dropping the inner label now fails the test. Update the Zig callable-flow comment: call_expression now wraps actuals in a required `arguments:` field. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Codex <codex@openai.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
4756e8a820
|
fix(release): gate publication on accuracy and paired evaluation (#3503)
* test(release): add fixed-answer native tool accuracy
* fix(release): gate stable artifacts on pinned paired evaluations
Apply review findings #1-4: gate Docker publication, grade in-flight retries, preserve repository context, and execute negative controls in CI.
* fix(eval): verify native context and resolve harness security findings
Inspect Claude's first startup reminder for ordinary repository guidance.
Bound launcher-option matching and escape Markdown backslashes and pipes.
Exclude only the parsed synthetic accuracy corpus from CodeQL; keep the
benchmark harness and evaluator under security analysis.
Validated focused Python and TypeScript regressions plus core typecheck.
* fix(eval): wake the EC2 runner and prove paired evaluator execution
Bootstrap the existing dedicated instance from a protected hosted job, bound
native runner pickup, and stop only instances started by this run. Keep paid
sessions inside the fixed stop window and add a runner-only dispatch.
Require a contained six-cell prepare/session/oracle/report canary in CI,
including a failed repair that remains in the measured denominator.
* fix(ci): reuse existing configuration and disambiguate accuracy cases
Remove the new AWS credential/settings path and release opt-in variable. Bound native runner pickup with the existing GitHub token and retain private EventBridge startup until its existing mechanism can be reused. Reuse current workflow environment names and evolution schedule controls.
Name malformed-observation cases explicitly so the execution audit distinguishes null from missing and actually tests invalid arrays.
* fix(review): isolate release builds and preserve benchmark evidence
* fix(release): gate RC publication on paired quality and manage EC2 lifecycle
* fix(ci): clarify release shell redirects and build script
* fix(eval): remove temporary patch sinks after capture
* fix(bench): retire tool-accuracy allowances repaired on main
Main at
|
||
|
|
82347f0f07
|
fix(scope): resolve local imports by lexical ownership (#3532) | ||
|
|
50aa4be3b2
|
fix(routes): prefer production handlers and preserve app.all (#3505)
Some checks failed
Trivy Image Scan / Trivy (gitnexus-cli) (push) Has been cancelled
Trivy Image Scan / Trivy (gitnexus-web) (push) Has been cancelled
Gitleaks / gitleaks (push) Has been cancelled
Publish / Classify release event (push) Has been cancelled
Scorecard / Scorecard analysis (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Publish / Build & Push RC Docker images (push) Has been cancelled
Publish / RC guard (marker + release-PR skip) (push) Has been cancelled
Publish / ci (push) Has been cancelled
Publish / Publish to npm (push) Has been cancelled
|
||
|
|
ff922c0a3b
|
fix(python): resolve calls through aliased package re-exports (#3504) | ||
|
|
4ccba12004
|
fix(scope): keep nested declarations out of module bindings (#3502) | ||
|
|
526b6f249b
|
test(search): guard native lookup and Unicode FTS after COPY (#3477) | ||
|
|
f99dde8aa3
|
fix(mcp): discover positional SDK tool registrations (#3450)
Some checks are pending
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
Publish / Classify release event (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (push) Blocked by required conditions
Publish / ci (push) Blocked by required conditions
Publish / Publish to npm (push) Blocked by required conditions
Publish / Build & Push RC Docker images (push) Blocked by required conditions
Scorecard / Scorecard analysis (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-cli) (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-web) (push) Waiting to run
|
||
|
|
a8f18f00b9
|
fix(swift): avoid false calls for injected closure properties (#3434) | ||
|
|
412446408d
|
fix(index): guard graph integrity and fail closed on incomplete risk (#3442) | ||
|
|
e42122a0f6
|
feat(go): index gin/echo routes and report them in impact (#3402) (#3417) | ||
|
|
0bcddec8e6
|
fix(python): keep uncertain decorated receivers unresolved (#3405)
Some checks are pending
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
Publish / Classify release event (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (push) Blocked by required conditions
Publish / ci (push) Blocked by required conditions
Publish / Publish to npm (push) Blocked by required conditions
Publish / Build & Push RC Docker images (push) Blocked by required conditions
Scorecard / Scorecard analysis (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-cli) (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-web) (push) Waiting to run
* fix(python): suppress uncertain decorated receivers * fix(ci): keep uncertain Python receivers out of method arity Unrecognized decorators now leave the receiver kind unproven, but the first parameter is still the implicit receiver slot for ordinary bound calls. Method extraction stopped stripping it, so decorated methods reported one extra parameter and shifted capture arity metadata. Share the uncertain-receiver classification between type-binding synthesis and parameter extraction, then refresh the Python capture golden and benchmark fingerprint for the intended capture change. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
c744ce1dfd
|
fix(python): resolve mixin calls with CPython C3 order (#3393)
* fix(python): resolve mixin calls with CPython C3 order Breadth-first MRO bound a diamond mixin call to the wrong base, and dropping the site left the real method out of the graph. Use C3 and take the first compatible method in that order. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(autofix): apply prettier + eslint fixes via /autofix command * fix(python): correct mixin receiver baseline counts * fix(python): guard incomplete mixin inheritance * fix(python): record unresolved MRO tail coverage (#3393) Track a missing subtype target when the last indexed MRO owner has an unindexed parent, and cover the case with an integration test. Correct the C3 fixture description. Note: local full npm test timed out amid parse-worker startup failures; focused tests and benchmark baseline passed. --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
f6e70016d6
|
fix(python): resolve mixin self calls to subtype implementations (#3390)
* fix(python): resolve missing mixin self members through subtypes * fix: honor Python effective MRO and static mixin targets * fix: bind Python subtype dispatch to receiver provenance * fix(python): limit mixin fanout to instance receivers * fix(python): capture call arity and invalidate stale parsed facts * fix(python): count bound receivers by method context Preserve static, free, nested and typed variadic parameters; test renamed target receivers without weakening incompatible-arity rejection. Regenerate capture goldens for receiver metadata and eight mixin fixtures. Record the deliberate missing_target coverage outcome: CI measured Python call drops 5->6 and total call drops 113->114; no shape or scaling threshold relaxed. * test(python): require a call capture before checking unknown arity * fix(python): bind subtype dispatch to receiver definition * test(python): include conditional renamed-receiver target * fix(python): prove positional mixin targets and report partial coverage Preserve upstream notebook coordinate mapping and maintainer changes. Reject incompatible/implicit-class targets, retain proven targets across ambiguous alternatives, and report capped or unresolved coverage without confusing edge deduplication. * fix(python): isolate subtype call proof and preserve lookup boundaries --------- Co-authored-by: Eva <eva@100yen.org> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> |
||
|
|
ccf6b4743d
|
feat(mcp): add read_file + grep tools (REST parity for /api/file slice + /api/grep) (#3377)
Some checks are pending
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
Publish / Publish to npm (push) Blocked by required conditions
Publish / Build & Push RC Docker images (push) Blocked by required conditions
Publish / Classify release event (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (push) Blocked by required conditions
Publish / ci (push) Blocked by required conditions
Scorecard / Scorecard analysis (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-cli) (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-web) (push) Waiting to run
* feat(mcp): add read_file + grep tools (REST parity for /api/file slice + /api/grep) * chore(autofix): apply prettier + eslint fixes via /autofix command * Address PR review feedback (#3377) - Fail read_file and grep when full source is unavailable, matching the HTTP 410 contract instead of an empty grep or a not-found on a missing checkout. - Reject branch on those tools so a pinned index is not labeled onto checkout bytes, and stop advertising branch in their schemas. - Point the grep hint at a 0-based read_file window, pass caseSensitive and literal through, and test the handlers. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3377) - Keep read_file and grep in the multi-repo schema requirement without advertising branch. - Reject negative maxLines and return integer slice bounds for fractional line positions. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3377) - Reject a negative read_file endLine before slicing so JavaScript does not treat it as an offset from the end of the file. - Drop the fractional startLine/endLine claim so the integer schema is the advertised contract. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3377) - Skip indexed grep paths whose realpath leaves the checkout so a symlink cannot return lines from outside the repo. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(bench): record the 19-tool MCP roster read_file and grep are real tools, so tools/list and GITNEXUS_TOOLS both moved from 17 to 19. The timing ratios were already inside budget. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(mcp): share read_file and grep contracts with existing helpers Boolean grep flags go through isFlagTrue, the whole-file cap is one constant, and checkout tools stay on the per-repo schema without advertising branch. --------- Co-authored-by: svjack <svjack@example.com> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
86a39202cf
|
fix(#2965): system headers must not resolve to in-repo files (#3341)
* fix(#2965): system headers must not resolve to in-repo files C and C++ use two syntactically distinct include forms: #include <x.h> -- angle-bracket: search system include paths only #include "x.h" -- quoted: search relative to the including file first The old suffix-match fallback in resolveCImportTarget had no awareness of this distinction, so a repo containing its own stdio.h would capture every #include <stdio.h> and resolve it to the local file. Fix: - Add isSystem?: boolean to the wildcard variant of ParsedImportSyntax - interpretCImport / interpretCppImport now set isSystem from the @import.system tree-sitter capture (present for angle-bracket form) - resolveImportTarget in both cScopeResolver and cppScopeResolver short-circuits to null when context.parsedImport.isSystem is true, refusing to suffix-match system headers against workspace files - Remove C and C++ from KNOWN_GAPS in the conformance test; add proper test cases with a parsedImport factory that distinguishes angle-bracket (isSystem:true) from quoted (isSystem:false) includes Test: all 36 external-import-conformance cases pass, including the two new c/cpp arms that were previously in KNOWN_GAPS. * fix(#2965): update cpp-imports unit tests for isSystem field Two test assertions were broken by the interpreter change: 1. Local include: the wildcard ParsedImport now always includes isSystem (false for quoted includes). Updated expected object to include isSystem:false. 2. System header: the old test asserted interpretCppImport returned null for system headers. The refactored design moves the null decision to the resolver layer (cppScopeResolver.resolveImportTarget) so the call graph and resolution stay separate concerns. The interpreter now returns { kind:'wildcard', isSystem:true } and the test name/assertion are updated to reflect this. * fix(#2965): resolve C and C++ includes on search paths Angle includes follow each translation unit's include roots, so a local stdio.h no longer captures system headers or another file's -I list. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3341) - Accept in-repo include roots whose names start with `..` while still rejecting parent escapes. - Correct the import-target bench comments so CONTEXT_LANGS and newPass match C/C++ header passes. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(c,cpp): read include config per directory for monorepos (#2965) Angle includes now resolve only against declared search roots, so config read only at the repo root left monorepo sub-projects with nothing declared. - compile_commands.json, compile_flags.txt, .ccls, .clangd and c_cpp_properties.json are read in every directory; a file takes the nearest one, and a nearer database's entry beats a shallower one (clangd). - CMake include_directories / target_include_directories are read: directory-scoped and PRIVATE roots reach their subtree, PUBLIC and INTERFACE roots reach every file. ${CMAKE_CURRENT_SOURCE_DIR} and friends expand; unresolvable variables and generator expressions are dropped. - Declared roots win: implicit include/Headers/inc roots apply only when no config speaks for the file, and never to a database-listed file. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(c,cpp): give CMake PUBLIC includes only to linked targets (#3341) target_link_libraries now decides who sees PUBLIC and INTERFACE roots, so an unrelated target no longer resolves another package's headers. --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
51fb64c976
|
fix(swift): model Swift modules like the compiler (nested packages, Xcode targets, linear visibility) (#3387)
* fix(swift): discover nested Package.swift manifests for module grouping A Swift monorepo laid out as Core/<pkg>/Package.swift has no root manifest and no root Sources/, so every Swift file fell into one __default__ module. The Swift resolver now walks the repo (bounded, skipping dot, ignored, and Xcode bundle directories) and adds each nested package's targets, keyed by repo-relative directory and ordered deepest-first so first-match grouping picks the most specific target. Import resolution keeps the root view. Refs #3355 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(swift): bound implicit IMPORTS edges by a total budget Implicit same-module IMPORTS are n*(n-1) edges per module, and the graph keeps every relationship in one Map capped by V8 at 2^24 entries. Emission now fills a 4M-edge budget smallest module first and skips, with a warning, any module that does not fit, so no module layout can crash analyze. Refs #3355 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(swift): skip pairwise sibling passes for oversized modules The target-siblings and sibling-type-bindings passes copy every file's declarations into every other file of a module, so heap grows as n^2: about 3.8 GB at 1,000 files with 15 defs each, about 15 GB at 2,000. Modules over 1,000 files now skip both passes with a warning and resolve through the global name fallback. GITNEXUS_SWIFT_MAX_MODULE_FILES changes the ceiling. Refs #3355 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(swift): cover nested SwiftPM packages end to end A fixture with three nested Package.swift manifests (two declaring a target named Net) and no root manifest. Each target gets its own implicit IMPORTS, none cross packages, and Config() resolves to the caller's own package. The Swift capture golden and scope-capture fingerprint grow with the new fixture corpus only. Refs #3355 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(review): apply review findings - Rebase nested target paths with the existing Zig path helpers, which also reject Windows drive paths and paths that resolve to the repo root (whose empty prefix would group every file into one target). - Document GITNEXUS_SWIFT_MAX_MODULE_FILES in the README env table. - State that skipped modules resolve through lower-confidence fallback edges, why nested-type fragments still run for oversized modules, and fix a stale loader name in the target-grouping header. Refs #3355 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(swift): cover every skipped Xcode bundle suffix in the package walk Refs #3355 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(swift): model modules the way the compiler does Replace the caps from the first round with representations that stay linear, and derive module identity from the same sources the compiler uses. - Same-module visibility is one File -> Module IMPORTS edge per file (reason `module-membership`) instead of an edge per ordered file pair. Incremental importer expansion treats files sharing a Module hub as importers of each other. The 4M edge budget is gone. - Sibling declarations and type bindings live in one shared table per module in the namespace channel C# uses since #1871, instead of being copied into every file. The 1,000-file ceiling and GITNEXUS_SWIFT_MAX_MODULE_FILES are gone. - Modules come from root and nested SwiftPM manifests (Sources, Source, src, srcs; plugins under Plugins; the newest Package@swift-X.Y.swift) and from Xcode native targets in project.pbxproj, including Xcode 16 synchronized folders. Target paths are matched from the repo root, so a vendored copy of the same layout is no longer grouped into a root target (this reverses #2931's floating match). - `import X` resolves to the modules named X instead of any folder named X. A name no module carries is external when every manifest and project was read completely. - The global-name-fallback veto uses the same membership, so test targets, custom-path targets and Xcode targets have module identity. Refs #3355 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(bench): move the Swift package bench to module grouping The bench still imported the removed groupSwiftFilesBySpmTarget. Its first-wins probe keeps its meaning under root-anchored grouping: the clash file sits under Sources/Mod0, and the Sources/Mod1 further down its path is a vendored copy. Plugins are now non-importable modules under Plugins/, so parse_targets counts importable source targets (still 3) and parse_binary_skipped also checks that the plugin is recorded that way. Baseline values unchanged; the notes say why the definitions moved. Refs #3355 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(swift): match compiler module names, manifests, and target filters - Module names follow the compiler's c99 mangling (`my-lib` imports as `my_lib`); Xcode targets use a literal PRODUCT_MODULE_NAME or PRODUCT_NAME when the project sets one. - Package manifests are one-file modules, as SwiftPM compiles them. Files outside every target are one-file modules once every manifest and project was read; otherwise they keep the shared __default__ module. - Xcode 16 synchronized-folder exceptions add a file to a target that does not list the folder, and remove it from one that does. - SwiftPM `sources:` / `exclude:` narrow a target; a computed list marks the manifest unreadable. - The default target folder is chosen once per package, as SwiftPM does, instead of per target. Refs #3355 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Address PR review feedback (#3387) - Inferred Swift folders keep SwiftPM's first predefined parent when a target name repeats (Sources before srcs). - The pbxproj parser rejects a \U escape without four hex digits instead of decoding garbage, so the project reads as incomplete. - Extension owners are stamped in every Xcode membership of a shared file. - A plugin name never reaches a plugin: neither the fallback veto nor the folder-index fallback treats a known non-importable module as imported. - A file an Xcode target compiles keeps that membership even when it also lies under a SwiftPM target directory. - The workspace scan bounds the queue, not only the directories read. - Integration tests require each module hub to exist before comparing. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
5fc518d2cb
|
fix(dart): resolve package imports by pubspec identity (#3369)
* fix(dart): resolve package imports by pubspec identity * fix(dart): keep package-identity edges out of the cycle check Pubspec identity edges invalidate importers when a manifest changes. They cannot form an init cycle, so the cycle query excludes them before the row cap. Discovery reads each manifest once, with a size bound, and resolution shares one package-URI parser with those edges. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3369) - Reject package URIs with an empty library path so they do not emit identity edges - Skip the pubspec permission test where chmod cannot deny reads - Document that the Dart heap probe is not a uniqueTarget spelling Note: pre-existing failure in test/unit/incremental-index-extension-dml-gate.test.ts not addressed by this PR. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(dart): list package directories through a no-follow descriptor A directory replaced by a symlink between the parent listing and the next visit must not be traversed. The walk opens it with O_DIRECTORY|O_NOFOLLOW and lists that inode. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(autofix): apply prettier + eslint fixes via /autofix command * fix(mcp): keep the Dart identity reason out of MCP startup The cycle query still excludes the same reason string. The constant now lives with the other non-initializing import reasons, so MCP startup does not load a language provider. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3369) Open discovered pubspecs and child directories through the parent directory inode on Linux, so replacing that directory with a symlink cannot redirect the walk. Note: pre-existing failure in test/unit/incremental-index-extension-dml-gate.test.ts (worker pool startup timeout) not addressed by this PR. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(dart): reject Windows junctions during pubspec walk * Address PR review feedback (#3369) Refuse pubspec discovery that cannot set O_NOFOLLOW, and verify macOS child opens against the pinned directory chain instead of reopening a mutable path. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(dart): bound live pubspec descriptors and close the macOS check-then-open A deep directory chain held one descriptor per level until open failed with EMFILE, and macOS child opens statted the path before using it. Refuse the next directory at 64 live handles, and stat only the descriptor opened with O_NOFOLLOW. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(dart): open pubspecs non-blocking so a FIFO cannot hang discovery A listed pubspec can be replaced by a FIFO before open. O_RDONLY alone waits inside open for a writer, so the file-type check never runs. O_NONBLOCK returns immediately and the walk rejects the non-regular file. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(dart): cap names read from each pubspec directory readdir kept every entry before the visit budget could run, so one huge directory could allocate without bound. Read the listing one name at a time and fail closed past 100,000 entries. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(dart): reject a pubspec that grows while its descriptor is read The size cap was taken from the stat before the read, so a file that grew in that window could be parsed from a short prefix. Re-stat the same descriptor afterward and fail closed when the size no longer matches the bytes captured. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ci): rebaseline the Dart scope-capture fingerprint for package-import fixtures The benchmark hashes every dart-* fixture. The new package-import corpus adds six Dart files and 33 capture groups. Parking that directory restores the previous fingerprint, so this is corpus growth, not a capture change. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
e06c2dd13e
|
fix(impact): fail closed on id-less targets and follow ??/||/?: callable values (#3354) (#3373)
* fix(impact): fail closed on id-less targets and follow ??/||/?: callable values (#3354) #3354 reports `impact` returning a byte-identical 1037/CRITICAL/`exact` result for three unrelated targets, with only `target.name` differing. The reporter's `target` had no `id` and no `filePath`, which the traversal path always emits, and a synthetic reproduction of their monorepo (pnpm, Cloudflare worker-configuration.d.ts in five packages, Hono, a Durable Object) resolves every target correctly on main. So the identical result was not reproduced. The repro did surface two real gaps and one hardening point: - `_runImpactBFS` now throws when the target has no node id. Every caller already catches, so impact reports `impactedCount: null, risk: UNKNOWN` instead of a normal-looking blast radius that cannot be about this symbol. - Callable-value flow followed only a single designator on the RHS, so `const sweep = env.__sweep ?? runSweep; await sweep(env)` produced no flow and `scheduled` was missing as a caller of `runSweep`, while the result still claimed `epistemic: exact`. Each branch of `??`, `||`, `or`, and `?:` now flows into the binding (language-neutral: operator and field names, no language checks). Parse cache bumped 104 -> 112 (105-111 are claimed by open PR #3326). - A whitespace-only `target_uid` (strict adapters materialize omitted optional strings) is treated as omitted and falls back to the name. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(mcp): treat a non-string uid as omitted instead of throwing (#3354) Review follow-up on #3373. `query.uid?.trim()` called `.trim()` on a client-supplied value, and the MCP envelope is not type-validated, so `context({uid: 42})` threw a TypeError that `context()` does not catch. Before #3373 the same input ended as a structured not_found. A non-string uid now counts as omitted, which matches how normalizeToolParams already treats a non-string `target_uid`. The impact and trace not-found messages print a trimmed uid only when it is a non-blank string, so a strict adapter sending " " sees the name it searched for instead of `' '`. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(ingestion): expand ??/?:/ternary branches through a provider hook (#3354) Review follow-up on #3373. The shared value-alternatives rule keys on tree-sitter field names, and several grammars spell the same construct differently, so the expansion never fired for them: - Kotlin `elvis_expression` has no fields. - Swift uses `value`/`if_nil` and `if_true`/`if_false`. - Dart uses `first`/`second`, and its conditional has no `condition` field. - Python `a if c else b` has no fields. The `'?:'` operator entry was dead, since no bundled grammar emits it. Add an optional `valueAlternatives` hook to CallableFlowCaptureOptions, consulted before the shared rule, and implement it in the Kotlin, Swift, Dart, Python and Ruby providers. Shared code still names no language. Ruby's statement-bodied `if`/`unless`/`elsif` also carries `condition`/`consequence`/`alternative`, so the shared ternary rule dug an identifier out of an arbitrary statement (`g = h; 0` flowed `h`) and produced a wrong CALLS edge. The Ruby hook now keeps a multi-statement branch as one opaque source, as before #3373. Tests: new provider fixtures for Python, Kotlin, Swift, Dart and Ruby (including a Ruby negative), and TS chain, parenthesized, callable-left and `&&` negative cases. Captures goldens gain one entry each for the new fixtures. SCHEMA_BUMP stays 112 (same unreleased PR). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(ingestion): keep long ||/??/?: chains linear in callable-flow capture (#3354) Expanding value-selecting sources into per-branch flows made long chains super-linear and, past a few thousand operands, a stack overflow. A generated `w === "k0" || w === "k1" || ...` keyword table took 6.7 s at 1000 operands and 48 s at 2000, and threw RangeError at 8000. Two causes, both fixed without changing any emitted capture: - valueAlternatives recursed once per operator level and spread the partial results at every level. It is now an explicit stack that writes to one output array. The left-to-right order, the paren unwrapping, and the provider-hook contract (`[node]` means opaque) are unchanged. - Every alternative ran its visibility walks from its own leaf, which can be as deep as the chain is long, all the way to the root. Also, tree-sitter's `parent` re-descends from the root, so each step costs the node's depth. The walks now jump between "anchor" nodes, the only nodes any check can match: region ids and formal owners. The nearest anchor is memoized per node across the file, and parents come from a map recorded by the one DFS the synthesizer already does. After the fix: 0.34 s / 0.23 s / 1.6 s at 1000 / 2000 / 8000 operands. That is within about 1.2x of main without the expansion; what remains is tree-sitter query time. Capture fingerprints are byte-identical before and after the fix for all 16 scope-capture bench languages and for the Python harness. A `typescript-deep-chain` case added to the scope-capture bench guards the scaling: 1.11-1.22 now, 7.5-8.0 before. A unit test pins a 10000-operand chain: it must still yield the seed for a callable operand, the copy for a formal at the deepest leaf, and the invoke. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(kotlin): see through braced if-branches in callable alternatives (#3354) tree-sitter-kotlin wraps a braced branch as `control_structure_body > statements > <expr>`, so for any non-empty block kotlinValueAlternatives saw exactly one named child (`statements`) and pushed the wrapper itself as the branch value. operandSyntax emits nothing for a `statements` node, so `val run = if (c) { ::f } else { ::g }; run()` produced no flow edges, and the "multi-statement block stays opaque" guard could never fire. Descend one level through `statements` and require exactly one non-comment expression there. Empty blocks (`{}` has no named children), multi-statement blocks, and `if` without `else` still return the whole `if` as one opaque source. The doc comment now describes that. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(ruby): skip only the multi-statement branch in callable alternatives (#3354) rubyValueAlternatives returned `[node]` (opaque) as soon as one branch held more than one statement. Two things went wrong because of that: - At the top level, `run = if c then g = h; 0 else method(:f) end` dropped the single-statement `else`, so `f` got no flow edge. - In an elsif chain, the outer `if` pushed the `elsif` node as a branch. The shared loop called the hook on it again, got `[elsif]` back, and used the whole elsif subtree as one source. So in `if a then method(:run_a) elsif b then g = h; 0 else method(:run_b) end` the `run_b` edge was lost. The hook now walks the elsif chain itself and skips each multi-statement branch, while every single-statement branch still becomes an alternative. This cannot add a wrong edge: each emitted alternative is a value the conditional really evaluates to, and nothing is taken from the skipped branch. Before, that branch did not contribute a resolvable value either. A whole conditional used as a source becomes a qualified-name seed, which resolves to nothing when it has more than one identifier leaf. With a single identifier leaf, it could even seed the condition variable. When no branch is a single statement, the conditional still stays one opaque source, as before. Ruby captures golden: ruby-callable-alternatives/app.rb goes from 33 to 58 capture groups. 23 of them come from the new fixture functions (checked against the old source). The other 2 are the new branch alternatives, `statement_if -> run_sweep` and `elsif_chain -> run_b`. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(ingestion): flow the right operand of && / and into callable bindings (#3354) `a && b` / `a and b` yields `a` when it is falsy and `b` otherwise. A falsy value is never a callable, so the right operand is the only one that can be invoked later. The capture left `&&` unexpanded, and the compound source became a qualified seed that resolves to nothing: `const run = x && f; run()` gained no edge to `f` while impact claimed `exact`. Python `x and f or g` reached only `g`. The shared expansion now maps `&&` / `and` to the right branch only. It recurses, so `x and f or g` reaches both `f` and `g`. Where `&&` yields a boolean (Java, C#, Go, Rust, C, C++, PHP, Zig), the destination cannot be invoked, so the flow never meets a call. A before/after CALLS diff over all 83 lang-resolution fixtures that contain `&&` or `and` shows exactly one new edge, logicalAnd -> runAndRight. PHP and Ruby bind low-precedence `and` looser than `=`, so `$g = $x and $y` never reaches this rule. The Python golden digest changes only for the extended python-callable-alternatives fixture. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(ingestion): keep operator branches of a value-selecting source opaque (#3354) The fan-out sent every branch of `??` / `||` / `or` / `?:` to emitAssignmentFact on its own, including branches that compute a value. `Handlers.fallback === run || fb` then emitted the comparison as a seed whose qualified text sliced to receiver `Handlers`, member `run`, and resolveBoundMemberCandidates minted a CALLS edge to `Handlers.run`. The same happened for `this.state !== run ?? this.fallback`, `this.state + run || this.fallback`, and Python `self.state != run or self.fallback`. Before the fan-out, the whole compound source was one opaque seed. A branch that is a binary operator expression now contributes nothing. The check uses the field vocabulary valueBranches already reads (a `left`/`right` pair, or an `operator`/`operators`/`op` token after the expression start), not grammar type names. Member accesses that field their `.`/`->` as `operator` (Ruby `call`, C/C++ `field_expression`) also field a member name through the list memberParts uses, now shared as memberNameNode, so they stay designators. Unary `&f`/`*fp` lead with their operator and stay designators. Call results were already dropped by emitAssignmentFact, and lambdas and callable references are unchanged. CALLS-edge diff over 87 lang-resolution fixtures (505 -> 501 edges): only the four false edges above were removed, and none were added. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(ingestion): pin the LEFT operand of ?? / or / elvis per provider (#3354) The Python, Kotlin, Swift and Dart "override ?? fn" cases put an unresolvable parameter on the left, so a fan-out that kept only the last operand still passed them. Each fixture now adds a callableLeft case with a real function on the left and a parameter on the right (`run_left or fallback`, `::runLeft ?: fallback`, `runLeft ?? fallback`), and each language asserts `callableLeft → runLeft`. Mutation check: dropping the left branch from the shared `??`/`||`/`or` rule and making the four provider hooks return only their last operand fails all four new tests, while the existing right-operand tests still pass. Capture goldens were regenerated with UPDATE_GOLDEN=1: - python app.py: 35 -> 85 groups. 35 -> 75 is stale drift from |
||
|
|
7376347058
|
feat(ingestion): add tRPC procedure detection and MCP chain/route surfacing (#3339)
* feat(ingestion): tRPC pattern detection — procedures, curried calls, route extraction
Three changes to properly index tRPC router files:
1. HOC-in-pair patterns: detect procedures like
'create: procedure.mutation(async ({ input }) => {...})'
as named Function nodes (pair > call_expression > arguments > arrow_function)
2. Curried call detection: capture 'workflow(db)(input)' chained calls
where call_expression.function is itself a call_expression
3. tRPC route extraction: new route-extractors/trpc.ts detects
.query()/.mutation()/.subscription() procedures, maps to /trpc/* routes
with prefix inference from router variable names
4. Function/Const dedup: structural check skips Const nodes when
variable_declarator value is arrow_function/function_expression
5. Process-route linking: match by (filePath, methodName) instead of
filePath only, preventing shared flows across procedures in same router
(cherry picked from commit eced15e60a39a181a48bff8c5bbe278d26aa53b8)
* fix(route-extractors): line-by-line scanner for chained tRPC procedures
Original regex only matched direct patterns (list: proc.query()) but not
chained patterns (create: proc.input(z.object({...})).mutation()). Only
41/256 routes were detected on Jurialis.
Rewrote extractTrpcRoutes() as a line-by-line scanner that:
- Detects procedure keys starting with *Procedure builders
- Tracks currentProcedure forward until terminal .query()/.mutation()
- Handles .input() chaining naturally
- Deduplicates via seen Set on procedurePath
Result: 245 routes from 30 routers (was 41), 256 total after re-index.
(cherry picked from commit 49edf953e93e6b67b77932e866fcbfb8d089b1f3)
* feat(mcp): expose tRPC chains via context/query tools
Eight fixes to make the tRPC route->procedure->workflow->sub-workflow chain
visible through the standard MCP tools (context, query) that AI agents use,
instead of requiring raw Cypher queries.
- A context: order incoming/outgoing CALLS test-last, raise LIMIT 30->100
- B query: batched ENTRY_POINT_OF lookup, surface route URL on processes
- C query: mark process_symbols entry point with is_entry_point=true
- D entry-point-scoring: skip UTILITY_PATTERNS (get*/set*) penalty for
symbols in tRPC router files so framework boost (3.0x) is preserved
- E fts-schema: index Route nodes so /trpc/* URLs are keyword-searchable
- F tools: bump max_symbols default 10->25 to fit procedure->workflow chain
- G context: optional chain_depth (0-3) param walks CALLS edges in both
directions and returns layered chain field
- H LadybugDB bug workaround: WHERE r.type IN [...] silently drops edges
on relationship properties; replace with OR chains (7 occurrences in
local-backend.ts, pdg-impact.ts, graph-queries.ts)
Validated on Jurialis: setProviderCap procedure now appears as caller of
setProviderCapWorkflow, /trpc/cabinet.setProviderCap Route is searchable,
chain_depth=3 returns the layered call graph.
(cherry picked from commit c24df0adce91e80f191a5c5d2e8b14e9da677366)
* feat(mcp): surface is_entry_point + routes in context, raise query limit
context() is the mandatory pre-edit tool (AGENTS.md). Until now an agent
had to issue a separate query() call just to learn whether its symbol is
a process entry point or which HTTP route it handles. These two fields
make context() self-sufficient for the bmad-dev flow.
- context: query STEP_IN_PROCESS now returns p.entryPointId; new
ENTRY_POINT_OF lookup attributes routes only from processes where the
symbol is the entry point (middle steps do not own the route) plus any
direct Route->symbol handler edge (tRPC procedures outside any Process)
- context: new top-level is_entry_point (true only) and routes[] fields
({url, method?}), emitted only when non-empty to keep the diff additive
- query: raise default limit 5->10 so dense domains (tRPC action router
with 20 chains, data-export with 9 flows) surface more of their flow
set without an explicit param
(cherry picked from commit 004f5b0ba985fcef3dfac5e67a2f2f7262184215)
* docs(mcp): document chain_depth, routes, and entry-point flag; neutralize examples in comments
* fix(mcp): address code-review findings on tRPC entry points, queries, and dispatch
- entry-point scoring: optional-chain framework detection and normalize
path separators before router-pattern matching (P1 crash on .js routers)
- tRPC extractor: emit controllerName as null (callers resolve via
lookupClassByName; a router object stringified as name corrupted lookups)
- route dedup: key seenRoutes by method:url so GET/POST pairs survive
- legacy TS queries: drop curried-call patterns (arity-corrupting for
overload resolution) and require non-array callee on pair member calls
- registry-primary TS query: mirror the non-array-callee predicate on the
new pair member-expression patterns (fixes query compile error)
- group tool port: forward chain_depth into per-tool context args
* fix(mcp): nested tRPC router paths, controller-less route binding, query chain_depth
- trpc extractor: brace-depth nesting stack composes sibling router paths (bare router() import style included); merge-prefix dot normalization; strict publicProcedure allowlist gate; drop phantom router metadata
- call-processor: bind controller-less tRPC routes to same-file handlers via exact single-match symbol lookup; ambiguous or missing handlers skipped
- query/group query: optional chain_depth (0-3) enriches ranked processes with their context chain; fix _computeContextChain layer docstring
- tree-sitter TS/JS scope queries capture string-key function declarations; tRPC pattern scoring narrowed to server router files
- parse-cache schema bump to v103 for extractor and route-binding changes
- add trpc route extractor regression tests (9 cases incl. sibling nesting and merge prefix)
* Address PR review feedback (#3339)
Close remaining review threads: compact tRPC keys, comment-safe terminals,
quoted-key identifier HOC captures, group-query default alignment, and
LadybugDB label scalars on context chains.
* chore(autofix): apply prettier + eslint fixes via /autofix command
* test: pin PARSE_CACHE schema bump to 103 (PR #3339 review fixes)
* fix(ingestion): bind same-name tRPC handlers and surface HANDLES_ROUTE
Same-name procedures resolve by startLine, the extractor keeps nested paths
through multiline schemas, and context/query UNION HANDLES_ROUTE for leaf
procedures that never become Process entries.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback (#3339)
Clamp group query bounds, drop HOC pair false positives, emit tRPC
terminal lines and hyphenated quoted keys, cap chain BFS concurrency,
and restrict the router utility exemption to accessor names.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback (#3339)
Score JS/JSX tRPC routers like TypeScript, ignore inner db.query and
unrelated .merge calls, mask regex braces, and assert clamp tests invoke
the query mock.
Co-authored-by: Cursor <cursoragent@cursor.com>
* chore(autofix): apply prettier + eslint fixes via /autofix command
* fix(ingestion,mcp): emit-side HOC callback guards + MCP schema prettier (PR #3339 round 2)
* Address PR review feedback (#3339)
Treat `/` after return-style keywords as a regex, drop the synthetic
appRouter path prefix, and bind the create mutation via an inline callback.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback (#3339)
Qualify query() docs so is_entry_point is promised only when the entry
symbol is among the search hits.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback (#3339)
Emit tRPC terminals only at procedure paren depth, drop the filename
prefix on bare appRouter = router(), mask regex after if (), and cap
groupQuery member fan-out.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback (#3339)
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback (#3339)
De-duplicate context-chain BFS nodes reached through multiple frontier
edges, and bind tRPC identifier callbacks (`.mutation(handler)`) to the
handler symbol instead of the procedure key.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback (#3339)
Apply LIMIT 50 after DISTINCT neighbors in the context-chain BFS, and
treat the official lowercase `procedure` builder as a tRPC procedure key.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback (#3339)
Keep the later duplicate tRPC object-literal key so route binding matches
the handler JavaScript actually ships.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback (#3339)
Compose same-file identifier-mounted tRPC subrouters so admin: adminRouter
emits the live admin.list path instead of an unprefixed /trpc/list.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback (#3339)
Memoize tRPC identifier-mount paths so a depth-N chain stays linear, and
gate it with the build-free measure.mjs / baselines.json harness.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback (#3339)
Compose identifier mounts without phantom /trpc URLs, bind wrapped and
multiline handlers, fail-close missing bench budgets, and reject query
page bounds before search.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback (#3339)
Reject advertised MCP query bounds in group mode and chain_depth
instead of clamping or accepting non-integers.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback (#3339)
Reject invalid groupContext chain_depth and ignore non-callable
same-file tRPC handler candidates.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback (#3339)
Memoize live tRPC mount paths so the depth-N chain bench stays linear,
and render invalid group/MCP bounds without throwing.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback (#3339)
Keep t.merge('prefix.', namedRouter) procedures live by recording a
zero-hop mount so the unmounted-router drop does not hide them.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Address PR review feedback (#3339)
Recognize type-annotated `const adminRouter: AppRouter = t.router(`
bindings so identifier mounts still compose.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
|
||
|
|
dcb2eb5cb4
|
fix(swift): resolve imports from Package.swift targets, not path segments (#3105)
Some checks are pending
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
Publish / Classify release event (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (push) Blocked by required conditions
Publish / ci (push) Blocked by required conditions
Publish / Publish to npm (push) Blocked by required conditions
Publish / Build & Push RC Docker images (push) Blocked by required conditions
Scorecard / Scorecard analysis (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-cli) (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-web) (push) Waiting to run
* fix(swift): match repeated SPM target prefixes * test(swift): cover repeated SPM target prefixes * test(swift): cover valid prefix before later partial match * docs(swift): clarify target grouping parity scope * docs(swift): clarify target grouping parity scope * docs(swift): clarify target grouping parity scope * fix(swift): resolve imports from Package.swift targets, not path segments Stop fabricating IMPORTS from import Foundation onto a same-named folder. Declare modules from Package.swift when the manifest is usable; keep Sources/* for grouping and fail-open folder resolve minus SDK names. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(swift): keep empty Package.swift declarations and nested .target() deps external An inferred Sources/* folder is grouping-only. A dependency .target(name:) is not a module. Treat both as unresolved so import Foundation cannot bind to a decoy folder. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(swift): keep implicit IMPORTS intra-group and gate linear Package.swift resolve @_exported must not paint sibling files as implicit imports. A dedicated bench pins declaration-only resolve and (t_4n/t_n)/4 linearity. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3105) Honor member-only @_exported imports, skip comments while scanning Package.swift factories, fail-open mixed helper-built target lists, and block CoreData/CoreGraphics decoy folders on the inferred path. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3105) Match path: "." as the package root, skip block-commented Package.swift factories, read import kind from the clause only, and skip capture tests when the optional Swift grammar is missing. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ci): scan Swift import-kind without nested regex backtracking CodeQL js/redos flagged the comment-skipping IMPORT_KIND_RE; a linear walk keeps the same kind tokens. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ci): linear Package.swift factory scan and gate Swift context parseSwiftPackageManifest re-walked every prefix for comments (O(n²) in factory count). Resume the scan and cover nested factories in one pass. Wire Swift into the import-target context arm now that resolveImportTarget is 5-arg. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3105) Tighten Package.swift and import-text scanners: skip comments/strings, reject escapes, treat ident + [ as incomplete, and drop the unused factory-comment wrapper. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ci): prettier the @_exported availability fixture Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3105) Judge Package.swift completeness from Package(...)'s own targets: argument instead of raw-text regexes, nest block comments when reading an import kind, and strip leading ./ from declared target paths. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3105) Collect Package.swift factories only from Package(targets: [...]), fail-open on computed array elements, and treat // after a label colon as a comment. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3105) Ignore stray factories when Package() exists but omits targets:. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3105) Require the Package-scan seen box so the always-true undefined guard goes away. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
a578747455
|
fix(swift): resolve nested constructors in extensions (#3308)
* fix(swift): resolve nested constructors in extensions * fix(swift): preserve qualified extension owners * Address PR review feedback (#3308) Recover qualified Swift extension owners through public / attribute prefixes, and stop last-dot-guessing when source text is present. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(swift): keep attribute text from stealing extension owners Bound header recovery so @available messages cannot rekey a fragment, and still inject nested types when the Class scope has no bindings. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(swift): nest comments and keep the public extension fixture valid Review follow-up: skip nested /* */ in the header scan, put the Inner.Entry decoy in a parsed file, and mark Outer/Container/Entry public so the live fixture is valid Swift. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(swift): recover Unicode identifiers as extension owners The header regex was ASCII-only, so extension Café.Container keyed as Caf and dropped nested-type siblings. Match ID_Start/ID_Continue segments instead. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(swift): skip raw strings and decode UTF-8 scope columns Header recovery treated #"..."# as an ordinary quote and sliced Tree-sitter byte columns as JS offsets, so a same-line Café prefix or a raw attribute message could steal or drop the extension owner. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
795cf0e151
|
fix(swift): resolve inherited protocol extension calls (#3309)
* fix(swift): resolve inherited protocol extension calls * fix(scope): gate inherited implicit receiver lookup * fix(swift): resolve call result types by exact callee * test(swift): align cache and local call expectations * fix(scope): reconcile replay diagnostics * fix(swift): preserve exact callable return types * fix(swift): capture throwing async call results * test(swift): refresh capture golden * test(swift): refresh scope capture baseline * fix(swift): require explicit callable returns * fix(scope): preserve duplicate return metadata * chore(scope): align index documentation * Address PR review feedback (#3309) Stamp only protocol/class-extension members (nested QN + SPM buckets), arity-narrow implicit-this across MRO, and keep Swift type peeling out of shared workspace-index via stripTypePreservingDecoration. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3309) Stamp extension members even when the extension declares a nested type, keep inherited class members ahead of protocol-extension defaults, and report replay-only interface-dispatch fan-out drops. Note: pre-existing failure in gitnexus tsc against an older gitnexus-shared dist not addressed by this PR. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3309) Walk inherited implicit-this owners nearest-first so a nearer override wins, and tighten Swift owner-stamp tests. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(autofix): apply prettier + eslint fixes via /autofix command --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
0ede6ae501
|
fix(rust): respect Cargo target boundaries in name fallback (#3294)
* fix(rust): respect Cargo target boundaries in name fallback * fix(rust): read Cargo sources through validated file descriptors * fix(rust): require matching imports for crate-root guesses * fix(rust): require Cargo root identity for cross-target imports * fix(rust): enforce Cargo identity across fallback imports * fix(rust): keep Cargo membership on typical derive/macros (#3294) Abort only genuine unknown expansion, ignore Cargo artifact layouts instead of every `target` path segment, and require a covering import for unanswered crate-root name fallback so #3253 still holds on ordinary Rust sources. Co-authored-by: Cursor <cursoragent@cursor.com> * test(rust): gate Cargo target membership in CI (#3253) Add a parse-dispatch-rounds-style bench so derive/macro abort, target-path globs, and superlinear membership walks fail in CI instead of staying graph-invisible. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(rust): verify Cargo macro and re-export evidence * style(bench): format Cargo membership benchmark * fix(rust): require imports for cross-file root guesses --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
79543c8f83
|
feat(storage): add configurable index storage and content retention tiers (#3060)
* feat(storage): add configurable index storage and content retention tiers Rebase #3060 onto current origin/main. Keep GITNEXUS_STORAGE_PATH, GITNEXUS_STORAGE_ROOT, and GITNEXUS_CONTENT_RETENTION, and fold in main's FTS skip, embed-session, and help-text updates. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3060) Keep legacy registry rows on the local storage fallback, resolve symlinks before the destructive-path guard, and align hook lookup with CLI branch slugs, branch-slot metadata, and longest-path match. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3060) Only list swept upload directories after a successful removal so callers cannot treat a permission or transient rm failure as gone. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3060) Document that getStoragePath may consult registered storage while this module still does not mutate the global registry. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(storage): close review findings for external indexes and retention Re-inspect ownership under the analyze lock, fail-closed when the registry file is missing, and keep skip-git hook discovery plus retention fields on HTTP/MCP list surfaces. /api/file stays 410 unless contentRetention is full. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(autofix): apply prettier + eslint fixes via /autofix command * Address PR review feedback (#3060) Treat lock-only index dirs as empty, honor HTTP --force storage policy, and prefer registered plus branch-aware slots in hooks and augment. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3060) Keep hook fallbacks inside the current worktree, compare foreign-local slots canonically, and make storage fixtures survive ownership validation. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix macOS hook test expecting realpath'd registry paths. resolveHookRepo returns the written registry path, not a filesystem realpath, so the assertion must match that. * Address gitnexus-check warnings on hook install docs and slot tests. The Cursor troubleshooting list omitted registry-query.cjs, and the writable-slot test only checked that isDirectory exists instead of that the path is a directory. * Align the HTTP catalog source-scan with skippable resolveRepo validation. resolveRepo lists fresh repos with validate: options.validateStorage !== false so DELETE can skip prune; the test still required a literal validate: true. * Harden storage path sinks so CodeQL path-injection and ReDoS alerts clear. Contain every filesystem probe inside the resolved storage slot with the inline path.relative idiom, reject filesystem-root slots, and trim slot basenames in linear time. * Settle bridge stamps before writing so CI size/mtime matches stay stable. LadybugDB can still flush into bridge.lbug after close+rename; persist whole-millisecond mtimes and wait for consecutive stats to agree so a freshly written pair matches. * Type the settled bridge stat as fs.Stats so tsc does not see bigint. Awaited<ReturnType<typeof fsp.stat>> collapsed the bigint overload and broke prepare/typecheck on CI. * Keep the bridge mtime stamp exact so same-size swaps still fail the pair check. Co-authored-by: Cursor <cursoragent@cursor.com> * Wrap the bridge stamp predicate so prettier --check stays green. Co-authored-by: Cursor <cursoragent@cursor.com> * Require a quiet interval before stamping a settled bridge file. Co-authored-by: Cursor <cursoragent@cursor.com> * Reuse shared storage and settle helpers instead of local copies. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
d1a3edd333
|
perf(mcp): avoid O(n) git spawns on tools/list with many repos (#3259)
* perf(mcp): avoid O(n) git spawns on tools/list with many repos toolSchemaRepoRequirements called listAllowedRepos -> listRepos -> checkStalenessAsync for every registered repo. With ~200 repos, this spawned 200 parallel git rev-list processes on every tools/list discovery call, causing a ~30s delay. Replaced with a lightweight countRepos() method that reads the registry file once without spawning git processes, preserving full staleness checks for list_repos. * Address PR review feedback (#3259) Count the validated registry in countRepos so tools/list cannot advertise a multi-repo schema for ENOENT ghosts, and update the unrestricted listTools mocks to that contract. Note: pre-existing failure in update-notice.test.ts (missing dist/cli/mcp.js) not addressed by this PR. Co-authored-by: Cursor <cursoragent@cursor.com> * Add a 200-repo tools/list bench for the countRepos path (#3259) Pin the #1363 comparison (listRepos git fan-out vs validated countRepos / listTools) in-tree so the latency claim can be re-run. Also drop the change-history comments on the unrestricted schema arm. Co-authored-by: Cursor <cursoragent@cursor.com> * Gate the tools/list bench with baselines and CI --check (#3259) Exact registry/schema floors plus ratio timing, no millisecond ceiling, so restoring listRepos() on tools/list fails CI. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3259) Align unrestricted tools/list schema flags with the refreshed registry snapshot, and make the bench reject a non-positive BENCH_REPS and isolate fixtures by N. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(autofix): apply prettier + eslint fixes via /autofix command * Address PR review feedback (#3259) Isolate the tools/list bench from GITNEXUS_MCP_READ_ONLY and create the default fixture under mkdtempSync so CodeQL is not looking at a predictable /tmp path. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
c9b391357e
|
fix(group): detect function-local Python imports (#3254)
* fix(group): detect function-local Python imports * fix(group): parse Python imports structurally * fix(group): use safe Python parser wrapper * fix(group): isolate Python parse timeouts * fix(group): skip recovered indented Python from-imports Error-recovered trees can promote unclosed-docstring lookalikes into real import_from_statement nodes. Drop those indented imports, bound file reads, log parse timeouts, and add fingerprint floors for the tree-sitter scan. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(autofix): apply prettier + eslint fixes via /autofix command --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
0edf9ce0ff
|
fix(ruby): guard gem requires with dependency metadata (#3096)
* docs(plans): add ruby gem require boundary plan * fix(ruby): guard gem requires with dependency metadata * fix(ruby): scope gem sources by manifest * test(ruby): model resolved lockfile specs * fix(ruby): stop local gem suffix fallthrough * docs: remove Ruby resolution plan * test(ruby): gate gem resolution correctness and scaling * test(ruby): align gem benchmark baseline with ratio gates * Address PR review feedback (#3096) - Strip a trailing .rb so local and external gem prefix matching follows Ruby's optional-suffix require. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> |