mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-04 02:31:36 +00:00
1349 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
fa8ebf672e
|
fix: Java cast-wrapped and this.method() call edges (#2357)
* fix: resolve Java cast-wrapped and this.method() call edges
Two fixes for missing call edges in Java method resolution:
1. compound-receiver.ts — cast expression handling:
- Strip (Type) cast wrappers from receiver text, tracking the
outermost meaningful cast type
- Resolve directly to the cast type class (not the field's
declared type), since the cast narrows the receiver type
- Add this.field chain walker for field-access receivers
- Replace text → workingText throughout the function body
2. scope-resolver.ts:
- Enable resolveThisViaEnclosingClass: true for Java
(activates Case 0.5 in receiver-bound-calls.ts)
Verified on a large-scale Java codebase with no regressions.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* chore(scope-resolution): format compound-receiver.ts with prettier (#2353 review F10)
Mechanical prettier --write from repo root — 6 brace-expansion sites and one
ternary re-join, zero logic changes. Clears the quality/format CI failure
that was blocking CI Gate on PR #2353.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* test(scope-resolution): pin working Java cast-receiver shapes (#2353 review F3)
Fixture-backs the cast resolutions PR #2353 gets right — simple cast,
nested/CFR cast, cast over this.field, and the deliberate declared-type
fallback for a resolvable-shape cast to an unindexed type — each with a
same-named decoy method on the receiver's declared type so later refactors
cannot silently regress them. No resolver changes; tests are green as-is.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(scope-resolution): resolve nothing for unparseable cast types (#2353 review F1)
A receiver paren-group that is type-shaped but unparseable — generic
(List<String>), array (Foo[]), fully-qualified (com.example.Foo) — is a
cast whose type cannot be looked up. Stripping it and falling through
resolved the pre-cast expression's own declared type, emitting a
confident wrong CALLS edge. Classification is now three-way per peel:
simple identifier → capture (outermost wins), type-shaped-unparseable →
resolve nothing (pre-#2353 behavior; noise casts after a captured type
still win), anything else → not a cast, text left untouched. Cast
candidates require a non-empty trailing expression, so plain
parenthesized receivers never capture a cast type.
Red-first: all four shapes reproduced the wrong edge before the fix;
golden digest byte-stable after.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor(scope-resolution): delete duplicate this.field walker, seed literal-this chain heads (#2353 review F4/F5/F7)
A/B against the fixture corpus confirmed the generic per-segment walker
(head resolved via the synthesized this typeBinding) already covers every
method-body this.field chain — only initializer contexts (instance
initializer block, field initializer) were walker-dependent, since no
function scope exists there to carry a this binding. Deleting the
duplicate walker removes the naive chainRest.split('.') (F5) and the
widened fieldFallback use (F7) with it; the findEnclosingClassDef head
seed is the deliberate residue covering initializer contexts —
head-resolution only, the per-segment walk stays the single shared
implementation. Post-seed edge set is byte-identical to pre-deletion.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(scope-resolution): gate cast stripping behind opt-in stripReceiverCastExpressions (#2353 review F2)
Cast handling in resolveCompoundReceiverClass now runs only for
languages that opt in via the new ScopeResolver toggle (default off);
Java is the sole opt-in. The peel loop is extracted into the pure,
exported stripCastWrappers helper (placed with the file's other pure
string helpers) so it can be unit-tested directly. Non-opting languages
see receiver text untouched — pre-#2353 behavior by construction
(golden digest unchanged, TS/C++/C# suites green, 796/796). Shared-code
comments are language-neutral per AGENTS.md; the contract JSDoc carries
the classifier grammar, the second-language escalation rule, and the
Case 3b/Case 4 pass-through non-goal.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(scope-resolution): cap cast-peel iterations in stripCastWrappers (#2353 review F8)
MAX_CAST_PEEL = 16 (each cast level costs at most two peels, so this
covers 8-level nesting with headroom — real cast nesting, including
decompiler output, is a handful of levels). Each peel rescans the
working text for its matching close paren, so pathological nested-paren
input was O(N²); the cap bounds it at O(N·16). Exceeding the cap bails
all-or-nothing with the original text (not-a-cast outcome). Adds the
helper's first unit tests: 14 scenarios covering capture, unparseable
shapes, redundant-paren unwrap, captured-type precedence, rawName
no-op, over/under-cap, and unbalanced-paren termination.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(scope-resolution): revert Java resolveThisViaEnclosingClass, pin Case 4 bare-this dispatch (#2353 review F6/F9)
Remove resolveThisViaEnclosingClass from the Java scope resolver: the
toggle's own contract doc prescribes keeping it disabled where Case 4
(the synthesized this typeBinding) already handles this, and Case 0.5's
C++-authored semantics (hiddenByName arity-hiding, method-before-field)
provably bypass the interface-dispatch fan-out only Case 4 emits.
A/B gate (new java-this-dispatch pinning fixtures): flag-off 7/7 green;
flag-on 2/7 red (hiddenByName drops the this.greet overload site —
masked by a free-call-fallback 'local-call' edge — and the
interface-dispatch fan-out is missing). Corpus A/B over all 54 java-*
fixtures: 2 fixtures differ — java-this-dispatch (reason
'local-call'→'global' on the bare-this overload site; +2
interface-dispatch fan-out edges flag-off) and java-this-field-chain
(2 initializer-context bare-this ACCESSES reads emitted only by Case
0.5, which Case 4 cannot resolve — no synthesized this binding without
a Function scope; the corresponding CALLS edges are unaffected via the
F4 commit's literal-this head seed).
Also (F9): insert Case 0.5 into the I4 case-order listings (contract +
receiver-bound-calls header, now 8-case, marked gated) so the next flag
flip is visible at review time; the two 'sole C++ language' comments
are accurate again unedited.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(scope-resolution): restrict literal-this head seed to initializer contexts (#2353 review follow-up)
Final-review finding (two independent reviewer angles): the literal-this
chain-head seed landed ungated in shared code, so any language's
this-headed chain in a scope without a synthesized this typeBinding —
including contexts where the language DELIBERATELY leaves this unbound
(object-literal methods, nested plain functions) — would seed from the
lexically enclosing class. isInitializerContext now permits the seed
only when no Function scope sits between the site and its class, which
is precisely the field-initializer / instance-initializer shape the
seed exists for. Adds a TS guard fixture pinning that an
object-literal method's this.field.method() chain emits no fabricated
edge (mechanism did not empirically reproduce even ungated — the
restriction is conservative hardening, and the pin keeps it that way).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore(scope-resolution): attach stripCastWrappers JSDoc, fast-path non-paren receivers (#2353 review nits)
Two final-review nits: a blank line detached the helper's 30-line
classification-contract JSDoc from the declaration (IDE hover showed
nothing at call sites); and the gate now skips the helper call plus
result allocation for the majority of receivers that cannot be casts
because they do not start with '(' — the helper's own check stays as
the safety net.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* bench(scope-capture): rebaseline Java fingerprint for new #2357 fixtures
The scope-capture correctness fingerprint hashes captures over the
java-* fixture corpus; the three fixture dirs added by this PR
(java-cast-receiver, java-this-field-chain, java-this-dispatch) extend
that corpus, so the fingerprint moves. Verified purely additive: with
the three new dirs parked, the fingerprint reproduces the prior
baseline byte-identically — no emit/capture behavior changed.
--check now passes for all 14 languages.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: ww <ww@wwdeMacBook-Pro.local>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
fb40d15a16
|
Add Kilo Code + GitNexus MCP setup guide (#2259)
* docs: add Kilo Code MCP workflow * Fixed Space Fixed 1 deleted blank line * Fixed Readme Link Fixed guide link from docs to documentation folder fixing 404 error * Added Image and linked to .md file * Removed Trailing Spaces --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> |
||
|
|
6ef173fc51
|
fix: consolidate icon imports, fix stale refs and package name collision (#2343)
* fix: consolidate icon imports, fix stale refs and package name collision three components were importing directly from lucide-react instead of going through the centralized @/lib/lucide-icons module like the rest of the codebase. added the missing Keyboard and BarChart2 exports to the icons module and updated the imports. also: - removed duplicate mermaid init comment in ProcessFlowModal - replaced placeholder issue #XXX with a descriptive note in git.ts - updated stale KuzuDB reference to LadybugDB in ARCHITECTURE.md - renamed gitnexus-web package.json name from "gitnexus" to "gitnexus-web" to avoid collision with the CLI package * fix: complete package rename in lockfile and cite #2054 in git.ts comment Address tri-review findings: package-lock.json name fields (top-level and packages[""]) now match the renamed gitnexus-web package, and the getCanonicalRemote doc comment cites #2054 instead of dropping the issue reference. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore(autofix): apply prettier + eslint fixes via /autofix command --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
63527cf44d
|
Update code owners in CODEOWNERS file | ||
|
|
3d022c6aa9
|
Fix duplicate GitHub funding entries | ||
|
|
42de00593b
|
Add new GitHub funding user | ||
|
|
5aada28da5
|
fix(embeddings): use system-matched onnxruntime-node CUDA build so CUDA 13 hosts use the GPU (#2341)
* fix(embeddings): use system-matched onnxruntime-node CUDA build so CUDA 13 hosts use the GPU
transformers.js exact-pins a CUDA-12 onnxruntime-node while gitnexus' own dep floats to a CUDA-13 build. npm/pnpm cannot dedupe an exact pin against a range, so npm i -g installs two copies and the gitnexus overrides block (root-only) is inert. On a CUDA-13-only host the nested CUDA-12 provider cannot load libcublasLt.so.12, the CUDA EP fails, and embeddings silently fall back to CPU (isCudaAvailable() also only probed .so.12).
Add onnxruntime-node-resolver.ts (module.registerHooks redirect to the host-matching build, no-op elsewhere) mirroring onnxruntime-common-resolver.ts; probe libcublasLt .so.12 OR .so.13 against the copy that actually loads; unit test with 12 cases.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(embeddings): wire CUDA-13 build-match resolver into MCP query embedder
The MCP query-time embedder (src/mcp/core/embedder.ts) has its own,
separate initEmbedder() used for semantic search — it only called
ensureOnnxRuntimeCommonResolvable() before importing transformers.js, so
the CUDA-13 build-matching redirect added for the analyze/CLI embedder
never applied here. A CUDA-13 host running MCP search with
--embedding-device cuda still loaded the mismatched default onnxruntime-node
build.
Wire ensureOnnxRuntimeNodeMatchesSystem() into the same call site, mirroring
the core embedder's ordering (registered after the common-resolver fallback,
before the dynamic transformers import).
* fix(embeddings): gate CUDA redirect decision on registerHooks availability
decide() computed the CUDA-major redirect independent of whether Node's
module.registerHooks API actually exists — only ensureOnnxRuntimeNodeMatchesSystem()
checked that. On Node 22.0-22.14 (allowed by this package's engines
floor; registerHooks needs >=22.15), isCudaAvailable() could therefore
report a redirect target that ensureOnnxRuntimeNodeMatchesSystem() then
silently failed to install, so transformers.js loaded the mismatched
default onnxruntime-node build while the embedder still requested
device:'cuda' against it — reintroducing the uncatchable native crash
this probe exists to prevent.
Move the registerHooks check to the top of decide() so the probe and the
loader can never disagree, and skip CUDA-major probing entirely in that
case (a redirect could never install anyway).
Also fixes a related test-helper bug found while writing this unit's
tests: loadResolver's destructuring default (`registerHooks = vi.fn()`)
silently substituted a real mock function even when a test passed
`registerHooks: undefined` to simulate Node < 22.15 — meaning the
existing 'no-ops... when registerHooks is unavailable' test never
actually exercised that path. Distinguish 'omitted' from 'explicitly
undefined' via an 'in' check.
* test(embeddings): drive decide() -> redirect:true and assert the resolve() closure
The PR's actual shipped behavior — the installed registerHooks resolve()
closure, and the full redirect-active decision path — had zero executed
test coverage. All 4 prior ensureOnnxRuntimeNodeMatchesSystem tests avoided
driving decide() into redirect:true because require.resolve/createRequire
were never mocked, so the two-distinct-directory comparison decide()
depends on always resolved against whatever's actually installed in this
test's real node_modules (a single real copy, not the PR's two-copy
scenario).
Extend loadResolver()'s existing node:module mock to also fake createRequire,
keyed by call origin, so resolveOurOrtNodeDir/resolveDefaultOrtNodeDir can be
driven to two distinct fake directories with distinct CUDA majors — reaching
redirect:true without adding any injection points to production code. Then
capture the installed resolve() closure (mirroring the sibling
onnxruntime-common-resolver.test.ts's captureResolve() pattern) and assert
its three branches directly: onnxruntime-node redirect, onnxruntime-common
redirect, and passthrough for any other specifier.
* fix(embeddings): distinguish ldd detection-failure from no-CUDA-provider
ortCudaMajor treated any execFileSync('ldd', ...) failure with no usable
stdout (missing ldd binary, permission-denied .so, sandboxed exec)
identically to 'CUDA provider genuinely absent'. The pre-PR detection
(hasOrtCudaProvider) only used existsSync, never ldd, so this is a
regression: a CUDA-12 host that worked fine before this PR can now
silently fall back to CPU if ldd itself can't run, even though the
provider .so and system CUDA libs are both genuinely present.
readSoNeeded now reports whether ldd produced any usable output at all,
distinct from 'ldd ran and just found no matching NEEDED entry' (the
existing, already-handled '=> not found' case). When detection genuinely
fails, log a warning so an operator can tell 'CPU fallback because
detection itself failed' apart from 'CPU fallback because no CUDA build
shipped' — the return value stays null either way (the type can't
distinguish a third state), but the two cases are now observably
different via the log.
* fix(embeddings): check ourDir independently of whether defaultDir resolved
decide()'s ourDir fallback lookup was nested inside
'if (systemMajor != null && defaultDir)', so a null defaultDir (transformers'
own onnxruntime-node resolution failing outright, e.g. a partial/broken
install) skipped checking ourDir entirely — getEffectiveOnnxRuntimeNodeDir()
returned null even when gitnexus' own matching CUDA-13 copy would have
resolved fine and worked.
defaultDir resolving is not a precondition for the comparison: an
unresolvable default already counts as 'the default doesn't match', so the
ourDir check now runs whenever systemMajor is known, regardless of whether
defaultDir resolved.
* fix(embeddings): prefer CUDA 13 globally across the env-var directory scan
detectSystemCudaMajor's CUDA_PATH/LD_LIBRARY_PATH scan returned on the
first CUDA-major match within a single dir/sub pair, so a stale .so.12
found early (e.g. a leftover CUDA_PATH entry from a prior install) shadowed
a genuine .so.13 found later in the search path, even though the scan's
own ordering (checking 13 before 12 within each pair) was clearly intended
to prefer 13 wherever possible.
Keep scanning the full search space once a 12 is found, only returning
early once a 13 is found (the best possible answer) or the space is
exhausted.
* fix(embeddings): have onnxruntime-common-resolver defer to the effective onnxruntime-node dir
onnxruntime-common-resolver.ts independently re-derived transformers'
default onnxruntime-node dir (its own copy of the 'resolve transformers'
main entry, then onnxruntime-node' walk) to compute which onnxruntime-common
to pair with — duplicating onnxruntime-node-resolver.ts's own walk, and
capable of disagreeing with it: when the CUDA-major redirect is active,
this hook would still pair onnxruntime-common with transformers' default
(unredirected) onnxruntime-node, not the redirected copy the other hook
just switched onnxruntime-node itself to.
Have it call the already-exported getEffectiveOnnxRuntimeNodeDir() instead
— the same decision the CUDA-major redirect hook uses — so both hooks
always agree on which onnxruntime-node they're pairing onnxruntime-common
against, and the duplicated resolve-walk is removed entirely rather than
merely factored out.
* fix(embeddings): cache the effective CUDA major to remove redundant subprocess spawns
isCudaAvailable() in embedder.ts re-invoked ortCudaMajor/detectSystemCudaMajor
directly even though decide() (via getEffectiveOnnxRuntimeNodeDir) had
already computed both to make its redirect decision — a second, wasted
ldconfig + up to 2 ldd spawns on every initEmbedder() call.
Add effectiveMajor to the memoized Decision, computed once inside decide()
alongside effectiveDir/systemMajor, and export a single
isEffectiveCudaAvailable() that reads straight from the cached decision.
embedder.ts's local isCudaAvailable() wrapper (and its now-unused
getEffectiveOnnxRuntimeNodeDir/ortCudaMajor/detectSystemCudaMajor imports)
is replaced by this one exported function.
* fix(embeddings): surface CUDA redirect state at info level and in doctor
A successful CUDA-build redirect logged only at logger.debug (filtered
by the default 'info' level), and gitnexus doctor's embeddings section
never mentioned the redirect at all — leaving no diagnostic path for
'why is my CUDA-13 host still on CPU' after this PR ships.
Log the successful-redirect line at info (no-redirect/failure paths stay
at debug, since those are the common, expected case). Add
cudaRedirectDoctorStatus(), a pure summary of decide()'s already-computed
decision mirroring doctor.ts's existing localEmbeddingDoctorStatus shape,
and print it as a new literal (non-i18n) 'CUDA:' line in doctor's
embeddings section alongside the existing 'Support:' line, matching that
line's established convention.
* test(embeddings): register onnxruntime-node-resolver.test.ts in the cross-platform subset
The new test file guards on process.platform (linux/darwin cases) but was
absent from cross-platform-tests.ts's PLATFORM_LOGIC list, which
TESTING.md says platform-sensitive tests should be added to — so it never
ran on the Windows/macOS CI matrix, only Ubuntu.
Note: the sibling onnxruntime-common-resolver.test.ts has the identical,
pre-existing gap (it predates this PR) — left as-is here, since fixing
unrelated pre-existing test-registration debt is out of scope for this
PR's own follow-up fixes.
* test(embeddings): strengthen weak assertions, add garbled-output and CUDA_PATH coverage
Three of the four ensureOnnxRuntimeNodeMatchesSystem tests only asserted
'doesn't throw' rather than a concrete outcome — including one literally
named 'idempotent' that never asserted a call count on its own spy.
Strengthen each to assert real outcomes (module stays functional after a
no-op; spy call counts; return-value shape), while keeping the true
install-once idempotency proof in the redirect-active test added earlier
(this file's no-redirect scenario can't exercise it, since registerHooks
is never called either way).
Add the missing edge cases flagged in review: a CUDA_PATH-only fallback
scan test (mirroring the existing LD_LIBRARY_PATH one), and garbled/
unrecognized ldconfig and ldd output cases for both detectSystemCudaMajor
and ortCudaMajor, confirming neither falsely matches a CUDA major on
unparseable input. Also parameterize the non-linux platform test across
both darwin and win32 rather than darwin alone.
Not changed: the process.env reassignment vs. Object.defineProperty
'inconsistency' flagged in review — process.env, unlike process.platform,
has no getter-only restriction, so plain reassignment is already correct
and switching it to Object.defineProperty would be unnecessary ceremony.
* docs(embeddings): note the npm link/symlinked dev-checkout resolution caveat
resolveOurOrtNodeDir/resolveDefaultOrtNodeDir anchor to this module's own
real (post-symlink) location via import.meta.url, so a linked local dev
checkout may resolve against its own node_modules rather than the
consuming app's. Narrow, dev-only blast radius (regular npm/pnpm installs
are unaffected) — document-only, no structural fix warranted.
* fix(test): point the windowsHide spawn-family registry at the file that actually spawns
hooks.test.ts's windowsHide regression check still listed
gitnexus/src/core/embeddings/embedder.ts as a child_process-spawning
file, but this PR itself already moved all execFileSync usage out of
embedder.ts and into the new onnxruntime-node-resolver.ts — without
updating this registry. The check was silently failing at the PR's own
head commit (confirmed: 0 spawn-family calls found in embedder.ts,
'expected 0 to be greater than 0'), a pre-existing gap this fix-pass
surfaced via a full-suite run rather than something introduced by any of
the preceding follow-up commits.
Swap the registry entry to onnxruntime-node-resolver.ts, which does
import execFileSync (ldd + ldconfig, both already correctly passing
windowsHide: true).
* fix(test): make onnxruntime-node-resolver.test.ts path comparisons OS-agnostic
Registering this file in cross-platform-tests.ts's PLATFORM_LOGIC (a
prior commit in this series) means it now runs on the Windows CI matrix,
not just Ubuntu — and several of the fakeDirs-based tests (redirect:true,
ourDir-independent, subprocess-count, doctor-status) compared the
resolver's real join()/dirname() output against hardcoded forward-slash
fixture strings via exact-match or .startsWith().
Node's module is bound to path.win32 (or path.posix) based on the
REAL host OS at process start — stubbing process.platform later, as these
tests already do for the resolver's own platform branching, has no effect
on it. So on a genuine Windows runner, join(effectiveDir, 'package.json')
backslash-normalizes even under a faked platform:'linux', silently
breaking every forward-slash comparison in this file: the createRequire
dispatch would route to the wrong fake require, throw MODULE_NOT_FOUND,
get swallowed by ensureOnnxRuntimeNodeMatchesSystem's outer try/catch, and
registerHooks would never fire — the redirect-active tests would fail
outright on Windows CI.
Normalize every comparison point (the createRequire dispatcher, and the
shared execFileSync/existsSync mocks) with a single toPosix() helper.
Added a forceWin32Path test option (using path.win32's real join/dirname
behavior) to prove this holds without needing an actual Windows runner —
confirmed by temporarily reverting the fix and observing the new test
fail with the exact predicted mismatch before restoring it.
* chore(autofix): apply prettier + eslint fixes via /autofix command
* fix(embeddings): keep CUDA auto-detect working on Node < 22.15 when the default build already matches
The registerHooks guard in decide() returned effectiveMajor: null
unconditionally, so on Node 22.0-22.14 / 23.0-23.4 (engines floor is
>=22.0.0) isEffectiveCudaAvailable() was always false and a CUDA-12 host
whose default onnxruntime-node build already matched — which needs no
hook at all to use the GPU — silently regressed from CUDA to CPU on the
auto device path (pre-PR isCudaAvailable() behavior).
Probe the system and the default copy regardless of registerHooks
availability; only the ourDir redirect branch stays gated on it, so the
probe still never reports a redirect target that cannot be installed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
|
||
|
|
1fc1a32d9c
|
chore(deps)(deps): bump lucide-react in /gitnexus-web (#2349)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 1.17.0 to 1.21.0. - [Release notes](https://github.com/lucide-icons/lucide/releases) - [Commits](https://github.com/lucide-icons/lucide/commits/1.21.0/packages/lucide-react) --- updated-dependencies: - dependency-name: lucide-react dependency-version: 1.21.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> |
||
|
|
3abb0267d1
|
chore(deps)(deps): bump @langchain/langgraph in /gitnexus-web (#2344)
Bumps [@langchain/langgraph](https://github.com/langchain-ai/langgraphjs/tree/HEAD/libs/langgraph-core) from 1.4.1 to 1.4.7. - [Release notes](https://github.com/langchain-ai/langgraphjs/releases) - [Changelog](https://github.com/langchain-ai/langgraphjs/blob/main/libs/langgraph-core/CHANGELOG.md) - [Commits](https://github.com/langchain-ai/langgraphjs/commits/@langchain/langgraph@1.4.7/libs/langgraph-core) --- updated-dependencies: - dependency-name: "@langchain/langgraph" dependency-version: 1.4.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> |
||
|
|
6a37ee1bdc
|
chore(deps)(deps-dev): bump @playwright/test in /gitnexus-web (#2346)
Bumps [@playwright/test](https://github.com/microsoft/playwright) from 1.60.0 to 1.61.1. - [Release notes](https://github.com/microsoft/playwright/releases) - [Commits](https://github.com/microsoft/playwright/compare/v1.60.0...v1.61.1) --- updated-dependencies: - dependency-name: "@playwright/test" dependency-version: 1.61.1 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> |
||
|
|
0087ce4fa1
|
chore(deps): bump softprops/action-gh-release from 3.0.0 to 3.0.1 (#2352)
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](
|
||
|
|
4c8aceecc2
|
chore(deps): bump actions/cache from 5.0.5 to 6.1.0 (#2351)
Bumps [actions/cache](https://github.com/actions/cache) from 5.0.5 to 6.1.0.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](
|
||
|
|
0f9474cbf7
|
chore(deps): bump actions/setup-python from 6.2.0 to 6.3.0 (#2350)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 6.2.0 to 6.3.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](
|
||
|
|
96bcd28d96
|
chore(deps)(deps): bump @langchain/openai in /gitnexus-web (#2348)
Bumps [@langchain/openai](https://github.com/langchain-ai/langchainjs) from 1.5.0 to 1.5.3. - [Release notes](https://github.com/langchain-ai/langchainjs/releases) - [Commits](https://github.com/langchain-ai/langchainjs/compare/@langchain/openai@1.5.0...@langchain/openai@1.5.3) --- updated-dependencies: - dependency-name: "@langchain/openai" dependency-version: 1.5.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
f9592c49ce
|
chore(deps)(deps): bump @langchain/google-genai in /gitnexus-web (#2345)
Bumps [@langchain/google-genai](https://github.com/langchain-ai/langchainjs) from 2.1.30 to 2.2.0. - [Release notes](https://github.com/langchain-ai/langchainjs/releases) - [Commits](https://github.com/langchain-ai/langchainjs/commits/@langchain/google-genai@2.2.0) --- updated-dependencies: - dependency-name: "@langchain/google-genai" dependency-version: 2.2.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
365de846d1
|
fix(lbug): retry single-writer transaction contention (#2342) | ||
|
|
859e4b75a4
|
fix(cli): --limit i18n, 0/negative guard, and correct truncation paths (#2310)
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: add --limit i18n, negative guard, correct property paths, and zh-CN translations - Add i18n keys for context/impact/cypher/detect-changes --limit options - Add zh-CN translations for all 4 --limit option descriptions - Add Math.max(0, parseInt()) guard to prevent negative --limit - Fix ALL property path mismatches discovered by audit: - context: callers/callees → incoming.calls/outgoing.calls+accesses - impact: upstream/downstream → affected_processes/affected_modules/byDepth - cypher: rows → row_count cap (rows embedded in markdown string) - detect-changes: affected_flows → affected_processes - Change query command from required to optional positional arg with -q alias - Update @ladybugdb/core from ^0.16.1 to ^0.17.1 - Update typescript from ^5.4.5 to ^5.9.3 * test: add E2E tests for --limit flag across all 5 CLI commands Tests context, impact, cypher, detect-changes, and query with --limit 1, baseline comparison, and --limit 0 (falsy/no-op). detect-changes output is formatted text (not JSON), so those tests count symbol lines matching 'Type name -> filePath' pattern. 14 tests, all passing. No regressions in 6455 existing tests. * fix: address Copilot review feedback on --limit guards - Add Math.max(0, ...) guard to queryCommand limit parsing - Change if(limit) to if(limit !== undefined) in all 5 commands (prevents --limit 0 from being treated as falsy/no-op) - Make queryText parameter optional (Commander may pass undefined) - Fix usage error strings: --search to -q, --query (en + zh-CN) * chore(autofix): apply prettier + eslint fixes via /autofix command * fix(cli): centralize --limit parsing, slice cypher markdown, fix usage text Address PR review feedback on --limit handling: - Add a shared parseLimit() helper (Number.isInteger(n) && n > 0), used by all 5 tool commands. Non-numeric / 0 / negative --limit now means "no limit" instead of the `options.limit ? Math.max(0, parseInt(...)) : undefined` path, where a string like "abc" is truthy and yields NaN -> slice(0, NaN) -> the guardrail commands (impact/context/detect-changes) silently emptied results with exit 0. - cypher: slice the markdown table to --limit data rows so the reported row_count matches what is actually printed (was capping row_count while printing every row). - Fix query usage string: [search_query] (optional positional) and `--query <text>` invocation form, not the option-definition `-q, --query <search_query>` syntax (en + zh-CN). - Add an E2E regression test for non-numeric --limit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(cli): escape newlines in cypher markdown cells A multi-line cell value (e.g. a symbol's `content`) was rendered with raw newlines via String(v), so one logical row spanned multiple physical lines. That corrupts the markdown table and breaks `cypher --limit`'s line-based slice (it kept the wrong number of rows, often zero, while row_count over-claimed). Collapse newlines in formatCypherAsMarkdown so one physical line == one row; the existing CLI slice is now correct and the pre-existing un---limited corruption is fixed too. (#2310 review) * test(cli): de-vacuum the --limit truncation tests The truncation it()s used the repo-banned vacuous-pass pattern (early-return on status===null, assertions guarded by if(Array.isArray), bounds-only toBeLessThanOrEqual — DoD.md:82) against `validateInput`, which has only 1 caller, so context/impact/query --limit 1 compared 1>=1 and stayed green even if the slice were deleted. Rewrite with unconditional, exact assertions and target `logMessage` (2 callers, 4 processes) so the no-limit baseline truly exceeds the limit; detect-changes now mutates two real function bodies (two changed symbols). Adds a multi-line-cell cypher --limit regression. (#2310) * test(ci): run cli-limit-e2e in the cross-platform matrix The --limit E2E suite spawns the real CLI (child_process) but was not in SPAWN_CLI, so it ran only on Ubuntu — the cross-platform check only fails on listed-but-missing files, not the reverse (TESTING.md §Cross-platform). Register it so the --limit regression guard also runs on Windows/macOS, where path separators, CRLF and the formatted-output arrow differ. (#2310) * fix(cli): document impact --limit affected-list cap, drop dead byDepth re-slice `impact --limit` also caps affected_processes/modules, but the help only mentioned the per-depth cap — so JSON consumers reading the affected lists got a silently-truncated array. Update en + zh-CN + the command description to say so. Also remove the client-side byDepth re-slice: the backend already paginates byDepth to the same limit (paginationLimit = clamp(limit,1,10000), offset applied backend-side), so the client slice was a guaranteed no-op. (#2310) * fix(cli): reconcile detect-changes --limit summary, list, and overflow formatDetectChangesResult computed the "... and N more" overflow from the already---limit-sliced array length, so under `--limit` the header (true summary total), the listed rows, and the marker disagreed — e.g. "2 symbols" in the header but a list of 1 with no marker. Base the overflow on the true summary.changed_count / affected_count instead, and add the same marker to the affected-processes list, so header + list + marker stay consistent. (#2310) * feat(cli): add -l shorthand to impact --limit The PR added the -l alias to context/cypher/detect-changes but left impact on the long --limit only, so `impact -l 5` errored while `context -l 5` worked. Add -l for parity and update the help-i18n OPTION_DESCRIPTION_KEYS key to the new `-l, --limit <n>` flag string so the description still resolves. (#2310) * fix(cli): bound all context --limit array categories context --limit sliced only incoming.calls / outgoing.calls / outgoing.accesses / processes, leaving the other relType buckets unbounded — notably incoming.accesses (bounded on outgoing but not incoming) plus imports/extends/ uses/… and typed_properties. Replace the hardcoded slices with a generic loop over every array-valued bucket under incoming/outgoing, plus typed_properties and processes, so --limit caps the whole context payload. (#2310) * refactor(cli): parse --offset with a parseLimit-style helper impactCommand parsed --offset with the legacy parseInt/Number.isFinite idiom while --limit had moved to parseLimit, leaving two parsing styles side by side. Add a sibling parseOffset helper (non-negative — offset 0 is valid) and use it, so both options share one idiom; as a bonus it now rejects negative/fractional offsets instead of forwarding them to the backend. (#2310) --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Gergo Magyar <gergomagyar@icloud.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
35ebe37c42
|
fix(deps): pin Ladybug 0.18.0, validate the multi-writer deadlock fix (#2340)
* chore(deps): bump @ladybugdb/core to 0.18.0 Pins the release containing LadybugDB/ladybug#605 (TransactionManager lock-order-inversion deadlock fix). Checked for known post-release regressions specific to 0.18.0 via the Ladybug issue tracker — none found. * fix(lbug): re-validate version-coupled comments and regexes for 0.18.0 Extends the LADYBUGDB-CONTRACT re-validation to two spots the marker convention doesn't catch (bridge-db.ts's LBUG_OPEN_RETRY_PATTERNS, conn-lock.ts's serialization rationale). Confirms via upstream source diff (v0.16.1..v0.18.0) that every matched error-text string is unchanged; conn-lock.ts's rationale is unaffected by #612/#623 since neither addresses concurrent queries on one connection. Adds a stemmer-sweep test proving the bundled 0.18.0 FTS extension accepts every entry in SUPPORTED_FTS_STEMMERS, not just the default porter. A live-trigger test for isMissingShadowSidecarError was attempted but abandoned after empirical probing showed it isn't reliably reproducible (even a SIGKILL-simulated crash didn't reproduce the error on reopen) — documented as inspection-verified instead of overclaiming test coverage that doesn't exist. * test(lbug): add concurrent multi-connection deadlock stress test (#2338) Directly validates LadybugDB/ladybug#605 — the TransactionManager lock-order-inversion deadlock between a commit()-triggered checkpoint and a concurrent beginAutoTransaction() — under a shape close to GitNexus's real concurrent-writer load, independent of conn-lock.ts's app-level serialization. Comparison run against 0.17.1 (pre-fix): 1 of 4 runs hung for the full 60s timeout, a direct reproduction of the deadlock. 9 consecutive runs against 0.18.0 (post-fix) all passed cleanly. Production is unchanged — conn-lock.ts still serializes every write; this test validates the engine-level fix without shipping multi-writer as a default. * fix(test): address code review findings in multiwriter deadlock test - Reuse lbug-config.ts's createLbugDatabase (via GITNEXUS_WAL_CHECKPOINT_THRESHOLD) instead of a hand-duplicated 9-arg raw constructor call whose stated justification (needing to bypass createLbugDatabase for the threshold override) was incorrect — the env var already provides it. - Close every QueryResult via the existing closeQueryResults helper (write loop, read loop, verify query, setup query) instead of leaking native cursors, matching lbug-adapter.ts's established pattern. - Move all cleanup (timers, connections, db close, env var restore) into the outer finally block so it runs on every exit path, not just the happy path — a timeout or a writer exhausting its retry budget no longer leaves dangling timers/connections/abandoned query loops. Verified: 8 consecutive runs after the refactor, all passing cleanly. Found via 8-angle parallel code review (medium effort); the two other findings (isDbBusyError not recognizing LadybugDB's 'Only one write transaction' message, and shadow-file poll timing sensitivity) are noted in the PR description as residual — the first is a production-code change beyond this validation test's scope, the second is inherent to observing a transient native sidecar file and not cleanly fixable without overengineering. * fix(test): apply ce-code-review autofix findings Fixes from an 8-persona parallel review round (correctness/testing/ maintainability/project-standards/reliability/adversarial/agent-native/ learnings): - Extract the duplicated skipUnlessFtsAvailable/FTS_UNAVAILABLE_NOTE helper (previously copy-pasted between lbug-core-adapter.test.ts and fts-stemmer-sweep.test.ts) into a shared test/helpers/fts-availability.ts. - Fix a native connection leak: verifyConn in the deadlock test's final verification block is now pushed into the readers array the outer finally already closes, so it's cleaned up even if the count query throws. - Fix a latent TypeScript type error (tsconfig.test.json catches it, tsconfig.json doesn't): conn.query() types as QueryResult | QueryResult[]; narrow to the single-result case before calling .getAll() rather than assuming the array branch never happens. - Replace repeated inline InstanceType<typeof import(...)> expressions with local LbugDatabase/LbugConnection type aliases. Verified: 12 consecutive runs of the deadlock test all pass, full lbug-db project (336 tests) green. Cross-reviewer-confirmed but left as residual (design judgment calls, not mechanical fixes) for the PR description: isDbBusyError doesn't recognize LadybugDB's 'Only one write transaction' message (pre-existing production gap, confirmed independently by 3 reviewers); the deadlock test's timeout path doesn't cancel in-flight writer/reader loops before closing connections; the reader loop has no bounded retry for transient errors during the race window; pinning @ladybugdb/core with a caret range trades automatic patch updates for less re-validation certainty. * docs: trim task-referencing JSDoc artifacts, add operator notes The U2 re-validation pass left verbose 'Re-validated on the 0.17.0->0.18.0 bump (#2338): ...' paragraphs stacked onto 5 production files' docstrings, alongside the already-updated version numbers. That narrative (SIGKILL-probe methodology, diff commands run, issue cross-references) belongs in the PR description, not in code comments that will accumulate a new paragraph on every future bump and confuse readers who just want the current fact. Trimmed each to state only the durable, current-state fact: - lbug-config.ts, sidecar-recovery.ts, lbug-adapter.ts, bridge-db.ts: dropped the bump-narrative paragraphs; kept only genuinely durable notes (e.g., which matchers are inspection-verified vs live-tested, what upstream wording changed). - conn-lock.ts: compressed a 12-line, 3-issue-number enumeration into 2 lines stating the current conclusion (no upstream 0.18.0 fix addresses the same-connection-concurrent-query risk this lock guards against). Also added operator-facing notes to GUARDRAILS.md and RUNBOOK.md's existing 'LadybugDB lock' sections: an isDbBusyError gap found during this validation (LadybugDB's 'Only one write transaction...' message isn't recognized by our busy/lock retry matcher) means that specific error can surface unretried. Documented so it's recognized as the same single-writer conflict, not a new failure mode. * refactor(test): use gitnexus-shared's withRetry in multiwriter deadlock test Replaces the hand-rolled writeWithRetry/sleep loop with the existing gitnexus-shared retry helper (already used by embeddings/hf-env.ts) instead of duplicating the pattern. * fix(test): guarantee non-zero retry delay in deadlock test's writer loop withRetry's isRetryable previously returned {retry: bool} with no afterMs, so computeBackoffMs's exponential-jitter formula gave a deterministic zero-delay on the first retry (floor(random()*1) is always 0 at attempt=0). This contradicted the file's own documented tuning, which specifically needs a non-zero 1-3ms delay to avoid tripping a different native guard. Return an explicit afterMs override on the retryable branch instead. * docs(test): remove dangling doc references from deadlock test JSDoc The JSDoc pointed to a local-session-only docs/plans/2026-07-01-001-... path (docs/ is repo-gitignored, so this never existed for anyone but the implementing session) and to "the PR description" as a source of truth that stops being current once the PR merges. Replace both with self-contained prose and durable references (issue/PR numbers, commit SHAs, GUARDRAILS.md/RUNBOOK.md) that stay resolvable after merge. * fix(search): harden SUPPORTED_FTS_STEMMERS against external mutation Type as ReadonlySet<string> to match this codebase's established convention for exported validation allowlists (EVAL_SERVER_TOOLS, STRUCTURAL_LABELS). Type-only change — no behavior change; both the internal .has() check and the sweep test's spread-iterate pattern continue to work unchanged. * docs(guardrails): fold Known-gap note into the LadybugDB Sign's Why label GUARDRAILS.md's own convention is strictly Trigger/Do/Why per Sign entry (stated in the file's header, followed by all 5 other entries). The new isDbBusyError gap note introduced a 4th label; fold it into Why instead, which is what it's actually explaining. * fix(test): run the multi-writer deadlock test on Windows too itLbugMultiwriter mirrored lbug-core-adapter.test.ts's win32 skip, but that pattern exists for a close-then-reopen-same-path lock lingering bug (kuzudb/kuzu#3872). This test never reopens the database — it holds connections open for the whole run — so the skip excluded the one test validating issue #2338's deadlock fix from the platform conn-lock.ts actually ships native bindings for. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
400cc6a440
|
feat(search): add opt-in CJK bigram segmentation for FTS search (#2339) | ||
|
|
316aaed928
|
fix(indexing): keep full text file content searchable (#2323)
* fix(indexing): keep full text file content searchable * fix(indexing): flush CSV chunks by byte size * fix(fts): flatten newlines/tabs in indexed content so multiline files are searchable (#2317) The end-to-end FTS test (review follow-up F2) exposed that removing the 10KB cap alone does NOT fix #2317: Ladybug's FTS tokenizer splits ONLY on the space character — \n, \r, and \t are not delimiters. So multiline file/symbol content indexes as a few giant cross-line tokens that no word query matches; full content is stored but stays unsearchable. (Verified: identical 8KB content is fully searchable when space-separated and entirely unsearchable when newline-separated.) The existing fts-description-search test never caught this because all its seed content is single-line. Collapse \r\n\t -> single space in the FTS-indexed text (extractContent's File and snippet content, plus the description column) via normalizeFtsText. This rewrites the stored column too, so File content returned via the graph API is space-flattened — an accepted trade for making file/symbol text searchable. Add the real end-to-end guard test/integration/fts-fullfile-search.test.ts: write a >16KB file, load it through the real streamAllCSVsToDisk -> COPY -> createSearchFTSIndexes path, and assert searchFTSFromLbug returns a needle past 10KB (plus a short-content no-regression and a stored-cell-not-truncated guard). It drives the COPY path a Cypher-seed test would bypass, reusing withTestLbugDB's FTS-availability gating via a new before-FTS load hook. * docs(lbug): note the deliberate File-unbounded / snippet-capped asymmetry The File branch returns full content (whitespace-normalized for FTS, bounded upstream by the walker cap) while the symbol snippet path 11 lines down stays MAX_SNIPPET-capped. Comment the intent so the uncapped File branch doesn't read as a forgotten guard. No behavior change. * test(lbug): update #2203 overlap round-trip for FTS whitespace normalization The newline/tab→space normalization (a170915a, #2317) flattens stored File content, so the #2203 overlap test's "File content == original multiline source" assertion no longer holds. The test's actual invariant — overlap path == serial path, byte-for-byte — is unchanged and still asserted; BasicBlock text (not FTS-indexed) still round-trips raw. Update only the File-content expectation to the whitespace-flattened form and document why. * fix(lbug): collapse CSV flush to a single byte threshold BufferedCSVWriter flushed on row-count (FLUSH_EVERY=500) OR byte-count (FLUSH_BYTES=8MB) — two independent triggers for one job. Byte count is the only one tied to the actual risk (an unbounded buffer.join('\n') string), so drop FLUSH_EVERY and make shouldFlushCSVBuffer single-arg. Rather than tune FLUSH_BYTES by guesswork or expose it as an env knob, derive its safety margin from constants the codebase already hard-enforces: a single row is capped at TREE_SITTER_MAX_BUFFER (32MB, clamped regardless of GITNEXUS_MAX_FILE_SIZE) and at most doubled by escapeCSVField's quote-escaping, so the worst-case joined chunk (FLUSH_BYTES + 2 * TREE_SITTER_MAX_BUFFER ≈ 72MB) sits >7x under Node's MAX_STRING_LENGTH (~512MB) — the ceiling that throws RangeError: Invalid string length. A new test pins that margin numerically so it can't erode unnoticed, which covers the "configurable" alternative better than a knob would: there's no evidence any deployment needs a different value, and an unbounded env var would let an operator silently walk the margin back into the danger zone. Also updates the two tests tied to the removed row-count path: the FLUSH_EVERY-boundary integration test now crosses FLUSH_BYTES with real oversized File content instead of relying on row count, and the shouldFlushCSVBuffer unit test drops to the new single-arg signature. --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> |
||
|
|
905b7dfa21
|
feat(embeddings): compact, description-forward embedding text (#2333) (#2334) | ||
|
|
f5a2e6a248
|
fix(search): make vector distance threshold configurable (#2330) | ||
|
|
e148bc089a
|
fix(group): replace LadybugDB-incompatible multi-label Cypher (#2325) (#2327)
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(group): use labels(n) IN allowlist instead of LadybugDB-incompatible multi-label Cypher (#2325) manifest-extractor and http-route-extractor built Cypher with the openCypher label disjunction `MATCH (n:A|B|C)`, which LadybugDB's parser rejects. The error was swallowed by try/catch, so manifest contracts silently fell back to synthetic UIDs with empty filePath and http-route cross-file handler resolution silently returned null. Replace all 7 queries with `MATCH (n) WHERE labels(n) IN [...]`. LadybugDB returns labels(n) as a single string, so this is an exact allowlist — a 1:1 behavior-preserving syntax translation (validated against LadybugDB 0.17.1). Export the two http-route query constants so integration tests can run the exact production strings against a real DB, and add per-branch real-DB regression coverage (the bug shipped because no test exercised these queries). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(group): import CypherExecutor from contract-extractor in #2325 test The new manifest regression test imported `CypherExecutor` from `group/types.js`, which does not export it — the type is defined only in `group/contract-extractor.js` (as all production extractors import it). This was a real TS2305 under `tsc -p tsconfig.test.json`, masked from CI because the default tsconfig excludes `test/` and `import type` is erased at runtime. Split the import so the type resolves from its real module. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(group): run #2325 native-LadybugDB tests in the lbug-db project Per TESTING.md, every test that opens a real `@ladybugdb/core` handle must be registered in the sequential `lbug-db` Vitest project (and excluded from `default`) to avoid native-mmap file-lock conflicts across parallel forks on Windows. The two new group integration tests use `withTestLbugDB`/pool-adapter but were in neither list, so they ran under the parallel `default` project. Add both to `lbug-db.include` and `default.exclude`, matching every sibling. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(group): export custom-contract resolve query for #2325 test The #2325 integration test hand-copied the 21-label `custom`-branch resolve query into a local `LABELS_CUSTOM_QUERY` constant, so editing the production allowlist would silently desync the canary. Promote the query to an exported `CUSTOM_CONTRACT_RESOLVE_QUERY` (mirroring http-route-extractor's exported query strings) and import it in the test, so the canary always runs the exact production query. Behavior unchanged — same query string. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(group): de-brittle the #2325 custom-query label assertion The unit test asserted a fixed 7-label ordered substring of the 21-label custom-branch allowlist, coupling it to label order and no-space formatting — a harmless reorder would have broken it. Replace with order/spacing-tolerant membership checks for a spread of individual labels, keeping the unconditional `not.toContain('Function|Method')` guard as the real regression check. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(group): correct #2325 http-route docstring + add real-trigger canary The http-route test claimed `MATCH (n:Function|Method|CodeElement)` "which LadybugDB rejects" — but that 3-label disjunction actually PARSES. Verified against the real parser, the genuine #2325 trigger is a *reserved-keyword* label in the disjunction: `Macro` and `Union` both are, and only the manifest custom branch (21-label list) and the lib branch (missing `Package` table) actually threw. The http-route conversion to `labels(n) IN [...]` was a consistency change, not a parser fix. Correct the misleading docstring and add a rejection canary pinned to the real cause (`MATCH (n:Function|Macro|Union)` rejects), so a future query that reintroduces a reserved-keyword disjunction is caught. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(group): cover the thrift package-strip path against a real LadybugDB The thrift-only branch of resolveSymbol strips a `package.` prefix from the service name (`com.example.AuthService` -> `AuthService`) before the Class/Interface lookup — previously exercised only with a mocked executor. Add a service-contract integration case (no method, so it takes the package-strip path, not the grpc-identical method path) that resolves the real `cls:AuthService`. Without the strip the lookup matches nothing and falls back to a synthetic uid, so this is a non-vacuous guard for the strip. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(group): drop vestigial 'Package' label from lib contract lookup The `lib` branch allowlisted `labels(n) IN ['Package','Module']`, but there is no `Package` node table (see NODE_TABLES) — the entry only ever matched nothing. Restrict to `['Module']`, the label libraries actually resolve to. Behavior-neutral: the lib integration case still resolves its Module symbol. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(group): update PIPELINE label-scoped queries to labels(n) IN form The resolveSymbol label-scoping bullets still showed the banned `MATCH (n:A|B)` disjunction; a contributor copying them would reintroduce #2325. Rewrite them in the actual `labels(n) IN [...]` form, note the real trigger (LadybugDB rejects a disjunction naming a reserved keyword such as `Macro`/`Union`), and reflect the lib allowlist as `['Module']` after dropping the vestigial `Package` label. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(group): correct #2325 root-cause comments in the extractors The production comments claimed LadybugDB rejects the `MATCH (n:A|B)` disjunction "outright". Verified against the real parser, it rejects only when a label is a reserved keyword (`Macro`, `Union`) or names a missing node table. So only the manifest `custom` branch (reserved keywords in its 21-label list) and the `lib` branch (missing `Package` table) actually threw; the http-route/grpc/thrift/topic disjunctions parse fine and were converted to `labels(n) IN [...]` for consistency and future-proofing, not because they were broken. Rewrite the comments to say so accurately. No behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(group): make #2325 test prose name the real reserved-keyword trigger The manifest test docstring/title and the unit-test comment said LadybugDB rejects the `MATCH (n:A|B)` disjunction generally. It rejects only when a label is a reserved keyword (`Macro`/`Union`) or a missing table. Reword the docstring (custom + lib branches threw; others parsed), retitle the rejection canary to "its list names reserved keywords Macro/Union", and correct the unit-test comment. The rejection canary still passes — the custom 21-label list does contain Macro/Union. No behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
9c5a174303
|
chore(deps)(deps): bump commander from 14.0.3 to 15.0.0 in /gitnexus (#2322)
Bumps [commander](https://github.com/tj/commander.js) from 14.0.3 to 15.0.0. - [Release notes](https://github.com/tj/commander.js/releases) - [Changelog](https://github.com/tj/commander.js/blob/master/CHANGELOG.md) - [Commits](https://github.com/tj/commander.js/compare/v14.0.3...v15.0.0) --- updated-dependencies: - dependency-name: commander dependency-version: 15.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Abhigyan Patwari <126312502+abhigyanpatwari@users.noreply.github.com> |
||
|
|
15583fc9e9
|
chore(deps)(deps): bump onnxruntime-node in /gitnexus (#2321)
Bumps [onnxruntime-node](https://github.com/Microsoft/onnxruntime) from 1.26.0 to 1.27.0. - [Release notes](https://github.com/Microsoft/onnxruntime/releases) - [Changelog](https://github.com/microsoft/onnxruntime/blob/main/docs/ReleaseManagement.md) - [Commits](https://github.com/Microsoft/onnxruntime/compare/v1.26.0...v1.27.0) --- updated-dependencies: - dependency-name: onnxruntime-node dependency-version: 1.27.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Abhigyan Patwari <126312502+abhigyanpatwari@users.noreply.github.com> |
||
|
|
028bd11053
|
fix(group): cache read-only bridge handle to fix Windows @group reopen (#2274) (#2313)
* fix(group): cache read-only bridge handle to fix Windows @group reopen (#2274) A long-lived MCP server opened bridge.lbug read-only, queried, and closed it on every @group trace/impact call. On Windows the in-process reopen of the same file fails (the OS handle is not fully released before the next open races in), so repeated @group calls broke. #2269 fixed Linux/macOS by skipping CHECKPOINT on read-only handles; Windows stayed broken. Instead of fighting LadybugDB's Windows close/reopen timing: cache one read-only handle per groupDir and reuse it across calls (open-once-per-process already works on Windows). getCachedBridgeReadOnly: - reuses a single handle keyed by resolved groupDir, - invalidates on mtime change (external writer / re-sync), - invalidates explicitly before same-process writes (writeBridge), - guards concurrent first-open with an in-flight promise (no handle leak), - closes all handles on process exit. closeBridgeDb now no-ops for the cached handle (cache owns its lifetime); uncached/writable handles are unaffected. ensureBridgeReady uses the cache. The in-process write->read reopen of the same bridge.lbug file remains a known LadybugDB Windows limitation, so the existing reopen tests stay win32-skipped. A new cache-aware itCacheReopen gate applies to the 3 new tests whose setup requires write-then-read in the same process (same class as itLbugReopen). The cache itself exercises read->read reuse and is unaffected. * fix(group): harden bridge RO-handle cache for concurrency, lifetime & Windows (#2313 review) Addresses the tri-review + Copilot findings on the read-only bridge-handle cache: - P1 (F2): serialize queryBridge per cached handle via a per-handle FIFO lock (the conn-lock.ts chain mechanic, keyed per cache entry, not the global lock). Two concurrent @group callers sharing one lbug.Connection can no longer dispatch two queries at once (the heap-corruption hazard). Uncached/writable handles skip the lock at zero cost. - P1 (F3): refcount lease — getCachedBridgeReadOnly acquires, closeBridgeDb releases (no caller change). The native close is deferred until in-flight readers drain (refs===0) and runs exactly once (closeStarted guard). invalidateBridgeCache and the mtime-evict path share one evict/close path. - Windows: bounded drain in evictBridgeEntry — a concurrent group_sync waits (<= WINDOWS_DRAIN_TIMEOUT_MS) for readers to release before the atomic rename on win32 so it stays clean; POSIX remains fully non-blocking; single-threaded sync still closes-before-rename on all platforms. - P0 (F1/F6): gate the mtime cache test with itCacheReopen (win32-skipped) and drop the manual invalidate so writeBridge self-invalidation is under test; add an external-writer (fsp.utimes) reopen case. - Windows coverage (F9): new cross-process integration test seeds bridge.lbug in a separate tsx process, so read->read handle reuse is proven on win32 CI (not skipped). Plus concurrent cold-open dedupe coverage. - P2/P3: scope the Windows NOTE to read->read (F4); JSDoc the closeBridgeDb release/close contract (F5); drop the if-branch in the B2 probe (F7); revert incidental Prettier churn in cross-impact.ts (F14); fix the stale describe header (F15); document the beforeExit/signal and ENOENT-mtime behavior (F11/F13). tsc clean; group unit + integration suites green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(group): run the B2 rename-clash probe on win32 via cross-process seed (#2313 review) Moves the B2 "external rename while a cached RO handle is held" probe out of the unit suite (where it was win32-skipped, because its in-process writeBridge->RO-open is the unfixed Windows reopen) into the cross-process integration test, where a separate-process seed makes the RO open clean. The probe now RUNS ON WIN32 CI and empirically answers whether an open RO handle blocks an external atomic rename over bridge.lbug — the assumption under writeBridge's invalidate-before-rename and the win32 drain. Hardened (per adversarial review) so a win32 RED is the real steady-state share-mode signal, not an artifact: - use production retryRename (not bare fsp.rename) so transient EBUSY/EPERM from the Windows AV/indexer scanning the fresh temp file is absorbed; a RED then means the rename is blocked even after retries (FILE_SHARE_DELETE absent -> invalidate-before- rename is load-bearing). - stage the byte-identical replacement BEFORE opening the RO handle, so no second OS handle touches bridge.lbug while LadybugDB holds it (avoids a FILE_SHARE_READ red for the wrong question). - drop the post-rename query (handle survival is covered by the reuse test); the probe's sole verdict is whether the rename is blocked. Removes the old win32-skipped unit B2 (a strict subset of the new probe). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
c1a1b2a553
|
chore(deps)(deps): bump onnxruntime-common in /gitnexus (#2320)
Bumps [onnxruntime-common](https://github.com/Microsoft/onnxruntime) from 1.26.0 to 1.27.0. - [Release notes](https://github.com/Microsoft/onnxruntime/releases) - [Changelog](https://github.com/microsoft/onnxruntime/blob/main/docs/ReleaseManagement.md) - [Commits](https://github.com/Microsoft/onnxruntime/compare/v1.26.0...v1.27.0) --- updated-dependencies: - dependency-name: onnxruntime-common dependency-version: 1.27.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
8ad4469e96
|
fix(test): stabilize local Windows gate baselines (#2314) | ||
|
|
a7df8f861a
|
fix(search): make FTS stemmer configurable (#2307)
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
|
||
|
|
7ca7166b8e
|
fix(fastapi): apply APIRouter constructor prefixes (#2312)
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
|
||
|
|
57e4afa4c8
|
fix(mcp): stabilize api_impact response shape for same-URL multi-verb routes (#2308) (#2309)
Some checks failed
Scorecard / Scorecard analysis (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
Trivy Image Scan / Trivy (gitnexus-cli) (push) Has been cancelled
Trivy Image Scan / Trivy (gitnexus-web) (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
* fix(mcp): stabilize api_impact response shape for same-URL multi-verb routes After #2302 made Route identity method-aware, a same URL exposes one Route node per HTTP verb, so a bare-URL api_impact lookup could silently flip from a direct route object to the wrapped { routes, total } envelope. Surface each route's `method` (via the shared fetch) so multi-verb results are distinguishable, and add an optional `method` selector that narrows a multi-verb URL/file to one verb and forces the singular shape. A verb that matches no route returns a clear error. Document the match-count contract in the tool schema. Refs #2308 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(mcp): cover same-URL multi-verb api_impact contract Regression coverage for #2308: bare-URL and bare-file lookups of a same-URL GET+POST pair return the wrapped form with distinct per-route methods; the method selector collapses to the singular shape (case-insensitively); an unmatched verb returns a verb-not-found error; and verbless routes surface a null method. Refs #2308 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(review): apply autofix feedback - tools.ts: correct api_impact contract docs — `method` narrows to one verb but the singular shape only holds when exactly one route remains after filtering (substring route/file matches can still wrap); cover file lookups; enumerate verbs. - local-backend.ts: surface `method` in route_map and shape_check output (the shared fetch already returns it; agents discover verbs there before api_impact). - local-backend.ts: compute routeCountByHandler from the unfiltered match so a method-scoped api_impact still flags a multi-verb handler's partial middleware. - tests: add file+method and verbless-exclusion cases; assert unconditionally via toMatchObject; lowercase the verb-not-found input to exercise error uppercasing. Refs #2308 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(mcp): treat wildcard '*' routes as matching any api_impact method selector (#2308) Method-agnostic routes (Django function views) persist with Route method '*', not null. The api_impact method selector used exact verb equality, so '*' routes were excluded and api_impact({route, method:'POST'}) falsely reported 'No routes found' for a route that handles every verb. Treat '*' as matching any requested verb, and correct the comment + tool-description strings that wrongly grouped Django wildcards with null/verbless routes. * fix(mcp): harden api_impact method input against non-string and empty values (#2308) The MCP envelope is not schema-validated, so a non-string `method` reached `.toUpperCase()` and threw a TypeError. Widen the param to `unknown` and guard it with a typeof check that returns a structured error (mirroring the resolveAliasString pattern from #2175), and collapse empty/whitespace verbs to no selector. * fix(mcp): distinguish url-not-found from verb-not-found in api_impact error (#2308) The verb-not-found error appended 'with method "X"' even when the URL/file itself did not exist, implying the URL exists with other verbs. Gate the verb clause on matched.length > 0 so a non-existent URL/file gets the plain message. * fix(mcp): clarify api_impact middlewareNote wording for verbless siblings (#2308) The partial-middleware note claimed 'other methods in this handler' even when the co-located sibling is a verbless (null) route rather than another HTTP verb. Refer to 'other route exports' instead, which covers both cases. * docs(mcp): document and test the method field on route_map and shape_check (#2308) The shared fetchRoutesWithConsumers change surfaced a method key on route_map and shape_check responses too, but their tool descriptions never mentioned it and no test covered it. Document the field on both descriptions and add unit tests asserting it (shape_check rows carry responseKeys + a consumer so they survive shape_check's keys-and-consumers filter). * test(mcp): cover middlewareDetection 'partial' survival under a method filter (#2308) The diff's core behavioral line counts verbs-per-handler from the unfiltered match set so a method-scoped query still flags a multi-verb handler's partial middleware, but no test exercised it (every verbRow hardcoded middleware:null). Add a middleware param to verbRow and a test that fails if the count is taken from the post-filter set instead. Verified via mutation: matched->routes fails it. * test(mcp): add live-LadybugDB integration coverage for route method round-trip (#2308) The new n.method query column was only unit-mocked. Add a self-contained integration suite that seeds GET+POST /api/orders and a method-agnostic '*' Django route, then asserts api_impact surfaces method, narrows by verb, and matches the '*' route end-to-end (the U1 fix), plus route_map surfacing. Own seed + no FTS so it neither perturbs api-impact-e2e nor silently skips. * refactor(mcp): type the api_impact response shape instead of Promise<any> (#2308) Replace apiImpact's Promise<any> with an explicit ApiImpactResult union (single route | wrapped { routes, total } | { error }) and a typed ApiImpactRoute. The results.map is annotated so the response builder is checked against the declared shape. Behavior unchanged; sibling MCP methods keep their Promise<any> convention. * fix(mcp): express the route-or-file requirement in the api_impact schema (#2308) The inputSchema left route/file as bare optionals, so the 'at least one of route/file' rule the handler enforces was invisible to clients. Add an optional anyOf to ToolDefinition (forwarded verbatim by the ListTools handler) and an anyOf:[{required:[route]},{required:[file]}] on api_impact. Matches runtime (both allowed, route wins); 'at least one' not 'exactly one'. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
c45d38f27a
|
fix(ingestion): index generator function declarations (#2305) | ||
|
|
8bef64baa1
|
feat(ingestion/routes): give Route nodes a (method, url) identity (#2289) (#2302)
* feat(ingestion/routes): give Route nodes a (method, url) identity (#2289) Route node identity was URL-only, so a same-URL multi-verb pair (GET /x + POST /x) collapsed into a single node and the second verb's handler and execution flow were silently lost. Route identity is now (method, url) via routeNodeKey(method, url): a known, specific verb keys as "METHOD url", while a method-less route (filesystem routes — Next.js / Expo / PHP — and Laravel resource/apiResource) or a wildcard "*" route (e.g. Django function views) falls back to URL-only. The fallback is byte-identical to the previous URL-only ids, so only genuine declaration-style multi-verb routes split into separate nodes. The identity key is shared across the three phases that must agree on the Route node id: - routes phase: registry key + node id + handler-symbol lookup; the Route node still carries the bare URL as its display name. - call-processor: resolveRouteHandlerSymbols re-keyed by identity so each verb resolves its own handler; a verb-less fetch() consumer matches by URL and connects to every Route node at that URL (one per verb). - processes phase: ENTRY_POINT_OF targets the identity-keyed node id. Bumps INCREMENTAL_SCHEMA_VERSION 4 -> 5: persisted pre-v5 Route nodes use the old url-only ids, so an incremental top-up would strand them alongside new composite-keyed nodes — force a full re-analyze instead. Part of #2280. * fix(ingestion/routes): address PR #2302 review (P1/P2/P3) P1 — Schema v5 fast-path bypass (run-analyze.ts): Adds a schemaVersion-mismatch guard above the alreadyUpToDate early-return, mirroring the pdgModeMismatch slot. Without it, a same-commit re-analyze on a pre-v5 stamp returned alreadyUpToDate without ever reaching the isIncremental gate, defeating the v5 schema bump's migration intent. Regression test covers: analyze (stamps v5) → meta downgrade to v4 → same commit re-analyze must NOT early-return and meta restamps to v5. P2 — ENTRY_POINT_OF handler-aware linking (processes.ts): Pre-fix routesByFile fanned every same-file Route to every same-file process, cross-wiring same-file GET/POST handlers. Now reads handlerSymbolId off the Route graph node (the source of truth routes.ts stamps) into routesByHandlerId, with a routesWithoutHandlerByFile fallback — mirrors the Tool linking precedent 10 lines below. Two regression tests: weak form (only one handler has a process; sibling verb does not get spuriously attached) and strong form (both handlers form distinct processes; each Route links to exactly its own entryPoint, 2 edges not pre-fix 4). P2 — Roundtrip composite-id (route-{method,handler-symbol}-roundtrip): Both tests now seed the Route node with generateId('Route', routeNodeKey('POST', '/api/orders')) and run the Cypher MATCH against the composite id, exercising the literal-space-in-id through CSV→COPY→HANDLES_ROUTE_QUERY. A space-in-id escape regression would surface here instead of being silently swallowed by the extractor's catch. P3 — doc-drift + test if: - route-path.ts:4 — header updated to "(method, url) via routeNodeKey" - java.ts:684 — drop "Route nodes are URL-keyed"; #2289 closes that gap - manifest-extractor.ts:196 — explicit that Route node *id* is composite while route.name remains the bare URL - multi-verb-route-identity.test.ts:88 — forEachRelationship+if rewritten as a .filter().map() chain (no test-level conditional). New route-process-linking tests are also if-free. Validation: tsc clean, prettier clean, 9 touched suites / 43 tests pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(ingestion/routes): drop routes.ts re-export, fix CI fast-path tests Two follow-ups on PR #2302's CHANGES_REQUESTED review: 1. Drop `routes.ts` re-export of `normalizeExtractedRoutePath` / `normalizeRouteMethod` / `routeNodeKey` (per @magyargergo's inline comment at routes.ts:153 — the symbols already live in `route-extractors/route-path.ts` and consumers should import them from the source, not via a routes-phase indirection that was kept only as a compat shim during the #2289 refactor). Updated the two remaining callers (blade-template-routes / spring-route-extractor- parity tests) to import directly from `route-extractors/route-path.js`. `call-processor.ts` and `processes.ts` already import from the source. 2. Fix two `run-analyze.test.ts` fast-path tests that started failing on CI after the schema-version mismatch guard landed ( "creates .gitnexus/.gitignore on the already-up-to-date fast path" and "reports isPrimaryBranch false for an up-to-date non-primary branch"). The test fixtures hand-built a RepoMeta with NO schemaVersion field; with the guard now checking `existingMeta.schemaVersion !== INCREMENTAL_SCHEMA_VERSION`, that pre-versioning shape was treated as a mismatch and forced a rebuild, short-circuiting the fast path the tests exercise. Stamp the current schemaVersion on those fixtures so they reflect the post-#2289 meta shape production actually writes (`runFullAnalysis` always stamps the field on git repos — see meta save site). Validation: tsc clean, prettier clean, 11 touched suites / 80 tests pass. --------- Co-authored-by: henry <zhangwei2017@unipus.cn> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
576e81442e
|
fix(search): index description field for FTS so doc comments are keyword-searchable (#2300)
Some checks failed
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
Devcontainer Smoke / Config-transform unit tests (push) Has been cancelled
Devcontainer Smoke / Build devcontainer image (push) Has been cancelled
* fix(search): index description column for FTS so doc comments are keyword-searchable Closes #2299. descriptionExtractor (#2286) populates the `description` column for every symbol table, but FTS only indexed name+content on 5 tables, so doc-comment keywords (Javadoc/KDoc/godoc/Rust ///) were invisible to BM25 keyword search. - Add `description` to the Function/Class/Method/Interface FTS indexes (File has no description column, left as name+content). - Add FTS indexes for the remaining EMBEDDABLE_LABELS symbol tables (Struct, Enum, Trait, Impl, Macro, Namespace, Constructor, TypeAlias, Typedef, Const, Property, Record, Union, Static, Variable). - createSearchFTSIndexes now drops-then-creates each index so the schema change reaches existing DBs on incremental re-analyze and --repair-fts (createFTSIndex is idempotent-by-name and would otherwise skip stale indexes). Tests: fts-schema column-subset + coverage guards; drop-before-create order; e2e doc-comment keyword search (Java class + Rust struct found by description-only terms). bm25-search assertions derive from FTS_INDEXES. * fix(review): apply autofix feedback - Guard the --repair-fts path on FTS-extension availability before createSearchFTSIndexes drops-then-creates indexes (P1 regression: without the gate, an unavailable extension could drop existing indexes then fail to recreate them, leaving the DB index-less). Mirrors the analyze path's ftsAvailable gate and fails loudly first. - Add a re-analyze upgrade integration test: seed an old name+content-only DB (no Struct index), run the real createSearchFTSIndexes(), and assert description keyword search + the previously un-indexed Struct now resolve. Proves drop-then-create upgrades a live stale index end-to-end. * fix(ci): add loadFTSExtension to --repair-fts test mocks The R3 review fix added a loadFTSExtension availability gate to the --repair-fts path, but run-analyze-fts-repair.test.ts mocked the lbug adapter without that export, so both repair tests threw `No "loadFTSExtension" export`. Add loadFTSExtension to the two mocks (returning true to preserve their original intent) and add a dedicated test proving the guard fails loudly — and does NOT drop any index — when the extension is unavailable. * test(fts): run fts-description-search in the sequential lbug-db project It was the only FTS-index-creating integration test left in the parallel `default` vitest project; every other ftsIndexes-using test (search-core, search-pool, augmentation, …) runs in the `lbug-db` project, which forces fileParallelism: false to avoid LadybugDB native mmap file-lock conflicts in parallel forks (Windows). Add it to the lbug-db include list and the default exclude list to match the convention and remove the flake risk. * test(ci): fail loudly when FTS extension is unavailable, never silently skip FTS-dependent lbug integration suites (search-core, search-pool, augmentation, fts-description-search, …) self-skip via ctx.skip() when the LadybugDB FTS extension can't load, emitting only a console.warn while the job stays green. That means a broken/missing FTS extension in CI would make these integration tests silently vanish with no signal — false confidence. withTestLbugDB now honors GITNEXUS_REQUIRE_FTS=1: when set and the extension is unavailable, setup() throws instead of skipping, so the suite fails loudly. The CI test jobs (ubuntu coverage + windows/macOS cross-platform) set the flag; local/offline runs leave it unset and keep skipping gracefully. (Verified the extension currently loads on all three runners, so this is a guard against regression, not a behavior change today.) * test(ci): run fts-description-search on macOS/Windows cross-platform jobs The new FTS description-search suite was registered in the sequential lbug-db vitest project (ubuntu/coverage) but absent from LBUG_NATIVE, so the macOS/Windows platform-sensitive jobs (which run only the explicit ALL_CROSS_PLATFORM allowlist via run-cross-platform.ts) never executed it. The GITNEXUS_REQUIRE_FTS=1 hardening on those jobs guarded the old FTS fixtures but not the new 20-index/description path. Add the suite to LBUG_NATIVE so the new path is validated cross-platform too. Refs #2299. * fix(search): verify FTS indexes cover description, not just queryability verifySearchFTSIndexes probed each index with QUERY_FTS_INDEX and treated 'queryable' as 'present'. A stale name+content-only index left on a pre-#2299 DB stays queryable yet silently misses the description column, so verification would pass green while doc-comment search stayed broken. Switch to a single CALL SHOW_INDEXES() that exposes property_names per index, and report an index as missing when it is absent OR does not cover its configured columns. Return contract (string[] of table.indexName) is unchanged, so both run-analyze.ts call sites are untouched. The per-index string interpolation is gone, so the now-dead safeIdentifier helper is removed. The real caller of the live function in tests is bm25-search.test.ts (the repair test mocks verifySearchFTSIndexes wholesale); its two probe-shaped cases are rewritten to feed SHOW_INDEXES rows and now assert column coverage, plus an absent-index case. Refs #2299. * test(search): assert description search via the public query surface The #2299 integration suite only exercised the searchFTSFromLbug helper. Add a third block that drives the public LocalBackend.callTool('query') path — which resolves the repo via the registry and routes BM25 through the pool adapter (a different connection context than the core-adapter helper) — and asserts a description-only keyword returns the seeded class. Reuses the existing description-only SEED and production FTS_INDEXES; partial-mocks repo-manager so listRegisteredRepos points at the test DB while cleanupOldKuzuFiles and the rest stay real. Refs #2299. * test(search): make lbug-core-adapter FTS gate honor GITNEXUS_REQUIRE_FTS lbug-core-adapter.test.ts has its own per-test FTS gate (skipUnlessFtsAvailable) that called ctx.skip() whenever the extension could not load — bypassing the GITNEXUS_REQUIRE_FTS=1 hardening that withTestLbugDB already honors. Since this file is in LBUG_NATIVE it runs on the ubuntu/macOS/windows jobs that all set GITNEXUS_REQUIRE_FTS=1, so an FTS regression on a runner would have let these FTS-primitive tests silently vanish from a green run — the exact gap #2299's test-infra hardening set out to close. Make the helper mirror withTestLbugDB: when GITNEXUS_REQUIRE_FTS=1 and the extension is unavailable, throw (hard fail) instead of skipping. Offline/local runs (no env var) still skip gracefully. Refs #2299. |
||
|
|
d7ff76e6e9
|
fix(ingestion/routes): resolve Spring interface-inherited routes (#2288) (#2290) | ||
|
|
269737982e
|
chore(deps)(deps): bump @langchain/openai in /gitnexus-web (#2291)
Bumps [@langchain/openai](https://github.com/langchain-ai/langchainjs) from 1.4.5 to 1.5.0. - [Release notes](https://github.com/langchain-ai/langchainjs/releases) - [Commits](https://github.com/langchain-ai/langchainjs/commits/@langchain/openai@1.5.0) --- updated-dependencies: - dependency-name: "@langchain/openai" dependency-version: 1.4.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
5f667c32a3
|
chore(deps): bump actions/checkout from 6.0.3 to 7.0.0 (#2292)
* chore(deps): bump actions/checkout from 6.0.3 to 7.0.0
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.3 to 7.0.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](
|
||
|
|
9b8d31a1f2
|
chore(deps)(deps): bump langchain from 1.4.4 to 1.4.6 in /gitnexus-web (#2294)
Bumps [langchain](https://github.com/langchain-ai/langchainjs) from 1.4.4 to 1.4.6. - [Release notes](https://github.com/langchain-ai/langchainjs/releases) - [Commits](https://github.com/langchain-ai/langchainjs/compare/@langchain/openai@1.4.4...langchain@1.4.6) --- updated-dependencies: - dependency-name: langchain dependency-version: 1.4.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
e6f2296d00
|
chore(deps)(deps-dev): bump @vitest/coverage-v8 in /gitnexus-web (#2297)
Bumps [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) from 4.1.8 to 4.1.9. - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.9/packages/coverage-v8) --- updated-dependencies: - dependency-name: "@vitest/coverage-v8" dependency-version: 4.1.9 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> |
||
|
|
a05a1659bd
|
chore(deps): bump release-drafter/release-drafter from 7.3.1 to 7.4.0 (#2295)
Bumps [release-drafter/release-drafter](https://github.com/release-drafter/release-drafter) from 7.3.1 to 7.4.0.
- [Release notes](https://github.com/release-drafter/release-drafter/releases)
- [Commits](
|
||
|
|
ba071b5bb3
|
chore(deps)(deps): bump lru-cache from 11.3.6 to 11.5.1 in /gitnexus-web (#2298) | ||
|
|
5165686798
|
chore(deps)(deps): bump @langchain/core in /gitnexus-web (#2293) | ||
|
|
9aa65ae3f8
|
feat: ✨ resolve Nuxt/Nitro auto-imports in TypeScript scope resolver (#2026)
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
* feat: ✨ resolve Nuxt/Nitro auto-imports in TypeScript scope resolver * fix: 🐛 skip self-referential edges in Nuxt auto-import emission * fix: 🐛 address Sourcery review -- gate Nitro scan on imports.d.ts and pre-index explicit imports * fix: scope Nuxt auto-import resolution * fix: address Nuxt auto-import review follow-ups * fix(ingestion): capture only LHS binding names in Nitro server-util exports The Nuxt server-util export scanner ran a declarator regex over the whole `export const …` right-hand side, so it registered RHS tokens as auto-import names: arrow-function parameters (`export const f = (event) => …` → `event`), object-literal keys (`export const c = { onError } ` → `onError`), and bare operands. It also dropped generic-typed declarators (`export const x: Map<a, b> = …`) because the type-annotation skip broke at the comma inside the generic. Both produced wrong/missing auto-import CALLS edges. Capture only the leading binding name of each top-level declarator via a depth-aware comma splitter (tracks (), [], {}, <>), skipping destructuring patterns. Nitro auto-imports only surface top-level binding names, so the RHS is never parsed. Adds unit coverage for the param/object-key/operand/generic and multi-declarator forms. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4W25WLfYD1JNy8icxeLPU * fix(ingestion): stop Nitro server callers resolving client composables `getNuxtAutoImportEntry` fell back to the client composable map when a `server/api|routes|middleware` caller's name had no `server/utils` entry. But Nitro only auto-imports `server/utils/**` into the server context — app `composables/` are Vue-app-only — so that fallback minted CALLS/IMPORTS edges Nitro never creates (e.g. a server route "calling" a composable it cannot see without an explicit import). Server callers now resolve the server map only. Restructure the barrel-directory integration test to use a client caller (which legitimately auto-imports the composable) so `index.*` resolution stays covered, and add a negative assertion that `server/api/route.ts` emits no edge to `composables/*` while its real `server/utils` call still resolves. Unit test locks that a server caller does not fall back to a client-only name. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4W25WLfYD1JNy8icxeLPU * fix(ingestion): let unresolved explicit imports shadow Nuxt auto-imports The explicit-import suppression index only recorded import local names whose edge resolved to a file (`edge.targetFile !== null`). An explicit import from an unresolved external package — `import { useAuto } from '@vueuse/core'; useAuto()` — therefore escaped suppression, and the post-resolution hook emitted a spurious Nuxt auto-import CALLS edge for a name the file already imports explicitly. Record the local name regardless of whether the import resolved: an explicit import is authoritative shadowing intent. Adds an integration fixture importing from an external package and a (non-vacuous) assertion that it emits no nuxt edge. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4W25WLfYD1JNy8icxeLPU * fix(ingestion): let type-annotated params shadow Nuxt auto-imports hasLocalBindingInScopeChain only consulted scope.bindings, but type-annotated function parameters live in scope.typeBindings (the TS scope query records them as `@type-binding.parameter`, not `@declaration`). A parameter named like a composable therefore failed to suppress the auto-import, leaking a spurious CALLS edge. Also check scope.typeBindings for the name (same-file scopes only). typeBindings holds value-space binders' type facts (parameter annotations, `self`, variable annotations) and never a pure type that belongs to callable space, so this cannot over-suppress a real auto-import. Documents the residual: function-typed params (`p: () => void`), untyped params, destructured locals, and catch-clause vars are captured by neither map and still leak — closing that needs shared scope-query changes beyond this feature, left as a follow-up. Also adds a no-vacuous-pass guard to the shadowing/noise test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4W25WLfYD1JNy8icxeLPU * fix(ingestion): treat server/plugins and server/tasks as Nitro runtime isNitroServerRuntimeFile only matched server/api, server/routes, and server/middleware. Nitro also auto-imports server/utils into server/plugins and (since Nitro 2.6) server/tasks, so callers there were misrouted to the client composable map. Extend the prefix set (now a named constant) to cover them. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4W25WLfYD1JNy8icxeLPU * fix(ingestion): merge duplicate JSDoc on collectImportsDts Two consecutive JSDoc blocks preceded collectImportsDts; tooling (IDEs, TypeDoc) attaches only the last one, silently dropping the descriptive block. Fold the "returns true when read" line into the descriptive block as a `@returns` tag. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4W25WLfYD1JNy8icxeLPU * fix(ingestion): contain .nuxt/imports.d.ts source resolution to the repo A crafted `.nuxt/imports.d.ts` source such as `from '../../../../etc/passwd'` passes the project-local relative-path check but resolves outside the analyzed repo, causing fs.stat probes against arbitrary host paths. Skip any source that resolves outside repoRoot before touching the filesystem. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4W25WLfYD1JNy8icxeLPU --------- Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
8886d55008
|
feat(ingestion): make doc comments searchable across all languages (#2286)
* feat(ingestion): add shared leading-doc-comment description extractor (#2270) Add `extractLeadingDocComment` plus a language-neutral `createLeadingDocDescriptionExtractor` factory and a shared `DOC_BEARING_LABELS` set to `utils/ast-helpers.ts`. The helper pulls the normalized text of a leading doc comment off a definition node's preceding named sibling, covering both block doc comments (Javadoc/KDoc/JSDoc/PHPDoc/ Doxygen, opened by double-star or bang) and runs of line doc comments (triple-slash, bang-slash, or caller-supplied prefixes such as Go's double-slash or Ruby's hash). Grammar-agnostic by prefix match; widens `getDefinitionNodeFromCaptures` to accept the optional-valued capture map. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Eh2UmA6f2p25F3ow75Hjzx * feat(languages): surface leading doc comments as description for all languages (#2270) Register the leading-doc `descriptionExtractor` on every documentable provider so Javadoc/KDoc/JSDoc/Doxygen/godoc/RDoc/`///` doc text lands in the `description` column and reaches the embedding metadata header — making methods/types semantically searchable by doc-only terms, matching the behavior Python (docstring) and PHP (Eloquent) already had. - Java, Kotlin, TypeScript, JavaScript, C, C++, C#, Dart, Rust, Swift: default config (block + triple-slash/bang-slash doc comments). - Go: godoc double-slash leading comments. - Ruby: leading hash (RDoc/YARD) comments. - PHP: existing Eloquent metadata takes precedence, else PHPDoc docblock. Field/property/variable/const docs are intentionally out of scope. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Eh2UmA6f2p25F3ow75Hjzx * fix(review): apply autofix feedback (#2270) Code-review autofix pass on the leading-doc-comment extractor: - Enforce start-row adjacency in the line-comment run so a doc run stops at a blank line (godoc/RDoc/rustdoc semantics). Prevents a Go license/earlier `//` block or a Ruby shebang + `# frozen_string_literal:` magic comment, separated by a blank line, from being absorbed into the first declaration's description. Adjacency uses startPosition.row (reliable across grammars). - Fix the degenerate empty comment `/**/` producing a spurious `/` description. - PHP: compose createLeadingDocDescriptionExtractor() as the docblock fallback instead of duplicating its body, and widen the param to CaptureMap to match the LanguageProvider hook contract. - Drop the factory's unused `labels` option (no consumer overrides it). - Add tests: degenerate `/**/`, multi-line `///` run, `//!` inner doc, `/*!` Doxygen block, Go/Ruby blank-line non-attachment + two-block adjacency, and PHP Eloquent-metadata-wins-over-docblock ordering. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Eh2UmA6f2p25F3ow75Hjzx * fix(ingestion): resolve exported TS/JS JSDoc via export_statement wrapper Exported TS/JS declarations dropped their JSDoc: the TS query captures the inner function_declaration/class_declaration, whose previousNamedSibling is null because the JSDoc precedes the wrapping export_statement (PR #2286 review, reproduced). Add a wrapperNodeTypes option to extractLeadingDocComment (folded into a LeadingDocCommentOptions object threaded through the factory); when the captured node yields no doc and its parent type is a configured wrapper, retry from the parent. TS/JS providers pass ['export_statement']. Language config stays at the call site (RFC #909). Mirrors the existing walk-up in languages/javascript/captures.ts for JSDoc params. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ingestion): bound DOC_BEARING_LABELS to embeddable labels Module/Delegate/Annotation were doc-bearing but absent from EMBEDDABLE_LABELS, so their descriptions were extracted and written to the DB yet never embedded or searchable (PR #2286 review) — wasted work, and the factory JSDoc overstated "becomes semantically searchable". Remove those three labels so DOC_BEARING_LABELS is a subset of EMBEDDABLE_LABELS, narrow the JSDoc, and add a subset-invariant unit test to guard against drift. Making those labels (and C++ `Template`) searchable needs an embedding-pipeline/schema change and is left as a follow-up. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ingestion): skip file-top license/header blocks as descriptions A file-top /** … */ license/copyright/overview block has no package/import sibling to shield it from the first declaration, so it was absorbed as that symbol's description and polluted the embedding text (PR #2286 review). The block-comment branch already cannot use a strict row-adjacency check (grammars fold the trailing newline into the comment node), so match header markers instead — SPDX-License-Identifier, @license/@file/@fileoverview, "Licensed under", and copyright-with-(c)/year. Markers are specific enough not to fire on an ordinary doc that merely mentions the word "copyright" (over-fire guard test). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ingestion): ignore Go/Ruby directive & magic comments in doc runs Go build/tool directives (//go:build, //go:generate, // +build, //nolint, //line) and Ruby magic comments / shebang (# frozen_string_literal:, # encoding:, # -*-, #!, …) sitting directly above a symbol were folded into its description and polluted the embedding text (PR #2286 review). Add a lineDirectivePrefixes option; a matching line is skipped in the doc run (skip-and-continue, so a real doc above an interleaved directive is still collected — godoc/RDoc semantics). Go and Ruby providers supply their own directive prefixes (RFC #909 — config at the call site). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ingestion): guard descriptionExtractor call against throws A throw inside any provider's descriptionExtractor escaped processFileGroup to the language-group catch, which treats any throw as "parser unavailable" and silently drops every remaining file in the group (PR #2286 review). Wrap the call in try/catch + reportWarning, mirroring the adjacent extractTemplateConstraints guard. Defensive parity — no behavior change on the success path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ingestion): treat Rust //! and /*! as inner docs Rust //! and /*! are INNER doc comments (they document the enclosing item/module), not the following item, but the shared helper attached them to the next definition (PR #2286 review; a test even enshrined the wrong behavior). Add a blockDocPrefixes option (default ['/**','/*!']); the Rust provider opts out of both inner-doc markers (lineCommentPrefixes ['///'], blockDocPrefixes ['/**']). Doxygen //! and /*! keep working for C/C++ via the defaults. Flip the Rust //! test to a negative assertion and add a Rust /*! negative case. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(ingestion): strip bidi/zero-width controls from doc descriptions Doc-comment text is attacker-influenceable (any indexed repo) and is returned verbatim to MCP clients, so a description could smuggle Trojan-Source-style bidi overrides or zero-width characters (PR #2286 review). Strip U+202A–202E, U+2066–2069, U+200B–200D and U+FEFF in the doc-comment normalization path (block + line). Scoped to the description path only — global sanitizeUTF8 is deliberately left alone (pre-existing, affects all fields). Implemented with a code-point predicate so no literal invisible bytes live in the source. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(ingestion): doc-comment helper maintainability cleanups PR #2286 review nits (no behavior change): drop the unused `export` on DEFAULT_LINE_DOC_PREFIXES (no importer outside ast-helpers.ts); widen getLabelFromCaptures' captureMap param to `Record<string, SyntaxNode | undefined>` to match getDefinitionNodeFromCaptures (all accesses are truthiness-guarded); and merge the split ast-helpers import statements in dart/ruby/rust into one each. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(architecture): document descriptionExtractor LanguageProvider hook descriptionExtractor is now a near-universal LanguageProvider field (issue #2270) but was missing from the architecture "Key fields" table (PR #2286 review). Add a row describing it and the shared createLeadingDocDescriptionExtractor factory. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(ingestion): end-to-end description searchability for exported symbols The unit tests stop at the descriptionExtractor hook; nothing proved a doc comment survives the full parse pipeline into node.properties.description (the field the embedding metadata header reads) — the exact gap that hid the exported TS/JS regression (PR #2286 review). Add an integration test running the real worker pipeline over an exported, JSDoc'd TS function and asserting its node description carries the doc text. Verified locally against a built worker (20s); runs in CI via pretest:integration build. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * style(ingestion): prettier-wrap a long line in the doc-comment test Formatting-only follow-up to the U3/U7 test additions so `quality / format` is green. No behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
0936553d63
|
fix(ingestion/routes): recognise Spring method-level array-form route mappings (#2281)
* feat(routes): extract Spring method-level array-form routes in ingestion + extractor parity test (#2138 follow-up) ingestion's `extractSpringRoutes` (route-extractors/spring.ts) matched only a single string literal on `@(Get|...)Mapping`, so the array form `@GetMapping({"/a","/b"})` produced no graph Route node — while the group-layer `java.ts` scan did match it. That divergence was the root of the #2265 array-form parse-skip gap. - spring.ts: add the array-form alternation `[(string_literal) @value (element_value_array_initializer (string_literal) @value)]` to the two method-declaration query branches (positional + `path=`/`value=`), mirroring the group query. A multi-element array yields one match per element, so the Phase 2 loop emits one route per path with no other change. Class-level `@RequestMapping` array prefixes remain single-literal (rare; left to a follow-up). - test: spring-route-parity runs one shared Java fixture through BOTH extractors (ingestion `extractSpringRoutes` + group `JAVA_HTTP_PLUGIN.scan`) and asserts identical provider {method,path} sets — the parity guard the maintainer asked for in #2078, so the two Spring extractors can't silently drift again (verified: reverting the array branch turns the parity test red). * fix(ingestion/routes): suppress wrong unprefixed route under class-array @RequestMapping; cover named-array + class-array parity Addresses PR review on #2281: - P2 class-array wrong-route: class branches now match the array form only to detect it; a method-level array route under a class-level array-form @RequestMapping is suppressed rather than emitted with a dropped prefix, so ingestion stays a strict subset of the group scan. Scalar method paths under an array class prefix are unchanged (pre-existing). Full class-array cross-product support tracked in a follow-up. - P2 named-array coverage: added value={...}/path={...} parity cases, a consumes/produces array false-positive case, and a dedicated empty-provider-set assertion. - P3 stale comments: updated the routeCoverage comment in java.ts and the route-parse-skip test note; narrowed the parity test drift claim. routeCoverage stays 'partial'. --------- Co-authored-by: henry <zhangwei2017@unipus.cn> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> |
||
|
|
ca396e38bc
|
chore(deps)(deps): bump uuid from 14.0.0 to 14.0.1 in /gitnexus (#2285) | ||
|
|
47477e5554
|
fix(mcp): tolerate adapter-materialized line:0 in impact callgraph mode (#2279) (#2283)
* fix(mcp): tolerate adapter-materialized line:0 in impact callgraph mode (#2279) Some MCP client/agent adapters serialize an omitted optional numeric field as `0` rather than dropping it, so callgraph `impact` calls arrive carrying a spurious `line: 0`. `line` is a PDG-only statement anchor and is meaningless on the callgraph path, so the backend rejected the call ("'line' is only supported with mode:'pdg'") and strict clients rejected it client-side against the advertised `minimum: 1`. Treat a literal `line: 0` as omitted in `_impactImpl` when mode !== 'pdg' and let the normal symbol→symbol BFS run. The coercion is deliberately narrow: only the literal 0, only on the callgraph path. A genuine positive `line` on callgraph still errors (real mode mistake), negative/ fractional values still error, and pdg mode is untouched — `line: 0` there is still rejected (there is no 1-based source line 0 to anchor on). Regression tests pin the full matrix: callgraph + line:0 runs the BFS and is byte-identical to omitting line; pdg + line:0 still errors; positive line on callgraph still errors. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(mcp): log swallowed best-effort query degradations at warn, not error `logQueryError` is the shared handler for query failures that every caller catches and degrades past with a safe fallback (the operation still returns a result). It logged all of them at `logger.error` (level 50) — the same severity as fatal failures — so a gracefully-handled degradation raised a false alarm and drowned genuine errors. This surfaced as an ERROR-level log firing during a passing unit test that intentionally injects a slice-callees query failure to verify the degrade path. Make the severity match reality: - benign missing optional table/label/column (a repo analyzed without processes/communities, or a pre-v3 PDG index lacking the `calleeIds` column — a query that fails on every pdg-downstream impact for such an index) → debug, the normal-configuration case. - any other swallowed failure → warn (handled degradation, still observable). - error is reserved for failures that actually abort an operation, which log directly rather than through this helper. Also fix the sibling bm25/FTS fallback, which logged its swallowed "FTS indexes may not exist" degradation at error while its own import-failure fallback already used warn. The slice-callees degradation test now captures the log and asserts it lands at warn (40), not error (50), pinning the severity against regression. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(mcp): relax impact `line` schema minimum to 0 for adapter compatibility (#2279) Strict MCP clients/agents validate against the advertised input schema and reject a request before sending it. With `line` declaring `minimum: 1`, a client that materializes the omitted optional `line` as `0` rejects a perfectly valid callgraph impact call client-side — so the backend tolerance added in the previous commit never gets a chance to run. Lower the advertised `line.minimum` to 0 and document that 0 (or omission) means "no statement anchor" while mode:'pdg' still requires a positive line. The advertised schema is advisory (the backend self-validates and is the real gate), so this cannot loosen any enforced contract — it only stops strict clients from pre-rejecting `line: 0`. Negative lines are still rejected at the client boundary. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(review): apply autofix feedback Code-review autofix pass on the #2279 branch: - Replace a newly-introduced `mode as any` cast in the #2279 it.each with the narrow `mode as 'callgraph' | undefined` (strict-typing-no-any). - Add a degradation test for the new logQueryError benign-missing-table → debug branch (asserts no warn/error record surfaces, i.e. it routed to debug). - Pin the bm25/FTS error→warn severity change with a _captureLogger assertion in the existing #1489 test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(mcp): make swallowed-failure callers surface degradation; narrow benign-error match (#2283) Tri-review (#2283) found the `error → {debug|warn}` rework reduced telemetry for `logQueryError` callers that do NOT degrade safely, while the docstring over-claimed "every caller degrades to a safe fallback". Address the substance rather than only the log level: - rename apply-edit: track failed writes and return status:'partial' with `failed_files` instead of reporting `status:'success'` when a write was swallowed. A partial rename is no longer indistinguishable from a clean one. - detect_changes: a swallowed symbol/process query failure now sets `partial:true` (rendered by the existing eval-server partial path) so the pre-commit safety gate can't return a false-clean `risk_level:'low'` no-op. - isBenignMissingTableError: scope the `not (defined|found)` arm to a schema object (table/label/rel/column/property), mirroring lbug-adapter's isMissingColumnError. An unscoped "not found" matched operation failures like `rg: not found` / `Symbol not found` and silently demoted them to debug. - logQueryError docstring: state the contract honestly — level reflects telemetry severity, and mutating/safety-critical callers MUST also surface a result-level degradation signal; `warn` alone is not a substitute. - pdg dispatch: pass the normalized `effectiveLine` (not raw params.line) so the validation gate and engine share one source of truth (identity today). Tests: - _captureLogger(level?) lets tests capture below info; the benign-missing-table test now asserts the record IS emitted at debug (20), not merely absent — no longer a vacuous pass if the call were deleted. - new: a non-schema "not found" failure logs at warn (regex-narrowing guard); rename write-failure degrades to status:'partial'+failed_files; line:-1 on the callgraph path still errors (line:0 coercion is narrow); typed the it.each tuple to drop a `mode as` cast. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(mcp): fix impact `line` description contradiction for whole-symbol pdg (#2283) The new `line` schema description said "mode:'pdg' requires a positive line", which contradicted the top-level impact description ("Without 'line', pdg returns whole-symbol inter-procedural reach plus local whole-symbol PDG diagnostics"). A pdg call without a line is a valid (degraded whole-symbol) call, not an error — the old wording could push an agent to avoid valid no-line pdg calls or synthesize line:0 (which then hard-errors). Reword to: omit line for whole-symbol pdg; a positive line anchors a statement slice; literal 0 is tolerated only as an omitted-line compatibility sentinel on the callgraph path and is rejected for mode:'pdg'. Update the schema test to pin the new, non-contradictory wording and assert "requires a positive line" is gone. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
698f5efc82
|
feat(group): resolve inline HTTP provider handlers via call-site line (#2276) (#2282)
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
* feat(group): resolve Go inline provider handlers via line containment (#2276) Widen the Go HandleFunc + framework-route handler capture to match func literals and emit name:null + call-site line for them, so an inline handler resolves to its containing/closure symbol instead of file-level. Named identifier handlers keep resolving by name. * feat(group): resolve Laravel closure provider handlers via line containment (#2276) Capture the Laravel route handler argument; a closure (anonymous function or arrow fn) now emits name:null + the registration line so it resolves to its containing symbol (service-provider boot, controller method) by containment. Named-controller routes keep the 'route' label. File-scope closures stay file-level (PHP closures not yet indexed). * feat(group): wire call-site line on FastAPI provider emits (#2276) Set line on the FastAPI @app/@router provider detections (already name:null) so the source-scan fallback resolves the decorated handler by line-span containment. Best-effort: FastAPI routes are graph-backed and the function span starts at def, so this lands the single-decorator case. Flask add_url_rule already carried line. * feat(group): wire call-site line on Kotlin/Java Spring provider emits (#2276) Add line to the Kotlin and Java Spring @*Mapping provider detections for parity with the consumer emits and a future inline DSL. Inert for current resolution: a named Spring controller method resolves by name and never falls through to line-span containment. * fix(review): apply autofix feedback Pin two documented limitations with tests: a file-scope Laravel closure and a multi-decorator FastAPI handler both degrade to file-level rather than mis-attributing (#2276 ce-code-review autofix). * test(group): lock named gin framework-route resolves by name not registrar (#2276) Reviewer verified named Go handlers still resolve by name across the widened queries; the HandleFunc path was already pinned, this adds the framework-route (gin/echo) path with a DB + enclosing registrar whose span covers the registration line, proving the emitted line never diverts a named provider to its registrar via containment. * test(group): end-to-end inline Go provider resolution against real LadybugDB (#2276) Closes the validation gap that all prior coverage mocked CONTAINING_QUERY: runs the real pipeline over a Go file with an inline http.HandleFunc func-literal handler, persists into a real LadybugDB, and runs the production HttpRouteExtractor against the real executor — proving the emitted call-site line lands inside main()'s real 0-based span and yields source_scan_resolved, not the file-level fallback. * fix(test): use fs.mkdtemp to satisfy CodeQL insecure-temporary-file gate (#2276) The new integration test created its temp base via a predictable os.tmpdir()+name join, which CodeQL flags as js/insecure-temporary-file (1 high). Switch to fs.mkdtemp for an atomic, randomly-named base dir. * fix(group): anchor Go provider @handler to the trailing argument (#2276) The widened framework-route and HandleFunc handler captures (`[(identifier) (func_literal)] @handler`) were unanchored, so a variadic middleware route `r.GET("/x", mw, func(){})` produced two provider detections — one for the middleware identifier and one for the closure. The contractId-only merge then kept the middleware detection and mis-attributed the route to it (and the pre-existing `mw, namedHandler` shape had the same defect), silently neutralizing the inline-handler containment resolution from #2276. Add a trailing tree-sitter anchor (`@handler .`) so the handler binds the LAST argument of the call, leaving middleware args before it unconstrained. Verified against tree-sitter-go: the multi-arg shapes now yield exactly one detection (the real handler) while every 2-arg case is unchanged. Adds two regression tests pinning that a middleware + inline closure resolves to its containing function and a middleware + named handler resolves by name. * test(group): cover FastAPI @router inline-handler containment (#2276) The @router/APIRouter provider emit gained a call-site `line` in #2276 but only the @app path was tested; the existing @router tests call `extract(null, …)` so the resolver/containment path never ran for @router. Add two tests mirroring the @app cases: a single-decorator @router handler resolves to its function via source_scan_resolved (which fails if `line` is dropped), and a multi-decorator one degrades to file-level. * fix(group): treat synthetic 'route' label as anonymous in cross-trace (#2276) After #2276 an unresolved file-scope Laravel closure emits name:null, so its persisted symbolName falls back to 'handler' — which providerLabel already anonymizes to '<contractId handler>'. But an unresolved named-controller route still carries the synthetic 'route' placeholder, which the sentinel did NOT cover, so group_trace/group_cross_impact rendered it as the literal 'route' while equivalent closures showed '<... handler>'. 'route' is only ever the synthetic Laravel placeholder (php.ts), never a resolved handler name, so add it to the unresolved-generic sentinel set alongside 'handler'/'fetch'. The resolved branch is untouched, so a real symbol genuinely named 'route' still displays its name. Adds a cross-trace test pinning the anonymized label. * fix(group): gate Spring provider line on a present method name (#2276) The Java/Kotlin Spring @*Mapping provider emits set `line` unconditionally while the method name is typed string|null. The 'a named provider never reaches containment' guarantee held only because the grammar always captures a method name — the type did not enforce it. A (grammar-impossible) null name would emit name:null + line and resolve by containment to the enclosing class body instead of staying file-level. Emit `line` only when the method name is truthy, so a nameless provider degrades to file-level (the safe no-mis-attribution outcome). Behavior is unchanged for every real Spring route (name is always present), but the inertness is now enforced rather than incidental. |
||
|
|
49ffd8e316
|
feat(group): resolve cross-file named HTTP handlers (#2275) (#2277)
* feat(group): resolve cross-file named HTTP handlers via unique repo-wide lookup U1 of #2275. When a provider's named handler is defined in a file other than its route registration (e.g. router.get('/x', listUsers) with listUsers imported), the registration file's symbols don't contain it, so resolution fell back to the file-level boundary. Add a repo-wide name query (RESOLVE_BY_NAME_QUERY, the label-union pattern from manifest-extractor) consulted only after the file-scoped lookup misses, and honored ONLY when exactly one Function/Method/CodeElement carries that name (zero/many → keep the file fallback, no wrong-symbol attribution). Provider-only, cached by name. 4 unit tests; 743 group tests pass. * test(bench): cross-file named handler scenario (end-to-end proof of #2275) U2 of #2275. Adds a fifth bench scenario: a backend route whose handler (listUsers) is imported from another file than its registration, with a frontend consumer. Asserts the provider resolves to the handler via the repo-wide unique name lookup (sym=listUsers, uid set) and that the cross-repo trace is symbol- precise (no file-level fallback). verify.mjs now 12/12 on the real pipeline. * fix(review): apply autofix feedback ce-code-review (autofix) — no correctness/security findings; applied test-coverage + robustness fixes: repo-wide query throw -> empty (no exception); by-name lookup cache fires once across same-named handlers; consumers never consult the repo-wide lookup; same-file-wins now asserts the global path is bypassed; bench provider find scoped by contractId; clarified the uniqueness-guard comment. 167 extractor tests. * fix(group): tri-review fixes for cross-file handler resolution Two-engine PR tri-review (Claude swarm+ce, Codex gpt-5.5 swarm+ce+adversarial) on #2277. Correctness/security clean (injection refuted, bind-param). Fixes: - Named-provider wrapper-attach (Codex swarm P1 + Claude ce-adversarial, cross-engine): a named handler that fails both name lookups no longer falls through to line-span containment, which attached the route to the enclosing registrar (e.g. a setupRoutes() wrapper) instead of leaving it empty. Containment now applies only to consumers and inline-arrow providers. - CodeElement/ORM empty-file nodes (Claude ce-adversarial reproduced + ce-maintainability): RESOLVE_BY_NAME_QUERY gains 'AND n.filePath <> ""' so a handler name colliding with a synthetic ORM model node (orm.ts emits filePath:'') neither resolves to an edge-less node nor inflates the uniqueness count and masks the real handler; + a defensive empty-filePath guard in resolveSymbolByNameUnique. Added LIMIT 2 (Codex swarm P3 + ce-maintainability) to bound homonym materialization (count guard stays exact). - Documented the aliased-import limitation (Codex adversarial): the route-site identifier is the local alias, fix deferred to #2275 import narrowing. - README expected verdict 9/9 -> 12/12 (Codex swarm+ce P3). Tests: +3 (wrapper-no-attach, empty-filePath reject, empty-registration-file resolves) covering the cross-engine gaps. 170 extractor / 748 group+integration pass; bench 12/12 end-to-end. * feat(group): import-pinned handler resolution (fixes deferred alias case) Resolves the tri-review's deferred item: cross-file named handlers are now pinned to their import's target module instead of resolved by name alone, so aliases and names that collide with a local symbol resolve correctly. - node.ts builds a local-binding -> {declared name, module} map from the file's named imports; the express handler emits the DECLARED name + a handlerImport {name, module} (HttpDetection gains the optional field). - resolveDetectionSymbol gains an imported-handler rung: resolveImportedSymbol pins to the import's target file via RESOLVE_IN_MODULE_QUERY (n.name= AND filePath STARTS WITH the resolved module path), unique-match only. An imported handler never uses file-scoped lookup (it is defined elsewhere); on a module miss it falls back to a unique repo-wide name match on the DECLARED name, then null. Relative imports only; bare/non-relative imports keep the repo-wide fallback. Cached by (module-prefix, name). - Closes the Codex-adversarial alias finding: import { listUsers as handleUsers } + an unrelated handleUsers no longer mis-resolves — the route resolves to the imported listUsers in its module, and the alias is never looked up. - Shared toResolvedSymbol helper (dedups the row->symbol + empty-filePath guard). Tests: alias-resolves-to-declared-name + module-pin-resolves-ambiguous-name unit tests; same-file-wins reworked to a genuinely LOCAL handler. Bench scenario 6 (aliased import with a decoy) proves it end-to-end. 172 extractor / 751 group+integration pass; bench 14/14. * feat(group): import-pinned resolution for Python aliased handlers Extends the JS/TS import-pinning to Python. The Python analog of express router.get(path, handler) is Flask's imperative add_url_rule(view_func=...), whose view is often an imported (aliased) symbol. - New Flask add_url_rule provider pattern (path + view_func handler + methods; default GET, methods=[...] honored). High Flask-specificity keeps false positives low — unlike bare path()/Route(), which the plugin deliberately leaves to graph Route nodes. - buildPythonImportMap resolves 'from .mod import name as alias' (and plain 'from mod import name') to the declared name + raw module spec. - resolveModuleBase generalized to two relative-import dialects: path-style (JS './h/users') and dotted (Python '.handlers.users', '..pkg.users' — leading dots are package levels). Bare/absolute imports keep the repo-wide fallback. - Django stays graph-resolved (handlerSymbolId); FastAPI/Flask decorators stay same-file (decorated function). This only adds the imperative imported-view case Python lacked. Tests: Flask aliased add_url_rule unit test (relative dotted module pinned, alias never queried) + bench scenario 7 (end-to-end, 16/16). 173 extractor / 752 group+integration pass. |
||
|
|
d27fd11c4b
|
fix(lang-kotlin): support fun interface extraction via tree-sitter-kotlin re-vendor (#2271)
* fix(lang-kotlin): support `fun interface` extraction via tree-sitter-kotlin re-vendor Vendored tree-sitter-kotlin@0.3.8 (fwcd) parsed `fun interface Foo` as an ERROR node and dropped the declaration plus its abstract method, so functional (SAM) interfaces were never extracted. The fix landed upstream in fwcd/tree-sitter-kotlin#169 (closes #87), merged to main 2025-04-25, but is not in any npm release (latest tag 0.3.8; main is the unreleased 0.4.0). Re-vendor the grammar from the unreleased fwcd main commit c8ac3d26: - refresh src/{parser.c,scanner.c,node-types.json,tree_sitter/*.h} and bindings/node/index.js; bump the vendor version 0.3.8 -> 0.4.0; record the pinned SHA + rationale in _vendoredBy and the vendor README. - switch the prebuild workflow's kotlin registry kind 'npm' -> 'vendored' (the fix is unreleased on npm, so prebuilds must build from the vendored C source, like swift/dart/proto). - add a hold to .github/vendored-grammars.json so the weekly auto-update monitor does not strict-inequality-revert the pin to the broken npm 0.3.8 (isNewer compares 0.3.8 != 0.4.0). - add 3 regression tests + a fixture asserting fun interfaces extract as Interface nodes with their abstract methods, and that plain-interface heritage still resolves. Existing KOTLIN_QUERIES need no change: the new grammar models `fun interface` as a class_declaration with an "interface" keyword child (plus an extra "fun" modifier child), which the existing interface rule already matches. Full Kotlin suite green against the new grammar (300 unit/cfg/resolver + 233 integration). NOTE: prebuilds/ are intentionally not in this commit. The version bump auto-triggers .github/workflows/build-tree-sitter-prebuilds.yml, which regenerates all 6 platform binaries from the vendored source in a separate PR. Until that lands, CI loads the committed 0.3.8 prebuild, so the new kotlin tests are red and the grammar change is inert at runtime. Merge the prebuild PR first or together. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(ci): count kotlin's vendored hold as a 0.25-readiness blocker The kotlin `hold` added in the previous commit makes the tree-sitter upgrade-readiness report count it as a blocker — the report treats every held vendored grammar as frozen below a runtime upgrade (same as the intentionally-pinned tree-sitter-cpp and the ABI-held tree-sitter-c), "in-range ABI or not". So the report's blocker count goes 2 -> 3. Update the hardcoded count in test_issue_update_summary_regex_matches_current_report (and the _render_report docstring) accordingly — exactly as that test instructs: "if a grammar is added/removed or a pin/hold changes, update the expected counts". kotlin's ABI (14) is in range; the hold is what flags it, with the reason recorded in .github/vendored-grammars.json. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(ci): refresh kotlin baselines for the grammar bump Two committed baselines pinned the pre-bump kotlin state and broke when the grammar was re-vendored (0.3.8 -> 0.4.0): - cli-commands.test.ts pinned the vendored kotlin package version at 0.3.8 -> update to 0.4.0. - bench/scope-capture/baselines.json: the new kotlin-fun-interface fixture joins the lang-resolution/kotlin-* corpus AND the new grammar parses `fun interface` as a class_declaration (not an ERROR node), so the capture fingerprint drifts. Rebaselined to the NEW grammar's fingerprint (verified by building the vendored parser.c against tree-sitter@0.21.1 and running measure.mjs --check); scaling ~0.83 (linear). Like the fun-interface integration tests, the scope-capture --check passes only once the regenerated prebuilds land; until then CI loads the committed 0.3.8 binary, so it stays red. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci(prebuilds): rebuild + commit grammar prebuilds into the PR on vendored-source change build-tree-sitter-prebuilds.yml previously rebuilt a grammar's native prebuilds only when its package.json VERSION bumped, and delivered them via a separate bot PR. Now any change to the vendored grammar source re-cuts the prebuilds and they ride into the same PR. - Trigger on any build-affecting change under gitnexus/vendor/tree-sitter-*/** (parser.c, grammar.js, binding.gyp, scanner, bindings), not just version bumps. The prebuilds/ subtree is negated in the paths filter AND excluded from the guard's source diff, so the bot's own prebuild commit can never retrigger the workflow (no build -> commit -> build loop). - The guard builds a grammar when its recorded version changed OR its vendored source changed vs the PR base. - Same-repo PRs get the rebuilt prebuilds committed straight onto their own head branch (included in the SAME PR) via a non-force push that only adds a commit on top of head. Manual dispatch still opens a fresh chore/ PR; fork PRs stay artifacts-only (a bot cannot push into a fork branch). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci(prebuilds): deliver rebuilt prebuilds to fork PRs via a trusted workflow_run stage A fork PR's producer run has a read-only token and no secrets, so it can build and validate the prebuilds but can't commit them. Add the safe two-stage handoff that mirrors the pr-autofix producer/publish split. - build-tree-sitter-prebuilds.yml (untrusted producer): on a fork PR, upload a pr-meta artifact (schema, pr_number, head_sha, head_ref, head_repo, base_repo) alongside the prebuild artifacts. Values flow through env + jq, never interpolated into a shell. - commit-fork-prebuilds.yml (trusted, workflow_run): downloads ONLY the artifacts (never executes fork code — it checks out the pinned HEAD SHA solely to add files), allowlist-validates every metadata field, cross-checks identity against the workflow_run authority (head_sha / head_repo / pr_number, via commits/{sha}/pulls for forks), then pushes the prebuilds onto the fork head branch with --force-with-lease + http.extraheader auth. No PAT: this works when the contributor left "Allow edits by maintainers" on; on push failure it posts a sticky comment telling them to enable it or commit the downloaded artifacts. zizmor: allowlist commit-fork-prebuilds.yml's workflow_run dangerous-trigger with the documented mitigation, matching the existing ci-report / pr-autofix entries. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(vendor): rebuild tree-sitter-kotlin prebuilds for the re-vendored fun-interface grammar The fun-interface re-vendor changed vendor/tree-sitter-kotlin source but left main's old (0.3.8) prebuilds in place, so all 6 platform binaries were stale relative to the new parser. Replace them with the freshly cross-built + ABI-validated binaries from build-tree-sitter-prebuilds run 28010841458 — each .node was require()-loaded and parsed a snippet on its target platform-arch before upload. This is the manual equivalent of the commit-fork-prebuilds.yml delivery, which can't run for this fork PR until it lands on main. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(lang-kotlin): read extension-function receiverType from the re-vendored grammar's `receiver` field The fun-interface re-vendor changed the kotlin AST: an extension function's receiver is now a `receiver_type` exposed via a named `receiver` field, where the old grammar emitted a bare user_type before the name. extractReceiverType only matched the old shape, so receiverType came back null (method-extraction.test.ts > Kotlin MethodExtractor > extracts receiverType). Prefer the `receiver` field (unwrapping it), and keep the old child-scan — now also recognizing `receiver_type` — as a fallback. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> |