fix(analyze): make FTS index creation non-fatal during analyze

When the LadybugDB FTS extension cannot be loaded (e.g. macOS 12 where
libc++ lacks std::to_chars(double), or container environments without
the native extension), `gitnexus analyze --embeddings` fails at 85%
and aborts before embedding generation can run.

This is inconsistent with the MCP server's behavior: pool-adapter.ts
already treats FTS load failure as a graceful degradation (ftsLoaded =
false, BM25 search degrades, other features continue).

Change: wrap createSearchFTSIndexes() in try/catch so that:
- FTS creation failure logs a warning instead of throwing
- Embedding generation (Phase 4) proceeds normally
- `--repair-fts` remains available for explicit FTS retry
- BM25 keyword search degrades gracefully (same as MCP read path)

Affected users: macOS 12 (Monterey), any platform where the FTS
extension binary references symbols missing from the system libc++.
This commit is contained in:
henry 2026-05-22 16:57:49 +08:00
parent ccf0b8b73c
commit 689f79acc1

View file

@ -669,22 +669,29 @@ export async function runFullAnalysis(
// ── Phase 3: FTS (85–90%) ─────────────────────────────────────────
progress('fts', 85, 'Creating search indexes...');
await createSearchFTSIndexes({
onIndexStart: options.verbose
? (table, indexName) => log(`FTS: creating ${table}.${indexName}`)
: undefined,
onIndexReady: options.verbose
? (table, indexName) => log(`FTS: ready ${table}.${indexName}`)
: undefined,
});
const missingIndexNames = await verifySearchFTSIndexes(executeQuery);
if (missingIndexNames.length > 0) {
throw new Error(
`FTS verification failed - missing indexes after analyze: ${missingIndexNames.join(', ')}. ` +
'Check FTS extension availability, then retry `gitnexus analyze --force` for a full rebuild.',
);
try {
await createSearchFTSIndexes({
onIndexStart: options.verbose
? (table, indexName) => log(`FTS: creating ${table}.${indexName}`)
: undefined,
onIndexReady: options.verbose
? (table, indexName) => log(`FTS: ready ${table}.${indexName}`)
: undefined,
});
const missingIndexNames = await verifySearchFTSIndexes(executeQuery);
if (missingIndexNames.length > 0) {
log(
`⚠️ FTS verification warning - missing indexes: ${missingIndexNames.join(', ')}. ` +
'BM25 keyword search will be degraded. Upgrade macOS or run on a compatible platform to enable FTS.',
);
} else {
progress('fts', 90, 'Search indexes ready');
}
} catch (ftsErr: unknown) {
const ftsMsg = ftsErr instanceof Error ? ftsErr.message : String(ftsErr);
log(`⚠️ FTS creation skipped (non-fatal): ${ftsMsg}`);
progress('fts', 90, 'Search indexes skipped (FTS unavailable)');
}
progress('fts', 90, 'Search indexes ready');
// ── Phase 3.5: Re-insert cached embeddings ────────────────────────
// Runs on BOTH the full-rebuild path and the incremental path: