brainclaw 1.9.1 → 1.10.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 (71) hide show
  1. package/README.md +47 -1
  2. package/dist/brainclaw-vscode.vsix +0 -0
  3. package/dist/cli.js +18 -1
  4. package/dist/commands/code-map.js +129 -0
  5. package/dist/commands/codev.js +7 -0
  6. package/dist/commands/mcp.js +121 -0
  7. package/dist/commands/run-profile.js +3 -2
  8. package/dist/commands/switch.js +100 -89
  9. package/dist/core/agent-files.js +12 -0
  10. package/dist/core/code-map/backend.js +123 -0
  11. package/dist/core/code-map/core.js +81 -0
  12. package/dist/core/code-map/drafts.js +2 -0
  13. package/dist/core/code-map/extractor.js +29 -0
  14. package/dist/core/code-map/finalizer.js +191 -0
  15. package/dist/core/code-map/freshness.js +108 -0
  16. package/dist/core/code-map/ids.js +0 -0
  17. package/dist/core/code-map/importable.js +35 -0
  18. package/dist/core/code-map/indexes.js +197 -0
  19. package/dist/core/code-map/lang/java/imports.scm +17 -0
  20. package/dist/core/code-map/lang/java/index.js +254 -0
  21. package/dist/core/code-map/lang/java/tags.scm +48 -0
  22. package/dist/core/code-map/lang/php/imports.scm +21 -0
  23. package/dist/core/code-map/lang/php/index.js +251 -0
  24. package/dist/core/code-map/lang/php/tags.scm +44 -0
  25. package/dist/core/code-map/lang/provider.js +9 -0
  26. package/dist/core/code-map/lang/providers.js +24 -0
  27. package/dist/core/code-map/lang/python/imports.scm +90 -0
  28. package/dist/core/code-map/lang/python/index.js +364 -0
  29. package/dist/core/code-map/lang/python/tags.scm +81 -0
  30. package/dist/core/code-map/lang/query-runtime.js +374 -0
  31. package/dist/core/code-map/lang/registry.js +125 -0
  32. package/dist/core/code-map/lang/typescript/imports.scm +90 -0
  33. package/dist/core/code-map/lang/typescript/index.js +306 -0
  34. package/dist/core/code-map/lang/typescript/tags.js.scm +106 -0
  35. package/dist/core/code-map/lang/typescript/tags.scm +151 -0
  36. package/dist/core/code-map/lock.js +210 -0
  37. package/dist/core/code-map/materialized.js +51 -0
  38. package/dist/core/code-map/memory-reader.js +59 -0
  39. package/dist/core/code-map/paths.js +53 -0
  40. package/dist/core/code-map/query.js +568 -0
  41. package/dist/core/code-map/refresh.js +0 -0
  42. package/dist/core/code-map/resolve.js +177 -0
  43. package/dist/core/code-map/store.js +206 -0
  44. package/dist/core/code-map/types.js +288 -0
  45. package/dist/core/code-map/vocabulary.js +57 -0
  46. package/dist/core/code-map/wasm-loader.js +294 -0
  47. package/dist/core/code-map/work-section.js +206 -0
  48. package/dist/core/codev-rounds.js +4 -0
  49. package/dist/core/execution-adapters.js +11 -10
  50. package/dist/core/execution-profile.js +58 -0
  51. package/dist/core/facade-schema.js +9 -0
  52. package/dist/core/instruction-templates.js +2 -0
  53. package/dist/core/mcp-command-resolution.js +3 -1
  54. package/dist/core/store-resolution.js +41 -4
  55. package/dist/facts.js +9 -5
  56. package/dist/facts.json +8 -4
  57. package/dist/vendor/web-tree-sitter/tree-sitter.js +3980 -0
  58. package/dist/vendor/web-tree-sitter/tree-sitter.wasm +0 -0
  59. package/dist/wasm/tree-sitter-java.wasm +0 -0
  60. package/dist/wasm/tree-sitter-javascript.wasm +0 -0
  61. package/dist/wasm/tree-sitter-php.wasm +0 -0
  62. package/dist/wasm/tree-sitter-python.wasm +0 -0
  63. package/dist/wasm/tree-sitter-tsx.wasm +0 -0
  64. package/dist/wasm/tree-sitter-typescript.wasm +0 -0
  65. package/dist/wasm/tree-sitter.wasm +0 -0
  66. package/docs/cli.md +46 -8
  67. package/docs/code-map.md +198 -0
  68. package/docs/integrations/mcp.md +13 -6
  69. package/docs/mcp-schema-changelog.md +7 -3
  70. package/docs/quickstart.md +1 -1
  71. package/package.json +11 -6
@@ -0,0 +1,306 @@
1
+ /**
2
+ * Code Map P1a — TypeScriptProvider (provider #1; spec §8).
3
+ *
4
+ * Owns `.js/.jsx/.ts/.tsx` (runtime langs javascript/typescript/tsx). `extractDraft`
5
+ * delegates to the generic query-runtime; `refine()` carries what tree-sitter
6
+ * queries CANNOT express:
7
+ * - React `component` (PascalCase name + a JSX-returning body) / `hook`
8
+ * (`/^use[A-Z0-9]/`) reclassification — needs a JSX-body walk (returnsJsx) on the
9
+ * in-memory source node.
10
+ * - `function` vs `variable` for lexical declarators: the query emits the
11
+ * structural `variable` subtype; a declarator whose value is a function/arrow is
12
+ * reclassified to `function` (then possibly component/hook), matching the legacy
13
+ * `classifySubtype`.
14
+ *
15
+ * Identity is owned by the CORE finalizer — this provider mints NO ids. The
16
+ * `.jsx → tsx` and `.js → javascript` resolution is explicit in `langForPath`.
17
+ *
18
+ * trp_5026812e: the shared `tags.scm` references TS-only node types and does NOT
19
+ * compile against the JAVASCRIPT grammar. This provider therefore serves a
20
+ * JS-compatible definition subset (`tags.js.scm`) for the `javascript` lang while
21
+ * using `tags.scm` for typescript/tsx. `imports.scm` compiles against all three.
22
+ */
23
+ import crypto from 'node:crypto';
24
+ import fs from 'node:fs';
25
+ import path from 'node:path';
26
+ import { fileURLToPath } from 'node:url';
27
+ import { grammarHash, grammarName, loadGrammar } from '../../wasm-loader.js';
28
+ import { extractWithQueries } from '../query-runtime.js';
29
+ const HERE = path.dirname(fileURLToPath(import.meta.url));
30
+ /** Resolve a vendored `.scm` next to this module (dist) or from the source tree. */
31
+ function readScm(basename) {
32
+ // Published / dist runtime: this module is dist/core/code-map/lang/typescript/
33
+ // index.js and the build copies the .scm assets alongside it
34
+ // (copy-code-map-wasm.mjs). Prefer that local copy.
35
+ const local = path.join(HERE, basename);
36
+ if (fs.existsSync(local))
37
+ return fs.readFileSync(local, 'utf-8');
38
+ // From-source / dist-test fallback: tsc emits to dist[-test]/... but does NOT
39
+ // copy .scm, so walk up to the repo root (the dir holding package.json) and read
40
+ // the curated asset from src/core/code-map/lang/typescript/.
41
+ let dir = HERE;
42
+ for (let i = 0; i < 12; i++) {
43
+ if (fs.existsSync(path.join(dir, 'package.json'))) {
44
+ const fromSrc = path.join(dir, 'src', 'core', 'code-map', 'lang', 'typescript', basename);
45
+ if (fs.existsSync(fromSrc))
46
+ return fs.readFileSync(fromSrc, 'utf-8');
47
+ break;
48
+ }
49
+ const parent = path.dirname(dir);
50
+ if (parent === dir)
51
+ break;
52
+ dir = parent;
53
+ }
54
+ throw new Error(`code-map: could not locate query asset ${basename} (from ${HERE})`);
55
+ }
56
+ function sha256(s) {
57
+ return `sha256:${crypto.createHash('sha256').update(s, 'utf-8').digest('hex')}`;
58
+ }
59
+ // Load the curated query assets once at module init. tags.scm = TS/TSX defs,
60
+ // tags.js.scm = JS-compatible def subset (trp_5026812e); imports.scm = all langs.
61
+ const TAGS_TS = readScm('tags.scm');
62
+ const TAGS_JS = readScm('tags.js.scm');
63
+ const IMPORTS = readScm('imports.scm');
64
+ const TAGS_TS_HASH = sha256(TAGS_TS);
65
+ const TAGS_JS_HASH = sha256(TAGS_JS);
66
+ const IMPORTS_HASH = sha256(IMPORTS);
67
+ /** The tags source + hash for a runtime lang (.js uses the JS subset). */
68
+ function tagsForLang(lang) {
69
+ if (lang === 'javascript')
70
+ return { source: TAGS_JS, hash: TAGS_JS_HASH };
71
+ return { source: TAGS_TS, hash: TAGS_TS_HASH };
72
+ }
73
+ const HOOK_RE = /^use[A-Z0-9]/;
74
+ const PASCAL_RE = /^[A-Z][A-Za-z0-9]*$/;
75
+ /** Walk to find the first descendant JSX node (mirrors legacy `returnsJsx`). */
76
+ function returnsJsx(node) {
77
+ const stack = [node];
78
+ let budget = 4000;
79
+ while (stack.length > 0 && budget-- > 0) {
80
+ const n = stack.pop();
81
+ const t = n.type;
82
+ if (t === 'jsx_element' || t === 'jsx_self_closing_element' || t === 'jsx_fragment')
83
+ return true;
84
+ for (let i = 0; i < n.namedChildCount; i++) {
85
+ const c = n.namedChild(i);
86
+ if (c)
87
+ stack.push(c);
88
+ }
89
+ }
90
+ return false;
91
+ }
92
+ /** Mirror of legacy `classifySubtype` (extractor.ts). */
93
+ function classifySubtype(name, valueNode, isFunctionLike) {
94
+ if (HOOK_RE.test(name))
95
+ return 'hook';
96
+ if (isFunctionLike && PASCAL_RE.test(name) && valueNode && returnsJsx(valueNode))
97
+ return 'component';
98
+ return isFunctionLike ? 'function' : 'variable';
99
+ }
100
+ const parser = {
101
+ grammarForLang: (lang) => loadGrammar(lang),
102
+ grammarNameForLang: (lang) => grammarName(lang),
103
+ grammarHashForLang: (lang) => grammarHash(lang),
104
+ };
105
+ const queries = {
106
+ tags: {
107
+ name: 'tags',
108
+ sourceForLang: (lang) => tagsForLang(lang).source,
109
+ hashForLang: (lang) => tagsForLang(lang).hash,
110
+ },
111
+ imports: {
112
+ name: 'imports',
113
+ sourceForLang: () => IMPORTS,
114
+ hashForLang: () => IMPORTS_HASH,
115
+ },
116
+ // JS/TS import/export statement node types (cadrage §3 / Codex R1). Both are
117
+ // listed because local exports + re-exports (`export … from`) also resolve
118
+ // through the runtime's enclosingStatement walk. PROVIDER-LOCAL — the runtime
119
+ // gets this set per file, never from a registry. (Same set the old module-global
120
+ // carried for JS/TS, so output stays byte-identical.)
121
+ enclosingStatementNodeTypes: ['import_statement', 'export_statement'],
122
+ // P1b §3.4: the runtime drives capture→draft mapping off the HARD-CODED
123
+ // capture-name convention (query-runtime.ts) — that convention IS the contract.
124
+ // This captureMap is a declared MIRROR of it, validated against the convention
125
+ // by `assertCaptureMapConforms` (provider-oracle test). Every entry's `capture`
126
+ // MUST be a convention-recognized role; it cannot invent new capture roles.
127
+ captureMap: [
128
+ { capture: 'definition.function.node', field: 'node', subtype: 'function' },
129
+ { capture: 'definition.function.name', field: 'name' },
130
+ { capture: 'definition.function.exported', field: 'exported', optional: true },
131
+ { capture: 'definition.class.node', field: 'node', subtype: 'class' },
132
+ { capture: 'definition.class.name', field: 'name' },
133
+ { capture: 'definition.class.exported', field: 'exported', optional: true },
134
+ { capture: 'definition.type.node', field: 'node', subtype: 'type' },
135
+ { capture: 'definition.type.name', field: 'name' },
136
+ { capture: 'definition.type.exported', field: 'exported', optional: true },
137
+ { capture: 'definition.interface.node', field: 'node', subtype: 'interface' },
138
+ { capture: 'definition.interface.name', field: 'name' },
139
+ { capture: 'definition.interface.exported', field: 'exported', optional: true },
140
+ { capture: 'definition.variable.node', field: 'node', subtype: 'variable' },
141
+ { capture: 'definition.variable.name', field: 'name' },
142
+ { capture: 'definition.variable.exported', field: 'exported', optional: true },
143
+ { capture: 'import.source', field: 'source' },
144
+ { capture: 'import.default.name', field: 'imported', optional: true },
145
+ { capture: 'import.namespace.name', field: 'imported', optional: true },
146
+ { capture: 'import.named.name', field: 'imported', optional: true },
147
+ { capture: 'export.name', field: 'name', optional: true },
148
+ ],
149
+ };
150
+ const vocabulary = {
151
+ nodeSubtypes: ['function', 'class', 'type', 'interface', 'variable', 'component', 'hook', 'export'],
152
+ edgeKinds: ['contains', 'defines', 'imports', 'exports'],
153
+ captureMap: queries.captureMap,
154
+ };
155
+ const capabilities = {
156
+ tiers: ['T1.definitions', 'T2.imports', 'T3.import_resolution'],
157
+ proven: {
158
+ 'T1.definitions': true,
159
+ 'T2.imports': true,
160
+ 'T3.import_resolution': true, // P1c file-level: relative specifiers, intra-project
161
+ 'T4.tests_for': false,
162
+ },
163
+ };
164
+ /** Extensions tried (in order) when resolving an extensionless relative specifier. */
165
+ const TS_RESOLVE_EXTS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'];
166
+ /** JS-family extensions a written specifier may use for a TS source file (ESM `./x.js` → `x.ts`). */
167
+ const JS_LIKE_EXTS = new Set(['.js', '.jsx', '.mjs', '.cjs']);
168
+ /**
169
+ * P1c file-level resolution (relative specifiers only). Given `./x` / `../x`
170
+ * resolved against the importer dir, try in order: the exact path (if it carries
171
+ * an extension), the TS-source siblings of a JS-family extension (ESM convention:
172
+ * `./b.js` may mean `b.ts`/`b.tsx`), the extensionless candidate + each known
173
+ * extension, then `<candidate>/index.<ext>`. Return the FIRST that is an indexed
174
+ * file. Bare/external specifiers (`react`, `@scope/x`) → no resolution (no edge).
175
+ */
176
+ function resolveTsImport(spec, fromPath, ctx) {
177
+ if (!spec.startsWith('./') && !spec.startsWith('../'))
178
+ return null; // external/bare → no edge
179
+ const base = path.posix.join(path.posix.dirname(fromPath), spec); // normalized project-relative
180
+ const ext = path.posix.extname(base);
181
+ const candidates = [];
182
+ if (ext) {
183
+ candidates.push(base);
184
+ if (JS_LIKE_EXTS.has(ext)) {
185
+ const noExt = base.slice(0, -ext.length);
186
+ candidates.push(`${noExt}.ts`, `${noExt}.tsx`);
187
+ }
188
+ }
189
+ else {
190
+ for (const e of TS_RESOLVE_EXTS)
191
+ candidates.push(`${base}${e}`);
192
+ for (const e of TS_RESOLVE_EXTS)
193
+ candidates.push(`${base}/index${e}`);
194
+ }
195
+ for (const c of candidates) {
196
+ if (ctx.fileExists(c))
197
+ return c;
198
+ }
199
+ return null;
200
+ }
201
+ function isDefSourceNode(v) {
202
+ return (typeof v === 'object' &&
203
+ v !== null &&
204
+ 'node' in v &&
205
+ 'nameNode' in v &&
206
+ typeof v.node === 'object');
207
+ }
208
+ /** Resolve a declarator's `value` field from its name node (best-effort). */
209
+ function declaratorValue(nameNode) {
210
+ const declarator = nameNode.parent;
211
+ if (!declarator)
212
+ return null;
213
+ try {
214
+ return declarator.childForFieldName('value');
215
+ }
216
+ catch {
217
+ return null;
218
+ }
219
+ }
220
+ const FN_VALUE_TYPES = new Set(['arrow_function', 'function_expression', 'function']);
221
+ export class TypeScriptProvider {
222
+ id = 'js-ts';
223
+ displayName = 'JavaScript / TypeScript';
224
+ languages = ['javascript', 'typescript', 'tsx'];
225
+ extensions = ['.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs'];
226
+ priority = 0;
227
+ version = '0.1.0';
228
+ parser = parser;
229
+ queries = queries;
230
+ vocabulary = vocabulary;
231
+ capabilities = capabilities;
232
+ /** `.jsx → tsx`, `.js/.mjs/.cjs → javascript`, `.tsx → tsx`, `.ts → typescript`. */
233
+ langForPath(p) {
234
+ const ext = path.extname(p).toLowerCase();
235
+ switch (ext) {
236
+ case '.ts':
237
+ return 'typescript';
238
+ case '.tsx':
239
+ return 'tsx';
240
+ case '.jsx':
241
+ return 'tsx'; // tsx grammar handles jsx (mirrors legacy langForExtension)
242
+ case '.js':
243
+ case '.mjs':
244
+ case '.cjs':
245
+ return 'javascript';
246
+ default:
247
+ return 'typescript';
248
+ }
249
+ }
250
+ async extractDraft(input, _services) {
251
+ const tags = tagsForLang(input.lang);
252
+ return extractWithQueries({
253
+ providerId: this.id,
254
+ lang: input.lang,
255
+ source: input.source,
256
+ sizeBytes: input.sizeBytes,
257
+ maxParseFileBytes: input.maxParseFileBytes,
258
+ maxQueryWaitMs: input.maxQueryWaitMs,
259
+ path: input.path,
260
+ grammarForLang: this.parser.grammarForLang,
261
+ tagsSource: tags.source,
262
+ tagsHash: tags.hash,
263
+ importsSource: IMPORTS,
264
+ importsHash: IMPORTS_HASH,
265
+ enclosingStatementNodeTypes: queries.enclosingStatementNodeTypes,
266
+ });
267
+ }
268
+ /**
269
+ * Reclassify definition subtypes the structural query cannot: function/arrow
270
+ * declarators → function/component/hook; non-fn declarators with a `use*` name →
271
+ * hook. Mirrors the legacy `classifySubtype` decisions exactly. Drafts-only.
272
+ */
273
+ refine(draft, _ctx) {
274
+ const definitions = draft.definitions.map((d) => {
275
+ // Only function-declaration + variable drafts are reclassified (classes,
276
+ // types, interfaces keep their fixed subtype — legacy never reclassifies them).
277
+ const src = isDefSourceNode(d.sourceNode) ? d.sourceNode : null;
278
+ if (d.subtype === 'function') {
279
+ // function declaration: classifySubtype(name, node, isFunctionLike=true).
280
+ const valueNode = src ? src.node : null;
281
+ const subtype = classifySubtype(d.name, valueNode, true);
282
+ return subtype === d.subtype ? d : { ...d, subtype };
283
+ }
284
+ if (d.subtype === 'variable') {
285
+ const value = src ? declaratorValue(src.nameNode) : null;
286
+ const isFnLike = !!value && FN_VALUE_TYPES.has(value.type);
287
+ const subtype = classifySubtype(d.name, value, isFnLike);
288
+ return subtype === d.subtype ? d : { ...d, subtype };
289
+ }
290
+ return d;
291
+ });
292
+ return { ...draft, definitions };
293
+ }
294
+ /**
295
+ * P1c file-level import resolution (intra-project, relative specifiers). Returns
296
+ * paths only — the core mints the `resolves_to` edge + target file id. Bare/
297
+ * external specifiers resolve to nothing (no edge). Confidence 1.0 (exact file).
298
+ */
299
+ async resolveImport(req, ctx) {
300
+ const resolved = resolveTsImport(req.source, req.fromPath, ctx);
301
+ return resolved ? [{ source: req.source, resolvedPath: resolved, confidence: 1.0 }] : [];
302
+ }
303
+ }
304
+ /** Singleton instance for registry wiring. */
305
+ export const typeScriptProvider = new TypeScriptProvider();
306
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,106 @@
1
+ ; Brainclaw Code Map — JAVASCRIPT-grammar DEFINITIONS query (curated subset of tags.scm).
2
+ ;
3
+ ; The shared tags.scm references TypeScript-ONLY node types
4
+ ; (type_alias_declaration, interface_declaration, type_identifier) which the
5
+ ; tree-sitter JAVASCRIPT grammar rejects ("Bad node name 'type_identifier'").
6
+ ; This file is the JS-compatible subset (trp_5026812e): it drops type/interface
7
+ ; entirely (JS has none) and resolves a class name via `identifier` (the JS
8
+ ; grammar names classes with `identifier`, not `type_identifier`).
9
+ ;
10
+ ; Capture convention + span semantics are IDENTICAL to tags.scm:
11
+ ; @definition.<subtype>.node -> DefinitionDraft.span (enclosing declaration
12
+ ; statement — every declarator in `const a=1,b=2`
13
+ ; shares it)
14
+ ; @definition.<subtype>.name -> DefinitionDraft.name
15
+ ; @definition.<subtype>.exported -> presence marks DefinitionDraft.exported = true
16
+ ;
17
+ ; Subtypes captured here: function | class | variable. (component / hook
18
+ ; reclassification happens in the provider's refine() pass.)
19
+
20
+ ; ---------------------------------------------------------------------------
21
+ ; function declarations (function foo() {}, function* gen() {})
22
+ ; ---------------------------------------------------------------------------
23
+ (program
24
+ (function_declaration
25
+ name: (identifier) @definition.function.name) @definition.function.node)
26
+
27
+ (program
28
+ (generator_function_declaration
29
+ name: (identifier) @definition.function.name) @definition.function.node)
30
+
31
+ (program
32
+ (export_statement
33
+ (function_declaration
34
+ name: (identifier) @definition.function.name) @definition.function.node) @definition.function.exported)
35
+
36
+ (program
37
+ (export_statement
38
+ (generator_function_declaration
39
+ name: (identifier) @definition.function.name) @definition.function.node) @definition.function.exported)
40
+
41
+ ; ---------------------------------------------------------------------------
42
+ ; class declarations (class Foo {}) — JS names the class with `identifier`.
43
+ ; ---------------------------------------------------------------------------
44
+ (program
45
+ (class_declaration
46
+ name: (identifier) @definition.class.name) @definition.class.node)
47
+
48
+ (program
49
+ (export_statement
50
+ (class_declaration
51
+ name: (identifier) @definition.class.name) @definition.class.node) @definition.class.exported)
52
+
53
+ ; ---------------------------------------------------------------------------
54
+ ; lexical / variable declarations (const a = 1, b = 2; let x; var y = () => {})
55
+ ; One match per declarator (one per identifier name); the enclosing statement is
56
+ ; the shared legacy identity span.
57
+ ; ---------------------------------------------------------------------------
58
+ (program
59
+ (lexical_declaration
60
+ (variable_declarator
61
+ name: (identifier) @definition.variable.name)) @definition.variable.node)
62
+
63
+ (program
64
+ (variable_declaration
65
+ (variable_declarator
66
+ name: (identifier) @definition.variable.name)) @definition.variable.node)
67
+
68
+ (program
69
+ (export_statement
70
+ (lexical_declaration
71
+ (variable_declarator
72
+ name: (identifier) @definition.variable.name)) @definition.variable.node) @definition.variable.exported)
73
+
74
+ (program
75
+ (export_statement
76
+ (variable_declaration
77
+ (variable_declarator
78
+ name: (identifier) @definition.variable.name)) @definition.variable.node) @definition.variable.exported)
79
+
80
+ ; ---------------------------------------------------------------------------
81
+ ; ERROR-root recovery (legacy parity). See tags.scm for the rationale: when the
82
+ ; file promotes to an `ERROR` root the declarations recover as direct children;
83
+ ; the legacy extractor captured them via `root.namedChild(i)`. JS subset: no
84
+ ; type/interface; class names resolve via `identifier`.
85
+ ; ---------------------------------------------------------------------------
86
+ (ERROR
87
+ (function_declaration
88
+ name: (identifier) @definition.function.name) @definition.function.node)
89
+
90
+ (ERROR
91
+ (generator_function_declaration
92
+ name: (identifier) @definition.function.name) @definition.function.node)
93
+
94
+ (ERROR
95
+ (class_declaration
96
+ name: (identifier) @definition.class.name) @definition.class.node)
97
+
98
+ (ERROR
99
+ (lexical_declaration
100
+ (variable_declarator
101
+ name: (identifier) @definition.variable.name)) @definition.variable.node)
102
+
103
+ (ERROR
104
+ (variable_declaration
105
+ (variable_declarator
106
+ name: (identifier) @definition.variable.name)) @definition.variable.node)
@@ -0,0 +1,151 @@
1
+ ; Brainclaw Code Map — TypeScript/TSX/JavaScript DEFINITIONS query (curated, vendored).
2
+ ; See ./README.md for the capture-name convention and provenance.
3
+ ;
4
+ ; Emits one logical definition per top-level declaration. The query-runtime maps:
5
+ ; @definition.<subtype>.node -> DefinitionDraft.span (the LEGACY IDENTITY span:
6
+ ; the enclosing declaration statement, NOT the
7
+ ; declarator/identifier — every declarator in
8
+ ; `const a = 1, b = 2` shares this statement span)
9
+ ; @definition.<subtype>.name -> DefinitionDraft.name (identifier text)
10
+ ; @definition.<subtype>.exported -> presence marks DefinitionDraft.exported = true
11
+ ;
12
+ ; Subtypes captured here: function | class | type | interface | variable.
13
+ ; (component / hook reclassification of function/variable subtypes happens in the
14
+ ; provider's refine() pass via PascalCase + returnsJsx / /^use[A-Z0-9]/ — queries
15
+ ; cannot perform JSX-body inspection, so this asset emits the structural subtype only.)
16
+ ;
17
+ ; Scope = TOP-LEVEL declarations only (P1a parity: no methods, no nested defs). Each
18
+ ; pattern is anchored to a child of the `program` root, either directly or inside an
19
+ ; `export_statement`. The unexported and exported forms are listed as sibling
20
+ ; alternatives so an exported declaration carries the @definition.*.exported marker.
21
+
22
+ ; ---------------------------------------------------------------------------
23
+ ; function declarations (function foo() {}, function* gen() {})
24
+ ; ---------------------------------------------------------------------------
25
+ (program
26
+ (function_declaration
27
+ name: (identifier) @definition.function.name) @definition.function.node)
28
+
29
+ (program
30
+ (generator_function_declaration
31
+ name: (identifier) @definition.function.name) @definition.function.node)
32
+
33
+ (program
34
+ (export_statement
35
+ (function_declaration
36
+ name: (identifier) @definition.function.name) @definition.function.node) @definition.function.exported)
37
+
38
+ (program
39
+ (export_statement
40
+ (generator_function_declaration
41
+ name: (identifier) @definition.function.name) @definition.function.node) @definition.function.exported)
42
+
43
+ ; ---------------------------------------------------------------------------
44
+ ; class declarations (class Foo {})
45
+ ; ---------------------------------------------------------------------------
46
+ (program
47
+ (class_declaration
48
+ name: (type_identifier) @definition.class.name) @definition.class.node)
49
+
50
+ (program
51
+ (export_statement
52
+ (class_declaration
53
+ name: (type_identifier) @definition.class.name) @definition.class.node) @definition.class.exported)
54
+
55
+ ; ---------------------------------------------------------------------------
56
+ ; type aliases (type Foo = ...)
57
+ ; ---------------------------------------------------------------------------
58
+ (program
59
+ (type_alias_declaration
60
+ name: (type_identifier) @definition.type.name) @definition.type.node)
61
+
62
+ (program
63
+ (export_statement
64
+ (type_alias_declaration
65
+ name: (type_identifier) @definition.type.name) @definition.type.node) @definition.type.exported)
66
+
67
+ ; ---------------------------------------------------------------------------
68
+ ; interfaces (interface Foo {})
69
+ ; ---------------------------------------------------------------------------
70
+ (program
71
+ (interface_declaration
72
+ name: (type_identifier) @definition.interface.name) @definition.interface.node)
73
+
74
+ (program
75
+ (export_statement
76
+ (interface_declaration
77
+ name: (type_identifier) @definition.interface.name) @definition.interface.node) @definition.interface.exported)
78
+
79
+ ; ---------------------------------------------------------------------------
80
+ ; lexical / variable declarations (const a = 1, b = 2; let x; var y = () => {})
81
+ ;
82
+ ; The @definition.variable.node capture is the ENCLOSING statement (lexical_declaration
83
+ ; / variable_declaration), so every declarator in a multi-declarator statement shares
84
+ ; the same legacy identity span. One match is produced per declarator (one per
85
+ ; identifier name); the runtime de-dupes node-handle reuse via the per-declarator name.
86
+ ; Only simple `identifier` declarator names are captured (parity: object/array
87
+ ; destructuring patterns are not emitted as symbols by the legacy extractor).
88
+ ; ---------------------------------------------------------------------------
89
+ (program
90
+ (lexical_declaration
91
+ (variable_declarator
92
+ name: (identifier) @definition.variable.name)) @definition.variable.node)
93
+
94
+ (program
95
+ (variable_declaration
96
+ (variable_declarator
97
+ name: (identifier) @definition.variable.name)) @definition.variable.node)
98
+
99
+ (program
100
+ (export_statement
101
+ (lexical_declaration
102
+ (variable_declarator
103
+ name: (identifier) @definition.variable.name)) @definition.variable.node) @definition.variable.exported)
104
+
105
+ (program
106
+ (export_statement
107
+ (variable_declaration
108
+ (variable_declarator
109
+ name: (identifier) @definition.variable.name)) @definition.variable.node) @definition.variable.exported)
110
+
111
+ ; ---------------------------------------------------------------------------
112
+ ; ERROR-root recovery (legacy parity).
113
+ ;
114
+ ; When tree-sitter cannot parse a file cleanly it may promote the WHOLE file to
115
+ ; an `ERROR` root rather than `program`, while still recovering the individual
116
+ ; top-level declarations as direct children of that ERROR node. The legacy
117
+ ; extractor walked `root.namedChild(i)` regardless of the root's type, so it
118
+ ; captured those declarations; an anchor on `(program ...)` alone silently drops
119
+ ; EVERY symbol in such a file. These sibling patterns mirror the `(program ...)`
120
+ ; forms under an `(ERROR ...)` root so content parity holds for files that only
121
+ ; parse under error recovery (e.g. test files the TS grammar trips on).
122
+ ; ---------------------------------------------------------------------------
123
+ (ERROR
124
+ (function_declaration
125
+ name: (identifier) @definition.function.name) @definition.function.node)
126
+
127
+ (ERROR
128
+ (generator_function_declaration
129
+ name: (identifier) @definition.function.name) @definition.function.node)
130
+
131
+ (ERROR
132
+ (class_declaration
133
+ name: (type_identifier) @definition.class.name) @definition.class.node)
134
+
135
+ (ERROR
136
+ (type_alias_declaration
137
+ name: (type_identifier) @definition.type.name) @definition.type.node)
138
+
139
+ (ERROR
140
+ (interface_declaration
141
+ name: (type_identifier) @definition.interface.name) @definition.interface.node)
142
+
143
+ (ERROR
144
+ (lexical_declaration
145
+ (variable_declarator
146
+ name: (identifier) @definition.variable.name)) @definition.variable.node)
147
+
148
+ (ERROR
149
+ (variable_declaration
150
+ (variable_declarator
151
+ name: (identifier) @definition.variable.name)) @definition.variable.node)