@aroman22/codegraph-vba 1.6.1 → 1.6.2

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.
@@ -7,7 +7,7 @@ import { SqliteDatabase } from './sqlite-adapter';
7
7
  /**
8
8
  * Current schema version
9
9
  */
10
- export declare const CURRENT_SCHEMA_VERSION = 9;
10
+ export declare const CURRENT_SCHEMA_VERSION = 10;
11
11
  /**
12
12
  * Migration definition
13
13
  */
@@ -57,6 +57,38 @@ export declare function isPlayRoutesFile(filePath: string): boolean;
57
57
  * are all treated as non-VBA — Dysflow always writes the `.txt` suffix.
58
58
  */
59
59
  export declare function detectVbaFormFile(filePath: string): boolean;
60
+ /**
61
+ * Dysflow VBA test manifests: `tests(.<slice>)*.json` (e.g. `tests.json`,
62
+ * `tests.vba.smoke.json`). Recognized by basename only — the content-shape gate
63
+ * (a top-level `tests` array of `{procedure}`) is applied inside
64
+ * `VbaTestManifestExtractor`, so `package.json` / `tsconfig.json` are excluded
65
+ * here and unrelated `tests.*.json` files emit nothing at extraction.
66
+ *
67
+ * `.json` is deliberately NOT in `EXTENSION_MAP` (ordinary JSON is not indexed);
68
+ * this is the sole gate that makes a manifest an indexable source file, mirroring
69
+ * the `.sql`/`queries.json` gate for `SqlQueryExtractor`.
70
+ */
71
+ export declare function isVbaTestManifestFile(filePath: string): boolean;
72
+ /**
73
+ * Dysflow VBA test-sequence file (`<root>/sequences/*.json`, e.g.
74
+ * `tests/sequences/cache-riesgo.json`). SUB-6 of epic #91. The path-detection
75
+ * gate is directory-based — a `.json` file anywhere under a `sequences/`
76
+ * directory — because the basename does not have to start with `tests`
77
+ * (a leaf-test file `tests.vba.cache-riesgo.json` is NOT a sequence; a
78
+ * `tests/sequences/cache-riesgo.json` IS).
79
+ *
80
+ * Disjoint from `isVbaTestManifestFile`:
81
+ * - `isVbaTestManifestFile('tests/tests.vba.smoke.json')` → true
82
+ * - `isVbaTestSequenceFile('tests/sequences/cache-riesgo.json')` → true
83
+ * - `isVbaTestSequenceFile('tests/tests.vba.smoke.json')` → false
84
+ * The basename regex on the manifest gate (`^tests(.[\w-]+)*.json$`) does
85
+ * NOT match `cache-riesgo.json`, so the two detectors do not overlap. The
86
+ * content-shape gate inside `VbaTestSequenceExtractor` further rejects the
87
+ * `executionUnits` (strict-sequence) and `slices[]` (slices) shapes — both
88
+ * of which live at `tests/`, NOT under `sequences/`, and so are excluded
89
+ * from this extractor even if a future file slips into the same directory.
90
+ */
91
+ export declare function isVbaTestSequenceFile(filePath: string): boolean;
60
92
  /**
61
93
  * Initialize the tree-sitter WASM runtime. Must be called before loading grammars.
62
94
  * Does NOT load any grammar WASM files — use loadGrammarsForLanguages() for that.
@@ -1,3 +1,15 @@
1
- import { VbaExtractorContext } from './context';
1
+ import { VbaExtractorContext, VbaClassifier } from './context';
2
+ /**
3
+ * Issue #83: factory for the calls/SQL classifier. The factory takes the
4
+ * pre-split `lines` array (so `trackSqlVariableAssignment` can do its
5
+ * multi-line look-ahead for `&`-accumulate semantics) and closes over the
6
+ * per-file state the legacy `sweepCallsAndSql` declared locally.
7
+ */
8
+ export declare function createCallsAndSqlClassifier(lines: readonly string[]): VbaClassifier;
9
+ /**
10
+ * Backward-compat wrapper (see procedures.ts). Returns void — the calls
11
+ * sweep never contributed to `hasAnySymbols` directly (every other
12
+ * concern's `count` is the signal the orchestrator reads).
13
+ */
2
14
  export declare function sweepCallsAndSql(ctx: VbaExtractorContext, src: string): void;
3
15
  //# sourceMappingURL=call-sweep.d.ts.map
@@ -19,6 +19,29 @@ export interface ProcInfo {
19
19
  visibility: 'public' | 'private' | 'protected' | 'internal';
20
20
  startLine: number;
21
21
  }
22
+ /**
23
+ * Issue #83: the per-concern classifier shape. The single walker in
24
+ * `vba-extractor.ts` calls `classifyLine(line, index, ctx)` once per
25
+ * pre-split line, in a stable order across all six concerns. No internal
26
+ * `.split('\n')` — the split happens once in the walker.
27
+ */
28
+ export interface VbaClassifier {
29
+ /** Stable, human-readable name for logs/metrics. */
30
+ readonly name: string;
31
+ /**
32
+ * Number of top-level symbols this classifier emitted. Read by the
33
+ * orchestrator to compute `hasAnySymbols` (skip module-node creation
34
+ * for files with NO symbols per REQ-CODE-10).
35
+ */
36
+ count: number;
37
+ /** Classify one pre-split line. May mutate `ctx` and bump `count`. */
38
+ classifyLine(line: string, index: number, ctx: VbaExtractorContext): void;
39
+ /**
40
+ * Optional end-of-file hook. Used by the calls-and-sql classifier to
41
+ * flush `procEndLines` → function node `endLine`.
42
+ */
43
+ finalize?(ctx: VbaExtractorContext): void;
44
+ }
22
45
  export declare class VbaExtractorContext {
23
46
  filePath: string;
24
47
  nodes: Node[];
@@ -44,6 +67,14 @@ export declare class VbaExtractorContext {
44
67
  * Let Foo`, and `Property Set Foo` all share the name `Foo`.
45
68
  */
46
69
  localProcs: Map<string, ProcInfo[]>;
70
+ /**
71
+ * Issue #83: flat list of every `ProcInfo` produced by the procedures
72
+ * classifier, in declaration order. Mirrors the array the legacy
73
+ * `sweepProcedures` returned; the orchestrator reads it after the single
74
+ * walker pass to (a) decide `hasAnySymbols`, and (b) check for a
75
+ * `New` initializer to set `hasClassInitializer` on the class node.
76
+ */
77
+ procedures: ProcInfo[];
47
78
  /**
48
79
  * Cache: procedure name → first matching function node emitted for that
49
80
  * name (audit S2 — O(1) same-file call resolution).
@@ -114,6 +145,17 @@ export declare class VbaExtractorContext {
114
145
  procStack: number[];
115
146
  /** Local event name (lowercase) → event node for `RaiseEvent` edge emission. */
116
147
  localEvents: Map<string, Node>;
148
+ /**
149
+ * Same-file function/property return types, keyed by lowercase proc name →
150
+ * declared return type. ONLY non-primitive (project-class) return types are
151
+ * stored. Populated by `sweepProcedures` (which runs before the call sweep);
152
+ * consumed by the call sweep's `Set x = Factory(...)` handling to type the
153
+ * assigned local var so a later `x.Method` qualified call resolves to the
154
+ * factory's class instead of a dead-end `x.Method` stub. Cross-file
155
+ * factories are not covered here (no return type is visible at extraction
156
+ * time) — that stays the resolver's frontier.
157
+ */
158
+ functionReturnTypes: Map<string, string>;
117
159
  constructor(filePath: string);
118
160
  /**
119
161
  * Emit a `contains` edge from the (lazily-created) module/class node to
@@ -156,8 +198,16 @@ export declare class VbaExtractorContext {
156
198
  * node named `targetName`. Used by Dim, WithEvents, Set-New, and SQL sweeps.
157
199
  * Fix 5: the synthetic node id is keyed on (filePath, kind, name) WITHOUT
158
200
  * lineNum so the same type/table referenced on N lines produces ONE node.
159
- */
160
- emitReference(targetName: string, lineNum: number, column: number, synthesizedBy: string): void;
201
+ *
202
+ * `access` (optional): when a caller can classify the reference as a data
203
+ * read or write — SQL table references derive it from the statement verb —
204
+ * it is stamped onto `edge.metadata.access` so consumers can answer "who
205
+ * WRITES table X" vs "who READS table X". Mirrors the read/write tagging the
206
+ * TempVars sweep already emits (`emitTempVarReference`). Omitted for
207
+ * structural references (Dim/WithEvents/Set-New) where the direction is not
208
+ * meaningful.
209
+ */
210
+ emitReference(targetName: string, lineNum: number, column: number, synthesizedBy: string, access?: 'read' | 'write'): void;
161
211
  /**
162
212
  * Issue #52: shared lookup helper for `scanDoCmdOpenCalls` and
163
213
  * `scanDoCmdOpenQuery`. The current scope is the procedure whose
@@ -1,3 +1,12 @@
1
- import { VbaExtractorContext } from './context';
1
+ import { VbaExtractorContext, VbaClassifier } from './context';
2
+ /**
3
+ * Issue #83: factory for the events/types/declares classifier. Closure
4
+ * state: `currentType` (the open `Type ... End Type` block).
5
+ */
6
+ export declare function createEventsTypesDeclaresClassifier(): VbaClassifier;
7
+ /**
8
+ * Backward-compat wrapper (see procedures.ts). Returns the classifier's
9
+ * `count` so the orchestrator can decide `hasAnySymbols`.
10
+ */
2
11
  export declare function sweepEventsTypesAndDeclares(ctx: VbaExtractorContext, src: string): number;
3
12
  //# sourceMappingURL=declarations.d.ts.map
@@ -1,3 +1,11 @@
1
- import { VbaExtractorContext } from './context';
1
+ import { VbaExtractorContext, VbaClassifier } from './context';
2
+ /**
3
+ * Issue #83: factory for the Dim / WithEvents classifier. Stateless per-line.
4
+ */
5
+ export declare function createDimsClassifier(): VbaClassifier;
6
+ /**
7
+ * Backward-compat wrapper (see procedures.ts). Returns the classifier's
8
+ * `count` so the orchestrator can decide `hasAnySymbols`.
9
+ */
2
10
  export declare function sweepDimsAndWithEvents(ctx: VbaExtractorContext, src: string): number;
3
11
  //# sourceMappingURL=dims.d.ts.map
@@ -1,15 +1,18 @@
1
- import { VbaExtractorContext } from './context';
1
+ import { VbaExtractorContext, VbaClassifier } from './context';
2
2
  /**
3
- * Walk the (uncommented, line-joined) source and emit:
4
- * - one `enum` node per `Enum <Name>` block, with one `enum_member` node
5
- * per member and a `contains` edge enum→member;
6
- * - one `constant` node per name declared on a `Const` line (multi-name
7
- * lines emit one node per name);
8
- * - a `contains` edge from the module/class node to each enum and constant
9
- * (held in `pendingModuleOrClassSource` until the module node exists).
3
+ * Issue #83: factory for the enum / const classifier. Closure state:
4
+ * `currentEnum` (open `Enum ... End Enum` block).
10
5
  *
11
- * Returns the number of top-level symbols (enums + constants) emitted so
12
- * the caller can flip `hasAnySymbols`.
6
+ * Also resets + advances the SHARED `ctx.procStack`/`ctx.currentProcKey`
7
+ * per line — same protocol the pre-#83 sweep followed. The calls-sql
8
+ * classifier runs AFTER this one in the per-line dispatch order and
9
+ * applies the same protocol, so the end-of-line scope state is identical
10
+ * to the legacy sequential-sweep behaviour.
11
+ */
12
+ export declare function createEnumsConstsClassifier(): VbaClassifier;
13
+ /**
14
+ * Backward-compat wrapper (see procedures.ts). Returns the classifier's
15
+ * `count` so the orchestrator can decide `hasAnySymbols`.
13
16
  */
14
17
  export declare function sweepEnumsAndConsts(ctx: VbaExtractorContext, src: string): number;
15
18
  //# sourceMappingURL=enums-consts.d.ts.map
@@ -1,3 +1,11 @@
1
- import { VbaExtractorContext } from './context';
1
+ import { VbaExtractorContext, VbaClassifier } from './context';
2
+ /**
3
+ * Issue #83: factory for the `Implements` classifier. Stateless per-line.
4
+ */
5
+ export declare function createImplementsClassifier(): VbaClassifier;
6
+ /**
7
+ * Backward-compat wrapper (see procedures.ts). Returns the classifier's
8
+ * `count` so the orchestrator can decide `hasAnySymbols`.
9
+ */
2
10
  export declare function sweepImplements(ctx: VbaExtractorContext, src: string): number;
3
11
  //# sourceMappingURL=implements.d.ts.map
@@ -1,3 +1,15 @@
1
- import { VbaExtractorContext, ProcInfo } from './context';
1
+ import { VbaExtractorContext, ProcInfo, VbaClassifier } from './context';
2
+ /**
3
+ * Issue #83: factory for the procedures classifier. Closure state: none
4
+ * beyond `count` (the per-concern accumulators live on `ctx`).
5
+ */
6
+ export declare function createProceduresClassifier(): VbaClassifier;
7
+ /**
8
+ * Backward-compat wrapper: pre-#83 callers (e.g. legacy test fixtures)
9
+ * used `sweepProcedures(ctx, src)` and got back the ProcInfo[].
10
+ * Now it returns `ctx.procedures` (the same flat list the factory
11
+ * appends to). The implementation still calls the classifier once per
12
+ * pre-split line, so the count is identical to the new walker path.
13
+ */
2
14
  export declare function sweepProcedures(ctx: VbaExtractorContext, src: string): ProcInfo[];
3
15
  //# sourceMappingURL=procedures.d.ts.map
@@ -0,0 +1,26 @@
1
+ import { ExtractionResult } from '../types';
2
+ /**
3
+ * Content-shape gate: is `parsed` a VBA test manifest — a top-level `tests`
4
+ * array with at least one item carrying a string `procedure`? Pure; the file's
5
+ * basename is gated separately by `isVbaTestManifestFile` in `grammars.ts`.
6
+ */
7
+ export declare function isVbaTestManifestShape(parsed: unknown): boolean;
8
+ export declare class VbaTestManifestExtractor {
9
+ private filePath;
10
+ private source;
11
+ private nodes;
12
+ private unresolvedReferences;
13
+ private errors;
14
+ constructor(filePath: string, source: string);
15
+ extract(): ExtractionResult;
16
+ /**
17
+ * One `UnresolvedReference` per `tests[]` entry carrying a string `procedure`,
18
+ * pointing at that procedure name. The `ReferenceResolver` (SUB-3) binds each
19
+ * to the existing `Test_*` `function` node — no duplicate node is emitted here.
20
+ * `name` defaults to the procedure name; `tags` defaults to `[]`.
21
+ */
22
+ private emitTestReferences;
23
+ private result;
24
+ private createFileNode;
25
+ }
26
+ //# sourceMappingURL=vba-test-manifest-extractor.d.ts.map
@@ -0,0 +1,29 @@
1
+ import { ExtractionResult } from '../types';
2
+ /**
3
+ * Content-shape gate: is `parsed` a Dysflow VBA test sequence — a top-level
4
+ * `runnerPolicy` object AND a `procedures` array whose items are strings
5
+ * (possibly empty)? Pure; the file's path is gated separately by
6
+ * `isVbaTestSequenceFile` in `grammars.ts`.
7
+ *
8
+ * The gate accepts an EMPTY `procedures` array on purpose: an empty sequence
9
+ * still gets a `file` node from the extractor (so the manifest is visible in
10
+ * the graph) but emits zero `UnresolvedReference`s (no procedures to bind).
11
+ *
12
+ * A shape that ALSO carries an `executionUnits` or `slices[]` key (the
13
+ * strict-sequence / slices shapes) is rejected — those are top-level
14
+ * orchestration/grouping plans, not per-atom sequences.
15
+ */
16
+ export declare function isVbaTestSequenceShape(parsed: unknown): boolean;
17
+ export declare class VbaTestSequenceExtractor {
18
+ private filePath;
19
+ private source;
20
+ private nodes;
21
+ private unresolvedReferences;
22
+ private errors;
23
+ constructor(filePath: string, source: string);
24
+ extract(): ExtractionResult;
25
+ private emitProcedureReferences;
26
+ private result;
27
+ private createFileNode;
28
+ }
29
+ //# sourceMappingURL=vba-test-sequence-extractor.d.ts.map
@@ -17,7 +17,7 @@
17
17
  * tools (node/search/callers/…) stay defined and are re-enablable via
18
18
  * CODEGRAPH_MCP_TOOLS, but they are NOT listed to agents, so don't name them.
19
19
  */
20
- export declare const SERVER_INSTRUCTIONS = "# Codegraph \u2014 code intelligence over an indexed knowledge graph\n\nCodegraph is a SQLite knowledge graph of every symbol, edge, and file in\nthe workspace \u2014 pre-computed structure you would otherwise re-derive by\nreading files (cached intelligence: thousands of parse/trace decisions you\ndon't pay to re-reason each run). Reads are sub-millisecond; the index lags\nwrites by ~1s through the file watcher. Reach for it BEFORE *and* while\nwriting or editing code \u2014 not just for questions: one call returns the\nverbatim source PLUS who calls it and what it affects, so you edit with the\nblast radius in view. More accurate context, in far fewer tokens and\nround-trips than reading files yourself.\n\n## One tool: codegraph_explore \u2014 use it instead of reading files\n\nThere is a single tool, `codegraph_explore`, and it is Read-equivalent. It\ntakes either a natural-language question or a bag of symbol/file names and\nreturns the **verbatim, line-numbered source** of the relevant symbols\ngrouped by file \u2014 the same `<n>\\t<line>` shape `Read` gives you, safe to\n`Edit` from \u2014 PLUS the call path among them (including dynamic-dispatch hops\nlike callbacks, React re-render, and JSX children that grep can't follow) and\na blast-radius summary of what depends on them.\n\nWhether you're answering \"how does X work\" or implementing a change (fixing a\nbug, adding a feature), call `codegraph_explore` before you Read. ONE call\nusually answers the whole question. Codegraph IS the pre-built search index \u2014\nso running your own grep + read loop, or delegating the lookup to a separate\nfile-reading sub-task/agent, repeats work codegraph already did and costs more\nfor the same answer. A direct codegraph answer is typically one to a few\ncalls; a grep/read exploration is dozens.\n\n## How to query\n\n- **Almost any question \u2014 \"how does X work\", architecture, a bug, \"what/where is X\", or surveying an area** \u2192 `codegraph_explore` with a natural-language question or the relevant names. ONE capped call returns the verbatim source grouped by file; most often the ONLY call you need.\n- **\"How does X reach/become Y? / the flow / the path from X to Y\"** \u2192 `codegraph_explore`, naming the symbols that span the flow (e.g. `mutateElement renderScene`) \u2014 it surfaces the call path among them, riding dynamic-dispatch hops, and returns their source.\n- **Reading or editing a file/symbol you can name** \u2192 put its name or file path in the `codegraph_explore` query \u2014 it returns that current line-numbered source (safe to `Edit` from) with the call path and blast radius attached, so you don't Read it separately. For an overloaded name it returns every matching definition's body in one call.\n- **Need more?** Call `codegraph_explore` again with more specific names \u2014 treat the source it returns as already Read.\n\n## Anti-patterns\n\n- **Trust codegraph's results \u2014 don't re-verify them with grep.** They come from a full AST parse; re-checking with grep is slower, less accurate, and wastes context.\n- **Don't grep or Read first** to find or understand indexed code \u2014 ONE `codegraph_explore` returns the relevant symbols' source together in a single round-trip. Reach for raw `Read`/`Grep` only to confirm a specific detail codegraph didn't cover, or for what codegraph doesn't index (configs, docs).\n- **Don't reconstruct a flow by hand** \u2014 name the endpoints in one `codegraph_explore` and it surfaces the path between them, dynamic-dispatch hops included.\n- **After editing, check the staleness banner.** When a tool response starts with \"\u26A0\uFE0F Some files referenced below were edited since the last index sync\u2026\", the listed files are pending re-index \u2014 Read those specific files for accurate content. Every file NOT in that banner is fresh, so still trust codegraph. A different, rarer banner \u2014 \"\u26A0\uFE0F CodeGraph auto-sync is DISABLED\u2026\" \u2014 means live watching stopped entirely (the whole index is frozen, not just a few files); until it's resolved, Read files directly to confirm anything that may have changed.\n\n## Limitations\n\n- If a tool reports a project isn't indexed (no `.codegraph/`), stop calling codegraph tools for that project for the rest of the session and use your built-in tools there instead. Indexing is the user's decision \u2014 mention they can run `codegraph init` if it comes up, but don't run it yourself.\n- Index lags file writes by ~1 second.\n- Cross-file resolution is best-effort name matching; ambiguous calls may return multiple candidates.\n- No live correctness validation \u2014 that's still the TypeScript compiler / test suite / linter's job. Codegraph supplements those with structural context they don't have.\n\n## Supported Languages\n\nThe indexer recognizes a fixed set of languages; if you ask about symbols in a\nfile with an unsupported extension, codegraph will report the project isn't\nindexed for that file and you should fall back to Read/Grep. The fork-specific\naddition beyond upstream codegraph is **VBA / Access** (Dysflow export\nformat):\n\n- **VBA / Access** - Dysflow exports Access/VBA source as `.bas`/`.cls`/\n `.form.txt`/`.report.txt`. Codegraph extracts `.bas`/`.cls` as `module`/\n `class`/`function` nodes with `calls`/`implements`/`references` edges\n (procedural-level; regex-based, not full AST). Cross-module calls, qualified\n `Dim As`, `WithEvents`, and SQL table references inside string literals\n emit synthesized edges tagged `metadata.synthesizedBy` (`vba-name-resolution`,\n `vba-withevents`, `vba-sql-table`). `.form.txt` and `.report.txt` are\n extracted as a `module` plus one `property` per Access control - **no**\n `function`/`sub`/`class` nodes come from form files; the canonical code\n lives in the sibling `.cls`, parsed by the same extractor on that file.\n Pass `projectPath` to a codegraph index that includes VBA files.\n";
20
+ export declare const SERVER_INSTRUCTIONS = "# Codegraph \u2014 code intelligence over an indexed knowledge graph\n\nCodegraph is a SQLite knowledge graph of every symbol, edge, and file in\nthe workspace \u2014 pre-computed structure you would otherwise re-derive by\nreading files (cached intelligence: thousands of parse/trace decisions you\ndon't pay to re-reason each run). Reads are sub-millisecond; the index lags\nwrites by ~1s through the file watcher. Reach for it BEFORE *and* while\nwriting or editing code \u2014 not just for questions: one call returns the\nverbatim source PLUS who calls it and what it affects, so you edit with the\nblast radius in view. More accurate context, in far fewer tokens and\nround-trips than reading files yourself.\n\n## One tool: codegraph_explore \u2014 use it instead of reading files\n\nThere is a single tool, `codegraph_explore`, and it is Read-equivalent. It\ntakes either a natural-language question or a bag of symbol/file names and\nreturns the **verbatim, line-numbered source** of the relevant symbols\ngrouped by file \u2014 the same `<n>\\t<line>` shape `Read` gives you, safe to\n`Edit` from \u2014 PLUS the call path among them (including dynamic-dispatch hops\nlike callbacks, React re-render, and JSX children that grep can't follow) and\na blast-radius summary of what depends on them.\n\nWhether you're answering \"how does X work\" or implementing a change (fixing a\nbug, adding a feature), call `codegraph_explore` before you Read. ONE call\nusually answers the whole question. Codegraph IS the pre-built search index \u2014\nso running your own grep + read loop, or delegating the lookup to a separate\nfile-reading sub-task/agent, repeats work codegraph already did and costs more\nfor the same answer. A direct codegraph answer is typically one to a few\ncalls; a grep/read exploration is dozens.\n\n## How to query\n\n- **Almost any question \u2014 \"how does X work\", architecture, a bug, \"what/where is X\", or surveying an area** \u2192 `codegraph_explore` with a natural-language question or the relevant names. ONE capped call returns the verbatim source grouped by file; most often the ONLY call you need.\n- **\"How does X reach/become Y? / the flow / the path from X to Y\"** \u2192 `codegraph_explore`, naming the symbols that span the flow (e.g. `mutateElement renderScene`) \u2014 it surfaces the call path among them, riding dynamic-dispatch hops, and returns their source.\n- **Reading or editing a file/symbol you can name** \u2192 put its name or file path in the `codegraph_explore` query \u2014 it returns that current line-numbered source (safe to `Edit` from) with the call path and blast radius attached, so you don't Read it separately. For an overloaded name it returns every matching definition's body in one call.\n- **Need more?** Call `codegraph_explore` again with more specific names \u2014 treat the source it returns as already Read.\n\n## Anti-patterns\n\n- **Trust codegraph's results \u2014 don't re-verify them with grep.** They come from a full AST parse; re-checking with grep is slower, less accurate, and wastes context.\n- **Don't grep or Read first** to find or understand indexed code \u2014 ONE `codegraph_explore` returns the relevant symbols' source together in a single round-trip. Reach for raw `Read`/`Grep` only to confirm a specific detail codegraph didn't cover, or for what codegraph doesn't index (configs, docs).\n- **Don't reconstruct a flow by hand** \u2014 name the endpoints in one `codegraph_explore` and it surfaces the path between them, dynamic-dispatch hops included.\n- **After editing, check the staleness banner.** When a tool response starts with \"\u26A0\uFE0F Some files referenced below were edited since the last index sync\u2026\", the listed files are pending re-index \u2014 Read those specific files for accurate content. Every file NOT in that banner is fresh, so still trust codegraph. A different, rarer banner \u2014 \"\u26A0\uFE0F CodeGraph auto-sync is DISABLED\u2026\" \u2014 means live watching stopped entirely (the whole index is frozen, not just a few files); until it's resolved, Read files directly to confirm anything that may have changed.\n\n## Limitations\n\n- If a tool reports a project isn't indexed (no `.codegraph/`), stop calling codegraph tools for that project for the rest of the session and use your built-in tools there instead. Indexing is the user's decision \u2014 mention they can run `codegraph init` if it comes up, but don't run it yourself.\n- Index lags file writes by ~1 second.\n- Cross-file resolution is best-effort name matching; ambiguous calls may return multiple candidates.\n- No live correctness validation \u2014 that's still the TypeScript compiler / test suite / linter's job. Codegraph supplements those with structural context they don't have.\n\n## Supported Languages\n\nThe indexer recognizes a fixed set of languages; if you ask about symbols in a\nfile with an unsupported extension, codegraph will report the project isn't\nindexed for that file and you should fall back to Read/Grep. The fork-specific\naddition beyond upstream codegraph is **VBA / Access** (Dysflow export\nformat):\n\n- **VBA / Access** - Dysflow exports Access/VBA source as `.bas`/`.cls`/\n `.form.txt`/`.report.txt`. Codegraph extracts `.bas`/`.cls` as `module`/\n `class`/`function` nodes with `calls`/`implements`/`references` edges\n (procedural-level; regex-based, not full AST). Cross-module calls, qualified\n `Dim As`, `WithEvents`, and SQL table references inside string literals\n emit synthesized edges tagged `metadata.synthesizedBy` (`vba-name-resolution`,\n `vba-withevents`, `vba-sql-table`). `.form.txt` and `.report.txt` are\n extracted as a `module` plus one `property` per Access control - **no**\n `function`/`sub`/`class` nodes come from form files; the canonical code\n lives in the sibling `.cls`, parsed by the same extractor on that file.\n Dysflow test manifests (`tests.*.json`) link each registered `Test_*`\n procedure to its manifest with a `references` edge tagged\n `vba-test-manifest` carrying the test name + tags, so `getCallers` of a\n production symbol reaches its covering test atoms with the manifest and tags\n to run.\n Pass `projectPath` to a codegraph index that includes VBA files.\n";
21
21
  /**
22
22
  * Instructions variant sent when the server's own root has NO codegraph index.
23
23
  *
@@ -24,6 +24,13 @@ export interface UnresolvedRef {
24
24
  language: Language;
25
25
  /** Possible qualified names it might resolve to */
26
26
  candidates?: string[];
27
+ /**
28
+ * Optional extractor-specific annotations carried from the source
29
+ * `UnresolvedReference` (e.g. `synthesizedBy: 'vba-test-manifest'` plus its
30
+ * `testName`/`tags`/`manifestFile`). Preserved in-memory through resolution
31
+ * so `createEdges` can stamp provenance onto the resolved edge.
32
+ */
33
+ metadata?: Record<string, unknown>;
27
34
  }
28
35
  /**
29
36
  * A resolved reference
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aroman22/codegraph-vba",
3
- "version": "1.6.1",
3
+ "version": "1.6.2",
4
4
  "description": "Local-first code intelligence for AI agents (MCP). Self-contained — bundles its own runtime.",
5
5
  "bin": {
6
6
  "codegraph-vba": "npm-shim.js"
@@ -15,12 +15,12 @@
15
15
  "./package.json": "./package.json"
16
16
  },
17
17
  "optionalDependencies": {
18
- "@aroman22/codegraph-vba-darwin-arm64": "1.6.1",
19
- "@aroman22/codegraph-vba-darwin-x64": "1.6.1",
20
- "@aroman22/codegraph-vba-linux-arm64": "1.6.1",
21
- "@aroman22/codegraph-vba-linux-x64": "1.6.1",
22
- "@aroman22/codegraph-vba-win32-arm64": "1.6.1",
23
- "@aroman22/codegraph-vba-win32-x64": "1.6.1"
18
+ "@aroman22/codegraph-vba-darwin-arm64": "1.6.2",
19
+ "@aroman22/codegraph-vba-darwin-x64": "1.6.2",
20
+ "@aroman22/codegraph-vba-linux-arm64": "1.6.2",
21
+ "@aroman22/codegraph-vba-linux-x64": "1.6.2",
22
+ "@aroman22/codegraph-vba-win32-arm64": "1.6.2",
23
+ "@aroman22/codegraph-vba-win32-x64": "1.6.2"
24
24
  },
25
25
  "files": [
26
26
  "npm-shim.js",