kirograph 0.28.1 → 1.0.0
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.
- package/dist/architecture/index.js +4 -1
- package/dist/architecture/index.js.map +2 -2
- package/dist/architecture/manifest/index.js +13 -2
- package/dist/architecture/manifest/index.js.map +2 -2
- package/dist/bin/commands/install.js +2 -1
- package/dist/bin/commands/install.js.map +2 -2
- package/dist/bin/commands/status.js +2 -1
- package/dist/bin/commands/status.js.map +2 -2
- package/dist/bin/commands/uninit.js +2 -1
- package/dist/bin/commands/uninit.js.map +2 -2
- package/dist/bin/commands/vulns.js +10 -5
- package/dist/bin/commands/vulns.js.map +2 -2
- package/dist/bin/installer/common.js +7 -1
- package/dist/bin/installer/common.js.map +2 -2
- package/dist/bin/installer/detect.js +10 -0
- package/dist/bin/installer/detect.js.map +2 -2
- package/dist/bin/installer/hooks.js +13 -8
- package/dist/bin/installer/hooks.js.map +2 -2
- package/dist/bin/installer/targets/antigravity.js +1 -1
- package/dist/bin/installer/targets/antigravity.js.map +2 -2
- package/dist/bin/installer/targets/claude.js +1 -1
- package/dist/bin/installer/targets/claude.js.map +2 -2
- package/dist/bin/installer/targets/codex.js +1 -1
- package/dist/bin/installer/targets/codex.js.map +2 -2
- package/dist/bin/installer/targets/commandcode.js +84 -0
- package/dist/bin/installer/targets/commandcode.js.map +7 -0
- package/dist/bin/installer/targets/copilot.js +1 -1
- package/dist/bin/installer/targets/copilot.js.map +2 -2
- package/dist/bin/installer/targets/cursor.js +2 -2
- package/dist/bin/installer/targets/cursor.js.map +2 -2
- package/dist/bin/installer/targets/devin.js +1 -1
- package/dist/bin/installer/targets/devin.js.map +2 -2
- package/dist/bin/installer/targets/gemini-cli.js +1 -1
- package/dist/bin/installer/targets/gemini-cli.js.map +2 -2
- package/dist/bin/installer/targets/index.js +10 -0
- package/dist/bin/installer/targets/index.js.map +2 -2
- package/dist/bin/installer/targets/opencode.js +1 -1
- package/dist/bin/installer/targets/opencode.js.map +2 -2
- package/dist/bin/installer/targets/windsurf.js +1 -1
- package/dist/bin/installer/targets/windsurf.js.map +2 -2
- package/dist/bin/kirograph.js +1 -1
- package/dist/bin/kirograph.js.map +1 -1
- package/dist/config.js +21 -1
- package/dist/config.js.map +2 -2
- package/dist/core/pipeline.js +18 -6
- package/dist/core/pipeline.js.map +2 -2
- package/dist/extraction/extractor.js +58 -1
- package/dist/extraction/extractor.js.map +2 -2
- package/dist/extraction/grammars.js +38 -3
- package/dist/extraction/grammars.js.map +2 -2
- package/dist/extraction/wasm/tree-sitter-bash.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-c.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-cpp.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-csharp.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-css.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-dart.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-elisp.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-elixir.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-elm.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-embedded_template.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-embeddedtemplate.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-go.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-html.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-java.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-javascript.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-json.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-kotlin.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-lua.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-objc.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-ocaml.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-php.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-python.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-ql.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-rescript.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-ruby.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-rust.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-solidity.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-swift.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-systemrdl.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-tlaplus.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-toml.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-tsx.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-typescript.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-vue.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-yaml.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-zig.wasm +0 -0
- package/dist/frameworks/index.js +68 -7
- package/dist/frameworks/index.js.map +2 -2
- package/dist/security/manifest/adapter.js +17 -2
- package/dist/security/manifest/adapter.js.map +2 -2
- package/dist/security/manifest/parser.js +2 -2
- package/dist/security/manifest/parser.js.map +2 -2
- package/dist/security/pipeline.js +4 -1
- package/dist/security/pipeline.js.map +2 -2
- package/dist/security/reachability.js +61 -45
- package/dist/security/reachability.js.map +3 -3
- package/dist/security/types.js.map +1 -1
- package/dist/security/vuln/epss-client.js +1 -1
- package/dist/security/vuln/epss-client.js.map +1 -1
- package/dist/security/vuln/osv-adapter.js +99 -31
- package/dist/security/vuln/osv-adapter.js.map +2 -2
- package/dist/sync/index.js +9 -2
- package/dist/sync/index.js.map +2 -2
- package/dist/vectors/libsql-index.js +287 -0
- package/dist/vectors/libsql-index.js.map +7 -0
- package/dist/vectors/turso-index.js +307 -0
- package/dist/vectors/turso-index.js.map +7 -0
- package/package.json +3 -2
package/dist/core/pipeline.js
CHANGED
|
@@ -59,6 +59,8 @@ class IndexPipeline {
|
|
|
59
59
|
let nodesCreated = 0;
|
|
60
60
|
let edgesCreated = 0;
|
|
61
61
|
const poisonedLanguages = /* @__PURE__ */ new Set();
|
|
62
|
+
const crashCounts = /* @__PURE__ */ new Map();
|
|
63
|
+
const POISON_THRESHOLD = 3;
|
|
62
64
|
try {
|
|
63
65
|
const files = await (0, import_sync.scanDirectory)(this.projectRoot, this.config, opts?.signal);
|
|
64
66
|
opts?.onProgress?.({ phase: "scanning", current: files.length, total: files.length });
|
|
@@ -85,7 +87,7 @@ class IndexPipeline {
|
|
|
85
87
|
const { detectLanguage } = await Promise.resolve().then(() => require("../extraction/languages.js"));
|
|
86
88
|
const lang = detectLanguage(file);
|
|
87
89
|
if (poisonedLanguages.has(lang)) continue;
|
|
88
|
-
const extracted = await (0, import_extractor.extractFile)(file, this.projectRoot, content, { enableComplexity: !!this.config.enableComplexity });
|
|
90
|
+
const extracted = await (0, import_extractor.extractFile)(file, this.projectRoot, content, { enableComplexity: !!this.config.enableComplexity, maxFileSize: this.config.maxFileSize });
|
|
89
91
|
if (!extracted) continue;
|
|
90
92
|
const oldNodes = this.db.getNodesByFile(extracted.filePath);
|
|
91
93
|
if (oldNodes.length > 0) await this.vectors.deleteEmbeddings(oldNodes.map((n) => n.id));
|
|
@@ -113,6 +115,7 @@ class IndexPipeline {
|
|
|
113
115
|
}
|
|
114
116
|
});
|
|
115
117
|
filesIndexed++;
|
|
118
|
+
crashCounts.set(lang, 0);
|
|
116
119
|
} catch (err) {
|
|
117
120
|
const msg = err instanceof Error ? err.message : String(err);
|
|
118
121
|
errors.push(`${file}: ${msg}`);
|
|
@@ -120,11 +123,14 @@ class IndexPipeline {
|
|
|
120
123
|
if (isWasmCrash) {
|
|
121
124
|
const { detectLanguage } = await Promise.resolve().then(() => require("../extraction/languages.js"));
|
|
122
125
|
const lang = detectLanguage(file);
|
|
123
|
-
|
|
126
|
+
const count = (crashCounts.get(lang) ?? 0) + 1;
|
|
127
|
+
crashCounts.set(lang, count);
|
|
128
|
+
if (count >= POISON_THRESHOLD) {
|
|
129
|
+
poisonedLanguages.add(lang);
|
|
130
|
+
}
|
|
124
131
|
(0, import_grammars.clearParserCache)();
|
|
125
132
|
try {
|
|
126
133
|
await (0, import_grammars.initGrammars)();
|
|
127
|
-
poisonedLanguages.clear();
|
|
128
134
|
} catch {
|
|
129
135
|
errors.push("WASM runtime unrecoverable after crash \u2014 aborting batch");
|
|
130
136
|
break;
|
|
@@ -344,6 +350,8 @@ class IndexPipeline {
|
|
|
344
350
|
result.filesScanned = result.filesScanned || filesToProcess.length;
|
|
345
351
|
onProgress?.({ phase: "scanning", current: result.filesScanned, total: result.filesScanned });
|
|
346
352
|
const poisonedLanguages = /* @__PURE__ */ new Set();
|
|
353
|
+
const crashCounts = /* @__PURE__ */ new Map();
|
|
354
|
+
const POISON_THRESHOLD = 3;
|
|
347
355
|
for (let i = 0; i < filesToProcess.length; i++) {
|
|
348
356
|
const file = filesToProcess[i];
|
|
349
357
|
onProgress?.({ phase: "parsing", current: i + 1, total: filesToProcess.length, currentFile: file });
|
|
@@ -356,7 +364,7 @@ class IndexPipeline {
|
|
|
356
364
|
const { detectLanguage } = await Promise.resolve().then(() => require("../extraction/languages.js"));
|
|
357
365
|
const lang = detectLanguage(file);
|
|
358
366
|
if (poisonedLanguages.has(lang)) continue;
|
|
359
|
-
const extracted = await (0, import_extractor.extractFile)(file, this.projectRoot, void 0, { enableComplexity: !!this.config.enableComplexity });
|
|
367
|
+
const extracted = await (0, import_extractor.extractFile)(file, this.projectRoot, void 0, { enableComplexity: !!this.config.enableComplexity, maxFileSize: this.config.maxFileSize });
|
|
360
368
|
if (!extracted) continue;
|
|
361
369
|
const existing = this.db.getFile(extracted.filePath);
|
|
362
370
|
const isNew = !existing;
|
|
@@ -390,6 +398,7 @@ class IndexPipeline {
|
|
|
390
398
|
}
|
|
391
399
|
});
|
|
392
400
|
this.resolver.invalidateFile(extracted.filePath);
|
|
401
|
+
crashCounts.set(lang, 0);
|
|
393
402
|
if (isNew) result.added.push(extracted.filePath);
|
|
394
403
|
else {
|
|
395
404
|
result.modified.push(extracted.filePath);
|
|
@@ -402,11 +411,14 @@ class IndexPipeline {
|
|
|
402
411
|
if (isWasmCrash) {
|
|
403
412
|
const { detectLanguage } = await Promise.resolve().then(() => require("../extraction/languages.js"));
|
|
404
413
|
const lang = detectLanguage(file);
|
|
405
|
-
|
|
414
|
+
const count = (crashCounts.get(lang) ?? 0) + 1;
|
|
415
|
+
crashCounts.set(lang, count);
|
|
416
|
+
if (count >= POISON_THRESHOLD) {
|
|
417
|
+
poisonedLanguages.add(lang);
|
|
418
|
+
}
|
|
406
419
|
(0, import_grammars.clearParserCache)();
|
|
407
420
|
try {
|
|
408
421
|
await (0, import_grammars.initGrammars)();
|
|
409
|
-
poisonedLanguages.clear();
|
|
410
422
|
} catch {
|
|
411
423
|
result.errors.push("WASM runtime unrecoverable after crash \u2014 aborting sync");
|
|
412
424
|
break;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/core/pipeline.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * IndexPipeline \u2014 full-index and incremental-sync pipelines.\n *\n * Owns the two heavy workflows:\n * - indexAll(): scan all files, extract, store, resolve, detect frameworks,\n * generate embeddings, analyze architecture.\n * - sync(): detect changed files via git (or full scan fallback),\n * re-extract only what changed, then run the same tail pipeline.\n *\n * Everything that touches the filesystem or sub-systems is injected via the\n * constructor, keeping this class testable and free of global state.\n */\n\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { GraphDatabase } from '../db/database';\nimport { scanDirectory, hashContent, getChangedFiles, shouldIncludeFile } from '../sync/index';\nimport { extractFile } from '../extraction/extractor';\nimport { clearParserCache, initGrammars, hasWasmGrammar } from '../extraction/grammars';\nimport { detectFrameworks } from '../frameworks/index';\nimport { ReferenceResolver } from '../resolution/index';\nimport { VectorManager } from '../vectors/index';\nimport { ArchitectureAnalyzer } from '../architecture/index';\nimport type { KiroGraphConfig } from '../config';\nimport type { IndexResult, IndexProgress, SyncResult } from '../types';\nimport { LockManager } from './lock-manager';\nimport { Mutex } from '../utils';\n\nconst FILE_IO_BATCH_SIZE = 10;\n\nexport class IndexPipeline {\n private readonly mutex = new Mutex();\n\n constructor(\n private readonly db: GraphDatabase,\n private readonly vectors: VectorManager,\n private readonly resolver: ReferenceResolver,\n private readonly arch: ArchitectureAnalyzer,\n private readonly lock: LockManager,\n private readonly config: KiroGraphConfig,\n private readonly projectRoot: string,\n ) {}\n\n async indexAll(opts?: {\n onProgress?: (p: IndexProgress) => void;\n force?: boolean;\n signal?: AbortSignal;\n }): Promise<IndexResult> {\n const release = await this.mutex.acquire();\n this.lock.acquire();\n const start = Date.now();\n const errors: string[] = [];\n let filesIndexed = 0;\n let nodesCreated = 0;\n let edgesCreated = 0;\n\n // Track languages whose WASM parser is currently poisoned (ABORT=true on the module).\n // Once a language's parser aborts, every subsequent parse call for that language\n // fails instantly. We skip those files until clearParserCache + initGrammars succeeds.\n const poisonedLanguages = new Set<string>();\n\n try {\n const files = await scanDirectory(this.projectRoot, this.config, opts?.signal);\n opts?.onProgress?.({ phase: 'scanning', current: files.length, total: files.length });\n\n // Batch-read files in parallel\n const contentMap = new Map<string, Buffer>();\n for (let b = 0; b < files.length; b += FILE_IO_BATCH_SIZE) {\n const batch = files.slice(b, b + FILE_IO_BATCH_SIZE);\n const results = await Promise.all(batch.map(f => fs.promises.readFile(f).catch(() => null)));\n for (let i = 0; i < batch.length; i++) {\n if (results[i]) contentMap.set(batch[i], results[i]!);\n }\n }\n\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n opts?.onProgress?.({ phase: 'parsing', current: i + 1, total: files.length, currentFile: file });\n\n try {\n const content = contentMap.get(file);\n if (!content) continue;\n if (content.length > this.config.maxFileSize) continue;\n\n const relPath = path.relative(this.projectRoot, file).replace(/\\\\/g, '/');\n\n if (!opts?.force) {\n const existing = this.db.getFile(relPath);\n if (existing && hashContent(content) === existing.contentHash) continue;\n }\n\n // Skip files whose language parser is currently poisoned\n const { detectLanguage } = await Promise.resolve().then(() => require('../extraction/languages.js'));\n const lang = detectLanguage(file);\n if (poisonedLanguages.has(lang)) continue;\n\n const extracted = await extractFile(file, this.projectRoot, content, { enableComplexity: !!(this.config as any).enableComplexity });\n if (!extracted) continue;\n\n const oldNodes = this.db.getNodesByFile(extracted.filePath);\n if (oldNodes.length > 0) await this.vectors.deleteEmbeddings(oldNodes.map(n => n.id));\n\n this.db.transaction(() => {\n this.db.deleteNodesByFile(extracted.filePath);\n this.db.deleteUnresolvedRefsByFile(extracted.filePath);\n this.db.upsertFile({\n path: extracted.filePath,\n contentHash: extracted.contentHash,\n language: extracted.language,\n fileSize: extracted.fileSize,\n symbolCount: extracted.nodes.length,\n indexedAt: Date.now(),\n });\n for (const node of extracted.nodes) { this.db.upsertNode(node); nodesCreated++; }\n for (const edge of extracted.edges) { this.db.insertEdge(edge); edgesCreated++; }\n for (const ref of extracted.unresolvedRefs) {\n this.db.insertUnresolvedRef(ref.sourceId, ref.refName, ref.refKind, extracted.filePath, ref.line, ref.column);\n }\n });\n\n filesIndexed++;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n errors.push(`${file}: ${msg}`);\n\n // Detect WASM runtime abort and attempt recovery\n const isWasmCrash = (err as any)?.constructor?.name === 'RuntimeError'\n || msg.includes('Aborted(') \n || msg.includes('RuntimeError')\n || msg.includes('WASM grammar exists but failed to load');\n if (isWasmCrash) {\n // Mark the language as poisoned so we skip remaining files of this language\n const { detectLanguage } = await Promise.resolve().then(() => require('../extraction/languages.js'));\n const lang = detectLanguage(file);\n poisonedLanguages.add(lang);\n\n clearParserCache();\n try {\n await initGrammars();\n // Recovery succeeded \u2014 un-poison all languages\n poisonedLanguages.clear();\n } catch {\n errors.push('WASM runtime unrecoverable after crash \u2014 aborting batch');\n break;\n }\n }\n }\n }\n\n // Re-process files that have symbolCount=0 but should have symbols (WASM recovery)\n const emptyFiles = this.db.getAllFiles().filter(\n (f: any) => f.symbolCount === 0 && hasWasmGrammar(f.language)\n );\n if (emptyFiles.length > 0) {\n opts?.onProgress?.({ phase: 'retrying', current: 0, total: emptyFiles.length });\n for (let i = 0; i < emptyFiles.length; i++) {\n const ef = emptyFiles[i];\n const absPath = path.join(this.projectRoot, ef.path);\n opts?.onProgress?.({ phase: 'retrying', current: i + 1, total: emptyFiles.length, currentFile: absPath });\n try {\n const extracted = await extractFile(absPath, this.projectRoot, undefined, { enableComplexity: !!(this.config as any).enableComplexity });\n if (!extracted || extracted.nodes.length === 0) continue;\n\n const oldNodes = this.db.getNodesByFile(extracted.filePath);\n if (oldNodes.length > 0) await this.vectors.deleteEmbeddings(oldNodes.map(n => n.id));\n\n this.db.transaction(() => {\n this.db.deleteNodesByFile(extracted.filePath);\n this.db.deleteUnresolvedRefsByFile(extracted.filePath);\n this.db.upsertFile({\n path: extracted.filePath,\n contentHash: extracted.contentHash,\n language: extracted.language,\n fileSize: extracted.fileSize,\n symbolCount: extracted.nodes.length,\n indexedAt: Date.now(),\n });\n for (const node of extracted.nodes) { this.db.upsertNode(node); nodesCreated++; }\n for (const edge of extracted.edges) { this.db.insertEdge(edge); edgesCreated++; }\n for (const ref of extracted.unresolvedRefs) {\n this.db.insertUnresolvedRef(ref.sourceId, ref.refName, ref.refKind, extracted.filePath, ref.line, ref.column);\n }\n });\n filesIndexed++;\n } catch {\n // Already logged in first pass or genuinely broken \u2014 skip\n }\n }\n }\n\n // Resolve cross-file references\n opts?.onProgress?.({ phase: 'resolving', current: 0, total: 1 });\n await this.resolver.resolveAll((current, total) => {\n opts?.onProgress?.({ phase: 'resolving', current, total });\n });\n\n // Detect frameworks\n opts?.onProgress?.({ phase: 'detecting frameworks', current: 0, total: 1 });\n const detectedFrameworks = await detectFrameworks(this.projectRoot, this.db);\n const languages = [...new Set(this.db.getAllFiles().map(f => (f as any).language).filter(Boolean))];\n opts?.onProgress?.({\n phase: 'detecting frameworks', current: 1, total: 1,\n meta: { frameworks: detectedFrameworks.map(f => f.name), languages },\n });\n\n // Generate embeddings (if enabled)\n if (this.vectors.isInitialized()) {\n opts?.onProgress?.({ phase: 'embeddings', current: 0, total: 1 });\n await this.vectors.embedAll((current, total) =>\n opts?.onProgress?.({ phase: 'embeddings', current, total })\n );\n }\n\n // Analyze architecture (if enabled, or auto-enabled for security)\n if (this.config.enableArchitecture || this.config.enableSecurity) {\n if (this.config.enableSecurity && !this.config.enableArchitecture) {\n const { logWarn } = await Promise.resolve().then(() => require('../errors.js'));\n logWarn('enableSecurity requires enableArchitecture \u2014 auto-enabling architecture analysis for this run');\n }\n opts?.onProgress?.({ phase: 'architecture', current: 0, total: 1 });\n await this.arch.analyze(msg =>\n opts?.onProgress?.({ phase: 'architecture', current: 0, total: 1, meta: { msg } })\n );\n opts?.onProgress?.({ phase: 'architecture', current: 1, total: 1 });\n }\n\n // Run security analysis (if enabled)\n if (this.config.enableSecurity) {\n try {\n const { SecurityPipeline } = await Promise.resolve().then(() => require('../security/pipeline.js'));\n this.db.applySecuritySchema();\n const secPipeline = new SecurityPipeline(this.db, this.config, this.projectRoot);\n opts?.onProgress?.({ phase: 'security', current: 0, total: 1 });\n await secPipeline.run((phase, current, total) =>\n opts?.onProgress?.({ phase: 'security', current, total, meta: { secPhase: phase } })\n );\n opts?.onProgress?.({ phase: 'security', current: 1, total: 1 });\n } catch { /* security analysis is non-critical */ }\n }\n\n // Index documentation (if enabled)\n if (this.config.enableDocs) {\n try {\n const { DocsIndexer } = await Promise.resolve().then(() => require('../docs/indexer.js'));\n this.db.applyDocsSchema();\n const docsIndexer = new DocsIndexer(this.db.getRawDb(), this.config, this.projectRoot);\n await docsIndexer.indexAll({\n force: opts?.force,\n onProgress: msg => opts?.onProgress?.({ phase: 'docs', current: 0, total: 1, meta: { msg } }),\n });\n } catch { /* docs indexing is non-critical */ }\n }\n\n // Index data files (if enabled)\n if ((this.config as any).enableData) {\n try {\n const { DataIndexer } = await Promise.resolve().then(() => require('../data/indexer.js'));\n this.db.applyDataSchema();\n const dataIndexer = new DataIndexer(this.db.getRawDb(), this.config, this.projectRoot);\n await dataIndexer.indexAll({\n onProgress: msg => opts?.onProgress?.({ phase: 'data', current: 0, total: 1, meta: { msg } }),\n });\n\n // Assign data files to 'data' architecture layer if architecture is enabled\n if (this.config.enableArchitecture) {\n try {\n const rawDb = this.db.getRawDb();\n // Check if arch_file_layers table exists\n const tableExists = rawDb.get(\"SELECT name FROM sqlite_master WHERE type='table' AND name='arch_file_layers'\");\n if (tableExists) {\n const datasets = rawDb.all('SELECT file_path FROM data_datasets') as Array<{ file_path: string }>;\n for (const ds of datasets) {\n rawDb.run(\n `INSERT OR REPLACE INTO arch_file_layers (file_path, layer_id, confidence) VALUES (?, ?, ?)`,\n [ds.file_path, 'layer:data', 1.0],\n );\n }\n }\n } catch { /* non-critical */ }\n }\n } catch { /* data indexing is non-critical */ }\n }\n\n // Index pattern matches (if enabled)\n if ((this.config as any).enablePatterns) {\n try {\n this.db.applyPatternsSchema();\n const { PatternIndexer } = await Promise.resolve().then(() => require('../patterns/indexer.js'));\n const indexer = new PatternIndexer(this.db.getRawDb(), this.config, this.projectRoot);\n await indexer.indexAll((phase, current, total) => {\n opts?.onProgress?.({ phase: 'patterns' as any, current, total });\n });\n } catch (err) {\n // Patterns are non-critical \u2014 log and continue\n const { logWarn } = await Promise.resolve().then(() => require('../errors.js'));\n const msg = err instanceof Error ? err.message : String(err);\n logWarn(`[patterns] Pattern indexing failed (non-critical): ${msg}`);\n }\n }\n\n this.lock.clearDirty();\n return { success: errors.length === 0, filesIndexed, nodesCreated, edgesCreated, errors, duration: Date.now() - start };\n } finally {\n this.lock.release();\n release();\n }\n }\n\n async sync(opts?: {\n changedFiles?: string[];\n onProgress?: (p: IndexProgress) => void;\n }): Promise<SyncResult> {\n const release = await this.mutex.acquire();\n this.lock.acquire();\n const start = Date.now();\n const changedFiles = opts?.changedFiles;\n const onProgress = opts?.onProgress;\n const result: SyncResult = {\n added: [], modified: [], removed: [],\n nodesCreated: 0, nodesUpdated: 0, nodesRemoved: 0,\n edgesCreated: 0, edgesRemoved: 0,\n filesScanned: 0, errors: [], duration: 0,\n };\n\n try {\n const removeFile = async (rel: string) => {\n const oldNodes = this.db.getNodesByFile(rel);\n const oldEdgeCount = this.db.getEdgesForNodes(oldNodes.map(n => n.id)).length;\n result.nodesRemoved += oldNodes.length;\n result.edgesRemoved += oldEdgeCount;\n await this.vectors.deleteEmbeddings(oldNodes.map(n => n.id));\n this.db.deleteFile(rel);\n this.db.deleteUnresolvedRefsByFile(rel);\n // Clean up pattern matches for removed files (only if patterns are enabled)\n if ((this.config as any).enablePatterns) {\n this.db.getRawDb().run('DELETE FROM pattern_matches WHERE file_path = ?', [rel]);\n }\n result.removed.push(rel);\n };\n\n // \u2500\u2500 Exclude-rule cleanup \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Remove any indexed files that now match the current exclude patterns.\n // This handles the case where a user adds a new exclude pattern (e.g.\n // \"**/.vite/**\") and expects those files to disappear from the index on\n // the next sync without needing a full --force re-index.\n const allIndexed = this.db.getAllFiles();\n for (const f of allIndexed) {\n if (!shouldIncludeFile(f.path, this.config)) {\n onProgress?.({ phase: 'scanning', current: 0, total: 0, meta: { excludeCleanup: true, file: f.path } });\n await removeFile(f.path);\n }\n }\n\n let filesToProcess: string[];\n\n onProgress?.({ phase: 'scanning', current: 0, total: 0 });\n\n if (changedFiles) {\n filesToProcess = changedFiles.map(f => path.resolve(this.projectRoot, f));\n } else {\n const gitChanged = await getChangedFiles(this.projectRoot, this.config);\n const hasChanges = gitChanged.added.length > 0 || gitChanged.modified.length > 0 || gitChanged.removed.length > 0;\n\n if (hasChanges) {\n for (const p of gitChanged.removed) {\n await removeFile(path.relative(this.projectRoot, p).replace(/\\\\/g, '/'));\n }\n filesToProcess = [...gitChanged.added, ...gitChanged.modified];\n } else {\n // Fallback: full scan + detect removed files\n const indexed = new Set(this.db.getAllFiles().map(f => f.path));\n const current = new Set(\n (await scanDirectory(this.projectRoot, this.config))\n .map(f => path.relative(this.projectRoot, f).replace(/\\\\/g, '/'))\n );\n result.filesScanned = current.size;\n for (const p of indexed) {\n if (!current.has(p)) await removeFile(p);\n }\n filesToProcess = await scanDirectory(this.projectRoot, this.config);\n }\n }\n\n result.filesScanned = result.filesScanned || filesToProcess.length;\n onProgress?.({ phase: 'scanning', current: result.filesScanned, total: result.filesScanned });\n\n const poisonedLanguages = new Set<string>();\n\n for (let i = 0; i < filesToProcess.length; i++) {\n const file = filesToProcess[i];\n onProgress?.({ phase: 'parsing', current: i + 1, total: filesToProcess.length, currentFile: file });\n\n if (!fs.existsSync(file)) {\n const rel = path.relative(this.projectRoot, file).replace(/\\\\/g, '/');\n await removeFile(rel);\n continue;\n }\n\n try {\n // Skip files whose language parser is currently poisoned\n const { detectLanguage } = await Promise.resolve().then(() => require('../extraction/languages.js'));\n const lang = detectLanguage(file);\n if (poisonedLanguages.has(lang)) continue;\n\n const extracted = await extractFile(file, this.projectRoot, undefined, { enableComplexity: !!(this.config as any).enableComplexity });\n if (!extracted) continue;\n\n const existing = this.db.getFile(extracted.filePath);\n const isNew = !existing;\n if (!isNew && existing!.contentHash === extracted.contentHash) continue;\n\n const oldNodes = this.db.getNodesByFile(extracted.filePath);\n const oldEdgeCount = this.db.getEdgesForNodes(oldNodes.map(n => n.id)).length;\n await this.vectors.deleteEmbeddings(oldNodes.map(n => n.id));\n\n this.db.transaction(() => {\n result.nodesRemoved += oldNodes.length;\n result.edgesRemoved += oldEdgeCount;\n this.db.deleteNodesByFile(extracted.filePath);\n this.db.deleteUnresolvedRefsByFile(extracted.filePath);\n this.db.upsertFile({\n path: extracted.filePath,\n contentHash: extracted.contentHash,\n language: extracted.language,\n fileSize: extracted.fileSize,\n symbolCount: extracted.nodes.length,\n indexedAt: Date.now(),\n });\n for (const node of extracted.nodes) { this.db.upsertNode(node); result.nodesCreated++; }\n for (const edge of extracted.edges) { this.db.insertEdge(edge); result.edgesCreated++; }\n for (const ref of extracted.unresolvedRefs) {\n this.db.insertUnresolvedRef(ref.sourceId, ref.refName, ref.refKind, extracted.filePath, ref.line, ref.column);\n }\n });\n\n this.resolver.invalidateFile(extracted.filePath);\n if (isNew) result.added.push(extracted.filePath);\n else { result.modified.push(extracted.filePath); result.nodesUpdated += extracted.nodes.length; }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n result.errors.push(`${file}: ${msg}`);\n\n // Detect WASM runtime abort and attempt recovery\n const isWasmCrash = (err as any)?.constructor?.name === 'RuntimeError'\n || msg.includes('Aborted(') \n || msg.includes('RuntimeError')\n || msg.includes('WASM grammar exists but failed to load');\n if (isWasmCrash) {\n const { detectLanguage } = await Promise.resolve().then(() => require('../extraction/languages.js'));\n const lang = detectLanguage(file);\n poisonedLanguages.add(lang);\n\n clearParserCache();\n try {\n await initGrammars();\n poisonedLanguages.clear();\n } catch {\n result.errors.push('WASM runtime unrecoverable after crash \u2014 aborting sync');\n break;\n }\n }\n }\n }\n\n // Resolve cross-file references\n onProgress?.({ phase: 'resolving', current: 0, total: 1 });\n await this.resolver.resolveAll((current, total) => {\n onProgress?.({ phase: 'resolving', current, total });\n });\n\n await detectFrameworks(this.projectRoot);\n\n // Generate embeddings (if enabled)\n if (this.vectors.isInitialized()) {\n onProgress?.({ phase: 'embeddings', current: 0, total: 1 });\n await this.vectors.embedAll((current, total) =>\n onProgress?.({ phase: 'embeddings', current, total })\n );\n }\n\n // Analyze architecture (if enabled, or auto-enabled for security)\n if (this.config.enableArchitecture || this.config.enableSecurity) {\n if (this.config.enableSecurity && !this.config.enableArchitecture) {\n const { logWarn } = await Promise.resolve().then(() => require('../errors.js'));\n logWarn('enableSecurity requires enableArchitecture \u2014 auto-enabling architecture analysis for this run');\n }\n onProgress?.({ phase: 'architecture', current: 0, total: 1 });\n await this.arch.analyze(msg =>\n onProgress?.({ phase: 'architecture', current: 0, total: 1, meta: { msg } })\n );\n onProgress?.({ phase: 'architecture', current: 1, total: 1 });\n }\n\n // Run security analysis (if enabled)\n if (this.config.enableSecurity) {\n try {\n const { SecurityPipeline } = await Promise.resolve().then(() => require('../security/pipeline.js'));\n this.db.applySecuritySchema();\n const secPipeline = new SecurityPipeline(this.db, this.config, this.projectRoot);\n onProgress?.({ phase: 'security', current: 0, total: 1 });\n await secPipeline.run((phase, current, total) =>\n onProgress?.({ phase: 'security', current, total, meta: { secPhase: phase } })\n );\n onProgress?.({ phase: 'security', current: 1, total: 1 });\n } catch { /* security analysis is non-critical */ }\n }\n\n // Re-index documentation (if enabled)\n if (this.config.enableDocs) {\n try {\n const { DocsIndexer } = await Promise.resolve().then(() => require('../docs/indexer.js'));\n this.db.applyDocsSchema();\n const docsIndexer = new DocsIndexer(this.db.getRawDb(), this.config, this.projectRoot);\n await docsIndexer.indexAll({\n onProgress: msg => onProgress?.({ phase: 'docs', current: 0, total: 1, meta: { msg } }),\n });\n } catch { /* docs indexing is non-critical */ }\n }\n\n // Re-index data files (if enabled)\n if ((this.config as any).enableData) {\n try {\n const { DataIndexer } = await Promise.resolve().then(() => require('../data/indexer.js'));\n this.db.applyDataSchema();\n const dataIndexer = new DataIndexer(this.db.getRawDb(), this.config, this.projectRoot);\n await dataIndexer.indexAll({\n onProgress: msg => onProgress?.({ phase: 'data', current: 0, total: 1, meta: { msg } }),\n });\n\n // Assign data files to 'data' architecture layer if architecture is enabled\n if (this.config.enableArchitecture) {\n try {\n const rawDb = this.db.getRawDb();\n const tableExists = rawDb.get(\"SELECT name FROM sqlite_master WHERE type='table' AND name='arch_file_layers'\");\n if (tableExists) {\n const datasets = rawDb.all('SELECT file_path FROM data_datasets') as Array<{ file_path: string }>;\n for (const ds of datasets) {\n rawDb.run(\n `INSERT OR REPLACE INTO arch_file_layers (file_path, layer_id, confidence) VALUES (?, ?, ?)`,\n [ds.file_path, 'layer:data', 1.0],\n );\n }\n }\n } catch { /* non-critical */ }\n }\n } catch { /* data indexing is non-critical */ }\n }\n\n // Re-index pattern matches for changed files (if enabled)\n if ((this.config as any).enablePatterns) {\n try {\n const tableExists = this.db.getRawDb().get(\n \"SELECT name FROM sqlite_master WHERE type='table' AND name='pattern_matches'\"\n );\n if (tableExists) {\n const { PatternIndexer } = await Promise.resolve().then(() => require('../patterns/indexer.js'));\n const { PatternLibraryLoader } = await Promise.resolve().then(() => require('../patterns/loader.js'));\n const { PatternRunner } = await Promise.resolve().then(() => require('../patterns/runner.js'));\n const runner = new PatternRunner();\n if (runner.isAvailable()) {\n const loader = new PatternLibraryLoader();\n const builtinPath = require('path').join(__dirname, '../patterns/library');\n const rules = loader.load(builtinPath, (this.config as any).patternLibraryPath);\n const threshold = (this.config as any).patternSeverityThreshold ?? 'low';\n const indexer = new PatternIndexer(this.db.getRawDb(), this.config, this.projectRoot);\n const changedPaths = [...result.added, ...result.modified];\n for (const filePath of changedPaths) {\n const fileRecord = this.db.getFile(filePath);\n const language = fileRecord?.language ?? 'unknown';\n await indexer.indexFile(filePath, language, rules, runner, threshold, Date.now());\n }\n }\n }\n } catch { /* non-critical */ }\n }\n\n this.lock.clearDirty();\n result.duration = Date.now() - start;\n return result;\n } finally {\n this.lock.release();\n release();\n }\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * IndexPipeline \u2014 full-index and incremental-sync pipelines.\n *\n * Owns the two heavy workflows:\n * - indexAll(): scan all files, extract, store, resolve, detect frameworks,\n * generate embeddings, analyze architecture.\n * - sync(): detect changed files via git (or full scan fallback),\n * re-extract only what changed, then run the same tail pipeline.\n *\n * Everything that touches the filesystem or sub-systems is injected via the\n * constructor, keeping this class testable and free of global state.\n */\n\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { GraphDatabase } from '../db/database';\nimport { scanDirectory, hashContent, getChangedFiles, shouldIncludeFile } from '../sync/index';\nimport { extractFile } from '../extraction/extractor';\nimport { clearParserCache, initGrammars, hasWasmGrammar } from '../extraction/grammars';\nimport { detectFrameworks } from '../frameworks/index';\nimport { ReferenceResolver } from '../resolution/index';\nimport { VectorManager } from '../vectors/index';\nimport { ArchitectureAnalyzer } from '../architecture/index';\nimport type { KiroGraphConfig } from '../config';\nimport type { IndexResult, IndexProgress, SyncResult } from '../types';\nimport { LockManager } from './lock-manager';\nimport { Mutex } from '../utils';\n\nconst FILE_IO_BATCH_SIZE = 10;\n\nexport class IndexPipeline {\n private readonly mutex = new Mutex();\n\n constructor(\n private readonly db: GraphDatabase,\n private readonly vectors: VectorManager,\n private readonly resolver: ReferenceResolver,\n private readonly arch: ArchitectureAnalyzer,\n private readonly lock: LockManager,\n private readonly config: KiroGraphConfig,\n private readonly projectRoot: string,\n ) {}\n\n async indexAll(opts?: {\n onProgress?: (p: IndexProgress) => void;\n force?: boolean;\n signal?: AbortSignal;\n }): Promise<IndexResult> {\n const release = await this.mutex.acquire();\n this.lock.acquire();\n const start = Date.now();\n const errors: string[] = [];\n let filesIndexed = 0;\n let nodesCreated = 0;\n let edgesCreated = 0;\n\n // Track languages whose WASM parser is currently poisoned (ABORT=true on the module).\n // Once a language's parser aborts, every subsequent parse call for that language\n // fails instantly. We skip those files until clearParserCache + initGrammars succeeds.\n const poisonedLanguages = new Set<string>();\n // Track consecutive WASM crashes per language. Only poison after threshold is exceeded.\n const crashCounts = new Map<string, number>();\n const POISON_THRESHOLD = 3;\n\n try {\n const files = await scanDirectory(this.projectRoot, this.config, opts?.signal);\n opts?.onProgress?.({ phase: 'scanning', current: files.length, total: files.length });\n\n // Batch-read files in parallel\n const contentMap = new Map<string, Buffer>();\n for (let b = 0; b < files.length; b += FILE_IO_BATCH_SIZE) {\n const batch = files.slice(b, b + FILE_IO_BATCH_SIZE);\n const results = await Promise.all(batch.map(f => fs.promises.readFile(f).catch(() => null)));\n for (let i = 0; i < batch.length; i++) {\n if (results[i]) contentMap.set(batch[i], results[i]!);\n }\n }\n\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n opts?.onProgress?.({ phase: 'parsing', current: i + 1, total: files.length, currentFile: file });\n\n try {\n const content = contentMap.get(file);\n if (!content) continue;\n if (content.length > this.config.maxFileSize) continue;\n\n const relPath = path.relative(this.projectRoot, file).replace(/\\\\/g, '/');\n\n if (!opts?.force) {\n const existing = this.db.getFile(relPath);\n if (existing && hashContent(content) === existing.contentHash) continue;\n }\n\n // Skip files whose language parser is currently poisoned\n const { detectLanguage } = await Promise.resolve().then(() => require('../extraction/languages.js'));\n const lang = detectLanguage(file);\n if (poisonedLanguages.has(lang)) continue;\n\n const extracted = await extractFile(file, this.projectRoot, content, { enableComplexity: !!(this.config as any).enableComplexity, maxFileSize: this.config.maxFileSize });\n if (!extracted) continue;\n\n const oldNodes = this.db.getNodesByFile(extracted.filePath);\n if (oldNodes.length > 0) await this.vectors.deleteEmbeddings(oldNodes.map(n => n.id));\n\n this.db.transaction(() => {\n this.db.deleteNodesByFile(extracted.filePath);\n this.db.deleteUnresolvedRefsByFile(extracted.filePath);\n this.db.upsertFile({\n path: extracted.filePath,\n contentHash: extracted.contentHash,\n language: extracted.language,\n fileSize: extracted.fileSize,\n symbolCount: extracted.nodes.length,\n indexedAt: Date.now(),\n });\n for (const node of extracted.nodes) { this.db.upsertNode(node); nodesCreated++; }\n for (const edge of extracted.edges) { this.db.insertEdge(edge); edgesCreated++; }\n for (const ref of extracted.unresolvedRefs) {\n this.db.insertUnresolvedRef(ref.sourceId, ref.refName, ref.refKind, extracted.filePath, ref.line, ref.column);\n }\n });\n\n filesIndexed++;\n // Reset crash count on successful parse for this language\n crashCounts.set(lang, 0);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n errors.push(`${file}: ${msg}`);\n\n // Detect WASM runtime abort and attempt recovery\n const isWasmCrash = (err as any)?.constructor?.name === 'RuntimeError'\n || msg.includes('Aborted(') \n || msg.includes('RuntimeError')\n || msg.includes('WASM grammar exists but failed to load');\n if (isWasmCrash) {\n const { detectLanguage } = await Promise.resolve().then(() => require('../extraction/languages.js'));\n const lang = detectLanguage(file);\n const count = (crashCounts.get(lang) ?? 0) + 1;\n crashCounts.set(lang, count);\n\n // Only poison the language after multiple consecutive crashes\n if (count >= POISON_THRESHOLD) {\n poisonedLanguages.add(lang);\n }\n\n clearParserCache();\n try {\n await initGrammars();\n // Recovery succeeded \u2014 WASM runtime is usable again.\n // Languages with count >= POISON_THRESHOLD remain permanently disabled\n // for this run. Other languages (below threshold) were never poisoned\n // and continue parsing normally.\n } catch {\n errors.push('WASM runtime unrecoverable after crash \u2014 aborting batch');\n break;\n }\n }\n }\n }\n\n // Re-process files that have symbolCount=0 but should have symbols (WASM recovery)\n const emptyFiles = this.db.getAllFiles().filter(\n (f: any) => f.symbolCount === 0 && hasWasmGrammar(f.language)\n );\n if (emptyFiles.length > 0) {\n opts?.onProgress?.({ phase: 'retrying', current: 0, total: emptyFiles.length });\n for (let i = 0; i < emptyFiles.length; i++) {\n const ef = emptyFiles[i];\n const absPath = path.join(this.projectRoot, ef.path);\n opts?.onProgress?.({ phase: 'retrying', current: i + 1, total: emptyFiles.length, currentFile: absPath });\n try {\n const extracted = await extractFile(absPath, this.projectRoot, undefined, { enableComplexity: !!(this.config as any).enableComplexity });\n if (!extracted || extracted.nodes.length === 0) continue;\n\n const oldNodes = this.db.getNodesByFile(extracted.filePath);\n if (oldNodes.length > 0) await this.vectors.deleteEmbeddings(oldNodes.map(n => n.id));\n\n this.db.transaction(() => {\n this.db.deleteNodesByFile(extracted.filePath);\n this.db.deleteUnresolvedRefsByFile(extracted.filePath);\n this.db.upsertFile({\n path: extracted.filePath,\n contentHash: extracted.contentHash,\n language: extracted.language,\n fileSize: extracted.fileSize,\n symbolCount: extracted.nodes.length,\n indexedAt: Date.now(),\n });\n for (const node of extracted.nodes) { this.db.upsertNode(node); nodesCreated++; }\n for (const edge of extracted.edges) { this.db.insertEdge(edge); edgesCreated++; }\n for (const ref of extracted.unresolvedRefs) {\n this.db.insertUnresolvedRef(ref.sourceId, ref.refName, ref.refKind, extracted.filePath, ref.line, ref.column);\n }\n });\n filesIndexed++;\n } catch {\n // Already logged in first pass or genuinely broken \u2014 skip\n }\n }\n }\n\n // Resolve cross-file references\n opts?.onProgress?.({ phase: 'resolving', current: 0, total: 1 });\n await this.resolver.resolveAll((current, total) => {\n opts?.onProgress?.({ phase: 'resolving', current, total });\n });\n\n // Detect frameworks\n opts?.onProgress?.({ phase: 'detecting frameworks', current: 0, total: 1 });\n const detectedFrameworks = await detectFrameworks(this.projectRoot, this.db);\n const languages = [...new Set(this.db.getAllFiles().map(f => (f as any).language).filter(Boolean))];\n opts?.onProgress?.({\n phase: 'detecting frameworks', current: 1, total: 1,\n meta: { frameworks: detectedFrameworks.map(f => f.name), languages },\n });\n\n // Generate embeddings (if enabled)\n if (this.vectors.isInitialized()) {\n opts?.onProgress?.({ phase: 'embeddings', current: 0, total: 1 });\n await this.vectors.embedAll((current, total) =>\n opts?.onProgress?.({ phase: 'embeddings', current, total })\n );\n }\n\n // Analyze architecture (if enabled, or auto-enabled for security)\n if (this.config.enableArchitecture || this.config.enableSecurity) {\n if (this.config.enableSecurity && !this.config.enableArchitecture) {\n const { logWarn } = await Promise.resolve().then(() => require('../errors.js'));\n logWarn('enableSecurity requires enableArchitecture \u2014 auto-enabling architecture analysis for this run');\n }\n opts?.onProgress?.({ phase: 'architecture', current: 0, total: 1 });\n await this.arch.analyze(msg =>\n opts?.onProgress?.({ phase: 'architecture', current: 0, total: 1, meta: { msg } })\n );\n opts?.onProgress?.({ phase: 'architecture', current: 1, total: 1 });\n }\n\n // Run security analysis (if enabled)\n if (this.config.enableSecurity) {\n try {\n const { SecurityPipeline } = await Promise.resolve().then(() => require('../security/pipeline.js'));\n this.db.applySecuritySchema();\n const secPipeline = new SecurityPipeline(this.db, this.config, this.projectRoot);\n opts?.onProgress?.({ phase: 'security', current: 0, total: 1 });\n await secPipeline.run((phase, current, total) =>\n opts?.onProgress?.({ phase: 'security', current, total, meta: { secPhase: phase } })\n );\n opts?.onProgress?.({ phase: 'security', current: 1, total: 1 });\n } catch { /* security analysis is non-critical */ }\n }\n\n // Index documentation (if enabled)\n if (this.config.enableDocs) {\n try {\n const { DocsIndexer } = await Promise.resolve().then(() => require('../docs/indexer.js'));\n this.db.applyDocsSchema();\n const docsIndexer = new DocsIndexer(this.db.getRawDb(), this.config, this.projectRoot);\n await docsIndexer.indexAll({\n force: opts?.force,\n onProgress: msg => opts?.onProgress?.({ phase: 'docs', current: 0, total: 1, meta: { msg } }),\n });\n } catch { /* docs indexing is non-critical */ }\n }\n\n // Index data files (if enabled)\n if ((this.config as any).enableData) {\n try {\n const { DataIndexer } = await Promise.resolve().then(() => require('../data/indexer.js'));\n this.db.applyDataSchema();\n const dataIndexer = new DataIndexer(this.db.getRawDb(), this.config, this.projectRoot);\n await dataIndexer.indexAll({\n onProgress: msg => opts?.onProgress?.({ phase: 'data', current: 0, total: 1, meta: { msg } }),\n });\n\n // Assign data files to 'data' architecture layer if architecture is enabled\n if (this.config.enableArchitecture) {\n try {\n const rawDb = this.db.getRawDb();\n // Check if arch_file_layers table exists\n const tableExists = rawDb.get(\"SELECT name FROM sqlite_master WHERE type='table' AND name='arch_file_layers'\");\n if (tableExists) {\n const datasets = rawDb.all('SELECT file_path FROM data_datasets') as Array<{ file_path: string }>;\n for (const ds of datasets) {\n rawDb.run(\n `INSERT OR REPLACE INTO arch_file_layers (file_path, layer_id, confidence) VALUES (?, ?, ?)`,\n [ds.file_path, 'layer:data', 1.0],\n );\n }\n }\n } catch { /* non-critical */ }\n }\n } catch { /* data indexing is non-critical */ }\n }\n\n // Index pattern matches (if enabled)\n if ((this.config as any).enablePatterns) {\n try {\n this.db.applyPatternsSchema();\n const { PatternIndexer } = await Promise.resolve().then(() => require('../patterns/indexer.js'));\n const indexer = new PatternIndexer(this.db.getRawDb(), this.config, this.projectRoot);\n await indexer.indexAll((phase, current, total) => {\n opts?.onProgress?.({ phase: 'patterns' as any, current, total });\n });\n } catch (err) {\n // Patterns are non-critical \u2014 log and continue\n const { logWarn } = await Promise.resolve().then(() => require('../errors.js'));\n const msg = err instanceof Error ? err.message : String(err);\n logWarn(`[patterns] Pattern indexing failed (non-critical): ${msg}`);\n }\n }\n\n this.lock.clearDirty();\n return { success: errors.length === 0, filesIndexed, nodesCreated, edgesCreated, errors, duration: Date.now() - start };\n } finally {\n this.lock.release();\n release();\n }\n }\n\n async sync(opts?: {\n changedFiles?: string[];\n onProgress?: (p: IndexProgress) => void;\n }): Promise<SyncResult> {\n const release = await this.mutex.acquire();\n this.lock.acquire();\n const start = Date.now();\n const changedFiles = opts?.changedFiles;\n const onProgress = opts?.onProgress;\n const result: SyncResult = {\n added: [], modified: [], removed: [],\n nodesCreated: 0, nodesUpdated: 0, nodesRemoved: 0,\n edgesCreated: 0, edgesRemoved: 0,\n filesScanned: 0, errors: [], duration: 0,\n };\n\n try {\n const removeFile = async (rel: string) => {\n const oldNodes = this.db.getNodesByFile(rel);\n const oldEdgeCount = this.db.getEdgesForNodes(oldNodes.map(n => n.id)).length;\n result.nodesRemoved += oldNodes.length;\n result.edgesRemoved += oldEdgeCount;\n await this.vectors.deleteEmbeddings(oldNodes.map(n => n.id));\n this.db.deleteFile(rel);\n this.db.deleteUnresolvedRefsByFile(rel);\n // Clean up pattern matches for removed files (only if patterns are enabled)\n if ((this.config as any).enablePatterns) {\n this.db.getRawDb().run('DELETE FROM pattern_matches WHERE file_path = ?', [rel]);\n }\n result.removed.push(rel);\n };\n\n // \u2500\u2500 Exclude-rule cleanup \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Remove any indexed files that now match the current exclude patterns.\n // This handles the case where a user adds a new exclude pattern (e.g.\n // \"**/.vite/**\") and expects those files to disappear from the index on\n // the next sync without needing a full --force re-index.\n const allIndexed = this.db.getAllFiles();\n for (const f of allIndexed) {\n if (!shouldIncludeFile(f.path, this.config)) {\n onProgress?.({ phase: 'scanning', current: 0, total: 0, meta: { excludeCleanup: true, file: f.path } });\n await removeFile(f.path);\n }\n }\n\n let filesToProcess: string[];\n\n onProgress?.({ phase: 'scanning', current: 0, total: 0 });\n\n if (changedFiles) {\n filesToProcess = changedFiles.map(f => path.resolve(this.projectRoot, f));\n } else {\n const gitChanged = await getChangedFiles(this.projectRoot, this.config);\n const hasChanges = gitChanged.added.length > 0 || gitChanged.modified.length > 0 || gitChanged.removed.length > 0;\n\n if (hasChanges) {\n for (const p of gitChanged.removed) {\n await removeFile(path.relative(this.projectRoot, p).replace(/\\\\/g, '/'));\n }\n filesToProcess = [...gitChanged.added, ...gitChanged.modified];\n } else {\n // Fallback: full scan + detect removed files\n const indexed = new Set(this.db.getAllFiles().map(f => f.path));\n const current = new Set(\n (await scanDirectory(this.projectRoot, this.config))\n .map(f => path.relative(this.projectRoot, f).replace(/\\\\/g, '/'))\n );\n result.filesScanned = current.size;\n for (const p of indexed) {\n if (!current.has(p)) await removeFile(p);\n }\n filesToProcess = await scanDirectory(this.projectRoot, this.config);\n }\n }\n\n result.filesScanned = result.filesScanned || filesToProcess.length;\n onProgress?.({ phase: 'scanning', current: result.filesScanned, total: result.filesScanned });\n\n const poisonedLanguages = new Set<string>();\n const crashCounts = new Map<string, number>();\n const POISON_THRESHOLD = 3;\n\n for (let i = 0; i < filesToProcess.length; i++) {\n const file = filesToProcess[i];\n onProgress?.({ phase: 'parsing', current: i + 1, total: filesToProcess.length, currentFile: file });\n\n if (!fs.existsSync(file)) {\n const rel = path.relative(this.projectRoot, file).replace(/\\\\/g, '/');\n await removeFile(rel);\n continue;\n }\n\n try {\n // Skip files whose language parser is currently poisoned\n const { detectLanguage } = await Promise.resolve().then(() => require('../extraction/languages.js'));\n const lang = detectLanguage(file);\n if (poisonedLanguages.has(lang)) continue;\n\n const extracted = await extractFile(file, this.projectRoot, undefined, { enableComplexity: !!(this.config as any).enableComplexity, maxFileSize: this.config.maxFileSize });\n if (!extracted) continue;\n\n const existing = this.db.getFile(extracted.filePath);\n const isNew = !existing;\n if (!isNew && existing!.contentHash === extracted.contentHash) continue;\n\n const oldNodes = this.db.getNodesByFile(extracted.filePath);\n const oldEdgeCount = this.db.getEdgesForNodes(oldNodes.map(n => n.id)).length;\n await this.vectors.deleteEmbeddings(oldNodes.map(n => n.id));\n\n this.db.transaction(() => {\n result.nodesRemoved += oldNodes.length;\n result.edgesRemoved += oldEdgeCount;\n this.db.deleteNodesByFile(extracted.filePath);\n this.db.deleteUnresolvedRefsByFile(extracted.filePath);\n this.db.upsertFile({\n path: extracted.filePath,\n contentHash: extracted.contentHash,\n language: extracted.language,\n fileSize: extracted.fileSize,\n symbolCount: extracted.nodes.length,\n indexedAt: Date.now(),\n });\n for (const node of extracted.nodes) { this.db.upsertNode(node); result.nodesCreated++; }\n for (const edge of extracted.edges) { this.db.insertEdge(edge); result.edgesCreated++; }\n for (const ref of extracted.unresolvedRefs) {\n this.db.insertUnresolvedRef(ref.sourceId, ref.refName, ref.refKind, extracted.filePath, ref.line, ref.column);\n }\n });\n\n this.resolver.invalidateFile(extracted.filePath);\n // Reset crash count on successful parse for this language\n crashCounts.set(lang, 0);\n if (isNew) result.added.push(extracted.filePath);\n else { result.modified.push(extracted.filePath); result.nodesUpdated += extracted.nodes.length; }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n result.errors.push(`${file}: ${msg}`);\n\n // Detect WASM runtime abort and attempt recovery\n const isWasmCrash = (err as any)?.constructor?.name === 'RuntimeError'\n || msg.includes('Aborted(') \n || msg.includes('RuntimeError')\n || msg.includes('WASM grammar exists but failed to load');\n if (isWasmCrash) {\n const { detectLanguage } = await Promise.resolve().then(() => require('../extraction/languages.js'));\n const lang = detectLanguage(file);\n const count = (crashCounts.get(lang) ?? 0) + 1;\n crashCounts.set(lang, count);\n\n if (count >= POISON_THRESHOLD) {\n poisonedLanguages.add(lang);\n }\n\n clearParserCache();\n try {\n await initGrammars();\n // Recovery succeeded \u2014 WASM runtime is usable again.\n // Languages at POISON_THRESHOLD stay disabled for this run.\n } catch {\n result.errors.push('WASM runtime unrecoverable after crash \u2014 aborting sync');\n break;\n }\n }\n }\n }\n\n // Resolve cross-file references\n onProgress?.({ phase: 'resolving', current: 0, total: 1 });\n await this.resolver.resolveAll((current, total) => {\n onProgress?.({ phase: 'resolving', current, total });\n });\n\n await detectFrameworks(this.projectRoot);\n\n // Generate embeddings (if enabled)\n if (this.vectors.isInitialized()) {\n onProgress?.({ phase: 'embeddings', current: 0, total: 1 });\n await this.vectors.embedAll((current, total) =>\n onProgress?.({ phase: 'embeddings', current, total })\n );\n }\n\n // Analyze architecture (if enabled, or auto-enabled for security)\n if (this.config.enableArchitecture || this.config.enableSecurity) {\n if (this.config.enableSecurity && !this.config.enableArchitecture) {\n const { logWarn } = await Promise.resolve().then(() => require('../errors.js'));\n logWarn('enableSecurity requires enableArchitecture \u2014 auto-enabling architecture analysis for this run');\n }\n onProgress?.({ phase: 'architecture', current: 0, total: 1 });\n await this.arch.analyze(msg =>\n onProgress?.({ phase: 'architecture', current: 0, total: 1, meta: { msg } })\n );\n onProgress?.({ phase: 'architecture', current: 1, total: 1 });\n }\n\n // Run security analysis (if enabled)\n if (this.config.enableSecurity) {\n try {\n const { SecurityPipeline } = await Promise.resolve().then(() => require('../security/pipeline.js'));\n this.db.applySecuritySchema();\n const secPipeline = new SecurityPipeline(this.db, this.config, this.projectRoot);\n onProgress?.({ phase: 'security', current: 0, total: 1 });\n await secPipeline.run((phase, current, total) =>\n onProgress?.({ phase: 'security', current, total, meta: { secPhase: phase } })\n );\n onProgress?.({ phase: 'security', current: 1, total: 1 });\n } catch { /* security analysis is non-critical */ }\n }\n\n // Re-index documentation (if enabled)\n if (this.config.enableDocs) {\n try {\n const { DocsIndexer } = await Promise.resolve().then(() => require('../docs/indexer.js'));\n this.db.applyDocsSchema();\n const docsIndexer = new DocsIndexer(this.db.getRawDb(), this.config, this.projectRoot);\n await docsIndexer.indexAll({\n onProgress: msg => onProgress?.({ phase: 'docs', current: 0, total: 1, meta: { msg } }),\n });\n } catch { /* docs indexing is non-critical */ }\n }\n\n // Re-index data files (if enabled)\n if ((this.config as any).enableData) {\n try {\n const { DataIndexer } = await Promise.resolve().then(() => require('../data/indexer.js'));\n this.db.applyDataSchema();\n const dataIndexer = new DataIndexer(this.db.getRawDb(), this.config, this.projectRoot);\n await dataIndexer.indexAll({\n onProgress: msg => onProgress?.({ phase: 'data', current: 0, total: 1, meta: { msg } }),\n });\n\n // Assign data files to 'data' architecture layer if architecture is enabled\n if (this.config.enableArchitecture) {\n try {\n const rawDb = this.db.getRawDb();\n const tableExists = rawDb.get(\"SELECT name FROM sqlite_master WHERE type='table' AND name='arch_file_layers'\");\n if (tableExists) {\n const datasets = rawDb.all('SELECT file_path FROM data_datasets') as Array<{ file_path: string }>;\n for (const ds of datasets) {\n rawDb.run(\n `INSERT OR REPLACE INTO arch_file_layers (file_path, layer_id, confidence) VALUES (?, ?, ?)`,\n [ds.file_path, 'layer:data', 1.0],\n );\n }\n }\n } catch { /* non-critical */ }\n }\n } catch { /* data indexing is non-critical */ }\n }\n\n // Re-index pattern matches for changed files (if enabled)\n if ((this.config as any).enablePatterns) {\n try {\n const tableExists = this.db.getRawDb().get(\n \"SELECT name FROM sqlite_master WHERE type='table' AND name='pattern_matches'\"\n );\n if (tableExists) {\n const { PatternIndexer } = await Promise.resolve().then(() => require('../patterns/indexer.js'));\n const { PatternLibraryLoader } = await Promise.resolve().then(() => require('../patterns/loader.js'));\n const { PatternRunner } = await Promise.resolve().then(() => require('../patterns/runner.js'));\n const runner = new PatternRunner();\n if (runner.isAvailable()) {\n const loader = new PatternLibraryLoader();\n const builtinPath = require('path').join(__dirname, '../patterns/library');\n const rules = loader.load(builtinPath, (this.config as any).patternLibraryPath);\n const threshold = (this.config as any).patternSeverityThreshold ?? 'low';\n const indexer = new PatternIndexer(this.db.getRawDb(), this.config, this.projectRoot);\n const changedPaths = [...result.added, ...result.modified];\n for (const filePath of changedPaths) {\n const fileRecord = this.db.getFile(filePath);\n const language = fileRecord?.language ?? 'unknown';\n await indexer.indexFile(filePath, language, rules, runner, threshold, Date.now());\n }\n }\n }\n } catch { /* non-critical */ }\n }\n\n this.lock.clearDirty();\n result.duration = Date.now() - start;\n return result;\n } finally {\n this.lock.release();\n release();\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -66,6 +66,18 @@ async function extractFile(filePath, projectRoot, content, opts) {
|
|
|
66
66
|
} catch {
|
|
67
67
|
return null;
|
|
68
68
|
}
|
|
69
|
+
if (opts?.maxFileSize !== void 0 && Buffer.byteLength(source, "utf8") > opts.maxFileSize) {
|
|
70
|
+
const relPathSkip = path.relative(projectRoot, filePath).replace(/\\/g, "/");
|
|
71
|
+
return {
|
|
72
|
+
filePath: relPathSkip,
|
|
73
|
+
language,
|
|
74
|
+
contentHash: crypto.createHash("sha256").update(source).digest("hex"),
|
|
75
|
+
fileSize: Buffer.byteLength(source, "utf8"),
|
|
76
|
+
nodes: [],
|
|
77
|
+
edges: [],
|
|
78
|
+
unresolvedRefs: []
|
|
79
|
+
};
|
|
80
|
+
}
|
|
69
81
|
if (language === "jupyter") {
|
|
70
82
|
return (0, import_notebook.extractNotebook)(filePath, projectRoot, source);
|
|
71
83
|
}
|
|
@@ -88,7 +100,36 @@ async function extractFile(filePath, projectRoot, content, opts) {
|
|
|
88
100
|
}
|
|
89
101
|
throw new Error(`Parser unavailable for ${language} (WASM grammar exists but failed to load)`);
|
|
90
102
|
}
|
|
91
|
-
|
|
103
|
+
if (language === "yaml" && source.includes("{{")) {
|
|
104
|
+
return {
|
|
105
|
+
filePath: relPath,
|
|
106
|
+
language,
|
|
107
|
+
contentHash,
|
|
108
|
+
fileSize,
|
|
109
|
+
nodes: [],
|
|
110
|
+
edges: [],
|
|
111
|
+
unresolvedRefs: []
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
let tree;
|
|
115
|
+
try {
|
|
116
|
+
tree = parser.parse(source);
|
|
117
|
+
} catch (parseErr) {
|
|
118
|
+
const parseMsg = parseErr?.message ?? String(parseErr);
|
|
119
|
+
const isWasmCrash = parseErr?.constructor?.name === "RuntimeError" || parseMsg.includes("memory access out of bounds") || parseMsg.includes("Aborted(");
|
|
120
|
+
if (isWasmCrash) {
|
|
121
|
+
return {
|
|
122
|
+
filePath: relPath,
|
|
123
|
+
language,
|
|
124
|
+
contentHash,
|
|
125
|
+
fileSize,
|
|
126
|
+
nodes: [],
|
|
127
|
+
edges: [],
|
|
128
|
+
unresolvedRefs: []
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
throw parseErr;
|
|
132
|
+
}
|
|
92
133
|
const nodes = [];
|
|
93
134
|
const edges = [];
|
|
94
135
|
const unresolvedRefs = [];
|
|
@@ -251,6 +292,8 @@ const KIND_MAP = {
|
|
|
251
292
|
// Java, C#
|
|
252
293
|
// Classes / structs
|
|
253
294
|
class_declaration: "class",
|
|
295
|
+
abstract_class_declaration: "class",
|
|
296
|
+
// TypeScript `abstract class` (distinct AST node from class_declaration)
|
|
254
297
|
class_expression: "class",
|
|
255
298
|
class_definition: "class",
|
|
256
299
|
// Python, Scala
|
|
@@ -403,6 +446,7 @@ function walkTree(node, source, filePath, language, nodes, edges, unresolvedRefs
|
|
|
403
446
|
isExported: isExported(node),
|
|
404
447
|
isAsync: isAsync(node),
|
|
405
448
|
isStatic: isStatic(node),
|
|
449
|
+
isAbstract: isAbstract(node),
|
|
406
450
|
updatedAt: now
|
|
407
451
|
};
|
|
408
452
|
nodes.push(graphNode);
|
|
@@ -821,6 +865,19 @@ function isStatic(node) {
|
|
|
821
865
|
}
|
|
822
866
|
return false;
|
|
823
867
|
}
|
|
868
|
+
function isAbstract(node) {
|
|
869
|
+
if (node.type === "abstract_class_declaration") return true;
|
|
870
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
871
|
+
const child = node.child(i);
|
|
872
|
+
if (child.type === "abstract") return true;
|
|
873
|
+
if (child.type === "modifiers") {
|
|
874
|
+
for (let j = 0; j < child.childCount; j++) {
|
|
875
|
+
if (child.child(j).type === "abstract") return true;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
return false;
|
|
880
|
+
}
|
|
824
881
|
const CALL_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
825
882
|
"call_expression",
|
|
826
883
|
// JS/TS/Go/Rust/Swift/Kotlin/Dart/C/C++
|