@aroman22/codegraph-vba 1.5.2 → 1.6.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.
Files changed (76) hide show
  1. package/README.md +1 -1
  2. package/dist/bin/codegraph.d.ts +1 -1
  3. package/dist/bin/command-supervision.d.ts +38 -1
  4. package/dist/db/index.d.ts +84 -5
  5. package/dist/db/migrations.d.ts +1 -1
  6. package/dist/db/queries.d.ts +116 -4
  7. package/dist/db/wal-valve.d.ts +106 -0
  8. package/dist/directory.d.ts +9 -5
  9. package/dist/extraction/cfml-extractor.d.ts +107 -0
  10. package/dist/extraction/grammars.d.ts +25 -1
  11. package/dist/extraction/index.d.ts +47 -2
  12. package/dist/extraction/languages/arkts.d.ts +3 -0
  13. package/dist/extraction/languages/c-cpp.d.ts +98 -0
  14. package/dist/extraction/languages/cfquery.d.ts +12 -0
  15. package/dist/extraction/languages/cfscript.d.ts +3 -0
  16. package/dist/extraction/languages/cobol.d.ts +33 -0
  17. package/dist/extraction/languages/erlang.d.ts +3 -0
  18. package/dist/extraction/languages/nix.d.ts +3 -0
  19. package/dist/extraction/languages/solidity.d.ts +3 -0
  20. package/dist/extraction/languages/terraform.d.ts +3 -0
  21. package/dist/extraction/languages/vbnet.d.ts +11 -0
  22. package/dist/extraction/mybatis-extractor.d.ts +30 -10
  23. package/dist/extraction/parse-pool.d.ts +28 -1
  24. package/dist/extraction/tree-sitter-types.d.ts +20 -1
  25. package/dist/extraction/tree-sitter.d.ts +60 -1
  26. package/dist/extraction/vba/call-sweep.d.ts +3 -0
  27. package/dist/extraction/vba/calls.d.ts +55 -0
  28. package/dist/extraction/vba/constants.d.ts +42 -0
  29. package/dist/extraction/vba/context.d.ts +175 -0
  30. package/dist/extraction/vba/controls.d.ts +24 -0
  31. package/dist/extraction/vba/declarations.d.ts +3 -0
  32. package/dist/extraction/vba/dims.d.ts +3 -0
  33. package/dist/extraction/vba/docmd.d.ts +16 -0
  34. package/dist/extraction/vba/enums-consts.d.ts +15 -0
  35. package/dist/extraction/vba/implements.d.ts +3 -0
  36. package/dist/extraction/vba/procedures.d.ts +3 -0
  37. package/dist/extraction/vba/sql-wrapper.d.ts +17 -0
  38. package/dist/extraction/vba/tempvars.d.ts +10 -0
  39. package/dist/extraction/vba/text-utils.d.ts +73 -0
  40. package/dist/extraction/vba-extractor.d.ts +3 -951
  41. package/dist/extraction/vba-preprocess.d.ts +1 -1
  42. package/dist/index.d.ts +81 -1
  43. package/dist/installer/index.d.ts +42 -0
  44. package/dist/mcp/daemon.d.ts +35 -3
  45. package/dist/mcp/early-ppid.d.ts +26 -0
  46. package/dist/mcp/liveness-watchdog.d.ts +18 -1
  47. package/dist/mcp/query-pool.d.ts +14 -0
  48. package/dist/mcp/session.d.ts +14 -0
  49. package/dist/mcp/startup-handshake.d.ts +44 -0
  50. package/dist/mcp/tools.d.ts +22 -0
  51. package/dist/project-config.d.ts +44 -0
  52. package/dist/resolution/c-fnptr-synthesizer.d.ts +2 -1
  53. package/dist/resolution/callback-synthesizer.d.ts +1 -1
  54. package/dist/resolution/cooperative-yield.d.ts +32 -0
  55. package/dist/resolution/frameworks/cics.d.ts +20 -0
  56. package/dist/resolution/frameworks/terraform.d.ts +38 -0
  57. package/dist/resolution/goframe-synthesizer.d.ts +2 -1
  58. package/dist/resolution/import-resolver.d.ts +7 -0
  59. package/dist/resolution/index.d.ts +64 -2
  60. package/dist/resolution/name-matcher.d.ts +22 -3
  61. package/dist/resolution/strip-comments.d.ts +1 -1
  62. package/dist/resolution/types.d.ts +29 -0
  63. package/dist/resolution/workspace-packages.d.ts +10 -0
  64. package/dist/search/identifier-segments.d.ts +60 -0
  65. package/dist/sync/watcher.d.ts +10 -5
  66. package/dist/sync/worktree.d.ts +9 -0
  67. package/dist/types.d.ts +25 -2
  68. package/dist/upgrade/index.d.ts +32 -0
  69. package/dist/upgrade/remove-binary.d.ts +87 -0
  70. package/dist/upgrade/update-check.d.ts +92 -0
  71. package/npm-shim.js +32 -3
  72. package/package.json +7 -7
  73. package/dist/reasoning/config.d.ts +0 -45
  74. package/dist/reasoning/credentials.d.ts +0 -5
  75. package/dist/reasoning/login.d.ts +0 -21
  76. package/dist/reasoning/reasoner.d.ts +0 -43
@@ -96,7 +96,7 @@ export declare function stripVbaComments(src: string): string;
96
96
  * downstream extraction keeps source-line parity. Unsupported/unsafe
97
97
  * expressions evaluate to false rather than throwing.
98
98
  */
99
- export declare function preprocessConditionalCompilation(src: string): string;
99
+ export declare function preprocessConditionalCompilation(src: string, customTargets?: Record<string, boolean>): string;
100
100
  export interface StringLiteralSpan {
101
101
  /** The literal content (no surrounding quotes; `""` collapsed to `"`). */
102
102
  text: string;
package/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';
@@ -110,6 +110,23 @@ export declare class CodeGraph {
110
110
  * @returns A CodeGraph instance
111
111
  */
112
112
  static open(projectRoot: string, options?: OpenOptions): Promise<CodeGraph>;
113
+ /**
114
+ * Rebuild the project's database from scratch and return a fresh, empty
115
+ * instance — the "same result as a fresh init" semantics that `codegraph
116
+ * index` documents.
117
+ *
118
+ * Unlike `open()` followed by `clear()`, this DISCARDS the existing
119
+ * `.codegraph/codegraph.db` (and its `-wal`/`-shm` sidecars) before
120
+ * re-initializing, instead of opening the old database and DELETE-ing every
121
+ * row. On a large or pre-fix poisoned index — e.g. an old graph that scanned
122
+ * an ignored gitlink corpus (#1065) into ~1.6M nodes with a multi-GB WAL —
123
+ * the per-row `nodes_fts` delete-trigger churn blocks the main thread long
124
+ * enough to trip the #850 liveness watchdog before indexing even starts, so a
125
+ * full re-index could never recover the bad state (#1067). Discarding the
126
+ * files is O(1) regardless of size, reclaims the disk, and sidesteps opening
127
+ * (and running migrations against) the poisoned database entirely.
128
+ */
129
+ static recreate(projectRoot: string): Promise<CodeGraph>;
113
130
  /**
114
131
  * Open synchronously (without sync)
115
132
  */
@@ -210,6 +227,16 @@ export declare class CodeGraph {
210
227
  * freshness without shelling out to `codegraph status --json`. (#329)
211
228
  */
212
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;
213
240
  /**
214
241
  * Which engine built the current index: the package version + extraction
215
242
  * version stamped at the last full `indexAll`. Either field is null for an
@@ -247,6 +274,14 @@ export declare class CodeGraph {
247
274
  * Processes chunks of unresolved refs, persisting results after each batch.
248
275
  */
249
276
  resolveReferencesBatched(onProgress?: (current: number, total: number) => void): Promise<ResolutionResult>;
277
+ /**
278
+ * References extracted but never attempted by a resolution pass. Zero on a
279
+ * healthy index — a completed pass consumes every pending row (resolving it
280
+ * or parking it as failed, #1240). Non-zero at rest means a pass was
281
+ * interrupted mid-run (killed indexer, crash — #1187), so some files' call
282
+ * edges are missing; the next `sync` sweeps them.
283
+ */
284
+ getPendingReferenceCount(): number;
250
285
  /**
251
286
  * Get detected frameworks in the project
252
287
  */
@@ -290,10 +325,55 @@ export declare class CodeGraph {
290
325
  * definition the caller wants is never dropped below a search cut.
291
326
  */
292
327
  getNodesByName(name: string): Node[];
328
+ /** Nodes whose name starts with `prefix` (index range scan, capped). */
329
+ getNodesByNamePrefix(prefix: string, limit?: number): Node[];
293
330
  /**
294
331
  * Search nodes by text
295
332
  */
296
333
  searchNodes(query: string, options?: SearchOptions): SearchResult[];
334
+ /**
335
+ * Graph-derived prompt matching for the front-load hook's MEDIUM tier:
336
+ * which indexed symbols do these prose words name? "state machine des
337
+ * commandes" → `OrderStateMachine`, in any human language whose technical
338
+ * nouns are Latin script — no keyword list involved.
339
+ *
340
+ * Precision comes from the repo's own naming statistics, not vocabulary:
341
+ * - CO-OCCURRENCE: ≥2 words that are segments of the SAME name ("state" +
342
+ * "machine" → OrderStateMachine) is strong evidence and always qualifies.
343
+ * - RARITY: a single matched word qualifies only when its segment is
344
+ * discriminative here (≤ {@link SEGMENT_RARITY_CEILING} distinct names) —
345
+ * "checkout" in a shop backend yes, "state" in a react app no.
346
+ * Every candidate is re-verified against `nodes` before being returned
347
+ * (vocab rows are proposals; deletions leave orphans by design), so a
348
+ * returned symbol is guaranteed to exist right now.
349
+ */
350
+ getSegmentMatches(words: string[], limit?: number): SegmentMatch[];
351
+ /** A single word ("state") can match hundreds of names in a big repo — that
352
+ * is noise, not signal. Ceiling for the single-word tier; co-occurrence is
353
+ * exempt because two words on one name is already discriminative. */
354
+ private static readonly SEGMENT_RARITY_CEILING;
355
+ /** Which of the prompt's original words match `name`'s segments (via
356
+ * variants). Segments are recomputed in JS — a name-keyed vocab lookup
357
+ * would scan the (segment, name) primary key. */
358
+ private wordsMatchingName;
359
+ /**
360
+ * One-shot upgrade heal for callers that open the graph WITHOUT syncing —
361
+ * concretely the prompt hook, whose MEDIUM tier reads the segment
362
+ * vocabulary: a database migrated from before the vocab table existed
363
+ * starts with it empty, and the only other backfill lives inside `sync()`,
364
+ * which such callers never run (#1142). Returns true when the vocab is
365
+ * usable (already populated — the overwhelmingly common one-SELECT case —
366
+ * or healed here); false when it isn't (empty graph, or another process
367
+ * holds the index lock — that process's own sync heals it).
368
+ */
369
+ healSegmentVocabIfEmpty(): Promise<boolean>;
370
+ /**
371
+ * Rebuild the segment vocabulary from the current graph, batched and
372
+ * yielding — the upgrade-heal path for indexes built before the vocab table
373
+ * existed. Runs inside the index mutex/lock (sync and
374
+ * healSegmentVocabIfEmpty hold them).
375
+ */
376
+ private rebuildNameSegmentVocab;
297
377
  /**
298
378
  * Normalized project-name tokens (go.mod / package.json / repo dir) used to
299
379
  * down-weight the non-discriminative project name in search ranking (#720).
@@ -46,6 +46,13 @@ export interface RunUninstallerOptions {
46
46
  location?: Location;
47
47
  /** Non-interactive: location=global, target=all, no prompts. */
48
48
  yes?: boolean;
49
+ /** Remove agent configs only — leave the CLI binary installed. */
50
+ keepCli?: boolean;
51
+ /**
52
+ * `__filename` of the CLI entry (dist/bin/codegraph.js) — install-method
53
+ * detection is keyed off the running binary's real location.
54
+ */
55
+ cliFilename?: string;
49
56
  }
50
57
  export type UninstallStatus = 'removed' | 'not-configured' | 'unsupported';
51
58
  /**
@@ -74,6 +81,41 @@ export interface UninstallReport {
74
81
  * across every target unconditionally.
75
82
  */
76
83
  export declare function uninstallTargets(targets: readonly AgentTarget[], location: Location): UninstallReport[];
84
+ export type RefreshStatus = 'refreshed' | 'unchanged' | 'not-configured' | 'unsupported';
85
+ /**
86
+ * Per-target outcome of a refresh sweep. `refreshed` means at least one
87
+ * filesystem entry was created, updated, or removed; `unchanged` means the target was
88
+ * already current (every write reported byte-identical); the other two
89
+ * mirror `UninstallStatus`.
90
+ */
91
+ export interface RefreshReport {
92
+ id: TargetId;
93
+ displayName: string;
94
+ location: Location;
95
+ status: RefreshStatus;
96
+ /** Absolute paths created, updated, or removed by the refresh. */
97
+ changedPaths: string[];
98
+ }
99
+ /**
100
+ * Pure refresh sweep — re-runs `install()` for every target that is
101
+ * ALREADY configured at `location`, so the surfaces a previous version
102
+ * wrote (the marker-fenced instructions section, the MCP server entry,
103
+ * the legacy-hook cleanups) match the binary that will serve them.
104
+ * Without this, those files keep the wording — and the tool names — of
105
+ * whatever version first wrote them, no matter how many upgrades later.
106
+ *
107
+ * Strictly a refresh, never a first install:
108
+ * - targets that aren't `alreadyConfigured` are skipped untouched;
109
+ * - permissions are not written (`autoAllow: false`) and the prompt
110
+ * hook is left as-is (`promptHook: undefined`), so choices the user
111
+ * made at install time — or by hand since — are preserved.
112
+ *
113
+ * Every write underneath is the targets' own idempotent upsert, so a
114
+ * re-run on an already-current machine reports `unchanged` everywhere.
115
+ * Exposed (and unit-tested) separately from the CLI wiring, same as
116
+ * `uninstallTargets`.
117
+ */
118
+ export declare function refreshTargets(targets: readonly AgentTarget[], location: Location): RefreshReport[];
77
119
  /**
78
120
  * Interactive uninstaller — the inverse of `runInstallerWithOptions`.
79
121
  * Asks global-vs-local first (unless `--location`/`--yes` is given),
@@ -41,6 +41,16 @@
41
41
  */
42
42
  import * as net from 'net';
43
43
  import { DaemonLockInfo } from './daemon-paths';
44
+ /**
45
+ * Finalize daemon shutdown. On POSIX, exit immediately — it's clean and fast.
46
+ * On Windows, do NOT force an exit while watchers may still be closing (that
47
+ * trips the libuv assertion above); instead mark success and let the loop drain
48
+ * to a natural exit, with an UNREF'd backstop that force-exits only if a stray
49
+ * handle would otherwise hang shutdown. Pure and platform-injected so both
50
+ * branches are unit-testable off-Windows. Returns the backstop timer (Windows)
51
+ * so callers/tests can clear it.
52
+ */
53
+ export declare function finalizeDaemonExit(platform: NodeJS.Platform, exit: (code: number) => void): NodeJS.Timeout | null;
44
54
  /** Bytes/parse-window for an oversized hello line — bounded against a malicious peer. */
45
55
  declare const MAX_HELLO_LINE_BYTES = 4096;
46
56
  /**
@@ -126,9 +136,11 @@ export declare class Daemon {
126
136
  /**
127
137
  * Defense-in-depth against a daemon that outlives its clients (#692), for the
128
138
  * cases the refcount + idle timer miss because a socket close never arrives:
129
- * - **Inactivity backstop:** exit if no inbound traffic for `maxIdleMs` while
130
- * clients are still (nominally) connected. A phantom client sends nothing,
131
- * so it can't pin the daemon past this window.
139
+ * - **Inactivity backstop:** after `maxIdleMs` with no inbound traffic, reap
140
+ * the daemon but ONLY if no connected client can be proven alive (see
141
+ * {@link backstopShouldExit}). This is the sole phantom class the sweep
142
+ * below can't catch: a client whose client-hello never arrived, so we have
143
+ * no pid to check.
132
144
  * - **Liveness sweep:** drop any client whose peer process has died (per the
133
145
  * client-hello pids), which re-arms the idle timer once the last real
134
146
  * client is gone. Catches a dead peer within one sweep instead of waiting
@@ -137,6 +149,26 @@ export declare class Daemon {
137
149
  * neither should hold it open on its own.
138
150
  */
139
151
  private startLivenessTimers;
152
+ /**
153
+ * Decide whether the inactivity backstop should reap the daemon right now.
154
+ * Public + `isAlive`-injected for deterministic tests; the timer calls it each
155
+ * tick with the real liveness probe.
156
+ *
157
+ * The backstop exists ONLY to catch a **phantom** client (#692) — one counted
158
+ * but actually gone, whose socket-close was never delivered. It must never
159
+ * reap a **live-but-quiet** session (connected, alive peer, just not querying):
160
+ * doing so silently severed the shared daemon and degraded that session — and
161
+ * any others sharing it — to an in-process engine. `lastActivityAt` only tracks
162
+ * inbound query bytes, and MCP has no keepalive, so a genuinely-live session
163
+ * trips the raw inactivity window after ~30 min of not being queried.
164
+ *
165
+ * So: once the inactivity window elapses, drop provably-dead peers (the same
166
+ * check the periodic sweep runs), then reap the daemon only when NOT ONE
167
+ * remaining client can be proven alive — i.e. every client left is an
168
+ * unknown-pid connection the sweep can't verify. A single provably-alive
169
+ * client keeps the daemon up. Has the sweep's side effect (drops dead peers).
170
+ */
171
+ backstopShouldExit(isAlive: (pid: number) => boolean): boolean;
140
172
  /**
141
173
  * Drop every connected client whose peer process is gone. Returns the count
142
174
  * reaped. `isAlive` is injected for testing. Clients with unknown pids (no
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Parent-pid baseline captured as early as possible in process life (#1185).
3
+ *
4
+ * The PPID watchdog's POSIX signal is "`process.ppid` CHANGED since startup" —
5
+ * but a launcher killed within the first ~100ms of our boot (an MCP host's
6
+ * config probe, an instant user cancel, an initialize-timeout teardown) can
7
+ * reparent this process to init BEFORE the serve/proxy code captured its
8
+ * baseline. The baseline then reads `1`, never diverges, and the watchdog is
9
+ * permanently blind — the orphaned-server accumulation reported in #1185.
10
+ * Reproduced on macOS: SIGKILL the launcher 50ms after spawn while the host
11
+ * holds the stdio pipes open, and the server survived indefinitely; at 150ms
12
+ * the old capture had already run and the watchdog reaped it.
13
+ *
14
+ * The CLI entry imports this module before anything else, so the capture runs
15
+ * within the first few ms of JS execution — the earliest a Node process can
16
+ * observe its parent. A kill landing in the remaining pre-JS window (process
17
+ * spawn → first require) still captures `1`; that residual case is covered by
18
+ * the startup-handshake timeout (see ./startup-handshake.ts), which reaps a
19
+ * server that never receives any MCP traffic.
20
+ *
21
+ * Library consumers don't load the CLI entry; for them the capture runs at
22
+ * first import of the MCP layer — no worse than the previous per-call-site
23
+ * capture, and identical once the module cache warms.
24
+ */
25
+ export declare const EARLY_PPID: number;
26
+ //# sourceMappingURL=early-ppid.d.ts.map
@@ -1,5 +1,12 @@
1
1
  /** Default: 60s — ~300× shorter than the 5h #850 wedge, far longer than any real main-thread block. */
2
2
  export declare const DEFAULT_WATCHDOG_TIMEOUT_MS = 60000;
3
+ /**
4
+ * Hard cap on disk-progress deferral: after this many timeouts' worth of
5
+ * CONTINUOUS heartbeat silence the process is killed even if the watched files
6
+ * keep advancing (a wedge coinciding with unrelated file writes, or I/O hung
7
+ * beyond any legitimate statement). 10× the 60s default ⇒ 10 minutes.
8
+ */
9
+ export declare const PROGRESS_CAP_MULTIPLIER = 10;
3
10
  /** Parse the timeout env, falling back to the default for missing/invalid values. */
4
11
  export declare function parseWatchdogTimeoutMs(raw: string | undefined, fallback?: number): number;
5
12
  /** Derive a heartbeat cadence that emits several beats inside the timeout window. */
@@ -8,11 +15,21 @@ export interface WatchdogHandle {
8
15
  /** Stop heartbeating and shut the watchdog child down. Idempotent. */
9
16
  stop(): void;
10
17
  }
18
+ export interface WatchdogOptions {
19
+ /**
20
+ * Files whose size/mtime advancing counts as forward progress (the SQLite
21
+ * DB + `-wal` for an in-process indexer). With paths supplied, a silent
22
+ * timeout only kills when the files did NOT advance — see the header. Omit
23
+ * for pure heartbeat behavior (the daemon, whose main thread never runs
24
+ * long synchronous work).
25
+ */
26
+ progressPaths?: string[];
27
+ }
11
28
  /**
12
29
  * Install the main-thread liveness watchdog for a long-lived process. Returns a
13
30
  * handle to stop it, or `null` when disabled or when the child can't be spawned
14
31
  * (degraded, never throws — a missing watchdog must never keep a process from
15
32
  * starting).
16
33
  */
17
- export declare function installMainThreadWatchdog(): WatchdogHandle | null;
34
+ export declare function installMainThreadWatchdog(options?: WatchdogOptions): WatchdogHandle | null;
18
35
  //# sourceMappingURL=liveness-watchdog.d.ts.map
@@ -81,6 +81,20 @@ export declare class QueryPool {
81
81
  * degrades to today's behavior instead of failing tool calls.
82
82
  */
83
83
  get healthy(): boolean;
84
+ /**
85
+ * True once at least one worker has completed its cold start (posted the
86
+ * 'ready' handshake). Until then the ToolHandler serves calls IN-PROCESS:
87
+ * a worker cold start is a full module load + DB open — seconds normally,
88
+ * tens of seconds on a loaded machine — and a call queued behind it gets
89
+ * nothing until the 45s busy backstop. The daemon's very first tool call
90
+ * hitting that window was the recurring #662 test flake (and a real
91
+ * first-call stall for agents). The pool exists for CONCURRENT load, which
92
+ * by definition arrives after warm-up; the pre-pool in-process path is
93
+ * strictly better while nothing is warm. Stays true for the pool's
94
+ * lifetime — later crash-respawn gaps are covered by retry + backstop.
95
+ */
96
+ get ready(): boolean;
97
+ private everReady;
84
98
  private spawnOne;
85
99
  private onMessage;
86
100
  private onWorkerGone;
@@ -21,6 +21,20 @@ export declare const SERVER_INFO: {
21
21
  name: string;
22
22
  version: string;
23
23
  };
24
+ /**
25
+ * Instructions for the `initialize` response, with the update-availability
26
+ * notice appended when one is known (#1243). Exported so the proxy's local
27
+ * handshake sends the IDENTICAL payload — same convention as SERVER_INFO.
28
+ * `getUpdateNotice` is a memoized synchronous cache read, so the #172
29
+ * respond-fast contract holds; when no notice exists the instructions are
30
+ * byte-identical to the bare constants.
31
+ *
32
+ * Test-authoring note: on a machine whose real `~/.codegraph` cache knows a
33
+ * newer release, spawned servers append the notice — a test asserting exact
34
+ * instructions equality must set `CODEGRAPH_NO_UPDATE_CHECK=1` in the spawn
35
+ * env or it will fail only in the weeks after a release ships.
36
+ */
37
+ export declare function initializeInstructions(base: string, notice?: string | null): string;
24
38
  /** MCP Protocol Version (latest the server claims). */
25
39
  export declare const PROTOCOL_VERSION = "2024-11-05";
26
40
  export interface MCPSessionOptions {
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Never-initialized backstop for `serve --mcp` (#1185).
3
+ *
4
+ * Every real MCP host sends `initialize` immediately after spawning a server.
5
+ * A server that has received NO bytes at all for many minutes is not serving
6
+ * anyone — it is the residue of an abandoned launch: the host killed the
7
+ * launcher chain during startup (config probe, instant cancel, initialize
8
+ * timeout) but kept our stdio pipe fds open, so stdin never EOFs. If the kill
9
+ * landed before {@link ../mcp/early-ppid} could observe the real parent, the
10
+ * PPID watchdog is blind too (baseline `1`), and — pre-#1185 — the orphan
11
+ * lived until the HOST process exited, accumulating one ~30MB node process
12
+ * per occurrence.
13
+ *
14
+ * This backstop closes that last hole: arm a one-shot timer at serve start
15
+ * and disarm it on the first byte of client traffic. If the timer fires, the
16
+ * caller shuts the server down. The default is deliberately generous (15
17
+ * minutes) — hosts initialize within milliseconds, so the only processes this
18
+ * ever reaps are ones nobody is talking to. It never affects a session that
19
+ * spoke even once: after the first byte the timer is gone for good (a
20
+ * quiet-but-live session is the PPID watchdog's / stdin teardown's job).
21
+ *
22
+ * IMPORTANT (callers): attaching a `'data'` listener switches the stream into
23
+ * flowing mode. Arm this AFTER the real stdin consumer is attached, in the
24
+ * same synchronous block, so no early bytes are emitted while only our
25
+ * listener exists. The detached daemon must never arm this — its stdin is
26
+ * `'ignore'` and its lifecycle is refcount/idle-based.
27
+ *
28
+ * Tune with `CODEGRAPH_STARTUP_HANDSHAKE_TIMEOUT_MS`; `0` disables.
29
+ */
30
+ /** Default wait for the first byte of MCP traffic before assuming orphaned. */
31
+ export declare const DEFAULT_STARTUP_HANDSHAKE_TIMEOUT_MS = 900000;
32
+ export declare const STARTUP_HANDSHAKE_TIMEOUT_ENV = "CODEGRAPH_STARTUP_HANDSHAKE_TIMEOUT_MS";
33
+ /**
34
+ * Parse the timeout env override. Missing/invalid → default; `<= 0` → `0`
35
+ * (disabled), the same disable convention as `CODEGRAPH_PPID_POLL_MS`.
36
+ */
37
+ export declare function parseStartupHandshakeTimeoutMs(raw: string | undefined): number;
38
+ /**
39
+ * Arm the backstop. `onAbandoned` runs at most once, only if no `'data'` event
40
+ * arrives on `stream` within the timeout. Returns a disarm function (idempotent;
41
+ * also detaches the listener). `stream`/`timeoutMs` are injectable for tests.
42
+ */
43
+ export declare function armStartupHandshakeTimeout(onAbandoned: () => void, stream?: NodeJS.ReadableStream, timeoutMs?: number): () => void;
44
+ //# sourceMappingURL=startup-handshake.d.ts.map
@@ -25,6 +25,28 @@ export declare class NotIndexedError extends Error {
25
25
  */
26
26
  export declare class PathRefusalError extends Error {
27
27
  }
28
+ /**
29
+ * Normalize Erlang-native symbol spellings in an explore query into the shapes
30
+ * the rest of the pipeline already understands. Agents working Erlang code
31
+ * name symbols the way the language spells them — `mod:fn/3`, `init/2` — and
32
+ * those tokens previously died in both consumers: the flow-builder's token
33
+ * filter rejects `:` and `/arity` outright, and the search-side field parser
34
+ * eats `mod:fn` as an unknown `field:value`. Measured on cowboy: the agent
35
+ * named `cowboy_stream_h:request_process/3` in two queries, got no body back
36
+ * either time, and fell back to Read.
37
+ *
38
+ * - `fn/3` → `fn` (arity tail after an identifier; a path segment like
39
+ * `src/2fa` doesn't match because the tail must be all digits)
40
+ * - `mod:fn` → `mod.fn` (exactly one colon between identifiers, so it rides
41
+ * the existing Class.method qualified handling; `::`, URLs, drive letters,
42
+ * and times don't match, and the query language's own field prefixes —
43
+ * kind:/lang:/language:/path:/name: — are left alone)
44
+ *
45
+ * Safe cross-language: Lua's `t:m` spelling maps to the same `t.m` its
46
+ * qualified names use, and no other supported spelling contains a bare
47
+ * single-colon identifier pair.
48
+ */
49
+ export declare function normalizeQuerySpelling(query: string): string;
28
50
  /**
29
51
  * Calculate the recommended number of codegraph_explore calls based on project size.
30
52
  * Larger codebases need more exploration calls to cover their surface area,
@@ -23,7 +23,27 @@ export interface ProjectConfig {
23
23
  * and your `.gitignore`.
24
24
  */
25
25
  exclude?: string[];
26
+ vba?: {
27
+ targets?: Record<string, boolean>;
28
+ };
29
+ /**
30
+ * Gitignore-style patterns for first-party source to force INTO the index even
31
+ * when `.gitignore` would drop it — the general whitelist `includeIgnored`
32
+ * never was (that one only revives *embedded git repos* inside ignored dirs).
33
+ * The case this exists for: a project under a second VCS (SVN, Perforce, …)
34
+ * deliberately `.gitignore`s its own real source so it never lands in Git, yet
35
+ * that source must still be indexed. Matched against project-root-relative
36
+ * paths, so `"Tools/"`, a recursive `"Tools/**"` glob, or `"Local/typescript"`
37
+ * all work.
38
+ * Built-in default-ignored dirs (`node_modules`, `dist`, …), `.git`, and
39
+ * CodeGraph's own data dir are never resurfaced; an explicit `exclude` still
40
+ * wins. Absent/empty (the default) forces nothing in.
41
+ */
42
+ include?: string[];
26
43
  }
44
+ export declare function loadVbaConfig(rootDir: string): {
45
+ targets?: Record<string, boolean>;
46
+ };
27
47
  /**
28
48
  * Load the validated extension overrides for a project, mtime-cached.
29
49
  *
@@ -51,6 +71,30 @@ export declare function loadIncludeIgnoredPatterns(rootDir: string): string[];
51
71
  * the built-in defaults and the project's `.gitignore`.
52
72
  */
53
73
  export declare function loadExcludePatterns(rootDir: string): string[];
74
+ /**
75
+ * Load the validated `include` patterns for a project, mtime-cached.
76
+ *
77
+ * These name first-party source to force INTO the index even when `.gitignore`
78
+ * would drop it — the whitelist for SVN/Perforce-only source a project
79
+ * gitignores out of Git. An empty result — the zero-config default — forces
80
+ * nothing in. Built-in default-ignored dirs, `.git`, and CodeGraph's data dir
81
+ * are never resurfaced, and an explicit `exclude` still wins.
82
+ */
83
+ export declare function loadIncludePatterns(rootDir: string): string[];
54
84
  /** Test/maintenance hook: forget cached config (e.g. after rewriting it in a test). */
55
85
  export declare function clearProjectConfigCache(): void;
86
+ /**
87
+ * Add gitignore-style patterns to a project's `codegraph.json` `includeIgnored`
88
+ * list, creating the file if absent and preserving every other key. Used by the
89
+ * CLI to opt a "super-repo of gitignored child repos" (#1156) into the index on
90
+ * the user's say-so. Returns the count of patterns actually ADDED (ones already
91
+ * present are skipped, so a re-run is idempotent).
92
+ *
93
+ * A plain-JSON round-trip: a `codegraph.json` carrying comments (not valid JSON)
94
+ * already fails to load with a warning, so rather than silently clobber such a
95
+ * file this throws when an existing config won't parse — the caller falls back
96
+ * to printing the manual snippet. Invalidates the config cache so a subsequent
97
+ * index in the same process sees the new patterns.
98
+ */
99
+ export declare function addIncludeIgnoredPatterns(rootDir: string, patterns: string[]): number;
56
100
  //# sourceMappingURL=project-config.d.ts.map
@@ -1,5 +1,6 @@
1
1
  import type { Edge } from '../types';
2
2
  import type { QueryBuilder } from '../db/queries';
3
3
  import type { ResolutionContext } from './types';
4
- export declare function cFnPointerDispatchEdges(queries: QueryBuilder, ctx: ResolutionContext): Edge[];
4
+ import type { MaybeYield } from './cooperative-yield';
5
+ export declare function cFnPointerDispatchEdges(_queries: QueryBuilder, ctx: ResolutionContext, onYield: MaybeYield): Promise<Edge[]>;
5
6
  //# sourceMappingURL=c-fnptr-synthesizer.d.ts.map
@@ -11,5 +11,5 @@ import type { ResolutionContext } from './types';
11
11
  * Sidekiq Worker.perform_async → #perform + Laravel event(new X) → listener handle).
12
12
  * Returns the count added. Never throws into indexing — callers wrap in try/catch.
13
13
  */
14
- export declare function synthesizeCallbackEdges(queries: QueryBuilder, ctx: ResolutionContext): number;
14
+ export declare function synthesizeCallbackEdges(queries: QueryBuilder, ctx: ResolutionContext): Promise<number>;
15
15
  //# sourceMappingURL=callback-synthesizer.d.ts.map
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Cooperative yielding for long synchronous resolution spans.
3
+ *
4
+ * Reference resolution and callback-edge synthesis run on the indexer's MAIN
5
+ * thread — unlike parsing, which is off-thread in the parse worker. The #850
6
+ * liveness watchdog (armed on `index`/`init` since #999) SIGKILLs the process
7
+ * when that thread doesn't turn its event loop for the timeout window (default
8
+ * 60s), because its heartbeat is a `setInterval` on that same thread. On a large
9
+ * repo, resolving refs + synthesizing dynamic-dispatch edges legitimately runs
10
+ * for minutes, so a span that never yields starves the heartbeat and the
11
+ * watchdog kills a VALID, in-progress index — the exact symptom of #1091 (the
12
+ * progress bar freezes at wherever it last rendered — 88% / 100% — then the
13
+ * process is killed).
14
+ *
15
+ * `createYielder` returns a `maybeYield()` that yields (via `setImmediate`) only
16
+ * once more than `budgetMs` of wall-clock has elapsed since the last yield, so
17
+ * fast repos pay essentially nothing while slow ones give the heartbeat a
18
+ * regular window to fire. Call it at natural boundaries in a long loop (between
19
+ * batches, between synthesis passes).
20
+ *
21
+ * This does NOT weaken the watchdog. A genuinely wedged loop — an infinite or
22
+ * non-terminating span, the case the watchdog exists to catch — never reaches a
23
+ * yield point, so the heartbeat still stops and the SIGKILL still fires. We only
24
+ * stop killing work that is demonstrably making progress.
25
+ */
26
+ /** Yield when more than `budgetMs` of wall-clock has passed since the last yield. */
27
+ export type MaybeYield = () => Promise<void>;
28
+ /** Default budget: well under the watchdog's minimum heartbeat cadence (~1s), so
29
+ * a heartbeat byte always has a chance to land between yields. */
30
+ export declare const DEFAULT_YIELD_BUDGET_MS = 250;
31
+ export declare function createYielder(budgetMs?: number): MaybeYield;
32
+ //# sourceMappingURL=cooperative-yield.d.ts.map
@@ -0,0 +1,20 @@
1
+ /**
2
+ * CICS Framework Resolver (COBOL)
3
+ *
4
+ * Resolves the pseudo-conversational transaction hop: a program ends with
5
+ * `EXEC CICS RETURN TRANSID('CB00')` (or START), and CICS re-invokes the
6
+ * program that OWNS transaction CB00 on the next attention key. The
7
+ * transaction→program mapping lives in the CICS CSD, which is never in the
8
+ * repo — but by near-universal convention each program declares its own
9
+ * transaction id as a working-storage constant:
10
+ *
11
+ * 05 WS-TRANID PIC X(04) VALUE 'CB00'.
12
+ *
13
+ * The COBOL extractor emits `cics-transid:CB00` call references for literal
14
+ * (or same-file-dereferenced) TRANSID options; this resolver maps the id to
15
+ * the program module whose TRAN*-named data item declares that VALUE. No
16
+ * match (an id owned by a program outside the repo) stays unresolved.
17
+ */
18
+ import { FrameworkResolver } from '../types';
19
+ export declare const cicsResolver: FrameworkResolver;
20
+ //# sourceMappingURL=cics.d.ts.map
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Terraform Framework Resolver
3
+ *
4
+ * Terraform's scoping rule is narrow and directory-shaped: `var.X`,
5
+ * `local.X`, `module.M`, and resource/data references resolve ONLY inside
6
+ * the same module directory as the reference site. The generic name matcher
7
+ * resolves by qualified-name alone, so a reference to `var.project_id` from
8
+ * `modules/net-vpc/main.tf` could bind to a `variable "project_id"` declared
9
+ * in an unrelated module — a wrong cross-module edge that poisons impact
10
+ * analysis. This resolver enforces the real semantics:
11
+ *
12
+ * 1. Same directory as the reference site → resolve (highest confidence).
13
+ * 2. `.tfvars` files additionally walk UP to the nearest ancestor
14
+ * directory declaring the variable (`terraform apply -var-file=envs/prod.tfvars`
15
+ * sets ROOT module variables from a subdirectory).
16
+ * 3. Otherwise: no edge. Terraform cannot reference across sibling module
17
+ * directories, so a non-local candidate is never a correct target.
18
+ *
19
+ * It also bridges the module boundary through `:`-scoped references that
20
+ * only this resolver understands (see the extractor's emitModuleWiring):
21
+ *
22
+ * - `module.M:file` → the entry file of the module's local source
23
+ * directory (an `imports` edge, so a module call connects to the code
24
+ * it instantiates).
25
+ * - `module.M:var.<in>` → the child module's `variable "<in>"` node —
26
+ * the module block sets that variable, so "what depends on the child's
27
+ * var.cidr" reaches every caller.
28
+ * - `module.M:output.<o>` → the child module's `output "<o>"` node —
29
+ * `module.M.o` uses flow through to the output's definition instead of
30
+ * dead-ending at the module declaration.
31
+ *
32
+ * The module's `source` is re-read from the declaration's file (cached
33
+ * lines); only local `./`/`../` sources bridge. Registry/git sources stay
34
+ * unresolved — an out-of-repo module is a visible boundary, never a guess.
35
+ */
36
+ import type { FrameworkResolver } from '../types';
37
+ export declare const terraformResolver: FrameworkResolver;
38
+ //# sourceMappingURL=terraform.d.ts.map
@@ -24,5 +24,6 @@
24
24
  */
25
25
  import type { Edge } from '../types';
26
26
  import type { ResolutionContext } from './types';
27
- export declare function goframeRouteEdges(ctx: ResolutionContext): Edge[];
27
+ import type { MaybeYield } from './cooperative-yield';
28
+ export declare function goframeRouteEdges(ctx: ResolutionContext, onYield: MaybeYield): Promise<Edge[]>;
28
29
  //# sourceMappingURL=goframe-synthesizer.d.ts.map
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import { Language } from '../types';
7
7
  import { UnresolvedRef, ResolvedRef, ResolutionContext, ImportMapping, ReExport } from './types';
8
+ export declare function isNixPathImportRef(ref: UnresolvedRef): boolean;
8
9
  /**
9
10
  * Resolve an import path to an actual file
10
11
  */
@@ -37,6 +38,12 @@ export declare function loadCppIncludeDirs(projectRoot: string): string[];
37
38
  * to a same-named symbol — so callers must not fall back to the name-matcher.
38
39
  */
39
40
  export declare function isPhpIncludePathRef(ref: UnresolvedRef): boolean;
41
+ /**
42
+ * Is this a COBOL COPY / EXEC SQL INCLUDE copybook reference? These resolve
43
+ * to files only (or stay unresolved for compiler-supplied members) — never
44
+ * to a same-named symbol via the name-matcher.
45
+ */
46
+ export declare function isCobolCopybookRef(ref: UnresolvedRef): boolean;
40
47
  /**
41
48
  * Extract import mappings from a file
42
49
  */