gitnexus 1.6.4-rc.18 → 1.6.4-rc.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,6 +14,8 @@ const DEFAULT_MATCHING = {
14
14
  bm25_threshold: 0.7,
15
15
  embedding_threshold: 0.65,
16
16
  max_candidates_per_step: 3,
17
+ exclude_links_paths: [],
18
+ exclude_links_param_only_paths: false,
17
19
  };
18
20
  export function parseGroupConfig(yamlContent) {
19
21
  const raw = yaml.load(yamlContent, { schema: yaml.JSON_SCHEMA });
@@ -1,4 +1,4 @@
1
- import type { StoredContract, CrossLink } from './types.js';
1
+ import type { StoredContract, CrossLink, MatchingConfig } from './types.js';
2
2
  export interface MatchResult {
3
3
  matched: CrossLink[];
4
4
  unmatched: StoredContract[];
@@ -8,6 +8,6 @@ export interface WildcardMatchResult {
8
8
  remaining: StoredContract[];
9
9
  }
10
10
  export declare function normalizeContractId(id: string): string;
11
- export declare function buildProviderIndex(contracts: StoredContract[]): Map<string, StoredContract[]>;
12
- export declare function runExactMatch(contracts: StoredContract[], providerIndex?: Map<string, StoredContract[]>): MatchResult;
11
+ export declare function buildProviderIndex(contracts: StoredContract[], matchingConfig?: MatchingConfig): Map<string, StoredContract[]>;
12
+ export declare function runExactMatch(contracts: StoredContract[], providerIndex?: Map<string, StoredContract[]>, matchingConfig?: MatchingConfig): MatchResult;
13
13
  export declare function runWildcardMatch(unmatched: StoredContract[], providerIndex: Map<string, StoredContract[]>): WildcardMatchResult;
@@ -1,6 +1,43 @@
1
1
  function isGrpcWildcard(cid) {
2
2
  return cid.startsWith('grpc::') && cid.endsWith('/*');
3
3
  }
4
+ /**
5
+ * Detect HTTP contracts that are too generic or infrastructure-level to
6
+ * produce meaningful cross-repo links. These are still extracted (useful
7
+ * for documentation / route maps) but excluded from cross-link matching.
8
+ *
9
+ * Two categories:
10
+ * 1. Health-check / readiness endpoints — every service has one, matching
11
+ * them produces N×M false links.
12
+ * 2. Param-only paths — routes like `/{param}` or `/{param}/{param}` that
13
+ * collapse to a single catch-all after normalization. These match any
14
+ * service with a similar shape, producing false positives.
15
+ *
16
+ * Both are configurable via matching.exclude_links_paths and
17
+ * matching.exclude_links_param_only_paths in group.yaml.
18
+ */
19
+ function buildNoisyContractFilter(matchingConfig) {
20
+ const excludePaths = matchingConfig?.exclude_links_paths?.length
21
+ ? new Set(matchingConfig.exclude_links_paths.map((p) => p.replace(/\/+$/, '')))
22
+ : new Set();
23
+ const excludeParamOnly = matchingConfig?.exclude_links_param_only_paths === true;
24
+ return function isNoisyHttpContract(contractId) {
25
+ if (!contractId.startsWith('http::'))
26
+ return false;
27
+ const parts = contractId.split('::');
28
+ if (parts.length < 3)
29
+ return false;
30
+ const pathPart = parts.slice(2).join('::').replace(/\/+$/, '');
31
+ if (excludePaths.has(pathPart))
32
+ return true;
33
+ if (excludeParamOnly) {
34
+ const segments = pathPart.split('/').filter(Boolean);
35
+ if (segments.length > 0 && segments.every((s) => s === '{param}'))
36
+ return true;
37
+ }
38
+ return false;
39
+ };
40
+ }
4
41
  export function normalizeContractId(id) {
5
42
  const colonIdx = id.indexOf('::');
6
43
  if (colonIdx === -1)
@@ -74,8 +111,9 @@ function findMatchingKeys(contractId, index) {
74
111
  }
75
112
  return [];
76
113
  }
77
- export function buildProviderIndex(contracts) {
78
- const providers = contracts.filter((c) => c.role === 'provider');
114
+ export function buildProviderIndex(contracts, matchingConfig) {
115
+ const isNoisy = buildNoisyContractFilter(matchingConfig);
116
+ const providers = contracts.filter((c) => c.role === 'provider' && !isNoisy(c.contractId));
79
117
  const index = new Map();
80
118
  for (const p of providers) {
81
119
  const key = normalizeContractId(p.contractId);
@@ -85,10 +123,10 @@ export function buildProviderIndex(contracts) {
85
123
  }
86
124
  return index;
87
125
  }
88
- export function runExactMatch(contracts, providerIndex) {
89
- const index = providerIndex ?? buildProviderIndex(contracts);
90
- // Skip gRPC wildcard consumers they go to wildcard pass only
91
- const consumers = contracts.filter((c) => c.role === 'consumer' && !isGrpcWildcard(c.contractId));
126
+ export function runExactMatch(contracts, providerIndex, matchingConfig) {
127
+ const isNoisy = buildNoisyContractFilter(matchingConfig);
128
+ const index = providerIndex ?? buildProviderIndex(contracts, matchingConfig);
129
+ const consumers = contracts.filter((c) => c.role === 'consumer' && !isGrpcWildcard(c.contractId) && !isNoisy(c.contractId));
92
130
  const matched = [];
93
131
  const matchedConsumerIds = new Set();
94
132
  const matchedProviderIds = new Set();
@@ -129,6 +167,8 @@ export function runExactMatch(contracts, providerIndex) {
129
167
  const normalUnmatched = contracts.filter((c) => {
130
168
  if (isGrpcWildcard(c.contractId))
131
169
  return false; // excluded from exact, handled separately
170
+ if (isNoisy(c.contractId))
171
+ return false; // excluded from matching — don't surface as unmatched
132
172
  const id = `${c.repo}::${c.contractId}`;
133
173
  return c.role === 'provider' ? !matchedProviderIds.has(id) : !matchedConsumerIds.has(id);
134
174
  });
@@ -85,6 +85,8 @@ matching:
85
85
  bm25_threshold: 0.7
86
86
  embedding_threshold: 0.65
87
87
  max_candidates_per_step: 3
88
+ # exclude_links_paths: [/ping, /health, /healthcheck]
89
+ # exclude_links_param_only_paths: false
88
90
  `;
89
91
  await fsp.writeFile(path.join(groupDir, 'group.yaml'), template, 'utf-8');
90
92
  return groupDir;
@@ -168,7 +168,7 @@ export async function syncGroup(config, opts) {
168
168
  console.log(` manifest: ${manifestCrossLinks.length} cross-links from ${config.links.length} declared links`);
169
169
  }
170
170
  }
171
- const { matched, unmatched } = runExactMatch(autoContracts);
171
+ const { matched, unmatched } = runExactMatch(autoContracts, undefined, config.matching);
172
172
  // Dedupe cross-links. Manifest contracts participate in runExactMatch, so a
173
173
  // manifest-declared link can also emit a matchType:'exact' CrossLink with the
174
174
  // same endpoints. Prefer the manifest version — it reflects operator intent
@@ -29,6 +29,24 @@ export interface MatchingConfig {
29
29
  bm25_threshold: number;
30
30
  embedding_threshold: number;
31
31
  max_candidates_per_step: number;
32
+ /**
33
+ * HTTP paths to exclude from cross-link matching. Contracts at these paths
34
+ * are still extracted and visible in the registry, but they don't produce
35
+ * cross-repo links. Useful for health-check endpoints (`/ping`, `/health`)
36
+ * that every service exposes and would otherwise create N×M false links.
37
+ * Trailing slashes are normalized before comparison.
38
+ * @default []
39
+ */
40
+ exclude_links_paths?: string[];
41
+ /**
42
+ * When `true`, exclude HTTP routes where every path segment is `{param}`
43
+ * (e.g. `/{param}`, `/{param}/{param}`) from cross-link matching. Mixed
44
+ * routes like `/users/{param}` are not affected. These param-only routes
45
+ * collapse to a single catch-all after normalization and produce false
46
+ * positives across unrelated services.
47
+ * @default false
48
+ */
49
+ exclude_links_param_only_paths?: boolean;
32
50
  }
33
51
  export interface SymbolRef {
34
52
  filePath: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitnexus",
3
- "version": "1.6.4-rc.18",
3
+ "version": "1.6.4-rc.19",
4
4
  "description": "Graph-powered code intelligence for AI agents. Index any codebase, query via MCP or CLI.",
5
5
  "author": "Abhigyan Patwari",
6
6
  "license": "PolyForm-Noncommercial-1.0.0",