@getfoyer/review-core 0.1.0 → 0.2.1

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 (49) hide show
  1. package/dist/fileReader.d.ts +17 -0
  2. package/dist/fileReader.d.ts.map +1 -0
  3. package/dist/fileReader.js +2 -0
  4. package/dist/fileReader.js.map +1 -0
  5. package/dist/index.d.ts +3 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +1 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/plan-context.d.ts +14 -0
  10. package/dist/plan-context.d.ts.map +1 -0
  11. package/dist/plan-context.js +133 -0
  12. package/dist/plan-context.js.map +1 -0
  13. package/dist/semantic/cache.d.ts +31 -0
  14. package/dist/semantic/cache.d.ts.map +1 -0
  15. package/dist/semantic/cache.js +50 -0
  16. package/dist/semantic/cache.js.map +1 -0
  17. package/dist/semantic/contextBuilder.d.ts +17 -0
  18. package/dist/semantic/contextBuilder.d.ts.map +1 -0
  19. package/dist/semantic/contextBuilder.js +92 -0
  20. package/dist/semantic/contextBuilder.js.map +1 -0
  21. package/dist/semantic/diffParse.d.ts +30 -0
  22. package/dist/semantic/diffParse.d.ts.map +1 -0
  23. package/dist/semantic/diffParse.js +48 -0
  24. package/dist/semantic/diffParse.js.map +1 -0
  25. package/dist/semantic/imports.d.ts +16 -0
  26. package/dist/semantic/imports.d.ts.map +1 -0
  27. package/dist/semantic/imports.js +102 -0
  28. package/dist/semantic/imports.js.map +1 -0
  29. package/dist/semantic/index.d.ts +45 -0
  30. package/dist/semantic/index.d.ts.map +1 -0
  31. package/dist/semantic/index.js +78 -0
  32. package/dist/semantic/index.js.map +1 -0
  33. package/dist/semantic/languages.d.ts +14 -0
  34. package/dist/semantic/languages.d.ts.map +1 -0
  35. package/dist/semantic/languages.js +40 -0
  36. package/dist/semantic/languages.js.map +1 -0
  37. package/dist/semantic/parser.d.ts +15 -0
  38. package/dist/semantic/parser.d.ts.map +1 -0
  39. package/dist/semantic/parser.js +83 -0
  40. package/dist/semantic/parser.js.map +1 -0
  41. package/dist/semantic/symbols.d.ts +54 -0
  42. package/dist/semantic/symbols.d.ts.map +1 -0
  43. package/dist/semantic/symbols.js +287 -0
  44. package/dist/semantic/symbols.js.map +1 -0
  45. package/dist/semantic/types.d.ts +43 -0
  46. package/dist/semantic/types.d.ts.map +1 -0
  47. package/dist/semantic/types.js +2 -0
  48. package/dist/semantic/types.js.map +1 -0
  49. package/package.json +20 -4
@@ -0,0 +1,287 @@
1
+ const TOP_LEVEL_DEFINITION_TYPES = {
2
+ typescript: new Set([
3
+ 'function_declaration',
4
+ 'class_declaration',
5
+ 'method_definition',
6
+ 'interface_declaration',
7
+ 'type_alias_declaration',
8
+ 'lexical_declaration', // `const foo = (...) => {...}`
9
+ 'export_statement',
10
+ ]),
11
+ tsx: new Set([
12
+ 'function_declaration',
13
+ 'class_declaration',
14
+ 'method_definition',
15
+ 'interface_declaration',
16
+ 'type_alias_declaration',
17
+ 'lexical_declaration',
18
+ 'export_statement',
19
+ ]),
20
+ javascript: new Set([
21
+ 'function_declaration',
22
+ 'class_declaration',
23
+ 'method_definition',
24
+ 'lexical_declaration',
25
+ 'export_statement',
26
+ ]),
27
+ python: new Set([
28
+ 'function_definition',
29
+ 'class_definition',
30
+ 'decorated_definition',
31
+ ]),
32
+ go: new Set([
33
+ 'function_declaration',
34
+ 'method_declaration',
35
+ 'type_declaration',
36
+ 'var_declaration',
37
+ 'const_declaration',
38
+ ]),
39
+ rust: new Set([
40
+ 'function_item',
41
+ 'struct_item',
42
+ 'enum_item',
43
+ 'trait_item',
44
+ 'impl_item',
45
+ 'mod_item',
46
+ 'const_item',
47
+ 'static_item',
48
+ 'type_item',
49
+ ]),
50
+ ruby: new Set([
51
+ 'method',
52
+ 'singleton_method',
53
+ 'class',
54
+ 'module',
55
+ 'assignment', // constants — uppercase LHS resolved in symbolName
56
+ ]),
57
+ };
58
+ /**
59
+ * Top-level definitions in order. We walk the root node's direct children
60
+ * (and one level into `export_statement` / `decorated_definition` wrappers).
61
+ */
62
+ export function topLevelDefinitions(parsed, lang) {
63
+ const wantedTypes = TOP_LEVEL_DEFINITION_TYPES[lang];
64
+ const out = [];
65
+ for (const child of parsed.tree.rootNode.namedChildren) {
66
+ if (!child)
67
+ continue;
68
+ if (wantedTypes.has(child.type)) {
69
+ // Unwrap `export_statement` so we report the inner declaration. The
70
+ // body line range is unchanged either way.
71
+ if (child.type === 'export_statement') {
72
+ const inner = child.namedChildren.find((c) => !!c && wantedTypes.has(c.type));
73
+ out.push(inner ?? child);
74
+ }
75
+ else if (child.type === 'decorated_definition') {
76
+ const inner = child.namedChildren.find((c) => !!c && (c.type === 'function_definition' || c.type === 'class_definition'));
77
+ out.push(inner ?? child);
78
+ }
79
+ else {
80
+ out.push(child);
81
+ }
82
+ }
83
+ }
84
+ return out;
85
+ }
86
+ /**
87
+ * Heuristic name extraction. Tree-sitter exposes a `name` field for most
88
+ * declaration types; for lexical_declaration we walk into the first
89
+ * variable_declarator and read its `name` field. Returns "<anonymous>" rather
90
+ * than null so the rendered block always has something printable.
91
+ */
92
+ export function symbolName(node) {
93
+ const named = node.childForFieldName('name');
94
+ if (named?.text)
95
+ return named.text;
96
+ if (node.type === 'lexical_declaration') {
97
+ const decl = node.namedChildren.find((c) => !!c && c.type === 'variable_declarator');
98
+ const name = decl?.childForFieldName('name');
99
+ if (name?.text)
100
+ return name.text;
101
+ }
102
+ // Go `type_declaration` / `var_declaration` / `const_declaration` wrap an
103
+ // inner spec node that carries the name field.
104
+ if (node.type === 'type_declaration' || node.type === 'var_declaration' || node.type === 'const_declaration') {
105
+ const spec = node.namedChildren.find((c) => !!c && (c.type === 'type_spec' || c.type === 'var_spec' || c.type === 'const_spec'));
106
+ const nm = spec?.childForFieldName('name');
107
+ if (nm?.text)
108
+ return nm.text;
109
+ }
110
+ // Ruby `assignment` for top-level constants: LHS is an `identifier` or
111
+ // `constant`. We surface only constants (uppercase start) — lowercase locals
112
+ // aren't useful in review context.
113
+ if (node.type === 'assignment') {
114
+ const lhs = node.childForFieldName('left');
115
+ if (lhs?.text && /^[A-Z]/.test(lhs.text))
116
+ return lhs.text;
117
+ }
118
+ // Rust `impl_item` exposes the implemented type via the `type` field.
119
+ if (node.type === 'impl_item') {
120
+ const ty = node.childForFieldName('type');
121
+ if (ty?.text)
122
+ return `impl ${ty.text}`;
123
+ }
124
+ return '<anonymous>';
125
+ }
126
+ export function symbolKind(node) {
127
+ switch (node.type) {
128
+ case 'function_declaration':
129
+ case 'function_definition':
130
+ case 'function_item':
131
+ case 'method':
132
+ case 'singleton_method':
133
+ case 'method_declaration':
134
+ return node.type.startsWith('method') ? 'method' : 'function';
135
+ case 'class_declaration':
136
+ case 'class_definition':
137
+ case 'class':
138
+ case 'struct_item':
139
+ case 'enum_item':
140
+ case 'trait_item':
141
+ case 'module':
142
+ case 'mod_item':
143
+ return 'class';
144
+ case 'method_definition':
145
+ return 'method';
146
+ case 'lexical_declaration':
147
+ case 'const_declaration':
148
+ case 'const_item':
149
+ case 'static_item':
150
+ case 'var_declaration':
151
+ case 'assignment':
152
+ return 'const';
153
+ default:
154
+ return 'unknown';
155
+ }
156
+ }
157
+ /**
158
+ * Return the symbols whose source range overlaps any of the supplied
159
+ * post-image line ranges. Lines are 1-based; tree-sitter positions are
160
+ * 0-based, so we shift by one when comparing.
161
+ */
162
+ export function findTouchedSymbols(parsed, lang, file, hunks, bodyCapBytes) {
163
+ if (hunks.length === 0)
164
+ return [];
165
+ const defs = topLevelDefinitions(parsed, lang);
166
+ const seen = new Set();
167
+ const out = [];
168
+ for (const def of defs) {
169
+ const startLine = def.startPosition.row + 1;
170
+ const endLine = def.endPosition.row + 1;
171
+ const overlaps = hunks.some((h) => {
172
+ const hStart = h.newStart;
173
+ const hEnd = h.newStart + Math.max(0, h.newLines - 1);
174
+ return hEnd >= startLine && hStart <= endLine;
175
+ });
176
+ if (!overlaps)
177
+ continue;
178
+ const name = symbolName(def);
179
+ const key = `${name}@${startLine}`;
180
+ if (seen.has(key))
181
+ continue;
182
+ seen.add(key);
183
+ const body = def.text.length > bodyCapBytes ? def.text.slice(0, bodyCapBytes) + '\n/* …truncated… */' : def.text;
184
+ out.push({
185
+ file,
186
+ name,
187
+ kind: symbolKind(def),
188
+ body,
189
+ line: startLine,
190
+ });
191
+ }
192
+ return out;
193
+ }
194
+ /**
195
+ * Extract import edges. JS/TS use `import_statement`; Python uses
196
+ * `import_from_statement` / `import_statement`. We surface only the cheap
197
+ * cases — full semantics (re-exports, computed paths) would require a real
198
+ * compiler, which is out of scope per the plan.
199
+ */
200
+ export function findImports(parsed, lang) {
201
+ const edges = [];
202
+ // Go imports name packages, not files; Rust `use` paths resolve through a
203
+ // module tree we don't model. Skip both — touched-symbol bodies still ship.
204
+ if (lang === 'go' || lang === 'rust')
205
+ return edges;
206
+ for (const child of parsed.tree.rootNode.namedChildren) {
207
+ if (!child)
208
+ continue;
209
+ if (lang === 'ruby') {
210
+ // Ruby `require_relative "./foo"` appears as a `call` with method
211
+ // `require_relative` and a string-literal argument. We surface the
212
+ // bare path; the resolver maps it to a `.rb` file.
213
+ if (child.type !== 'call')
214
+ continue;
215
+ const method = child.childForFieldName('method')?.text;
216
+ if (method !== 'require_relative' && method !== 'require')
217
+ continue;
218
+ const args = child.childForFieldName('arguments');
219
+ const strArg = args?.namedChildren.find((c) => !!c && c.type === 'string');
220
+ if (!strArg)
221
+ continue;
222
+ const raw = strArg.text.replace(/^['"]|['"]$/g, '');
223
+ // For `require_relative`, treat as relative; for plain `require`, only
224
+ // surface when the path looks relative (rare but harmless).
225
+ if (method === 'require_relative' || raw.startsWith('./') || raw.startsWith('../')) {
226
+ edges.push({ source: raw.startsWith('.') ? raw : `./${raw}`, names: ['*'] });
227
+ }
228
+ continue;
229
+ }
230
+ if (lang === 'python') {
231
+ if (child.type === 'import_from_statement') {
232
+ const moduleName = child.childForFieldName('module_name')?.text;
233
+ if (!moduleName)
234
+ continue;
235
+ const names = [];
236
+ for (const n of child.namedChildren) {
237
+ if (n && (n.type === 'dotted_name' || n.type === 'aliased_import')) {
238
+ const txt = n.childForFieldName('name')?.text ?? n.text;
239
+ if (txt)
240
+ names.push(txt);
241
+ }
242
+ }
243
+ if (names.length > 0)
244
+ edges.push({ source: moduleName, names });
245
+ }
246
+ continue;
247
+ }
248
+ if (child.type !== 'import_statement')
249
+ continue;
250
+ const sourceNode = child.childForFieldName('source');
251
+ if (!sourceNode)
252
+ continue;
253
+ // `source` text is the raw quoted string. Strip quotes.
254
+ const source = sourceNode.text.replace(/^['"]|['"]$/g, '');
255
+ const names = [];
256
+ // Walk import_clause → named_imports / namespace_import / identifier.
257
+ for (const c of child.namedChildren) {
258
+ if (!c)
259
+ continue;
260
+ if (c.type === 'import_clause') {
261
+ for (const inner of c.namedChildren) {
262
+ if (!inner)
263
+ continue;
264
+ if (inner.type === 'identifier') {
265
+ names.push(inner.text);
266
+ }
267
+ else if (inner.type === 'namespace_import') {
268
+ names.push('*');
269
+ }
270
+ else if (inner.type === 'named_imports') {
271
+ for (const spec of inner.namedChildren) {
272
+ if (!spec || spec.type !== 'import_specifier')
273
+ continue;
274
+ const nm = spec.childForFieldName('name')?.text;
275
+ if (nm)
276
+ names.push(nm);
277
+ }
278
+ }
279
+ }
280
+ }
281
+ }
282
+ if (source)
283
+ edges.push({ source, names });
284
+ }
285
+ return edges;
286
+ }
287
+ //# sourceMappingURL=symbols.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbols.js","sourceRoot":"","sources":["../../src/semantic/symbols.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Shared types for the semantic-context module.
3
+ *
4
+ * Purpose: enrich the diff fed to the code-review LLM with definitions of the
5
+ * symbols the diff touches and the symbols those touched files import. The
6
+ * diff says *what changed*; this block says *what those changes refer to*.
7
+ */
8
+ export type LanguageId = 'typescript' | 'tsx' | 'javascript' | 'python' | 'go' | 'rust' | 'ruby';
9
+ export interface TouchedSymbol {
10
+ /** Repo-relative file path from the diff `+++ b/` header. */
11
+ file: string;
12
+ /** Symbol name (function, class, method, top-level const with function value). */
13
+ name: string;
14
+ kind: 'function' | 'class' | 'method' | 'const' | 'unknown';
15
+ /** Full source text of the symbol's definition (not just diff hunks). Capped
16
+ * upstream by FileReader's per-file byte cap. */
17
+ body: string;
18
+ /** 1-based line where the symbol starts in the post-image file. */
19
+ line: number;
20
+ }
21
+ export interface ImportedSymbol {
22
+ /** Local name as used in the importing file. */
23
+ name: string;
24
+ /** Repo-relative path of the file the symbol was resolved to. */
25
+ fromFile: string;
26
+ /** Signature line(s) — the first line of the definition. Cheaper than the
27
+ * full body and usually enough to catch arg-shape mismatches. */
28
+ signature: string;
29
+ }
30
+ export interface SemanticBlock {
31
+ /** Rendered markdown block ready to inline in the LLM user message. Empty
32
+ * string when nothing useful was extracted. */
33
+ rendered: string;
34
+ /** Diagnostic counts for logging. */
35
+ stats: {
36
+ touchedFiles: number;
37
+ touchedSymbols: number;
38
+ importedSymbols: number;
39
+ bytes: number;
40
+ truncated: boolean;
41
+ };
42
+ }
43
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/semantic/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,GAClB,YAAY,GACZ,KAAK,GACL,YAAY,GACZ,QAAQ,GACR,IAAI,GACJ,MAAM,GACN,MAAM,CAAC;AAEX,MAAM,WAAW,aAAa;IAC5B,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;IAC5D;sDACkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB;sEACkE;IAClE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B;oDACgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,KAAK,EAAE;QACL,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,eAAe,EAAE,MAAM,CAAC;QACxB,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,OAAO,CAAC;KACpB,CAAC;CACH"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/semantic/types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@getfoyer/review-core",
3
- "version": "0.1.0",
4
- "description": "Frozen contract for Foyer run artifacts (RunArtifact v0.1) — the shared shape consumed by the GitHub App, the CLI, the hosted report, and PR-comment writers.",
3
+ "version": "0.2.1",
4
+ "description": "Frozen contract for Foyer run artifacts (RunArtifact v0.1) — the shared shape consumed by the GitHub App, the CLI, the hosted report, and PR-comment writers. Also ships the cross-cutting semantic-context builder used by code review.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -13,6 +13,14 @@
13
13
  "./types": {
14
14
  "types": "./dist/types.d.ts",
15
15
  "import": "./dist/types.js"
16
+ },
17
+ "./plan-context": {
18
+ "types": "./dist/plan-context.d.ts",
19
+ "import": "./dist/plan-context.js"
20
+ },
21
+ "./semantic": {
22
+ "types": "./dist/semantic/index.d.ts",
23
+ "import": "./dist/semantic/index.js"
16
24
  }
17
25
  },
18
26
  "files": [
@@ -26,9 +34,17 @@
26
34
  },
27
35
  "scripts": {
28
36
  "build": "tsc",
29
- "typecheck": "tsc --noEmit"
37
+ "typecheck": "tsc --noEmit",
38
+ "test": "vitest run"
39
+ },
40
+ "dependencies": {
41
+ "@getfoyer/client": "portal:../client",
42
+ "tree-sitter-wasms": "^0.1.12",
43
+ "web-tree-sitter": "^0.25.0"
30
44
  },
31
45
  "devDependencies": {
32
- "typescript": "^5.5.0"
46
+ "@types/node": "^22.0.0",
47
+ "typescript": "^5.5.0",
48
+ "vitest": "^4.1.2"
33
49
  }
34
50
  }