gitnexus 1.6.10-rc.45 → 1.6.10-rc.46

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.
@@ -15,7 +15,7 @@ import { runPipelineFromRepo } from './ingestion/pipeline.js';
15
15
  import { resetDegradedParseCounter } from './tree-sitter/safe-parse.js';
16
16
  import { initLbug, loadGraphToLbug, getLbugStats, executeQuery, executeWithReusedStatement, closeLbug, closeLbugBeforeExit, loadCachedEmbeddings, deleteNodesForFiles, deleteAllCommunitiesAndProcesses, deleteAllInterprocTaintPaths, deleteAllCallSummaries, deleteAllInjects, queryImportersBatch, loadFTSExtension, wipeLbugDbFiles, LbugWipeError, DELETE_FILES_CHUNK_SIZE, } from './lbug/lbug-adapter.js';
17
17
  import { escapeCypherString } from './lbug/cypher-escape.js';
18
- import { createSearchFTSIndexes, initialiseSearchFTSStemmer, verifySearchFTSIndexes, } from './search/fts-indexes.js';
18
+ import { buildSearchIndexesOrDegrade, createSearchFTSIndexes, initialiseSearchFTSStemmer, verifySearchFTSIndexes, } from './search/fts-indexes.js';
19
19
  import { cjkSegmentationModeMismatch, getSearchFTSCjkSegmentation, initialiseSearchFTSCjkSegmentation, } from './search/cjk-segmentation.js';
20
20
  import { getExtensionCapabilities, resolveAnalyzeInstallPolicy } from './lbug/extension-loader.js';
21
21
  import { diagnoseExtensionLoad } from './lbug/extension-load-error.js';
@@ -1206,8 +1206,17 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
1206
1206
  const ftsAvailable = await loadFTSExtension(undefined, {
1207
1207
  policy: resolveAnalyzeInstallPolicy(),
1208
1208
  });
1209
+ // Tracks whether search indexes actually ended up usable this run — starts
1210
+ // as ftsAvailable (extension loaded) but flips to false below when the
1211
+ // build/verify step itself fails, so capabilities.fts.status / ftsSkipped
1212
+ // stay honest even though that failure no longer aborts the whole analyze.
1213
+ let ftsReady = ftsAvailable;
1209
1214
  if (ftsAvailable) {
1210
- await createSearchFTSIndexes({
1215
+ // Degrade rather than throw: createSearchFTSIndexes re-tokenizes every
1216
+ // stored row on every run, so a native tokenizer error on a single
1217
+ // pre-existing row (#2544/#2546) must not discard this run's otherwise-
1218
+ // successful graph/embeddings work — only keyword search degrades.
1219
+ const ftsResult = await buildSearchIndexesOrDegrade(executeQuery, {
1211
1220
  onIndexStart: options.verbose
1212
1221
  ? (table, indexName) => log(`FTS: creating ${table}.${indexName}`)
1213
1222
  : undefined,
@@ -1215,12 +1224,15 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
1215
1224
  ? (table, indexName) => log(`FTS: ready ${table}.${indexName}`)
1216
1225
  : undefined,
1217
1226
  });
1218
- const missingIndexNames = await verifySearchFTSIndexes(executeQuery);
1219
- if (missingIndexNames.length > 0) {
1220
- throw new Error(`FTS verification failed - missing indexes after analyze: ${missingIndexNames.join(', ')}. ` +
1221
- 'Check FTS extension availability, then retry `gitnexus analyze --force` for a full rebuild.');
1227
+ if (ftsResult.ok) {
1228
+ progress('fts', 90, 'Search indexes ready');
1229
+ }
1230
+ else {
1231
+ ftsReady = false;
1232
+ log(`FTS index build failed (${ftsResult.error}) — keyword search degraded this run. ` +
1233
+ 'Graph and embeddings analysis completed successfully. Run `gitnexus analyze --repair-fts` to retry.');
1234
+ progress('fts', 90, 'Search indexes skipped (build failed)');
1222
1235
  }
1223
- progress('fts', 90, 'Search indexes ready');
1224
1236
  }
1225
1237
  else {
1226
1238
  // For a missing runtime dependency (#2374) the file is present, so the
@@ -1559,7 +1571,7 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
1559
1571
  // meta.json / `gitnexus doctor` honest about degraded search.
1560
1572
  fts: {
1561
1573
  provider: 'ladybugdb-fts',
1562
- status: ftsAvailable ? runtimeCapabilities.fts : 'unavailable',
1574
+ status: ftsReady ? runtimeCapabilities.fts : 'unavailable',
1563
1575
  },
1564
1576
  vectorSearch: {
1565
1577
  provider: effectiveSemanticMode === 'vector-index' ? 'ladybugdb-vector' : 'exact-scan',
@@ -1723,7 +1735,7 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
1723
1735
  repoPath,
1724
1736
  stats: meta.stats,
1725
1737
  pipelineResult,
1726
- ftsSkipped: !ftsAvailable,
1738
+ ftsSkipped: !ftsReady,
1727
1739
  isPrimaryBranch: !placement.branch,
1728
1740
  };
1729
1741
  }
@@ -26,3 +26,18 @@ export declare function initialiseSearchFTSStemmer(): string;
26
26
  export declare function getSearchFTSStemmer(): string;
27
27
  export declare function createSearchFTSIndexes(options?: CreateSearchFTSIndexesOptions): Promise<void>;
28
28
  export declare function verifySearchFTSIndexes(executeQuery: (cypher: string) => Promise<unknown[]>): Promise<string[]>;
29
+ export interface BuildSearchIndexesResult {
30
+ ok: boolean;
31
+ error?: string;
32
+ }
33
+ /**
34
+ * Build + verify FTS indexes, catching any failure instead of letting it
35
+ * propagate. `createSearchFTSIndexes` re-tokenizes every stored row on every
36
+ * analyze run (see the `ponytail:` comment above) — a native LadybugDB
37
+ * tokenizer error on a single pre-existing row (e.g. a "Failed calling
38
+ * LOWER: Invalid UTF-8", #2544/#2546) must not discard an otherwise-
39
+ * successful analyze's graph/embeddings work. The caller degrades keyword
40
+ * search for this run instead, mirroring the existing FTS-extension-
41
+ * unavailable degrade path in `run-analyze.ts`.
42
+ */
43
+ export declare function buildSearchIndexesOrDegrade(executeQuery: (cypher: string) => Promise<unknown[]>, options?: CreateSearchFTSIndexesOptions): Promise<BuildSearchIndexesResult>;
@@ -152,3 +152,26 @@ export async function verifySearchFTSIndexes(executeQuery) {
152
152
  }
153
153
  return missing;
154
154
  }
155
+ /**
156
+ * Build + verify FTS indexes, catching any failure instead of letting it
157
+ * propagate. `createSearchFTSIndexes` re-tokenizes every stored row on every
158
+ * analyze run (see the `ponytail:` comment above) — a native LadybugDB
159
+ * tokenizer error on a single pre-existing row (e.g. a "Failed calling
160
+ * LOWER: Invalid UTF-8", #2544/#2546) must not discard an otherwise-
161
+ * successful analyze's graph/embeddings work. The caller degrades keyword
162
+ * search for this run instead, mirroring the existing FTS-extension-
163
+ * unavailable degrade path in `run-analyze.ts`.
164
+ */
165
+ export async function buildSearchIndexesOrDegrade(executeQuery, options) {
166
+ try {
167
+ await createSearchFTSIndexes(options);
168
+ const missing = await verifySearchFTSIndexes(executeQuery);
169
+ if (missing.length > 0) {
170
+ return { ok: false, error: `missing indexes after build: ${missing.join(', ')}` };
171
+ }
172
+ return { ok: true };
173
+ }
174
+ catch (e) {
175
+ return { ok: false, error: e instanceof Error ? e.message : String(e) };
176
+ }
177
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitnexus",
3
- "version": "1.6.10-rc.45",
3
+ "version": "1.6.10-rc.46",
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",