@colbymchenry/codegraph-win32-x64 1.2.0 → 1.3.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/lib/dist/bin/codegraph.d.ts +1 -1
- package/lib/dist/bin/codegraph.d.ts.map +1 -1
- package/lib/dist/bin/codegraph.js +232 -61
- package/lib/dist/bin/codegraph.js.map +1 -1
- package/lib/dist/bin/command-supervision.d.ts.map +1 -1
- package/lib/dist/bin/command-supervision.js +4 -1
- package/lib/dist/bin/command-supervision.js.map +1 -1
- package/lib/dist/db/migrations.d.ts +1 -1
- package/lib/dist/db/migrations.d.ts.map +1 -1
- package/lib/dist/db/migrations.js +19 -1
- package/lib/dist/db/migrations.js.map +1 -1
- package/lib/dist/db/queries.d.ts +51 -0
- package/lib/dist/db/queries.d.ts.map +1 -1
- package/lib/dist/db/queries.js +141 -0
- package/lib/dist/db/queries.js.map +1 -1
- package/lib/dist/db/schema.sql +19 -0
- package/lib/dist/directory.d.ts +9 -5
- package/lib/dist/directory.d.ts.map +1 -1
- package/lib/dist/directory.js +210 -19
- package/lib/dist/directory.js.map +1 -1
- package/lib/dist/extraction/cfml-extractor.d.ts +107 -0
- package/lib/dist/extraction/cfml-extractor.d.ts.map +1 -0
- package/lib/dist/extraction/cfml-extractor.js +494 -0
- package/lib/dist/extraction/cfml-extractor.js.map +1 -0
- package/lib/dist/extraction/grammars.d.ts +9 -0
- package/lib/dist/extraction/grammars.d.ts.map +1 -1
- package/lib/dist/extraction/grammars.js +115 -3
- package/lib/dist/extraction/grammars.js.map +1 -1
- package/lib/dist/extraction/index.d.ts +46 -1
- package/lib/dist/extraction/index.d.ts.map +1 -1
- package/lib/dist/extraction/index.js +254 -3
- package/lib/dist/extraction/index.js.map +1 -1
- package/lib/dist/extraction/languages/arkts.d.ts +3 -0
- package/lib/dist/extraction/languages/arkts.d.ts.map +1 -0
- package/lib/dist/extraction/languages/arkts.js +127 -0
- package/lib/dist/extraction/languages/arkts.js.map +1 -0
- package/lib/dist/extraction/languages/c-cpp.d.ts +42 -0
- package/lib/dist/extraction/languages/c-cpp.d.ts.map +1 -1
- package/lib/dist/extraction/languages/c-cpp.js +369 -4
- package/lib/dist/extraction/languages/c-cpp.js.map +1 -1
- package/lib/dist/extraction/languages/cfquery.d.ts +12 -0
- package/lib/dist/extraction/languages/cfquery.d.ts.map +1 -0
- package/lib/dist/extraction/languages/cfquery.js +28 -0
- package/lib/dist/extraction/languages/cfquery.js.map +1 -0
- package/lib/dist/extraction/languages/cfscript.d.ts +3 -0
- package/lib/dist/extraction/languages/cfscript.d.ts.map +1 -0
- package/lib/dist/extraction/languages/cfscript.js +73 -0
- package/lib/dist/extraction/languages/cfscript.js.map +1 -0
- package/lib/dist/extraction/languages/cobol.d.ts +33 -0
- package/lib/dist/extraction/languages/cobol.d.ts.map +1 -0
- package/lib/dist/extraction/languages/cobol.js +499 -0
- package/lib/dist/extraction/languages/cobol.js.map +1 -0
- package/lib/dist/extraction/languages/erlang.d.ts +3 -0
- package/lib/dist/extraction/languages/erlang.d.ts.map +1 -0
- package/lib/dist/extraction/languages/erlang.js +350 -0
- package/lib/dist/extraction/languages/erlang.js.map +1 -0
- package/lib/dist/extraction/languages/index.d.ts.map +1 -1
- package/lib/dist/extraction/languages/index.js +18 -0
- package/lib/dist/extraction/languages/index.js.map +1 -1
- package/lib/dist/extraction/languages/nix.d.ts +3 -0
- package/lib/dist/extraction/languages/nix.d.ts.map +1 -0
- package/lib/dist/extraction/languages/nix.js +294 -0
- package/lib/dist/extraction/languages/nix.js.map +1 -0
- package/lib/dist/extraction/languages/solidity.d.ts +3 -0
- package/lib/dist/extraction/languages/solidity.d.ts.map +1 -0
- package/lib/dist/extraction/languages/solidity.js +293 -0
- package/lib/dist/extraction/languages/solidity.js.map +1 -0
- package/lib/dist/extraction/languages/terraform.d.ts +3 -0
- package/lib/dist/extraction/languages/terraform.d.ts.map +1 -0
- package/lib/dist/extraction/languages/terraform.js +641 -0
- package/lib/dist/extraction/languages/terraform.js.map +1 -0
- package/lib/dist/extraction/languages/vbnet.d.ts +11 -0
- package/lib/dist/extraction/languages/vbnet.d.ts.map +1 -0
- package/lib/dist/extraction/languages/vbnet.js +141 -0
- package/lib/dist/extraction/languages/vbnet.js.map +1 -0
- package/lib/dist/extraction/mybatis-extractor.d.ts +30 -10
- package/lib/dist/extraction/mybatis-extractor.d.ts.map +1 -1
- package/lib/dist/extraction/mybatis-extractor.js +140 -38
- package/lib/dist/extraction/mybatis-extractor.js.map +1 -1
- package/lib/dist/extraction/tree-sitter-helpers.d.ts.map +1 -1
- package/lib/dist/extraction/tree-sitter-helpers.js +1 -0
- package/lib/dist/extraction/tree-sitter-helpers.js.map +1 -1
- package/lib/dist/extraction/tree-sitter-types.d.ts +3 -1
- package/lib/dist/extraction/tree-sitter-types.d.ts.map +1 -1
- package/lib/dist/extraction/tree-sitter.d.ts +38 -0
- package/lib/dist/extraction/tree-sitter.d.ts.map +1 -1
- package/lib/dist/extraction/tree-sitter.js +753 -10
- package/lib/dist/extraction/tree-sitter.js.map +1 -1
- package/lib/dist/extraction/wasm/tree-sitter-arkts.wasm +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-cfml.wasm +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-cfquery.wasm +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-cfscript.wasm +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-cobol.wasm +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-erlang.wasm +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-nix.wasm +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-terraform.wasm +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-vbnet.wasm +0 -0
- package/lib/dist/index.d.ts +63 -1
- package/lib/dist/index.d.ts.map +1 -1
- package/lib/dist/index.js +306 -2
- package/lib/dist/index.js.map +1 -1
- package/lib/dist/installer/index.d.ts.map +1 -1
- package/lib/dist/installer/index.js +3 -1
- package/lib/dist/installer/index.js.map +1 -1
- package/lib/dist/mcp/daemon.d.ts +25 -3
- package/lib/dist/mcp/daemon.d.ts.map +1 -1
- package/lib/dist/mcp/daemon.js +39 -7
- package/lib/dist/mcp/daemon.js.map +1 -1
- package/lib/dist/mcp/dynamic-boundaries.d.ts.map +1 -1
- package/lib/dist/mcp/dynamic-boundaries.js +2 -1
- package/lib/dist/mcp/dynamic-boundaries.js.map +1 -1
- package/lib/dist/mcp/early-ppid.d.ts +26 -0
- package/lib/dist/mcp/early-ppid.d.ts.map +1 -0
- package/lib/dist/mcp/early-ppid.js +29 -0
- package/lib/dist/mcp/early-ppid.js.map +1 -0
- package/lib/dist/mcp/index.d.ts.map +1 -1
- package/lib/dist/mcp/index.js +21 -4
- package/lib/dist/mcp/index.js.map +1 -1
- package/lib/dist/mcp/proxy.d.ts.map +1 -1
- package/lib/dist/mcp/proxy.js +21 -3
- package/lib/dist/mcp/proxy.js.map +1 -1
- package/lib/dist/mcp/startup-handshake.d.ts +44 -0
- package/lib/dist/mcp/startup-handshake.d.ts.map +1 -0
- package/lib/dist/mcp/startup-handshake.js +73 -0
- package/lib/dist/mcp/startup-handshake.js.map +1 -0
- package/lib/dist/mcp/tools.d.ts +22 -0
- package/lib/dist/mcp/tools.d.ts.map +1 -1
- package/lib/dist/mcp/tools.js +74 -9
- package/lib/dist/mcp/tools.js.map +1 -1
- package/lib/dist/project-config.d.ts +38 -0
- package/lib/dist/project-config.d.ts.map +1 -1
- package/lib/dist/project-config.js +101 -2
- package/lib/dist/project-config.js.map +1 -1
- package/lib/dist/resolution/callback-synthesizer.d.ts.map +1 -1
- package/lib/dist/resolution/callback-synthesizer.js +672 -0
- package/lib/dist/resolution/callback-synthesizer.js.map +1 -1
- package/lib/dist/resolution/frameworks/cics.d.ts +20 -0
- package/lib/dist/resolution/frameworks/cics.d.ts.map +1 -0
- package/lib/dist/resolution/frameworks/cics.js +90 -0
- package/lib/dist/resolution/frameworks/cics.js.map +1 -0
- package/lib/dist/resolution/frameworks/index.d.ts.map +1 -1
- package/lib/dist/resolution/frameworks/index.js +6 -0
- package/lib/dist/resolution/frameworks/index.js.map +1 -1
- package/lib/dist/resolution/frameworks/java.d.ts.map +1 -1
- package/lib/dist/resolution/frameworks/java.js +14 -6
- package/lib/dist/resolution/frameworks/java.js.map +1 -1
- package/lib/dist/resolution/frameworks/terraform.d.ts +38 -0
- package/lib/dist/resolution/frameworks/terraform.d.ts.map +1 -0
- package/lib/dist/resolution/frameworks/terraform.js +277 -0
- package/lib/dist/resolution/frameworks/terraform.js.map +1 -0
- package/lib/dist/resolution/import-resolver.d.ts +7 -0
- package/lib/dist/resolution/import-resolver.d.ts.map +1 -1
- package/lib/dist/resolution/import-resolver.js +129 -4
- package/lib/dist/resolution/import-resolver.js.map +1 -1
- package/lib/dist/resolution/index.d.ts +39 -6
- package/lib/dist/resolution/index.d.ts.map +1 -1
- package/lib/dist/resolution/index.js +287 -50
- package/lib/dist/resolution/index.js.map +1 -1
- package/lib/dist/resolution/name-matcher.d.ts +0 -3
- package/lib/dist/resolution/name-matcher.d.ts.map +1 -1
- package/lib/dist/resolution/name-matcher.js +225 -33
- package/lib/dist/resolution/name-matcher.js.map +1 -1
- package/lib/dist/resolution/strip-comments.d.ts +1 -1
- package/lib/dist/resolution/strip-comments.d.ts.map +1 -1
- package/lib/dist/resolution/strip-comments.js +49 -0
- package/lib/dist/resolution/strip-comments.js.map +1 -1
- package/lib/dist/resolution/types.d.ts +20 -0
- package/lib/dist/resolution/types.d.ts.map +1 -1
- package/lib/dist/resolution/workspace-packages.d.ts +10 -0
- package/lib/dist/resolution/workspace-packages.d.ts.map +1 -1
- package/lib/dist/resolution/workspace-packages.js +142 -4
- package/lib/dist/resolution/workspace-packages.js.map +1 -1
- package/lib/dist/search/identifier-segments.d.ts +60 -0
- package/lib/dist/search/identifier-segments.d.ts.map +1 -0
- package/lib/dist/search/identifier-segments.js +176 -0
- package/lib/dist/search/identifier-segments.js.map +1 -0
- package/lib/dist/sync/git-hooks.d.ts.map +1 -1
- package/lib/dist/sync/git-hooks.js +2 -0
- package/lib/dist/sync/git-hooks.js.map +1 -1
- package/lib/dist/sync/watcher.d.ts +10 -5
- package/lib/dist/sync/watcher.d.ts.map +1 -1
- package/lib/dist/sync/watcher.js +51 -14
- package/lib/dist/sync/watcher.js.map +1 -1
- package/lib/dist/sync/worktree.d.ts.map +1 -1
- package/lib/dist/sync/worktree.js +5 -0
- package/lib/dist/sync/worktree.js.map +1 -1
- package/lib/dist/types.d.ts +19 -1
- package/lib/dist/types.d.ts.map +1 -1
- package/lib/dist/types.js +10 -0
- package/lib/dist/types.js.map +1 -1
- package/lib/node_modules/.package-lock.json +1 -1
- package/lib/package.json +1 -1
- package/package.json +1 -1
- package/lib/dist/reasoning/config.d.ts +0 -45
- package/lib/dist/reasoning/config.d.ts.map +0 -1
- package/lib/dist/reasoning/config.js +0 -171
- package/lib/dist/reasoning/config.js.map +0 -1
- package/lib/dist/reasoning/credentials.d.ts +0 -5
- package/lib/dist/reasoning/credentials.d.ts.map +0 -1
- package/lib/dist/reasoning/credentials.js +0 -83
- package/lib/dist/reasoning/credentials.js.map +0 -1
- package/lib/dist/reasoning/login.d.ts +0 -21
- package/lib/dist/reasoning/login.d.ts.map +0 -1
- package/lib/dist/reasoning/login.js +0 -85
- package/lib/dist/reasoning/login.js.map +0 -1
- package/lib/dist/reasoning/reasoner.d.ts +0 -43
- package/lib/dist/reasoning/reasoner.d.ts.map +0 -1
- package/lib/dist/reasoning/reasoner.js +0 -308
- package/lib/dist/reasoning/reasoner.js.map +0 -1
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/lib/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* A local-first code intelligence system that builds a semantic
|
|
5
5
|
* knowledge graph from any codebase.
|
|
6
6
|
*/
|
|
7
|
-
import { Node, Edge, FileRecord, ExtractionResult, Subgraph, TraversalOptions, SearchOptions, SearchResult, Context, GraphStats, TaskInput, TaskContext, BuildContextOptions, FindRelevantContextOptions } from './types';
|
|
7
|
+
import { Node, Edge, FileRecord, ExtractionResult, Subgraph, TraversalOptions, SearchOptions, SearchResult, SegmentMatch, Context, GraphStats, TaskInput, TaskContext, BuildContextOptions, FindRelevantContextOptions } from './types';
|
|
8
8
|
import { IndexProgress, IndexResult, SyncResult } from './extraction';
|
|
9
9
|
import { ResolutionResult } from './resolution';
|
|
10
10
|
import { WatchOptions, PendingFile } from './sync';
|
|
@@ -227,6 +227,16 @@ export declare class CodeGraph {
|
|
|
227
227
|
* freshness without shelling out to `codegraph status --json`. (#329)
|
|
228
228
|
*/
|
|
229
229
|
getLastIndexedAt(): number | null;
|
|
230
|
+
/**
|
|
231
|
+
* Completeness of the last full index run. `'complete'` is the only good
|
|
232
|
+
* state. `'indexing'` after the fact means a run was killed mid-index (OOM,
|
|
233
|
+
* SIGKILL, liveness watchdog) and the on-disk index is truncated;
|
|
234
|
+
* `'partial'` means the run finished but silently dropped files
|
|
235
|
+
* (discovered > indexed+skipped+errored); `'failed'` means it reported
|
|
236
|
+
* failure. `null` = index predates this marker. Surfaced by
|
|
237
|
+
* `codegraph status`.
|
|
238
|
+
*/
|
|
239
|
+
getIndexState(): 'indexing' | 'complete' | 'partial' | 'failed' | null;
|
|
230
240
|
/**
|
|
231
241
|
* Which engine built the current index: the package version + extraction
|
|
232
242
|
* version stamped at the last full `indexAll`. Either field is null for an
|
|
@@ -264,6 +274,13 @@ export declare class CodeGraph {
|
|
|
264
274
|
* Processes chunks of unresolved refs, persisting results after each batch.
|
|
265
275
|
*/
|
|
266
276
|
resolveReferencesBatched(onProgress?: (current: number, total: number) => void): Promise<ResolutionResult>;
|
|
277
|
+
/**
|
|
278
|
+
* References extracted but not yet resolved into edges. Zero on a healthy
|
|
279
|
+
* index — a completed resolution pass consumes every row. Non-zero at rest
|
|
280
|
+
* means a pass was interrupted mid-run (killed indexer, crash — #1187), so
|
|
281
|
+
* some files' call edges are missing; the next `sync` sweeps them.
|
|
282
|
+
*/
|
|
283
|
+
getPendingReferenceCount(): number;
|
|
267
284
|
/**
|
|
268
285
|
* Get detected frameworks in the project
|
|
269
286
|
*/
|
|
@@ -307,10 +324,55 @@ export declare class CodeGraph {
|
|
|
307
324
|
* definition the caller wants is never dropped below a search cut.
|
|
308
325
|
*/
|
|
309
326
|
getNodesByName(name: string): Node[];
|
|
327
|
+
/** Nodes whose name starts with `prefix` (index range scan, capped). */
|
|
328
|
+
getNodesByNamePrefix(prefix: string, limit?: number): Node[];
|
|
310
329
|
/**
|
|
311
330
|
* Search nodes by text
|
|
312
331
|
*/
|
|
313
332
|
searchNodes(query: string, options?: SearchOptions): SearchResult[];
|
|
333
|
+
/**
|
|
334
|
+
* Graph-derived prompt matching for the front-load hook's MEDIUM tier:
|
|
335
|
+
* which indexed symbols do these prose words name? "state machine des
|
|
336
|
+
* commandes" → `OrderStateMachine`, in any human language whose technical
|
|
337
|
+
* nouns are Latin script — no keyword list involved.
|
|
338
|
+
*
|
|
339
|
+
* Precision comes from the repo's own naming statistics, not vocabulary:
|
|
340
|
+
* - CO-OCCURRENCE: ≥2 words that are segments of the SAME name ("state" +
|
|
341
|
+
* "machine" → OrderStateMachine) is strong evidence and always qualifies.
|
|
342
|
+
* - RARITY: a single matched word qualifies only when its segment is
|
|
343
|
+
* discriminative here (≤ {@link SEGMENT_RARITY_CEILING} distinct names) —
|
|
344
|
+
* "checkout" in a shop backend yes, "state" in a react app no.
|
|
345
|
+
* Every candidate is re-verified against `nodes` before being returned
|
|
346
|
+
* (vocab rows are proposals; deletions leave orphans by design), so a
|
|
347
|
+
* returned symbol is guaranteed to exist right now.
|
|
348
|
+
*/
|
|
349
|
+
getSegmentMatches(words: string[], limit?: number): SegmentMatch[];
|
|
350
|
+
/** A single word ("state") can match hundreds of names in a big repo — that
|
|
351
|
+
* is noise, not signal. Ceiling for the single-word tier; co-occurrence is
|
|
352
|
+
* exempt because two words on one name is already discriminative. */
|
|
353
|
+
private static readonly SEGMENT_RARITY_CEILING;
|
|
354
|
+
/** Which of the prompt's original words match `name`'s segments (via
|
|
355
|
+
* variants). Segments are recomputed in JS — a name-keyed vocab lookup
|
|
356
|
+
* would scan the (segment, name) primary key. */
|
|
357
|
+
private wordsMatchingName;
|
|
358
|
+
/**
|
|
359
|
+
* One-shot upgrade heal for callers that open the graph WITHOUT syncing —
|
|
360
|
+
* concretely the prompt hook, whose MEDIUM tier reads the segment
|
|
361
|
+
* vocabulary: a database migrated from before the vocab table existed
|
|
362
|
+
* starts with it empty, and the only other backfill lives inside `sync()`,
|
|
363
|
+
* which such callers never run (#1142). Returns true when the vocab is
|
|
364
|
+
* usable (already populated — the overwhelmingly common one-SELECT case —
|
|
365
|
+
* or healed here); false when it isn't (empty graph, or another process
|
|
366
|
+
* holds the index lock — that process's own sync heals it).
|
|
367
|
+
*/
|
|
368
|
+
healSegmentVocabIfEmpty(): Promise<boolean>;
|
|
369
|
+
/**
|
|
370
|
+
* Rebuild the segment vocabulary from the current graph, batched and
|
|
371
|
+
* yielding — the upgrade-heal path for indexes built before the vocab table
|
|
372
|
+
* existed. Runs inside the index mutex/lock (sync and
|
|
373
|
+
* healSegmentVocabIfEmpty hold them).
|
|
374
|
+
*/
|
|
375
|
+
private rebuildNameSegmentVocab;
|
|
314
376
|
/**
|
|
315
377
|
* Normalized project-name tokens (go.mod / package.json / repo dir) used to
|
|
316
378
|
* down-weight the non-discriminative project name in search ranking (#720).
|
package/lib/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,IAAI,EACJ,IAAI,EACJ,UAAU,EACV,gBAAgB,EAChB,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,OAAO,EACP,UAAU,EACV,SAAS,EACT,WAAW,EACX,mBAAmB,EACnB,0BAA0B,EAC3B,MAAM,SAAS,CAAC;AASjB,OAAO,EAEL,aAAa,EACb,WAAW,EACX,UAAU,EAGX,MAAM,cAAc,CAAC;AACtB,OAAO,EAGL,gBAAgB,EACjB,MAAM,cAAc,CAAC;AAItB,OAAO,EAAe,YAAY,EAAE,WAAW,EAAwB,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,IAAI,EACJ,IAAI,EACJ,UAAU,EACV,gBAAgB,EAChB,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,OAAO,EACP,UAAU,EACV,SAAS,EACT,WAAW,EACX,mBAAmB,EACnB,0BAA0B,EAC3B,MAAM,SAAS,CAAC;AASjB,OAAO,EAEL,aAAa,EACb,WAAW,EACX,UAAU,EAGX,MAAM,cAAc,CAAC;AACtB,OAAO,EAGL,gBAAgB,EACjB,MAAM,cAAc,CAAC;AAItB,OAAO,EAAe,YAAY,EAAE,WAAW,EAAwB,MAAM,QAAQ,CAAC;AAStF,cAAc,SAAS,CAAC;AAKxB,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,MAAM,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EACL,eAAe,EACf,aAAa,EACb,wBAAwB,EACxB,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,eAAe,EAAE,qBAAqB,EAAE,YAAY,EAAE,wBAAwB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpK,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EACL,cAAc,EACd,SAAS,EACT,UAAU,EACV,aAAa,EACb,WAAW,EACX,WAAW,EACX,WAAW,EACX,MAAM,EACN,SAAS,EACT,SAAS,EACT,YAAY,EACZ,aAAa,GACd,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC/F,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AACtF,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,iDAAiD;IACjD,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,qCAAqC;IACrC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;CAChD;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,gDAAgD;IAChD,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,wBAAwB;IACxB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;IAE/C,oCAAoC;IACpC,MAAM,CAAC,EAAE,WAAW,CAAC;IAErB,kEAAkE;IAClE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;GAIG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,EAAE,CAAqB;IAC/B,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,WAAW,CAAS;IAI5B,OAAO,CAAC,YAAY,CAA0B;IAC9C,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,cAAc,CAAkB;IAGxC,OAAO,CAAC,UAAU,CAAe;IAGjC,OAAO,CAAC,QAAQ,CAAW;IAG3B,OAAO,CAAC,OAAO,CAA4B;IAE3C,OAAO;IAcP;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAmBlB;;;;;;;;;;;;;OAaG;IACH,gBAAgB,IAAI,OAAO;IAqB3B;;;;;;;;OAQG;WACU,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,SAAS,CAAC;IA2BrF;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS;IAmB/C;;;;;;OAMG;WACU,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,SAAS,CAAC;IA8BrF;;;;;;;;;;;;;;;OAeG;WACU,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAgC9D;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS;IAsB/C;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAIlD;;OAEG;IACH,KAAK,IAAI,IAAI;IAOb;;OAEG;IACH,cAAc,IAAI,MAAM;IAQxB;;;;OAIG;IACG,QAAQ,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,WAAW,CAAC;IAgIhE;;;;OAIG;IACG,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IAe3D;;;;OAIG;IACG,IAAI,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,UAAU,CAAC;IAiI3D;;OAEG;IACH,UAAU,IAAI,OAAO;IAQrB;;;;;;;;OAQG;IACH,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO;IAwB1C;;OAEG;IACH,OAAO,IAAI,IAAI;IAOf;;OAEG;IACH,UAAU,IAAI,OAAO;IAIrB;;;;;;;OAOG;IACH,iBAAiB,IAAI,OAAO;IAI5B,0EAA0E;IAC1E,wBAAwB,IAAI,MAAM,GAAG,IAAI;IAIzC;;;;;;;;;;;OAWG;IACH,eAAe,IAAI,WAAW,EAAE;IAIhC;;;;OAIG;IACH,qBAAqB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxD;;OAEG;IACH,eAAe,IAAI;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE;IAI7E;;;;OAIG;IACH,gBAAgB,IAAI,MAAM,GAAG,IAAI;IAIjC;;;;;;;;OAQG;IACH,aAAa,IAAI,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,IAAI;IAOtE;;;;;OAKG;IACH,iBAAiB,IAAI;QAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;IAOjF;;;;;;OAMG;IACH,YAAY,IAAI,OAAO;IAMvB;;OAEG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB;IAQrE;;;;;;;;OAQG;IACH,iBAAiB,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,gBAAgB;IAM1F;;;OAGG;IACG,wBAAwB,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAIhH;;;;;OAKG;IACH,wBAAwB,IAAI,MAAM;IAIlC;;OAEG;IACH,qBAAqB,IAAI,MAAM,EAAE;IAIjC;;OAEG;IACH,oBAAoB,IAAI,IAAI;IAQ5B;;OAEG;IACH,QAAQ,IAAI,UAAU;IAMtB;;;;OAIG;IACH,UAAU,IAAI,OAAO,MAAM,EAAE,aAAa;IAI1C;;;;;OAKG;IACH,cAAc,IAAI,MAAM;IAQxB;;OAEG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAIhC;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE;IAIxC;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE;IAI1C;;;;OAIG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE;IAIpC,wEAAwE;IACxE,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,IAAI,EAAE;IAIxD;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,YAAY,EAAE;IAInE;;;;;;;;;;;;;;;OAeG;IACH,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,GAAE,MAAU,GAAG,YAAY,EAAE;IA8ErE;;0EAEsE;IACtE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAAM;IAEpD;;sDAEkD;IAClD,OAAO,CAAC,iBAAiB;IASzB;;;;;;;;;OASG;IACG,uBAAuB,IAAI,OAAO,CAAC,OAAO,CAAC;IAsBjD;;;;;OAKG;YACW,uBAAuB;IAWrC;;;;;;OAMG;IACH,oBAAoB,IAAI,GAAG,CAAC,MAAM,CAAC;IAInC;;;;;;;OAOG;IACH,eAAe,IAAI;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAIvF;;;;;OAKG;IACH,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG;QAClC,OAAO,EAAE,KAAK,CAAC;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAChH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,mBAAmB,EAAE,MAAM,CAAC;QAC5B,WAAW,EAAE,MAAM,CAAC;KACrB,GAAG,IAAI;IAQR;;OAEG;IACH,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE;IAIxC;;OAEG;IACH,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE;IAQxC;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAI5C;;OAEG;IACH,QAAQ,IAAI,UAAU,EAAE;IAQxB;;;;;;;;;OASG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAInC;;;;;;;;;OASG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,QAAQ;IAI/D;;;;;;;;;OASG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,QAAQ;IAIzD;;;;;;;;OAQG;IACH,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ;IAI1C;;;;;;;;OAQG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,IAAI,CAAA;KAAE,CAAC;IAI7D;;;;;;OAMG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAU,GAAG,KAAK,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,IAAI,CAAA;KAAE,CAAC;IAInF;;;;;;OAMG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAU,GAAG,KAAK,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,IAAI,CAAA;KAAE,CAAC;IAInF;;;;;;;;OAQG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAU,GAAG,QAAQ;IAI/D;;;;;;;OAOG;IACH,QAAQ,CACN,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,GACzB,KAAK,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;KAAE,CAAC,GAAG,IAAI;IAIlD;;;;;OAKG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE;IAIpC;;;;;OAKG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE;IAInC;;;;;OAKG;IACH,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAI/C;;;;;OAKG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAI7C;;;;OAIG;IACH,wBAAwB,IAAI,MAAM,EAAE,EAAE;IAItC;;;;;OAKG;IACH,YAAY,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,EAAE;IAI5C;;;;;OAKG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG;QAC9B,iBAAiB,EAAE,MAAM,CAAC;QAC1B,iBAAiB,EAAE,MAAM,CAAC;QAC1B,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;KACf;IAQD;;;;;;;OAOG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIrD;;;;;;;;;OASG;IACG,mBAAmB,CACvB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,0BAA0B,GACnC,OAAO,CAAC,QAAQ,CAAC;IAIpB;;;;;;;;;;;;OAYG;IACG,YAAY,CAChB,KAAK,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC;IAQhC;;OAEG;IACH,QAAQ,IAAI,IAAI;IAIhB;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;;OAGG;IACH,OAAO,IAAI,IAAI;IAIf;;;;;OAKG;IACH,YAAY,IAAI,IAAI;CAIrB;AAGD,eAAe,SAAS,CAAC"}
|
package/lib/dist/index.js
CHANGED
|
@@ -57,6 +57,8 @@ const extraction_version_1 = require("./extraction/extraction-version");
|
|
|
57
57
|
const directory_2 = require("./directory");
|
|
58
58
|
const query_utils_1 = require("./search/query-utils");
|
|
59
59
|
const version_1 = require("./mcp/version");
|
|
60
|
+
const identifier_segments_1 = require("./search/identifier-segments");
|
|
61
|
+
const cooperative_yield_1 = require("./resolution/cooperative-yield");
|
|
60
62
|
// Re-export types for consumers
|
|
61
63
|
__exportStar(require("./types"), exports);
|
|
62
64
|
// Storage building blocks for embedded/SDK consumers that drive the graph
|
|
@@ -370,6 +372,21 @@ class CodeGraph {
|
|
|
370
372
|
}
|
|
371
373
|
try {
|
|
372
374
|
const before = this.queries.getNodeAndEdgeCount();
|
|
375
|
+
// Mark the index as in-flight BEFORE any writes: a run killed
|
|
376
|
+
// mid-index (OOM, SIGKILL, the #850 liveness watchdog) leaves this
|
|
377
|
+
// marker behind, so `codegraph status` can tell a truncated index
|
|
378
|
+
// from a completed one instead of silently serving partial results.
|
|
379
|
+
try {
|
|
380
|
+
this.queries.setMetadata('index_state', 'indexing');
|
|
381
|
+
}
|
|
382
|
+
catch { /* metadata is advisory */ }
|
|
383
|
+
// Segment vocabulary starts empty and is repopulated by the node write
|
|
384
|
+
// path as every file (re-)indexes below — so a full index is also the
|
|
385
|
+
// orphan-cleanup pass for names deleted since the last one.
|
|
386
|
+
try {
|
|
387
|
+
this.queries.clearNameSegmentVocab();
|
|
388
|
+
}
|
|
389
|
+
catch { /* vocab is advisory — never fail an index over it */ }
|
|
373
390
|
const result = await this.orchestrator.indexAll(options.onProgress, options.signal, options.verbose);
|
|
374
391
|
// Re-detect frameworks now that the index is populated. The resolver
|
|
375
392
|
// is constructed with createResolver() before any files exist, so
|
|
@@ -434,6 +451,39 @@ class CodeGraph {
|
|
|
434
451
|
}
|
|
435
452
|
catch { /* metadata is advisory — never fail an index over it */ }
|
|
436
453
|
}
|
|
454
|
+
// Reconcile the scan's ground truth against what the pipeline
|
|
455
|
+
// accounted for. A shortfall means files were silently dropped
|
|
456
|
+
// (observed in the wild: a run under heavy load came up 37 files
|
|
457
|
+
// short with no error) — record it and tell the user, don't let the
|
|
458
|
+
// index pass as complete.
|
|
459
|
+
try {
|
|
460
|
+
if (!result.success) {
|
|
461
|
+
this.queries.setMetadata('index_state', 'failed');
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
const accounted = result.filesIndexed + result.filesSkipped + result.filesErrored;
|
|
465
|
+
const discovered = result.filesDiscovered;
|
|
466
|
+
const shortfall = discovered !== undefined ? discovered - accounted : 0;
|
|
467
|
+
if (discovered !== undefined && shortfall > 0) {
|
|
468
|
+
this.queries.setMetadata('index_state', 'partial');
|
|
469
|
+
this.queries.setMetadata('index_files_discovered', String(discovered));
|
|
470
|
+
this.queries.setMetadata('index_files_accounted', String(accounted));
|
|
471
|
+
result.errors.push({
|
|
472
|
+
message: `Index is missing ${shortfall} of ${discovered} discovered files (indexed ${result.filesIndexed}, skipped ${result.filesSkipped}, errored ${result.filesErrored}). The index is PARTIAL — re-run \`codegraph index\`.`,
|
|
473
|
+
severity: 'warning',
|
|
474
|
+
code: 'index_partial',
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
this.queries.setMetadata('index_state', 'complete');
|
|
479
|
+
if (discovered !== undefined) {
|
|
480
|
+
this.queries.setMetadata('index_files_discovered', String(discovered));
|
|
481
|
+
this.queries.setMetadata('index_files_accounted', String(accounted));
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
catch { /* metadata is advisory — never fail an index over it */ }
|
|
437
487
|
return result;
|
|
438
488
|
}
|
|
439
489
|
finally {
|
|
@@ -476,6 +526,18 @@ class CodeGraph {
|
|
|
476
526
|
return { filesChecked: 0, filesAdded: 0, filesModified: 0, filesRemoved: 0, nodesUpdated: 0, durationMs: 0 };
|
|
477
527
|
}
|
|
478
528
|
try {
|
|
529
|
+
// Captured BEFORE the sync runs: the sync's own incremental writes
|
|
530
|
+
// populate vocab rows for the files it touches, so an end-of-sync
|
|
531
|
+
// emptiness check would see "non-empty" and skip the backfill forever,
|
|
532
|
+
// leaving every unchanged file's names unsegmented.
|
|
533
|
+
const vocabWasEmpty = (() => {
|
|
534
|
+
try {
|
|
535
|
+
return this.queries.isNameSegmentVocabEmpty();
|
|
536
|
+
}
|
|
537
|
+
catch {
|
|
538
|
+
return false;
|
|
539
|
+
}
|
|
540
|
+
})();
|
|
479
541
|
const result = await this.orchestrator.sync(options.onProgress);
|
|
480
542
|
// Cross-file finalization (e.g. NestJS RouterModule prefixes). Run on
|
|
481
543
|
// every sync that touched files so edits to `app.module.ts` propagate
|
|
@@ -485,7 +547,8 @@ class CodeGraph {
|
|
|
485
547
|
this.resolver.runPostExtract();
|
|
486
548
|
}
|
|
487
549
|
// Resolve references if files were updated
|
|
488
|
-
|
|
550
|
+
const filesChanged = result.filesAdded > 0 || result.filesModified > 0;
|
|
551
|
+
if (filesChanged) {
|
|
489
552
|
if (result.changedFilePaths) {
|
|
490
553
|
// Scope resolution to changed files (git fast path — bounded set)
|
|
491
554
|
const unresolvedRefs = this.queries.getUnresolvedReferencesByFiles(result.changedFilePaths);
|
|
@@ -518,6 +581,35 @@ class CodeGraph {
|
|
|
518
581
|
});
|
|
519
582
|
});
|
|
520
583
|
}
|
|
584
|
+
}
|
|
585
|
+
// Orphan sweep (#1187). A resolution pass that dies mid-run — the #850
|
|
586
|
+
// daemon liveness watchdog's SIGKILL (#1122), Ctrl-C, a crash — leaves
|
|
587
|
+
// the refs it never reached in unresolved_refs, and the git-scoped fast
|
|
588
|
+
// path above never revisits them (it reads only the changed files'
|
|
589
|
+
// rows). Those files' call edges were then missing PERMANENTLY, with
|
|
590
|
+
// nothing to see except a too-small blast radius, until a full
|
|
591
|
+
// re-index. A completed pass deletes every row it processed (resolved
|
|
592
|
+
// or not), so any row still present now is such an orphan — or a row
|
|
593
|
+
// parked by an older engine whose scoped pass kept unresolvable refs.
|
|
594
|
+
// Grind them down with the batched resolver; this also makes a bare
|
|
595
|
+
// `codegraph sync` the recovery command for a wedged index. On a
|
|
596
|
+
// healthy index this is one COUNT query.
|
|
597
|
+
const orphanCount = this.queries.getUnresolvedReferencesCount();
|
|
598
|
+
if (orphanCount > 0) {
|
|
599
|
+
options.onProgress?.({
|
|
600
|
+
phase: 'resolving',
|
|
601
|
+
current: 0,
|
|
602
|
+
total: orphanCount,
|
|
603
|
+
});
|
|
604
|
+
await this.resolveReferencesBatched((current, total) => {
|
|
605
|
+
options.onProgress?.({
|
|
606
|
+
phase: 'resolving',
|
|
607
|
+
current,
|
|
608
|
+
total,
|
|
609
|
+
});
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
if (filesChanged || orphanCount > 0) {
|
|
521
613
|
// Second pass: chained calls whose method lives on a supertype the
|
|
522
614
|
// receiver conforms to (protocol-extension / inherited). Needs the
|
|
523
615
|
// implements/extends edges built above (#750).
|
|
@@ -527,9 +619,21 @@ class CodeGraph {
|
|
|
527
619
|
await this.resolver.resolveDeferredThisMemberRefs();
|
|
528
620
|
}
|
|
529
621
|
// Refresh planner stats + checkpoint the WAL after bulk writes.
|
|
530
|
-
if (
|
|
622
|
+
if (filesChanged || result.filesRemoved > 0 || orphanCount > 0) {
|
|
531
623
|
this.db.runMaintenance();
|
|
532
624
|
}
|
|
625
|
+
// Heal the segment vocabulary on indexes built before the table
|
|
626
|
+
// existed (upgrade path): incremental writes above only cover changed
|
|
627
|
+
// files, so a vocab that was empty when this sync STARTED means the
|
|
628
|
+
// bulk was never segmented — backfill it (INSERT OR IGNORE, so the
|
|
629
|
+
// rows the sync just wrote are fine). Batched + yielding — sync can
|
|
630
|
+
// run on the daemon's liveness-watchdog thread (#850/#1091).
|
|
631
|
+
try {
|
|
632
|
+
if (vocabWasEmpty && this.queries.getNodeAndEdgeCount().nodes > 0) {
|
|
633
|
+
await this.rebuildNameSegmentVocab();
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
catch { /* vocab is advisory — never fail a sync over it */ }
|
|
533
637
|
return result;
|
|
534
638
|
}
|
|
535
639
|
finally {
|
|
@@ -640,6 +744,21 @@ class CodeGraph {
|
|
|
640
744
|
getLastIndexedAt() {
|
|
641
745
|
return this.queries.getLastIndexedAt();
|
|
642
746
|
}
|
|
747
|
+
/**
|
|
748
|
+
* Completeness of the last full index run. `'complete'` is the only good
|
|
749
|
+
* state. `'indexing'` after the fact means a run was killed mid-index (OOM,
|
|
750
|
+
* SIGKILL, liveness watchdog) and the on-disk index is truncated;
|
|
751
|
+
* `'partial'` means the run finished but silently dropped files
|
|
752
|
+
* (discovered > indexed+skipped+errored); `'failed'` means it reported
|
|
753
|
+
* failure. `null` = index predates this marker. Surfaced by
|
|
754
|
+
* `codegraph status`.
|
|
755
|
+
*/
|
|
756
|
+
getIndexState() {
|
|
757
|
+
const raw = this.queries.getMetadata('index_state');
|
|
758
|
+
return raw === 'indexing' || raw === 'complete' || raw === 'partial' || raw === 'failed'
|
|
759
|
+
? raw
|
|
760
|
+
: null;
|
|
761
|
+
}
|
|
643
762
|
/**
|
|
644
763
|
* Which engine built the current index: the package version + extraction
|
|
645
764
|
* version stamped at the last full `indexAll`. Either field is null for an
|
|
@@ -695,6 +814,15 @@ class CodeGraph {
|
|
|
695
814
|
async resolveReferencesBatched(onProgress) {
|
|
696
815
|
return this.resolver.resolveAndPersistBatched(onProgress);
|
|
697
816
|
}
|
|
817
|
+
/**
|
|
818
|
+
* References extracted but not yet resolved into edges. Zero on a healthy
|
|
819
|
+
* index — a completed resolution pass consumes every row. Non-zero at rest
|
|
820
|
+
* means a pass was interrupted mid-run (killed indexer, crash — #1187), so
|
|
821
|
+
* some files' call edges are missing; the next `sync` sweeps them.
|
|
822
|
+
*/
|
|
823
|
+
getPendingReferenceCount() {
|
|
824
|
+
return this.queries.getUnresolvedReferencesCount();
|
|
825
|
+
}
|
|
698
826
|
/**
|
|
699
827
|
* Get detected frameworks in the project
|
|
700
828
|
*/
|
|
@@ -764,12 +892,188 @@ class CodeGraph {
|
|
|
764
892
|
getNodesByName(name) {
|
|
765
893
|
return this.queries.getNodesByName(name);
|
|
766
894
|
}
|
|
895
|
+
/** Nodes whose name starts with `prefix` (index range scan, capped). */
|
|
896
|
+
getNodesByNamePrefix(prefix, limit = 20) {
|
|
897
|
+
return this.queries.getNodesByNamePrefix(prefix, limit);
|
|
898
|
+
}
|
|
767
899
|
/**
|
|
768
900
|
* Search nodes by text
|
|
769
901
|
*/
|
|
770
902
|
searchNodes(query, options) {
|
|
771
903
|
return this.queries.searchNodes(query, options);
|
|
772
904
|
}
|
|
905
|
+
/**
|
|
906
|
+
* Graph-derived prompt matching for the front-load hook's MEDIUM tier:
|
|
907
|
+
* which indexed symbols do these prose words name? "state machine des
|
|
908
|
+
* commandes" → `OrderStateMachine`, in any human language whose technical
|
|
909
|
+
* nouns are Latin script — no keyword list involved.
|
|
910
|
+
*
|
|
911
|
+
* Precision comes from the repo's own naming statistics, not vocabulary:
|
|
912
|
+
* - CO-OCCURRENCE: ≥2 words that are segments of the SAME name ("state" +
|
|
913
|
+
* "machine" → OrderStateMachine) is strong evidence and always qualifies.
|
|
914
|
+
* - RARITY: a single matched word qualifies only when its segment is
|
|
915
|
+
* discriminative here (≤ {@link SEGMENT_RARITY_CEILING} distinct names) —
|
|
916
|
+
* "checkout" in a shop backend yes, "state" in a react app no.
|
|
917
|
+
* Every candidate is re-verified against `nodes` before being returned
|
|
918
|
+
* (vocab rows are proposals; deletions leave orphans by design), so a
|
|
919
|
+
* returned symbol is guaranteed to exist right now.
|
|
920
|
+
*/
|
|
921
|
+
getSegmentMatches(words, limit = 6) {
|
|
922
|
+
if (words.length === 0)
|
|
923
|
+
return [];
|
|
924
|
+
// Variant → original word (plural folding), for coverage accounting.
|
|
925
|
+
const variantToWord = new Map();
|
|
926
|
+
for (const word of words) {
|
|
927
|
+
for (const variant of (0, identifier_segments_1.segmentLookupVariants)(word)) {
|
|
928
|
+
if (!variantToWord.has(variant))
|
|
929
|
+
variantToWord.set(variant, word);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
const variants = [...variantToWord.keys()];
|
|
933
|
+
// Tier A: co-occurrence. The SQL folds variants back to their original
|
|
934
|
+
// word (#1146), so minWords=2 means two distinct PROMPT WORDS — a name
|
|
935
|
+
// matching both `service` and `services` can't tie with (or crowd past
|
|
936
|
+
// the LIMIT) a genuine two-word match. The JS re-check below recomputes
|
|
937
|
+
// the fold from live segments as the honesty layer.
|
|
938
|
+
const variantPairs = [...variantToWord.entries()].map(([segment, word]) => ({ segment, word }));
|
|
939
|
+
const candidates = [];
|
|
940
|
+
for (const hit of this.queries.getSegmentCoOccurrence(variantPairs, 2, 24)) {
|
|
941
|
+
const matched = this.wordsMatchingName(hit.name, variantToWord);
|
|
942
|
+
if (matched.size >= 2)
|
|
943
|
+
candidates.push({ name: hit.name, matchedWords: matched });
|
|
944
|
+
}
|
|
945
|
+
// Tier B: single rare word. Only when co-occurrence found nothing — a
|
|
946
|
+
// co-occurring name is categorically stronger evidence — and under
|
|
947
|
+
// stricter rules, because one word is thin: the word must be ≥5 chars
|
|
948
|
+
// (measured FPs: "this", "typo"); the segment must appear in AT LEAST TWO
|
|
949
|
+
// names (a concept the codebase is about clusters across names —
|
|
950
|
+
// CheckoutService/CheckoutController — while a prose coincidence is a
|
|
951
|
+
// singleton: measured FP "deploy to PRODUCTION" → the one name
|
|
952
|
+
// matchesNonProductionDir); and the candidate name must have ≥2 segments
|
|
953
|
+
// (a bare common verb matching a bare function name — "write" → `write` —
|
|
954
|
+
// is prose coincidence, not the user naming a symbol).
|
|
955
|
+
if (candidates.length === 0) {
|
|
956
|
+
const singleWordVariants = variants.filter((v) => variantToWord.get(v).length >= 5);
|
|
957
|
+
const counts = this.queries.getSegmentNameCounts(singleWordVariants);
|
|
958
|
+
const rare = [...counts.entries()]
|
|
959
|
+
.filter(([, n]) => n >= 2 && n <= CodeGraph.SEGMENT_RARITY_CEILING)
|
|
960
|
+
.sort((a, b) => a[1] - b[1])
|
|
961
|
+
.slice(0, 2);
|
|
962
|
+
for (const [variant] of rare) {
|
|
963
|
+
const word = variantToWord.get(variant);
|
|
964
|
+
for (const name of this.queries.getNamesForSegment(variant, 12)) {
|
|
965
|
+
if ((0, identifier_segments_1.splitIdentifierSegments)(name).length < 2)
|
|
966
|
+
continue;
|
|
967
|
+
candidates.push({ name, matchedWords: new Set([word]) });
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
// Verify against nodes (the honesty gate) and pick a representative
|
|
972
|
+
// definition per name. A name whose only nodes are file/import kind has
|
|
973
|
+
// no real definition to point at — surfacing the import statement instead
|
|
974
|
+
// reads as a matched symbol but isn't one (#1144) — so it's skipped, the
|
|
975
|
+
// same way an orphaned vocab row is. (Import names no longer enter the
|
|
976
|
+
// vocab at write time, but rows written before that exclusion persist
|
|
977
|
+
// until the next full index.)
|
|
978
|
+
const out = [];
|
|
979
|
+
const seen = new Set();
|
|
980
|
+
candidates.sort((a, b) => b.matchedWords.size - a.matchedWords.size || a.name.length - b.name.length);
|
|
981
|
+
for (const candidate of candidates) {
|
|
982
|
+
if (out.length >= limit)
|
|
983
|
+
break;
|
|
984
|
+
if (seen.has(candidate.name))
|
|
985
|
+
continue;
|
|
986
|
+
seen.add(candidate.name);
|
|
987
|
+
const nodes = this.queries.getNodesByName(candidate.name);
|
|
988
|
+
if (nodes.length === 0)
|
|
989
|
+
continue; // orphaned vocab row — name no longer exists
|
|
990
|
+
const rep = nodes.find((n) => n.kind !== 'file' && n.kind !== 'import');
|
|
991
|
+
if (!rep)
|
|
992
|
+
continue; // no real definition — don't surface an import/file as one
|
|
993
|
+
out.push({
|
|
994
|
+
name: candidate.name,
|
|
995
|
+
kind: rep.kind,
|
|
996
|
+
filePath: rep.filePath,
|
|
997
|
+
startLine: rep.startLine ?? 0,
|
|
998
|
+
matchedWords: [...candidate.matchedWords].sort(),
|
|
999
|
+
});
|
|
1000
|
+
}
|
|
1001
|
+
return out;
|
|
1002
|
+
}
|
|
1003
|
+
/** A single word ("state") can match hundreds of names in a big repo — that
|
|
1004
|
+
* is noise, not signal. Ceiling for the single-word tier; co-occurrence is
|
|
1005
|
+
* exempt because two words on one name is already discriminative. */
|
|
1006
|
+
static SEGMENT_RARITY_CEILING = 25;
|
|
1007
|
+
/** Which of the prompt's original words match `name`'s segments (via
|
|
1008
|
+
* variants). Segments are recomputed in JS — a name-keyed vocab lookup
|
|
1009
|
+
* would scan the (segment, name) primary key. */
|
|
1010
|
+
wordsMatchingName(name, variantToWord) {
|
|
1011
|
+
const segments = new Set((0, identifier_segments_1.splitIdentifierSegments)(name));
|
|
1012
|
+
const matched = new Set();
|
|
1013
|
+
for (const [variant, word] of variantToWord) {
|
|
1014
|
+
if (segments.has(variant))
|
|
1015
|
+
matched.add(word);
|
|
1016
|
+
}
|
|
1017
|
+
return matched;
|
|
1018
|
+
}
|
|
1019
|
+
/**
|
|
1020
|
+
* One-shot upgrade heal for callers that open the graph WITHOUT syncing —
|
|
1021
|
+
* concretely the prompt hook, whose MEDIUM tier reads the segment
|
|
1022
|
+
* vocabulary: a database migrated from before the vocab table existed
|
|
1023
|
+
* starts with it empty, and the only other backfill lives inside `sync()`,
|
|
1024
|
+
* which such callers never run (#1142). Returns true when the vocab is
|
|
1025
|
+
* usable (already populated — the overwhelmingly common one-SELECT case —
|
|
1026
|
+
* or healed here); false when it isn't (empty graph, or another process
|
|
1027
|
+
* holds the index lock — that process's own sync heals it).
|
|
1028
|
+
*/
|
|
1029
|
+
async healSegmentVocabIfEmpty() {
|
|
1030
|
+
const empty = (() => {
|
|
1031
|
+
try {
|
|
1032
|
+
return this.queries.isNameSegmentVocabEmpty();
|
|
1033
|
+
}
|
|
1034
|
+
catch {
|
|
1035
|
+
return false;
|
|
1036
|
+
}
|
|
1037
|
+
})();
|
|
1038
|
+
if (!empty)
|
|
1039
|
+
return true;
|
|
1040
|
+
if (this.queries.getNodeAndEdgeCount().nodes === 0)
|
|
1041
|
+
return false;
|
|
1042
|
+
return this.indexMutex.withLock(async () => {
|
|
1043
|
+
try {
|
|
1044
|
+
this.fileLock.acquire();
|
|
1045
|
+
}
|
|
1046
|
+
catch {
|
|
1047
|
+
return false; // an index/sync is running — it backfills the vocab itself
|
|
1048
|
+
}
|
|
1049
|
+
try {
|
|
1050
|
+
if (!this.queries.isNameSegmentVocabEmpty())
|
|
1051
|
+
return true; // raced: healed meanwhile
|
|
1052
|
+
await this.rebuildNameSegmentVocab();
|
|
1053
|
+
return true;
|
|
1054
|
+
}
|
|
1055
|
+
finally {
|
|
1056
|
+
this.fileLock.release();
|
|
1057
|
+
}
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
1060
|
+
/**
|
|
1061
|
+
* Rebuild the segment vocabulary from the current graph, batched and
|
|
1062
|
+
* yielding — the upgrade-heal path for indexes built before the vocab table
|
|
1063
|
+
* existed. Runs inside the index mutex/lock (sync and
|
|
1064
|
+
* healSegmentVocabIfEmpty hold them).
|
|
1065
|
+
*/
|
|
1066
|
+
async rebuildNameSegmentVocab() {
|
|
1067
|
+
const maybeYield = (0, cooperative_yield_1.createYielder)();
|
|
1068
|
+
const BATCH = 2000;
|
|
1069
|
+
for (let offset = 0;; offset += BATCH) {
|
|
1070
|
+
const names = this.queries.getDistinctNodeNames(BATCH, offset);
|
|
1071
|
+
if (names.length === 0)
|
|
1072
|
+
break;
|
|
1073
|
+
this.queries.insertNameSegmentsBatch(names);
|
|
1074
|
+
await maybeYield();
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
773
1077
|
/**
|
|
774
1078
|
* Normalized project-name tokens (go.mod / package.json / repo dir) used to
|
|
775
1079
|
* down-weight the non-discriminative project name in search ranking (#720).
|