GitNexus/gitnexus/test/unit
ivkond 1ff324ca16
feat(group): bridge.lbug storage + contract matching expansion (1/4 of #606 split) (#795)
* feat(group): bridge.lbug storage + contract matching expansion

Part 1 of 4 in the split of #606 (ticket: #791, closes #790 with a
revised plan per @magyargergo's request).

## What changed

Adds the LadybugDB-backed bridge storage infrastructure and extends
the contract matching algorithm with wildcard support. All changes are
additive: storage.ts, sync.ts, service.ts, cli/group.ts, mcp/tools.ts
are left on their upstream main versions and will migrate to the new
bridge in follow-up PRs (#792, #793, #794).

### Files

**New (844 LOC prod):**
- `gitnexus/src/core/group/bridge-db.ts` — atomic write-to-temp with
  `retryRename` for Windows EBUSY/EPERM, per-item write tolerance via
  `WriteBridgeReport`, `findContractNode` with three-tier symbol
  lookup (uid → filePath+name → filePath)
- `gitnexus/src/core/group/bridge-schema.ts` — schema DDL
- `gitnexus/src/core/group/normalization.ts` — contract ID
  canonicalization + `dedupeContracts` / `dedupeCrossLinks` helpers
  used by both matching and bridge write

**Modified (+137 LOC prod):**
- `gitnexus/src/core/group/matching.ts` — adds `runWildcardMatch` for
  `grpc::Service/*` wildcard consumers, `buildProviderIndex` helper,
  and canonical gRPC ID handling in `normalizeContractId`
- `gitnexus/src/core/group/types.ts` — `MatchType` gains `'wildcard'`;
  new `BridgeHandle` and `BridgeMeta` interfaces

**New tests (658 LOC):**
- `gitnexus/test/unit/group/bridge-db.test.ts` — core write/read round
  trip, `WriteBridgeReport` shape, dropped-links counter, retryRename
  behavior on EBUSY/ENOENT/EPERM/EACCES
- `gitnexus/test/unit/group/bridge-db-edge.test.ts` — edge cases
  (malformed meta, missing contract nodes, concurrent access)

**Modified tests (+225 LOC):**
- `gitnexus/test/unit/group/matching.test.ts` — wildcard consumer
  matching, gRPC canonical ID handling, same-service guard

### Self-review fixes folded in

Carried forward from the original #606 self-review:
- `writeBridge` try/finally handle lifecycle + `handleClosed` sentinel
- `openBridgeDbReadOnly` partial-handle cleanup
- `writeBridgeMeta` uses `retryRename` for Windows consistency
- `retryRename` unit tests (was zero coverage)
- Per-item try/catch around every CREATE loop so one malformed contract
  doesn't abort the whole write
- Dropped cross-link counter (`linksDroppedMissingNode`)

### Why now

magyargergo asked for the #606 PR to be split so we can iterate with
confidence (https://github.com/abhigyanpatwari/GitNexus/pull/606#issuecomment-4229612271).
This is the foundational layer — pure infra, no user-facing surface,
no callers of the new APIs in this PR. Later PRs wire it in.

### How to verify

- `cd gitnexus && npx tsc --noEmit`
- `cd gitnexus && npx vitest run test/unit/group/bridge-db.test.ts --pool=forks`
- `cd gitnexus && npx vitest run test/unit/group/bridge-db-edge.test.ts --pool=forks`
- `cd gitnexus && npx vitest run test/unit/group/matching.test.ts --pool=forks`
- Pre-commit hook runs clean

### Risk / rollback

**Low.** All new code sits under `src/core/group/` in new files plus a
minimal `+16/-1` diff to `types.ts` and a `+136/-0` diff to `matching.ts`
(both purely additive). No existing callers reference the new APIs
(bridge-db, openBridgeOrFallback, runWildcardMatch) — the PRs that wire
them in come later in the split chain. Rollback = `git revert` of the
merge commit; no state introduced, no schema migration triggered.

### Scope discipline (per GUARDRAILS.md)

- Only the 8 files listed above are touched; no drive-by refactors
- No CI/release/security config changes
- No secrets, tokens, or machine-specific paths
- Content is lifted from the #606 branch which already passed CI 11/11
  green on `d15b8cb` (before the split)

### Dependencies

- **Base:** `main` (no dependencies on other split PRs)
- **Blocks:** extractor expansion (#792), sync pipeline (#793),
  cross-impact feature (#794)
- **Related ticket:** #791

Co-authored-by: Claude <noreply@anthropic.com>

* fix(group): address @claude review on #795

Addresses the findings from the automated review on PR #795
(https://github.com/abhigyanpatwari/GitNexus/pull/795#issuecomment-4229770000
— posted by @magyargergo / claude-code Action run).

### Medium severity (reviewer flagged as blockers)

- **bridge-db.ts `openBridgeDbReadOnly` bak recovery** — the `.bak`
  recovery path used bare `fsp.rename(bakPath, dbPath)`, which is
  exactly the scenario most likely to hit Windows EBUSY/EPERM (an
  interrupted writer still holding the handle for a few ms). Switched
  to `retryRename` for consistency with the rest of the file's
  Windows-safe rename path.
- **bridge-db.ts `ensureBridgeSchema` error detection** — the inline
  `msg.includes('already exists')` substring match has been lifted
  into a named constant `LBUG_ALREADY_EXISTS_MSG` with a comment
  documenting the coupling to LadybugDB's error message wording and
  why we can't use `IF NOT EXISTS` (LadybugDB DDL doesn't support it)
  or typed errors (LadybugDB's JS driver doesn't expose error codes).
  Also tightened the `catch (err: any)` to `catch (err: unknown)`.
- **bridge-db.ts `findContractNode` — extracted out of writeBridge**
  — the 35-line async closure living inside `writeBridge` has been
  lifted to three module-level functions: `createContractLookupIndex`,
  `indexContract`, and `findContractNode`. `findContractNode` is now
  a pure synchronous function taking a prebuilt index instead of
  doing its own DB queries. The `writeBridge` cross-link loop is now
  ~25 lines instead of ~100.
- **bridge-db.ts `findContractNode` — N+1 query elimination** — the
  old inner-closure version issued up to 6 DB round-trips per
  cross-link (2 endpoints × up to 3 tiers of fallback queries). For a
  group with 1000 cross-links, that's up to 6000 DB queries just to
  resolve endpoints. The new version consults an in-memory
  `ContractLookupIndex` built incrementally as contracts are inserted
  (`indexContract` called AFTER each successful insert so failed
  inserts don't poison the index). Cross-link resolution is now
  O(1) per link instead of O(3) DB queries per link, with zero DB
  round-trips during the cross-link loop.

### Minor severity

- **bridge-db.ts `queryBridge` empty-array guard** — if LadybugDB
  ever returns an empty `QueryResult[]` at the top level (shouldn't
  happen with single-statement calls, but driver contract isn't
  explicit), the old code would call `.getAll()` on `undefined` and
  crash with a confusing stack. Added an `unwrapQueryResult` helper
  that throws an explicit `'empty QueryResult array'` error instead,
  making a potential driver regression visible immediately.
- **normalization.ts `contractRichness` weights** — added a
  block-level comment documenting the weight ordering (+3 for
  symbolUid, +2 for each symbol-identifying field, +1 for service
  tag or non-manifest origin) and explicitly noting that the
  absolute numbers don't matter, only the relative ordering. Matches
  the "comment for contributors" suggestion in the review.
- **bridge-schema.ts `BRIDGE_SCHEMA_VERSION` migration comment** —
  added a 4-point contract explaining what bumping the constant
  means ("discard and re-sync" strategy for V1, no in-place
  migration yet, new migration logic should live in a separate
  `bridge-migrations.ts` module when it becomes necessary).
- **test/unit/group/fixtures.ts** — extracted the `makeContract`
  helper previously copy-pasted between `bridge-db.test.ts` and
  `bridge-db-edge.test.ts` into a shared fixtures module. Both test
  files now import from `./fixtures.js`. Kept the scope minimal:
  fixtures is NOT a general-purpose factory module, just the shared
  baseline contract builder.

### New tests

Added 9 pure-function unit tests for the now-extracted
`findContractNode` in `bridge-db.test.ts`:
  - returns null on empty index
  - tier 1 (symbolUid) match, including repo-scope and role-scope
    isolation
  - tier 2 (filePath + symbolName) fallback when symbolUid is empty
    or mismatches
  - tier 3 (filePath only) when exactly one contract lives in the
    file, and refusal when multiple do
  - priority ordering when multiple tiers could resolve

These are fully isolated — no DB, no temp directories, no native
LadybugDB binding — so they run in &lt;10ms total and are
immediately trustworthy as a regression safety net.

### Deliberately deferred (reviewer marked as "fine for now")

- `BridgeHandle._db` / `._conn` typing to `unknown` with casts in
  `bridge-db.ts` — reviewer's note: "The typing is fine for now."
- Batch inserts via `UNWIND` — needs LadybugDB support confirmation,
  tracked as a follow-up; the per-item pattern remains.
- `queryBridge` prepared-statement lifecycle — the current pattern
  (prepare → execute → GC) relies on LadybugDB's internals, worth
  verifying against their docs in a separate audit.

### Scope discipline (per `GUARDRAILS.md`)

- Only files touched by this PR (`bridge-db.ts`, `bridge-schema.ts`,
  `normalization.ts`, both bridge test files, new `fixtures.ts`) —
  no drive-by refactors
- No CI/release/security config changes
- No secrets

### Test + typecheck status

- `npx tsc --noEmit` clean
- `bridge-db.test.ts`: added 9 `findContractNode` tests, all pass in
  isolation. The full-file run still hits the pre-existing native
  LadybugDB cleanup segfault that flakes the reported count — same
  as every prior commit on this branch, not a regression.
- `bridge-db-edge.test.ts`: 4/4 pass
- `matching.test.ts`: 28/28 pass
- `types.test.ts`: 5/5 pass
- `retryRename` tests (4/4) and `findContractNode` tests (9/9)
  verified in isolation via `-t` filter

Co-authored-by: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-11 19:46:12 +01:00
..
call-routing feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
group feat(group): bridge.lbug storage + contract matching expansion (1/4 of #606 split) (#795) 2026-04-11 19:46:12 +01:00
import-resolution feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
named-bindings refactor: SICP-informed LanguageProvider architecture (#488) 2026-03-24 13:42:39 +00:00
ai-context.test.ts feat: added skip-agents-md cli flag (#517) 2026-03-28 21:23:59 +00:00
analyze-api.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
analyze-job.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
api-graph-streaming.test.ts [codex] fix large repository graph loading (#732) 2026-04-09 17:40:24 +01:00
ast-cache.test.ts fix: guard createASTCache against zero maxSize to prevent LRU cache crash 2026-03-02 08:47:20 +00:00
binding-accumulator.test.ts feat(SM-15): Wire BindingAccumulator into processCallsFromExtracted for cross-file return type propagation (#763) 2026-04-10 10:29:31 +01:00
bm25-search.test.ts refactor: migrate from KuzuDB to LadybugDB v0.15 (#275) 2026-03-15 15:53:01 +00:00
call-form.test.ts feat(SM-18): Delete lookupFuzzy, lookupFuzzyCallable, globalIndex, callableIndex (#769) 2026-04-10 14:56:24 +01:00
call-processor.test.ts SM-19: Delete resolveCallTarget — replace with thin dispatcher (#770) 2026-04-11 10:20:57 +01:00
calltool-dispatch.test.ts feat(group): add sync pipeline, CLI, MCP tools, and monorepo fixture 2026-04-02 00:40:31 +03:00
cli-commands.test.ts feat: configure eslint with unused import removal (#564) 2026-03-28 15:28:09 +00:00
cli-index-help.test.ts fix: address PR review — remove redundancies and add wiki help test 2026-03-25 11:39:37 +05:30
cobol-copy-expander.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
cobol-preprocessor.test.ts feat: configure eslint with unused import removal (#564) 2026-03-28 15:28:09 +00:00
cohesion-consistency.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
community-processor.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
compatible-stdio-transport.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
cors.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
csv-escaping.test.ts refactor: migrate from KuzuDB to LadybugDB v0.15 (#275) 2026-03-15 15:53:01 +00:00
dart-import-resolver.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
dart-type-extractor.test.ts feat: configure eslint with unused import removal (#564) 2026-03-28 15:28:09 +00:00
embedder.test.ts test: add test suite with vitest (unit + integration + fixtures) 2026-03-01 20:07:02 +05:30
entry-point-scoring.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
eval-formatters.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
expo-routes.test.ts feat: add Expo Router file-based route detection (#503) 2026-03-25 11:05:55 +00:00
extract-element-type-from-string.test.ts feat: Phase 6 type resolution — for-loop Tier 1c, pattern matching, container descriptors, 10-language coverage (#318) 2026-03-17 17:10:22 +00:00
extract-generic-type-args.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
fetch-reason-parsing.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
field-extraction.test.ts feat(ts,js): TypeScript/JavaScript MethodExtractor config (#588) 2026-04-01 14:09:59 +01:00
framework-detection.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
git-clone.test.ts Fix security issues and critical bugs found in code review (#709) 2026-04-10 05:20:29 +01:00
git-utils.test.ts feat: configure eslint with unused import removal (#564) 2026-03-28 15:28:09 +00:00
git.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
graph.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
has-method.test.ts feat: MethodExtractor configs for Python, PHP, Swift, Dart, Rust, Ruby (#624) 2026-04-03 16:11:31 +01:00
heritage-map.test.ts feat(SM-8): Build HeritageMap from accumulated ExtractedHeritage[] (#739) 2026-04-08 19:00:08 +01:00
heritage-processor.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
hooks.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
http-embedder.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
hybrid-search.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
ignore-service.test.ts fix(ignore): respect negation patterns in .gitnexusignore (#654) 2026-04-06 08:32:47 +01:00
impact-batching-grouping.test.ts feat(group): add sync pipeline, CLI, MCP tools, and monorepo fixture 2026-04-02 00:40:31 +03:00
impact-confidence.test.ts feat: METHOD_IMPLEMENTS edges, overload disambiguation, MethodExtractor unification (#574) (#642) 2026-04-04 18:41:47 +01:00
import-processor.test.ts refactor: SICP-informed LanguageProvider architecture (#488) 2026-03-24 13:42:39 +00:00
index-repo-command.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
ingestion-utils.test.ts feat: METHOD_IMPLEMENTS edges, overload disambiguation, MethodExtractor unification (#574) (#642) 2026-04-04 18:41:47 +01:00
isWriteQuery.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
jcl-parser.test.ts feat: configure eslint with unused import removal (#564) 2026-03-28 15:28:09 +00:00
language-skip.test.ts feat(ingestion): respect .gitignore and .gitnexusignore during file discovery (#231) 2026-03-16 13:26:20 +00:00
lazy-action.test.ts Improve MCP startup compatibility and lazy-load CLI commands (#207) 2026-03-07 07:47:09 +00:00
method-extraction.test.ts feat: same-arity overload disambiguation via type-hash suffix (#651) (#658) 2026-04-05 21:51:55 +01:00
method-props.test.ts feat: same-arity overload disambiguation via type-hash suffix (#651) (#658) 2026-04-05 21:51:55 +01:00
mro-processor.test.ts feat: METHOD_IMPLEMENTS edges, overload disambiguation, MethodExtractor unification (#574) (#642) 2026-04-04 18:41:47 +01:00
noise-filter.test.ts refactor: split global BUILT_IN_NAMES into per-language provider fields (#523) 2026-03-26 12:15:29 +00:00
parse-diff-hunks.test.ts fix: map diff hunks to symbol line ranges in detect_changes (#779) 2026-04-11 11:29:52 +01:00
parser-loader.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
pipeline-exports.test.ts test: add test suite with vitest (unit + integration + fixtures) 2026-03-01 20:07:02 +05:30
process-processor.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
receiver-extraction.test.ts Fix HTTP client vs Express route detection and Spring interface attribution (#780) 2026-04-11 11:24:47 +01:00
repo-manager.test.ts feat: configure eslint with unused import removal (#564) 2026-03-28 15:28:09 +00:00
resources.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
route-tool-detection.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
run-analyze.test.ts feat: unify web and cli ingestion pipeline (#536) 2026-03-28 14:07:11 +00:00
schema.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
security.test.ts feat: METHOD_IMPLEMENTS edges, overload disambiguation, MethodExtractor unification (#574) (#642) 2026-04-04 18:41:47 +01:00
sequential-language-availability.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
server.test.ts feat: configure eslint with unused import removal (#564) 2026-03-28 15:28:09 +00:00
setup-codex.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
setup.test.ts fix(setup): prefer global gitnexus binary over npx for MCP config (#653) 2026-04-06 07:46:10 +01:00
shape-check.test.ts fix: shape_check false positives — quoted keys, DOM leaks, errorKeys (#501) 2026-03-26 05:43:37 +00:00
shared-type-extractors.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
skill-gen.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
skip-git-cli.test.ts feat: added skip-agents-md cli flag (#517) 2026-03-28 21:23:59 +00:00
staleness.test.ts feat(group): add group infrastructure and contract matching 2026-04-02 00:39:43 +03:00
stdout-silence.test.ts fix(mcp): unify stdout silencing to prevent embedder/pool-adapter conflicts (#645) 2026-04-04 11:56:49 +01:00
structure-processor.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
suffix-index-ambiguity.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
symbol-resolver.test.ts feat(SM-18): Delete lookupFuzzy, lookupFuzzyCallable, globalIndex, callableIndex (#769) 2026-04-10 14:56:24 +01:00
symbol-table.test.ts SM-19: Delete resolveCallTarget — replace with thin dispatcher (#770) 2026-04-11 10:20:57 +01:00
tools.test.ts feat(group): add sync pipeline, CLI, MCP tools, and monorepo fixture 2026-04-02 00:40:31 +03:00
topological-sort.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
tree-sitter-queries.test.ts Java method reference (#622) 2026-04-02 15:16:35 +01:00
type-env.test.ts feat(SM-18): Delete lookupFuzzy, lookupFuzzyCallable, globalIndex, callableIndex (#769) 2026-04-10 14:56:24 +01:00
utils.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
vue-sfc-extractor.test.ts feat(vue): Vue SFC support + destructured call result tracking (#604) 2026-04-03 14:18:55 +05:30
wiki-flags.test.ts feat: configure prettier with pre-commit hook (#563) 2026-03-28 14:58:04 +00:00
wiki-llm-client.test.ts fix(wiki): Azure OpenAI compat and HTML viewer script injection (#618) 2026-04-01 21:30:43 +05:30