brainclaw 1.9.0 → 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 (149) hide show
  1. package/README.md +631 -499
  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/harvest.js +1 -1
  7. package/dist/commands/hooks.js +73 -73
  8. package/dist/commands/init.js +1 -1
  9. package/dist/commands/install-hooks.js +78 -78
  10. package/dist/commands/mcp-read-handlers.js +57 -14
  11. package/dist/commands/mcp.js +200 -13
  12. package/dist/commands/run-profile.js +3 -2
  13. package/dist/commands/switch.js +125 -93
  14. package/dist/commands/version.js +1 -1
  15. package/dist/core/agent-capability.js +19 -4
  16. package/dist/core/agent-files.js +131 -119
  17. package/dist/core/code-map/backend.js +123 -0
  18. package/dist/core/code-map/core.js +81 -0
  19. package/dist/core/code-map/drafts.js +2 -0
  20. package/dist/core/code-map/extractor.js +29 -0
  21. package/dist/core/code-map/finalizer.js +191 -0
  22. package/dist/core/code-map/freshness.js +108 -0
  23. package/dist/core/code-map/ids.js +0 -0
  24. package/dist/core/code-map/importable.js +35 -0
  25. package/dist/core/code-map/indexes.js +197 -0
  26. package/dist/core/code-map/lang/java/imports.scm +17 -0
  27. package/dist/core/code-map/lang/java/index.js +254 -0
  28. package/dist/core/code-map/lang/java/tags.scm +48 -0
  29. package/dist/core/code-map/lang/php/imports.scm +21 -0
  30. package/dist/core/code-map/lang/php/index.js +251 -0
  31. package/dist/core/code-map/lang/php/tags.scm +44 -0
  32. package/dist/core/code-map/lang/provider.js +9 -0
  33. package/dist/core/code-map/lang/providers.js +24 -0
  34. package/dist/core/code-map/lang/python/imports.scm +90 -0
  35. package/dist/core/code-map/lang/python/index.js +364 -0
  36. package/dist/core/code-map/lang/python/tags.scm +81 -0
  37. package/dist/core/code-map/lang/query-runtime.js +374 -0
  38. package/dist/core/code-map/lang/registry.js +125 -0
  39. package/dist/core/code-map/lang/typescript/imports.scm +90 -0
  40. package/dist/core/code-map/lang/typescript/index.js +306 -0
  41. package/dist/core/code-map/lang/typescript/tags.js.scm +106 -0
  42. package/dist/core/code-map/lang/typescript/tags.scm +151 -0
  43. package/dist/core/code-map/lock.js +210 -0
  44. package/dist/core/code-map/materialized.js +51 -0
  45. package/dist/core/code-map/memory-reader.js +59 -0
  46. package/dist/core/code-map/paths.js +53 -0
  47. package/dist/core/code-map/query.js +568 -0
  48. package/dist/core/code-map/refresh.js +0 -0
  49. package/dist/core/code-map/resolve.js +177 -0
  50. package/dist/core/code-map/store.js +206 -0
  51. package/dist/core/code-map/types.js +288 -0
  52. package/dist/core/code-map/vocabulary.js +57 -0
  53. package/dist/core/code-map/wasm-loader.js +294 -0
  54. package/dist/core/code-map/work-section.js +206 -0
  55. package/dist/core/codev-prompts.js +38 -38
  56. package/dist/core/codev-rounds.js +4 -0
  57. package/dist/core/default-profiles/doctor.yaml +11 -11
  58. package/dist/core/default-profiles/janitor.yaml +11 -11
  59. package/dist/core/default-profiles/onboarder.yaml +11 -11
  60. package/dist/core/default-profiles/reviewer.yaml +13 -13
  61. package/dist/core/dispatcher.js +1 -1
  62. package/dist/core/entity-operations.js +29 -3
  63. package/dist/core/execution-adapters.js +11 -10
  64. package/dist/core/execution-profile.js +58 -0
  65. package/dist/core/execution.js +1 -1
  66. package/dist/core/facade-schema.js +9 -0
  67. package/dist/core/instruction-templates.js +2 -0
  68. package/dist/core/loops/verbs.js +0 -1
  69. package/dist/core/mcp-command-resolution.js +3 -1
  70. package/dist/core/messaging.js +2 -2
  71. package/dist/core/protocol-skills.js +164 -164
  72. package/dist/core/runtime-signals.js +1 -1
  73. package/dist/core/search.js +19 -2
  74. package/dist/core/security-guard.js +207 -207
  75. package/dist/core/spawn-check.js +16 -2
  76. package/dist/core/staleness.js +1 -1
  77. package/dist/core/store-resolution.js +67 -11
  78. package/dist/core/worktree.js +18 -18
  79. package/dist/facts.js +9 -5
  80. package/dist/facts.json +8 -4
  81. package/dist/vendor/web-tree-sitter/tree-sitter.js +3980 -0
  82. package/dist/vendor/web-tree-sitter/tree-sitter.wasm +0 -0
  83. package/dist/wasm/tree-sitter-java.wasm +0 -0
  84. package/dist/wasm/tree-sitter-javascript.wasm +0 -0
  85. package/dist/wasm/tree-sitter-php.wasm +0 -0
  86. package/dist/wasm/tree-sitter-python.wasm +0 -0
  87. package/dist/wasm/tree-sitter-tsx.wasm +0 -0
  88. package/dist/wasm/tree-sitter-typescript.wasm +0 -0
  89. package/dist/wasm/tree-sitter.wasm +0 -0
  90. package/docs/PROTOCOL.md +1 -1
  91. package/docs/adapters/openclaw.md +43 -43
  92. package/docs/architecture/project-refs.md +328 -328
  93. package/docs/cli.md +2131 -2093
  94. package/docs/code-map.md +198 -0
  95. package/docs/concepts/coordination.md +52 -52
  96. package/docs/concepts/coordinator-runbook.md +129 -129
  97. package/docs/concepts/dispatch-lifecycle.md +245 -245
  98. package/docs/concepts/event-log-store.md +928 -928
  99. package/docs/concepts/ideation-loop.md +317 -317
  100. package/docs/concepts/loop-engine.md +520 -511
  101. package/docs/concepts/mcp-governance.md +268 -268
  102. package/docs/concepts/memory.md +84 -84
  103. package/docs/concepts/multi-agent-workflows.md +167 -167
  104. package/docs/concepts/observer-protocol.md +361 -361
  105. package/docs/concepts/plans-and-claims.md +217 -217
  106. package/docs/concepts/project-md-convention.md +35 -35
  107. package/docs/concepts/runtime-notes.md +38 -38
  108. package/docs/concepts/troubleshooting.md +254 -254
  109. package/docs/concepts/workspace-bootstrapping.md +142 -142
  110. package/docs/context-format-changelog.md +35 -35
  111. package/docs/context-format.md +48 -48
  112. package/docs/index.md +65 -65
  113. package/docs/integrations/agents.md +158 -158
  114. package/docs/integrations/claude-code.md +23 -23
  115. package/docs/integrations/cline.md +77 -77
  116. package/docs/integrations/continue.md +55 -55
  117. package/docs/integrations/copilot.md +68 -68
  118. package/docs/integrations/cursor.md +23 -23
  119. package/docs/integrations/kilocode.md +72 -72
  120. package/docs/integrations/mcp.md +385 -378
  121. package/docs/integrations/mistral-vibe.md +122 -122
  122. package/docs/integrations/openclaw.md +92 -92
  123. package/docs/integrations/opencode.md +84 -84
  124. package/docs/integrations/overview.md +115 -115
  125. package/docs/integrations/roo.md +71 -71
  126. package/docs/integrations/windsurf.md +77 -77
  127. package/docs/mcp-schema-changelog.md +364 -356
  128. package/docs/playbooks/integration/index.md +121 -121
  129. package/docs/playbooks/orchestration.md +37 -0
  130. package/docs/playbooks/productivity/index.md +99 -99
  131. package/docs/playbooks/team/index.md +117 -117
  132. package/docs/product/agent-first-model.md +184 -184
  133. package/docs/product/entity-model-audit.md +462 -462
  134. package/docs/product/positioning.md +86 -86
  135. package/docs/quickstart-existing-project.md +107 -107
  136. package/docs/quickstart.md +183 -183
  137. package/docs/release-maintenance.md +79 -79
  138. package/docs/reputation.md +52 -52
  139. package/docs/review.md +45 -45
  140. package/docs/security.md +212 -212
  141. package/docs/server-operations.md +118 -118
  142. package/docs/storage.md +106 -106
  143. package/package.json +86 -66
  144. package/docs/concepts/event-log-store-critique-A.md +0 -333
  145. package/docs/concepts/event-log-store-critique-B.md +0 -353
  146. package/docs/concepts/event-log-store-phase0-measurements.md +0 -58
  147. package/docs/concepts/event-log-store-proposal-A.md +0 -365
  148. package/docs/concepts/event-log-store-proposal-B.md +0 -404
  149. package/docs/concepts/identity-model-proposal.md +0 -371
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Code Map index builders (spec §5.6, §5.7).
3
+ *
4
+ * Both indexes are derived purely from `files/**` shards and written atomically
5
+ * (store.ts uses writeFileAtomic). Queries answer from these + shards alone;
6
+ * materialized JSONL is never required.
7
+ *
8
+ * Ordering is deterministic so two refreshes over identical inputs produce
9
+ * byte-identical indexes (concurrency rule 5 spirit; helps "no JSONL committed"
10
+ * diffs stay clean).
11
+ */
12
+ import { CODE_MAP_SCHEMA_VERSION, } from './types.js';
13
+ import { fileNodeId } from './ids.js';
14
+ /** Lowercase token normalization (spec §5.6 keys). */
15
+ function tokenize(name) {
16
+ const lower = name.toLowerCase();
17
+ const tokens = new Set();
18
+ tokens.add(lower);
19
+ // split camelCase / snake / kebab boundaries into sub-tokens for partial recall
20
+ for (const part of name.split(/[^A-Za-z0-9]+/)) {
21
+ if (!part)
22
+ continue;
23
+ // camelCase split
24
+ for (const sub of part.replace(/([a-z0-9])([A-Z])/g, '$1 $2').split(/\s+/)) {
25
+ if (sub)
26
+ tokens.add(sub.toLowerCase());
27
+ }
28
+ }
29
+ return [...tokens];
30
+ }
31
+ export function buildSymbolsIndex(projectId, shards, extractorVersion) {
32
+ // Null-proto map: symbol-name tokens can collide with Object.prototype members
33
+ // (e.g. a method named `constructor`, or a `__proto__` key), which would make
34
+ // `entries[token] ??= []` see the inherited function and crash on .push, or make
35
+ // `entries['__proto__'] = …` mutate the prototype instead of adding a key.
36
+ const entries = Object.create(null);
37
+ // Deterministic shard order by path.
38
+ const ordered = [...shards].sort((a, b) => a.path.localeCompare(b.path));
39
+ for (const shard of ordered) {
40
+ for (const node of shard.nodes) {
41
+ if (node.kind !== 'symbol')
42
+ continue;
43
+ const entry = {
44
+ node_id: node.id,
45
+ name: node.name,
46
+ kind: node.kind,
47
+ subtype: node.subtype ?? null,
48
+ path: node.path,
49
+ file_id: shard.file_id,
50
+ score_hint: node.exported ? 1.0 : 0.8,
51
+ };
52
+ for (const token of tokenize(node.name)) {
53
+ (entries[token] ??= []).push(entry);
54
+ }
55
+ }
56
+ }
57
+ // Deterministic ordering within each token bucket.
58
+ for (const token of Object.keys(entries)) {
59
+ entries[token].sort((a, b) => a.path.localeCompare(b.path) ||
60
+ a.name.localeCompare(b.name) ||
61
+ a.node_id.localeCompare(b.node_id));
62
+ }
63
+ // Sort keys for byte-stable output.
64
+ const sortedEntries = Object.create(null);
65
+ for (const key of Object.keys(entries).sort())
66
+ sortedEntries[key] = entries[key];
67
+ return {
68
+ schema_version: CODE_MAP_SCHEMA_VERSION,
69
+ project_id: projectId,
70
+ updated_at: new Date().toISOString(),
71
+ extractor_version: extractorVersion,
72
+ entries: sortedEntries,
73
+ };
74
+ }
75
+ export function buildImportsIndex(projectId, shards) {
76
+ // module specifier -> (path -> entry)
77
+ const byModule = new Map();
78
+ const ordered = [...shards].sort((a, b) => a.path.localeCompare(b.path));
79
+ for (const shard of ordered) {
80
+ for (const node of shard.nodes) {
81
+ if (node.kind !== 'module')
82
+ continue;
83
+ const module = node.name;
84
+ const perPath = byModule.get(module) ?? new Map();
85
+ const entry = perPath.get(shard.path) ?? {
86
+ path: shard.path,
87
+ file_id: shard.file_id,
88
+ imported: [],
89
+ };
90
+ // Merge imported bindings across multiple imports of the same module in one
91
+ // file, deduped + sorted for byte-stable output (spec §5.7 imported[]).
92
+ const merged = new Set(entry.imported);
93
+ for (const name of node.imported_names ?? [])
94
+ merged.add(name);
95
+ entry.imported = [...merged].sort();
96
+ perPath.set(shard.path, entry);
97
+ byModule.set(module, perPath);
98
+ }
99
+ }
100
+ const entries = Object.create(null);
101
+ for (const key of [...byModule.keys()].sort()) {
102
+ const list = [...byModule.get(key).values()].sort((a, b) => a.path.localeCompare(b.path));
103
+ entries[key] = list;
104
+ }
105
+ return {
106
+ schema_version: CODE_MAP_SCHEMA_VERSION,
107
+ project_id: projectId,
108
+ updated_at: new Date().toISOString(),
109
+ entries,
110
+ };
111
+ }
112
+ /**
113
+ * P1d reverse-dependency index: "who imports this target". Derived from the P1c
114
+ * resolution edges that live on each IMPORTER's shard:
115
+ * - `resolves_to` (module → target FILE node) → `dependents_by_file[targetPath]`
116
+ * - `imports_symbol` (module → target SYMBOL node) → `dependents_by_symbol[nodeId]`
117
+ *
118
+ * `resolves_to.to` is a file NODE ID (not a path), so we invert fileNodeId→path by
119
+ * computing the id for every indexed shard (Codex review). One entry per (target,
120
+ * importer file): multiple module nodes in one importer that hit the same target are
121
+ * merged (imported names unioned, strongest confidence, lexicographically-smallest
122
+ * specifier) for byte-stable output. Deterministic key + array ordering.
123
+ */
124
+ export function buildResolutionIndex(projectId, shards) {
125
+ // Invert file-node id → path so reverse resolves_to can be keyed by target path.
126
+ const fileNodeIdToPath = new Map();
127
+ for (const shard of shards) {
128
+ fileNodeIdToPath.set(fileNodeId(projectId, shard.path, shard.lang), shard.path);
129
+ }
130
+ // target key -> (importer path -> merged entry)
131
+ const byFile = new Map();
132
+ const bySymbol = new Map();
133
+ const addDependent = (bucket, targetKey, importerPath, importerFileId, module, imported, confidence) => {
134
+ const perImporter = bucket.get(targetKey) ?? new Map();
135
+ const prev = perImporter.get(importerPath);
136
+ if (!prev) {
137
+ perImporter.set(importerPath, {
138
+ path: importerPath,
139
+ file_id: importerFileId,
140
+ module,
141
+ imported: [...new Set(imported)].sort(),
142
+ confidence,
143
+ });
144
+ }
145
+ else {
146
+ // Merge a second edge from the same importer to the same target.
147
+ const mergedNames = new Set(prev.imported);
148
+ for (const n of imported)
149
+ mergedNames.add(n);
150
+ prev.imported = [...mergedNames].sort();
151
+ if (module && (!prev.module || module < prev.module))
152
+ prev.module = module; // smallest spec, stable
153
+ if (typeof confidence === 'number') {
154
+ prev.confidence = typeof prev.confidence === 'number' ? Math.max(prev.confidence, confidence) : confidence;
155
+ }
156
+ }
157
+ bucket.set(targetKey, perImporter);
158
+ };
159
+ const ordered = [...shards].sort((a, b) => a.path.localeCompare(b.path));
160
+ for (const shard of ordered) {
161
+ // module node id -> its specifier + imported names (for reason metadata).
162
+ const moduleById = new Map();
163
+ for (const n of shard.nodes) {
164
+ if (n.kind === 'module')
165
+ moduleById.set(n.id, { name: n.name, imported: n.imported_names ?? [] });
166
+ }
167
+ for (const e of shard.edges) {
168
+ if (e.kind !== 'resolves_to' && e.kind !== 'imports_symbol')
169
+ continue;
170
+ const mod = moduleById.get(e.from);
171
+ if (e.kind === 'resolves_to') {
172
+ const targetPath = fileNodeIdToPath.get(e.to);
173
+ if (!targetPath)
174
+ continue; // target id not an indexed file (defensive)
175
+ addDependent(byFile, targetPath, shard.path, shard.file_id, mod?.name, mod?.imported ?? [], e.confidence);
176
+ }
177
+ else {
178
+ addDependent(bySymbol, e.to, shard.path, shard.file_id, mod?.name, mod?.imported ?? [], e.confidence);
179
+ }
180
+ }
181
+ }
182
+ const finalize = (bucket) => {
183
+ const out = Object.create(null);
184
+ for (const key of [...bucket.keys()].sort()) {
185
+ out[key] = [...bucket.get(key).values()].sort((a, b) => a.path.localeCompare(b.path));
186
+ }
187
+ return out;
188
+ };
189
+ return {
190
+ schema_version: CODE_MAP_SCHEMA_VERSION,
191
+ project_id: projectId,
192
+ updated_at: new Date().toISOString(),
193
+ dependents_by_file: finalize(byFile),
194
+ dependents_by_symbol: finalize(bySymbol),
195
+ };
196
+ }
197
+ //# sourceMappingURL=indexes.js.map
@@ -0,0 +1,17 @@
1
+ ; Code Map — Java imports (imports.scm). Provider #4 (langs#3-4).
2
+ ;
3
+ ; enclosingStatementNodeTypes = [import_declaration] (provider declaration); that
4
+ ; statement is the import span/ordinal anchor. Java import shapes (Codex R1):
5
+ ; import a.b.C; -> module a.b.C
6
+ ; import a.b.*; -> module a.b + imported name '*'
7
+ ; import static a.b.C.m; -> module a.b.C + imported name 'm' (split type/member)
8
+ ; import static a.b.C.*; -> module a.b.C + imported name '*'
9
+ ;
10
+ ; A single capture takes the scoped_identifier path verbatim (e.g. "a.b.C" or, for a
11
+ ; wildcard import, the package "a.b" — the grammar puts the `*` in a sibling
12
+ ; `asterisk` node, NOT inside scoped_identifier). The provider's refine() inspects
13
+ ; each import_declaration for the `static` keyword and the `asterisk` sibling and
14
+ ; rewrites source/imported-names accordingly (the static-split and wildcard rules
15
+ ; can't be expressed structurally without overlapping matches).
16
+
17
+ (import_declaration [(scoped_identifier) (identifier)] @import.source)
@@ -0,0 +1,254 @@
1
+ /**
2
+ * Code Map langs#3-4 — JavaProvider (provider #4; cadrage v2 §6, dec#113).
3
+ *
4
+ * Owns `.java` (runtime lang `java`). `extractDraft` delegates to the generic
5
+ * query-runtime; the curated `tags.scm`/`imports.scm` (this dir) drive structural
6
+ * extraction. All definition subtypes are fixed by the query (no def
7
+ * reclassification needed). `refine()` carries ONLY the import shaping the
8
+ * structural query cannot express without overlapping matches (Codex R1):
9
+ * - wildcard `import a.b.*;` → imported name `*` (the package source `a.b` is
10
+ * already captured; the grammar puts `*` in a sibling `asterisk` node).
11
+ * - static `import static a.b.C.m;` → split the declaring type `a.b.C` (module
12
+ * source) from the member `m` (imported name); `import static a.b.C.*;` →
13
+ * source `a.b.C` + name `*`.
14
+ * - plain `import a.b.C;` → source `a.b.C`, no imported name.
15
+ *
16
+ * NO exports edges — Java has no export statement (capabilities: T2 = imports).
17
+ * Nested/inner classes + their members are emitted by the same class/method
18
+ * patterns; the finalizer emits only file-level contains/defines (no nesting edges).
19
+ *
20
+ * Identity is owned by the CORE finalizer — this provider mints NO ids. The grammar
21
+ * is loaded through the SHARED engine glue (`loadGrammarWasm`), NEVER a fresh
22
+ * `web-tree-sitter` import (trp_8df65ab7).
23
+ */
24
+ import crypto from 'node:crypto';
25
+ import fs from 'node:fs';
26
+ import path from 'node:path';
27
+ import { fileURLToPath } from 'node:url';
28
+ import { loadGrammarWasm, grammarHashForWasm } from '../../wasm-loader.js';
29
+ import { extractWithQueries } from '../query-runtime.js';
30
+ const HERE = path.dirname(fileURLToPath(import.meta.url));
31
+ /** The java grammar .wasm: dist basename + node_modules devDep fallback spec. */
32
+ const JAVA_WASM_BASENAME = 'tree-sitter-java.wasm';
33
+ const JAVA_WASM_NODE_MODULES_SPEC = 'tree-sitter-wasms/out/tree-sitter-java.wasm';
34
+ const JAVA_GRAMMAR_NAME = 'tree-sitter-java';
35
+ /** Resolve a vendored `.scm` next to this module (dist) or from the source tree. */
36
+ function readScm(basename) {
37
+ // Published / dist runtime: this module is dist/core/code-map/lang/java/index.js
38
+ // and the build copies the .scm assets alongside it (copy-code-map-wasm.mjs).
39
+ const local = path.join(HERE, basename);
40
+ if (fs.existsSync(local))
41
+ return fs.readFileSync(local, 'utf-8');
42
+ // From-source / dist-test fallback: tsc emits to dist[-test]/... but does NOT copy
43
+ // .scm, so walk up to the repo root (the dir holding package.json) and read the
44
+ // curated asset from src/core/code-map/lang/java/.
45
+ let dir = HERE;
46
+ for (let i = 0; i < 12; i++) {
47
+ if (fs.existsSync(path.join(dir, 'package.json'))) {
48
+ const fromSrc = path.join(dir, 'src', 'core', 'code-map', 'lang', 'java', basename);
49
+ if (fs.existsSync(fromSrc))
50
+ return fs.readFileSync(fromSrc, 'utf-8');
51
+ break;
52
+ }
53
+ const parent = path.dirname(dir);
54
+ if (parent === dir)
55
+ break;
56
+ dir = parent;
57
+ }
58
+ throw new Error(`code-map: could not locate query asset ${basename} (from ${HERE})`);
59
+ }
60
+ function sha256(s) {
61
+ return `sha256:${crypto.createHash('sha256').update(s, 'utf-8').digest('hex')}`;
62
+ }
63
+ // Load the curated query assets once at module init.
64
+ const TAGS = readScm('tags.scm');
65
+ const IMPORTS = readScm('imports.scm');
66
+ const TAGS_HASH = sha256(TAGS);
67
+ const IMPORTS_HASH = sha256(IMPORTS);
68
+ const parser = {
69
+ grammarForLang: () => loadGrammarWasm(JAVA_WASM_BASENAME, JAVA_WASM_NODE_MODULES_SPEC),
70
+ grammarNameForLang: () => JAVA_GRAMMAR_NAME,
71
+ grammarHashForLang: () => grammarHashForWasm(JAVA_WASM_BASENAME, JAVA_WASM_NODE_MODULES_SPEC),
72
+ };
73
+ const queries = {
74
+ tags: {
75
+ name: 'tags',
76
+ sourceForLang: () => TAGS,
77
+ hashForLang: () => TAGS_HASH,
78
+ },
79
+ imports: {
80
+ name: 'imports',
81
+ sourceForLang: () => IMPORTS,
82
+ hashForLang: () => IMPORTS_HASH,
83
+ },
84
+ // Java import declarations are the import statement; Java has no export statement.
85
+ enclosingStatementNodeTypes: ['import_declaration'],
86
+ // P1b §3.4 / cadrage: every capture mirrors the hard-coded runtime convention and
87
+ // is validated by `assertCaptureMapConforms`. The namespaced java.annotation /
88
+ // java.record are still definition.<subtype>.* captures.
89
+ captureMap: [
90
+ { capture: 'definition.package.node', field: 'node', subtype: 'package' },
91
+ { capture: 'definition.package.name', field: 'name' },
92
+ { capture: 'definition.class.node', field: 'node', subtype: 'class' },
93
+ { capture: 'definition.class.name', field: 'name' },
94
+ { capture: 'definition.interface.node', field: 'node', subtype: 'interface' },
95
+ { capture: 'definition.interface.name', field: 'name' },
96
+ { capture: 'definition.enum.node', field: 'node', subtype: 'enum' },
97
+ { capture: 'definition.enum.name', field: 'name' },
98
+ { capture: 'definition.java.annotation.node', field: 'node', subtype: 'java.annotation' },
99
+ { capture: 'definition.java.annotation.name', field: 'name' },
100
+ { capture: 'definition.java.record.node', field: 'node', subtype: 'java.record' },
101
+ { capture: 'definition.java.record.name', field: 'name' },
102
+ { capture: 'definition.method.node', field: 'node', subtype: 'method' },
103
+ { capture: 'definition.method.name', field: 'name' },
104
+ { capture: 'definition.constructor.node', field: 'node', subtype: 'constructor' },
105
+ { capture: 'definition.constructor.name', field: 'name' },
106
+ { capture: 'definition.field.node', field: 'node', subtype: 'field' },
107
+ { capture: 'definition.field.name', field: 'name' },
108
+ { capture: 'definition.constant.node', field: 'node', subtype: 'constant' },
109
+ { capture: 'definition.constant.name', field: 'name' },
110
+ { capture: 'import.source', field: 'source' },
111
+ ],
112
+ };
113
+ const vocabulary = {
114
+ nodeSubtypes: [
115
+ 'package',
116
+ 'class',
117
+ 'interface',
118
+ 'enum',
119
+ 'java.annotation',
120
+ 'java.record',
121
+ 'method',
122
+ 'constructor',
123
+ 'field',
124
+ 'constant',
125
+ ],
126
+ edgeKinds: ['contains', 'defines', 'imports'],
127
+ captureMap: queries.captureMap,
128
+ };
129
+ const capabilities = {
130
+ tiers: ['T1.definitions', 'T2.imports'],
131
+ proven: {
132
+ 'T1.definitions': true,
133
+ 'T2.imports': true,
134
+ 'T3.import_resolution': false,
135
+ 'T4.tests_for': false,
136
+ },
137
+ };
138
+ /** A span key matching the runtime's `spanOf` (1-based start/end line+col). */
139
+ function spanKey(span) {
140
+ return `${span.start_line}:${span.start_col}:${span.end_line}:${span.end_col}`;
141
+ }
142
+ function spanKeyOfNode(node) {
143
+ return `${node.startPosition.row + 1}:${node.startPosition.column + 1}:${node.endPosition.row + 1}:${node.endPosition.column + 1}`;
144
+ }
145
+ /** Iterative named-node DFS collecting nodes whose type is in `types`. */
146
+ function collectByType(root, types) {
147
+ const found = [];
148
+ const stack = [root];
149
+ while (stack.length > 0) {
150
+ const n = stack.pop();
151
+ if (types.has(n.type))
152
+ found.push(n);
153
+ for (let i = 0; i < n.namedChildCount; i++) {
154
+ const c = n.namedChild(i);
155
+ if (c)
156
+ stack.push(c);
157
+ }
158
+ }
159
+ return found;
160
+ }
161
+ const IMPORT_DECL = new Set(['import_declaration']);
162
+ /** Map each import_declaration's statement span → its static/wildcard shape. */
163
+ function importShapesBySpan(tree) {
164
+ const out = new Map();
165
+ for (const decl of collectByType(tree.rootNode, IMPORT_DECL)) {
166
+ let isStatic = false;
167
+ let isWildcard = false;
168
+ // `static` is an anonymous keyword token; `asterisk` is a named node. Iterate
169
+ // ALL children (named + anonymous) to detect both.
170
+ for (let i = 0; i < decl.childCount; i++) {
171
+ const c = decl.child(i);
172
+ if (!c)
173
+ continue;
174
+ if (c.type === 'static')
175
+ isStatic = true;
176
+ else if (c.type === 'asterisk')
177
+ isWildcard = true;
178
+ }
179
+ out.set(spanKeyOfNode(decl), { isStatic, isWildcard });
180
+ }
181
+ return out;
182
+ }
183
+ export class JavaProvider {
184
+ id = 'java';
185
+ displayName = 'Java';
186
+ languages = ['java'];
187
+ extensions = ['.java'];
188
+ priority = 0;
189
+ version = '0.1.0';
190
+ parser = parser;
191
+ queries = queries;
192
+ vocabulary = vocabulary;
193
+ capabilities = capabilities;
194
+ /** `.java` → `java`. */
195
+ langForPath(_p) {
196
+ return 'java';
197
+ }
198
+ async extractDraft(input, _services) {
199
+ return extractWithQueries({
200
+ providerId: this.id,
201
+ lang: input.lang,
202
+ source: input.source,
203
+ sizeBytes: input.sizeBytes,
204
+ maxParseFileBytes: input.maxParseFileBytes,
205
+ maxQueryWaitMs: input.maxQueryWaitMs,
206
+ path: input.path,
207
+ grammarForLang: this.parser.grammarForLang,
208
+ tagsSource: TAGS,
209
+ tagsHash: TAGS_HASH,
210
+ importsSource: IMPORTS,
211
+ importsHash: IMPORTS_HASH,
212
+ enclosingStatementNodeTypes: queries.enclosingStatementNodeTypes,
213
+ });
214
+ }
215
+ /**
216
+ * Drafts-only refinement (cadrage v2 §6): shape import source / imported-names
217
+ * per the static-split and wildcard rules. Definitions need no reclassification.
218
+ */
219
+ refine(draft, _ctx) {
220
+ const tree = draft.attributes?.__tree;
221
+ if (!tree || draft.imports.length === 0)
222
+ return draft;
223
+ const shapes = importShapesBySpan(tree);
224
+ if (shapes.size === 0)
225
+ return draft;
226
+ const imports = draft.imports.map((im) => {
227
+ const shape = shapes.get(spanKey(im.span));
228
+ if (!shape)
229
+ return im;
230
+ if (shape.isWildcard) {
231
+ // `import a.b.*` / `import static a.b.C.*` → source is the captured path; add '*'.
232
+ return { ...im, importedNames: ['*'] };
233
+ }
234
+ if (shape.isStatic) {
235
+ // `import static a.b.C.m` → split declaring type (module) vs member (name).
236
+ const dot = im.source.lastIndexOf('.');
237
+ if (dot > 0) {
238
+ return {
239
+ ...im,
240
+ source: im.source.slice(0, dot),
241
+ importedNames: [im.source.slice(dot + 1)],
242
+ };
243
+ }
244
+ return im;
245
+ }
246
+ // Plain `import a.b.C` → module a.b.C, no imported name.
247
+ return im;
248
+ });
249
+ return { ...draft, imports };
250
+ }
251
+ }
252
+ /** Singleton instance for registry wiring. */
253
+ export const javaProvider = new JavaProvider();
254
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,48 @@
1
+ ; Code Map — Java definitions (tags.scm). Provider #4 (langs#3-4).
2
+ ;
3
+ ; Capture-name convention (query-runtime.ts is the contract):
4
+ ; @definition.<subtype>.node = identity-span anchor (the whole declaration)
5
+ ; @definition.<subtype>.name = the symbol name node
6
+ ; Subtypes: package/class/interface/enum/method/constructor/field/constant are
7
+ ; universal; annotation types → java.annotation and records → java.record are
8
+ ; namespaced (they are class-like at the JVM level but users reason about them as
9
+ ; distinct kinds — Codex R1). Nested/inner classes are captured by the same
10
+ ; class_declaration pattern (the finalizer emits file-level contains/defines only;
11
+ ; no fabricated nesting edges). enum constants → constant; constructors are a
12
+ ; distinct grammar node (constructor_declaration → constructor, not method).
13
+
14
+ (package_declaration
15
+ [(scoped_identifier) (identifier)] @definition.package.name) @definition.package.node
16
+
17
+ (class_declaration
18
+ name: (identifier) @definition.class.name) @definition.class.node
19
+
20
+ (interface_declaration
21
+ name: (identifier) @definition.interface.name) @definition.interface.node
22
+
23
+ (enum_declaration
24
+ name: (identifier) @definition.enum.name) @definition.enum.node
25
+
26
+ (enum_constant
27
+ name: (identifier) @definition.constant.name) @definition.constant.node
28
+
29
+ (annotation_type_declaration
30
+ name: (identifier) @definition.java.annotation.name) @definition.java.annotation.node
31
+
32
+ (record_declaration
33
+ name: (identifier) @definition.java.record.name) @definition.java.record.node
34
+
35
+ (method_declaration
36
+ name: (identifier) @definition.method.name) @definition.method.node
37
+
38
+ (constructor_declaration
39
+ name: (identifier) @definition.constructor.name) @definition.constructor.node
40
+
41
+ ; `int a, b;` yields one match per variable_declarator (all sharing the
42
+ ; field_declaration identity span) — mirrors the const/property multi-declarator rule.
43
+ (field_declaration
44
+ declarator: (variable_declarator name: (identifier) @definition.field.name)) @definition.field.node
45
+
46
+ ; Annotation member declarations are method-shaped (`String value() default ""`).
47
+ (annotation_type_element_declaration
48
+ name: (identifier) @definition.method.name) @definition.method.node
@@ -0,0 +1,21 @@
1
+ ; Code Map — PHP imports (imports.scm). Provider #3 (langs#3-4).
2
+ ;
3
+ ; enclosingStatementNodeTypes = [namespace_use_declaration] (provider declaration);
4
+ ; that statement is the import span/ordinal anchor. PHP `use` brings a namespaced
5
+ ; symbol/module into scope; the source-side path is the module specifier.
6
+ ;
7
+ ; - simple / comma / `use function` / `use const`: each clause's qualified_name
8
+ ; (or bare name) is the full source path → captured directly as @import.source.
9
+ ; Aliases (`use A\B as C`) are dropped (we capture the path, not the alias) —
10
+ ; Codex R1.
11
+ ; - GROUP use (`use A\{B, C as Bee}`): no single tree node carries the full
12
+ ; `A\B` (the prefix `A` and the leaf `B` are separate nodes — Codex R1). We
13
+ ; capture each group clause's leaf name here; the provider's refine() prepends
14
+ ; the group prefix to synthesize the full source path.
15
+ ; - include/require are OUT of scope (dynamic/runtime, not static specifiers).
16
+
17
+ (namespace_use_clause [(qualified_name) (name)] @import.source)
18
+
19
+ ; Group clauses only ever carry a `namespace_name` (which itself spans
20
+ ; backslash-separated paths, e.g. `B\C`); `qualified_name` is not a valid child here.
21
+ (namespace_use_group_clause (namespace_name) @import.source)