@mmnto/totem 1.0.0 → 1.2.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.
@@ -1,5 +1,13 @@
1
1
  import type { AstContext } from './compiler.js';
2
2
  export type SupportedLanguage = 'typescript' | 'tsx' | 'javascript';
3
+ /**
4
+ * Initialize web-tree-sitter WASM engine. Idempotent — safe to call multiple times.
5
+ */
6
+ export declare function ensureInit(): Promise<void>;
7
+ /**
8
+ * Load a Tree-sitter grammar WASM file for the given language.
9
+ */
10
+ export declare function loadGrammar(lang: SupportedLanguage): Promise<import('web-tree-sitter').Language>;
3
11
  /**
4
12
  * Classify specific lines of source code by their AST context.
5
13
  *
@@ -1 +1 @@
1
- {"version":3,"file":"ast-classifier.d.ts","sourceRoot":"","sources":["../src/ast-classifier.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAIhD,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,KAAK,GAAG,YAAY,CAAC;AAgGpE;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EAAE,EACrB,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CA+ClC;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAe9E"}
1
+ {"version":3,"file":"ast-classifier.d.ts","sourceRoot":"","sources":["../src/ast-classifier.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAIhD,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,KAAK,GAAG,YAAY,CAAC;AASpE;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAgBhD;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,OAAO,iBAAiB,EAAE,QAAQ,CAAC,CA0B7C;AAqCD;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EAAE,EACrB,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CA+ClC;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAe9E"}
@@ -6,7 +6,7 @@ const grammarCache = new Map();
6
6
  /**
7
7
  * Initialize web-tree-sitter WASM engine. Idempotent — safe to call multiple times.
8
8
  */
9
- async function ensureInit() {
9
+ export async function ensureInit() {
10
10
  if (Parser)
11
11
  return;
12
12
  if (initPromise)
@@ -25,7 +25,7 @@ async function ensureInit() {
25
25
  /**
26
26
  * Load a Tree-sitter grammar WASM file for the given language.
27
27
  */
28
- async function loadGrammar(lang) {
28
+ export async function loadGrammar(lang) {
29
29
  const cached = grammarCache.get(lang);
30
30
  if (cached)
31
31
  return cached;
@@ -1 +1 @@
1
- {"version":3,"file":"ast-classifier.js","sourceRoot":"","sources":["../src/ast-classifier.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ast-classifier.js","sourceRoot":"","sources":["../src/ast-classifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { NapiConfig } from '@ast-grep/napi';
2
+ /** ast-grep pattern: either a simple string or a full NapiConfig rule object */
3
+ export type AstGrepRule = string | NapiConfig;
4
+ export interface AstGrepMatch {
5
+ lineNumber: number;
6
+ lineText: string;
7
+ }
8
+ /**
9
+ * Run an ast-grep pattern against file content, filtering to added lines.
10
+ * Accepts either a string pattern or a NapiConfig rule object (compound rules).
11
+ */
12
+ export declare function matchAstGrepPattern(content: string, ext: string, pattern: AstGrepRule, addedLineNumbers: number[]): AstGrepMatch[];
13
+ /**
14
+ * Parse a file once and run multiple ast-grep rules against it.
15
+ * O(M + N) — file parsed exactly once regardless of rule count.
16
+ * Returns results indexed by position in the input array.
17
+ */
18
+ export declare function matchAstGrepPatternsBatch(content: string, ext: string, queries: Array<{
19
+ rule: AstGrepRule;
20
+ addedLineNumbers: number[];
21
+ }>): AstGrepMatch[][];
22
+ //# sourceMappingURL=ast-grep-query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-grep-query.d.ts","sourceRoot":"","sources":["../src/ast-grep-query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAKjD,gFAAgF;AAChF,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,UAAU,CAAC;AAE9C,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AA8DD;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,WAAW,EACpB,gBAAgB,EAAE,MAAM,EAAE,GACzB,YAAY,EAAE,CAUhB;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,gBAAgB,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,GAChE,YAAY,EAAE,EAAE,CAkBlB"}
@@ -0,0 +1,86 @@
1
+ import { Lang, parse } from '@ast-grep/napi';
2
+ // ─── Language mapping ───────────────────────────────
3
+ /** Map file extensions to ast-grep Lang enum. */
4
+ function extensionToLang(ext) {
5
+ switch (ext.toLowerCase()) {
6
+ case '.ts':
7
+ return Lang.TypeScript;
8
+ case '.tsx':
9
+ return Lang.Tsx;
10
+ case '.js':
11
+ case '.mjs':
12
+ case '.cjs':
13
+ return Lang.JavaScript;
14
+ case '.jsx':
15
+ return Lang.Tsx;
16
+ default:
17
+ return undefined;
18
+ }
19
+ }
20
+ // ─── Core matching ──────────────────────────────────
21
+ function executeQuery(root, rule, addedLineNumbers, lines) {
22
+ if (addedLineNumbers.length === 0)
23
+ return [];
24
+ const addedSet = new Set(addedLineNumbers);
25
+ try {
26
+ // findAll accepts both string patterns and NapiConfig objects
27
+ const matches = root.root().findAll(rule);
28
+ const results = [];
29
+ for (const match of matches) {
30
+ const startLine = match.range().start.line + 1;
31
+ const endLine = match.range().end.line + 1;
32
+ for (let lineNum = startLine; lineNum <= endLine; lineNum++) {
33
+ if (addedSet.has(lineNum)) {
34
+ results.push({
35
+ lineNumber: lineNum,
36
+ lineText: lines[lineNum - 1] ?? '',
37
+ });
38
+ break;
39
+ }
40
+ }
41
+ }
42
+ return results;
43
+ }
44
+ catch {
45
+ return [];
46
+ }
47
+ }
48
+ // ─── Public API ─────────────────────────────────────
49
+ /**
50
+ * Run an ast-grep pattern against file content, filtering to added lines.
51
+ * Accepts either a string pattern or a NapiConfig rule object (compound rules).
52
+ */
53
+ export function matchAstGrepPattern(content, ext, pattern, addedLineNumbers) {
54
+ const lang = extensionToLang(ext);
55
+ if (!lang)
56
+ return [];
57
+ try {
58
+ const root = parse(lang, content);
59
+ return executeQuery(root, pattern, addedLineNumbers, content.split('\n'));
60
+ }
61
+ catch {
62
+ return [];
63
+ }
64
+ }
65
+ /**
66
+ * Parse a file once and run multiple ast-grep rules against it.
67
+ * O(M + N) — file parsed exactly once regardless of rule count.
68
+ * Returns results indexed by position in the input array.
69
+ */
70
+ export function matchAstGrepPatternsBatch(content, ext, queries) {
71
+ if (queries.length === 0)
72
+ return [];
73
+ const lang = extensionToLang(ext);
74
+ if (!lang) {
75
+ return queries.map(() => []);
76
+ }
77
+ const lines = content.split('\n');
78
+ try {
79
+ const root = parse(lang, content);
80
+ return queries.map(({ rule, addedLineNumbers }) => executeQuery(root, rule, addedLineNumbers, lines));
81
+ }
82
+ catch {
83
+ return queries.map(() => []);
84
+ }
85
+ }
86
+ //# sourceMappingURL=ast-grep-query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-grep-query.js","sourceRoot":"","sources":["../src/ast-grep-query.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export interface AstMatch {
2
+ lineNumber: number;
3
+ lineText: string;
4
+ }
5
+ /**
6
+ * Convenience wrapper: read + parse + query in one call.
7
+ * For batch operations, use `matchAstQueriesBatch` instead.
8
+ */
9
+ export declare function matchAstQuery(filePath: string, astQuery: string, addedLineNumbers: number[], cwd: string): Promise<AstMatch[]>;
10
+ /**
11
+ * Parse a file once and run multiple AST queries against it efficiently.
12
+ * O(M + N) instead of O(M * N) — file is read and parsed exactly once.
13
+ */
14
+ export declare function matchAstQueriesBatch(filePath: string, queries: Array<{
15
+ astQuery: string;
16
+ addedLineNumbers: number[];
17
+ }>, cwd: string): Promise<Map<string, AstMatch[]>>;
18
+ //# sourceMappingURL=ast-query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-query.d.ts","sourceRoot":"","sources":["../src/ast-query.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AA6FD;;;GAGG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,gBAAgB,EAAE,MAAM,EAAE,EAC1B,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,QAAQ,EAAE,CAAC,CA0CrB;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,EAChE,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,CA6DlC"}
@@ -0,0 +1,177 @@
1
+ import { execFile } from 'node:child_process';
2
+ import * as fs from 'node:fs/promises';
3
+ import * as path from 'node:path';
4
+ import { promisify } from 'node:util';
5
+ import { ensureInit, extensionToLanguage, loadGrammar } from './ast-classifier.js';
6
+ const execFileAsync = promisify(execFile);
7
+ // ─── File reading ───────────────────────────────────
8
+ /**
9
+ * Read file content — try `git show :path` first (staged content), fall back to disk.
10
+ * Fully async — does not block the event loop.
11
+ */
12
+ async function readFileContent(filePath, cwd) {
13
+ try {
14
+ const { stdout } = await execFileAsync('git', ['show', `:${filePath}`], {
15
+ cwd,
16
+ encoding: 'utf-8',
17
+ maxBuffer: 10 * 1024 * 1024, // 10MB safety cap
18
+ });
19
+ return stdout;
20
+ }
21
+ catch {
22
+ // Fall back to disk
23
+ }
24
+ try {
25
+ const fullPath = path.resolve(cwd, filePath);
26
+ return await fs.readFile(fullPath, 'utf-8');
27
+ }
28
+ catch {
29
+ return null;
30
+ }
31
+ }
32
+ // ─── Query execution ────────────────────────────────
33
+ /**
34
+ * Run a single S-expression query against a parsed tree.
35
+ * Returns matches that overlap with added line numbers.
36
+ */
37
+ function runQuery(QueryClass, grammar, rootNode, lines, astQuery, addedLineNumbers) {
38
+ let query = null;
39
+ try {
40
+ query = new QueryClass(grammar, astQuery);
41
+ const matches = query.matches(rootNode);
42
+ const results = [];
43
+ for (const match of matches) {
44
+ // Find the @violation capture, or use the first capture
45
+ let targetNode = null;
46
+ for (const capture of match.captures) {
47
+ if (capture.name === 'violation') {
48
+ targetNode = capture.node;
49
+ break;
50
+ }
51
+ }
52
+ if (!targetNode && match.captures.length > 0) {
53
+ targetNode = match.captures[0].node;
54
+ }
55
+ if (!targetNode)
56
+ continue;
57
+ const startLine = targetNode.startPosition.row + 1;
58
+ const endLine = targetNode.endPosition.row + 1;
59
+ for (let lineNum = startLine; lineNum <= endLine; lineNum++) {
60
+ if (addedLineNumbers.has(lineNum)) {
61
+ results.push({
62
+ lineNumber: lineNum,
63
+ lineText: lines[lineNum - 1] ?? '',
64
+ });
65
+ break;
66
+ }
67
+ }
68
+ }
69
+ return results;
70
+ }
71
+ catch {
72
+ // Invalid query — fail-open
73
+ return [];
74
+ }
75
+ finally {
76
+ query?.delete();
77
+ }
78
+ }
79
+ // ─── Public API ─────────────────────────────────────
80
+ /**
81
+ * Convenience wrapper: read + parse + query in one call.
82
+ * For batch operations, use `matchAstQueriesBatch` instead.
83
+ */
84
+ export async function matchAstQuery(filePath, astQuery, addedLineNumbers, cwd) {
85
+ if (addedLineNumbers.length === 0)
86
+ return [];
87
+ const ext = path.extname(filePath);
88
+ const lang = extensionToLanguage(ext);
89
+ if (!lang)
90
+ return [];
91
+ const content = await readFileContent(filePath, cwd);
92
+ if (!content)
93
+ return [];
94
+ try {
95
+ await ensureInit();
96
+ const grammar = await loadGrammar(lang);
97
+ const TreeSitter = await import('web-tree-sitter');
98
+ const ParserClass = TreeSitter.default?.Parser ?? TreeSitter.Parser;
99
+ const QueryClass = TreeSitter.default?.Query ?? TreeSitter.Query;
100
+ const parser = new ParserClass();
101
+ try {
102
+ parser.setLanguage(grammar);
103
+ const tree = parser.parse(content);
104
+ if (!tree)
105
+ return [];
106
+ try {
107
+ return runQuery(QueryClass, grammar, tree.rootNode, content.split('\n'), astQuery, new Set(addedLineNumbers));
108
+ }
109
+ finally {
110
+ tree.delete();
111
+ }
112
+ }
113
+ finally {
114
+ parser.delete();
115
+ }
116
+ }
117
+ catch {
118
+ return [];
119
+ }
120
+ }
121
+ /**
122
+ * Parse a file once and run multiple AST queries against it efficiently.
123
+ * O(M + N) instead of O(M * N) — file is read and parsed exactly once.
124
+ */
125
+ export async function matchAstQueriesBatch(filePath, queries, cwd) {
126
+ const results = new Map();
127
+ if (queries.length === 0)
128
+ return results;
129
+ const ext = path.extname(filePath);
130
+ const lang = extensionToLanguage(ext);
131
+ if (!lang) {
132
+ for (const q of queries)
133
+ results.set(q.astQuery, []);
134
+ return results;
135
+ }
136
+ const content = await readFileContent(filePath, cwd);
137
+ if (!content) {
138
+ for (const q of queries)
139
+ results.set(q.astQuery, []);
140
+ return results;
141
+ }
142
+ try {
143
+ await ensureInit();
144
+ const grammar = await loadGrammar(lang);
145
+ const TreeSitter = await import('web-tree-sitter');
146
+ const ParserClass = TreeSitter.default?.Parser ?? TreeSitter.Parser;
147
+ const QueryClass = TreeSitter.default?.Query ?? TreeSitter.Query;
148
+ const parser = new ParserClass();
149
+ try {
150
+ parser.setLanguage(grammar);
151
+ const tree = parser.parse(content);
152
+ if (!tree) {
153
+ for (const q of queries)
154
+ results.set(q.astQuery, []);
155
+ return results;
156
+ }
157
+ const lines = content.split('\n');
158
+ try {
159
+ for (const { astQuery, addedLineNumbers } of queries) {
160
+ results.set(astQuery, runQuery(QueryClass, grammar, tree.rootNode, lines, astQuery, new Set(addedLineNumbers)));
161
+ }
162
+ }
163
+ finally {
164
+ tree.delete();
165
+ }
166
+ }
167
+ finally {
168
+ parser.delete();
169
+ }
170
+ }
171
+ catch {
172
+ for (const q of queries)
173
+ results.set(q.astQuery, []);
174
+ }
175
+ return results;
176
+ }
177
+ //# sourceMappingURL=ast-query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-query.js","sourceRoot":"","sources":["../src/ast-query.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ast-query.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-query.test.d.ts","sourceRoot":"","sources":["../src/ast-query.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,79 @@
1
+ import * as fs from 'node:fs';
2
+ import * as os from 'node:os';
3
+ import * as path from 'node:path';
4
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5
+ import { matchAstQuery } from './ast-query.js';
6
+ // ─── Helpers ────────────────────────────────────────
7
+ let tmpDir;
8
+ beforeEach(() => {
9
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-ast-query-'));
10
+ });
11
+ afterEach(() => {
12
+ fs.rmSync(tmpDir, { recursive: true, force: true });
13
+ });
14
+ function writeFile(name, content) {
15
+ const filePath = path.join(tmpDir, name);
16
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
17
+ fs.writeFileSync(filePath, content, 'utf-8');
18
+ return name;
19
+ }
20
+ // ─── matchAstQuery ──────────────────────────────────
21
+ describe('matchAstQuery', () => {
22
+ it('matches a valid S-expression query against code', async () => {
23
+ const file = writeFile('src/app.ts', ['const x = 1;', 'console.log(x);', 'const y = 2;'].join('\n'));
24
+ // Query to find console.log calls — match member_expression with console.log
25
+ const query = '(call_expression function: (member_expression object: (identifier) @obj (#eq? @obj "console"))) @violation';
26
+ const matches = await matchAstQuery(file, query, [2], tmpDir);
27
+ expect(matches).toHaveLength(1);
28
+ expect(matches[0].lineNumber).toBe(2);
29
+ expect(matches[0].lineText).toContain('console.log');
30
+ });
31
+ it('filters matches to only added lines', async () => {
32
+ const file = writeFile('src/multi.ts', ['console.log("line 1");', 'const x = 1;', 'console.log("line 3");'].join('\n'));
33
+ const query = '(call_expression function: (member_expression object: (identifier) @obj (#eq? @obj "console"))) @violation';
34
+ // Only line 3 is "added"
35
+ const matches = await matchAstQuery(file, query, [3], tmpDir);
36
+ expect(matches).toHaveLength(1);
37
+ expect(matches[0].lineNumber).toBe(3);
38
+ });
39
+ it('returns empty array for invalid S-expression (fail-open)', async () => {
40
+ const file = writeFile('src/safe.ts', 'const x = 1;\n');
41
+ const matches = await matchAstQuery(file, '(this is not valid!!!', [1], tmpDir);
42
+ expect(matches).toEqual([]);
43
+ });
44
+ it('returns empty array for non-JS/TS files', async () => {
45
+ const file = writeFile('config.py', 'import os\nprint("hello")\n');
46
+ const query = '(identifier) @violation';
47
+ const matches = await matchAstQuery(file, query, [1, 2], tmpDir);
48
+ expect(matches).toEqual([]);
49
+ });
50
+ it('returns empty array when no added lines overlap with matches', async () => {
51
+ const file = writeFile('src/no-overlap.ts', ['console.log("line 1");', 'const x = 1;', 'const y = 2;'].join('\n'));
52
+ const query = '(call_expression function: (member_expression object: (identifier) @obj (#eq? @obj "console"))) @violation';
53
+ // Lines 2 and 3 are "added" but console.log is on line 1
54
+ const matches = await matchAstQuery(file, query, [2, 3], tmpDir);
55
+ expect(matches).toEqual([]);
56
+ });
57
+ it('returns empty array for nonexistent file', async () => {
58
+ const matches = await matchAstQuery('nonexistent.ts', '(identifier) @violation', [1], tmpDir);
59
+ expect(matches).toEqual([]);
60
+ });
61
+ it('returns empty array for empty addedLineNumbers', async () => {
62
+ const file = writeFile('src/empty.ts', 'const x = 1;\n');
63
+ const matches = await matchAstQuery(file, '(identifier) @violation', [], tmpDir);
64
+ expect(matches).toEqual([]);
65
+ });
66
+ it('handles JavaScript files', async () => {
67
+ const file = writeFile('src/app.js', ['const x = 1;', 'console.log(x);'].join('\n'));
68
+ const query = '(call_expression function: (member_expression object: (identifier) @obj (#eq? @obj "console"))) @violation';
69
+ const matches = await matchAstQuery(file, query, [2], tmpDir);
70
+ expect(matches).toHaveLength(1);
71
+ });
72
+ it('handles TSX files', async () => {
73
+ const file = writeFile('src/component.tsx', ['const x = 1;', 'console.log(x);', 'const el = <div>hello</div>;'].join('\n'));
74
+ const query = '(call_expression function: (member_expression object: (identifier) @obj (#eq? @obj "console"))) @violation';
75
+ const matches = await matchAstQuery(file, query, [2], tmpDir);
76
+ expect(matches).toHaveLength(1);
77
+ });
78
+ });
79
+ //# sourceMappingURL=ast-query.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-query.test.js","sourceRoot":"","sources":["../src/ast-query.test.ts"],"names":[],"mappings":"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"}
@@ -8,8 +8,12 @@ export declare const CompiledRuleSchema: z.ZodObject<{
8
8
  pattern: z.ZodString;
9
9
  /** Human-readable violation message shown when the pattern matches */
10
10
  message: z.ZodString;
11
- /** Engine type — only 'regex' for MVP */
12
- engine: z.ZodLiteral<"regex">;
11
+ /** Engine type — 'regex' for line-level matching, 'ast' for Tree-sitter S-expression queries, 'ast-grep' for ast-grep structural patterns */
12
+ engine: z.ZodEnum<["regex", "ast", "ast-grep"]>;
13
+ /** Tree-sitter S-expression query (required when engine is 'ast') */
14
+ astQuery: z.ZodOptional<z.ZodString>;
15
+ /** ast-grep pattern — string for simple patterns, object for compound rules (has/inside/not) */
16
+ astGrepPattern: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
13
17
  /** ISO timestamp of when this rule was compiled */
14
18
  compiledAt: z.ZodString;
15
19
  /** ISO timestamp of when this rule was first created (survives recompilation) */
@@ -25,8 +29,10 @@ export declare const CompiledRuleSchema: z.ZodObject<{
25
29
  lessonHeading: string;
26
30
  pattern: string;
27
31
  message: string;
28
- engine: "regex";
32
+ engine: "regex" | "ast" | "ast-grep";
29
33
  compiledAt: string;
34
+ astQuery?: string | undefined;
35
+ astGrepPattern?: string | Record<string, unknown> | undefined;
30
36
  createdAt?: string | undefined;
31
37
  fileGlobs?: string[] | undefined;
32
38
  category?: "security" | "architecture" | "style" | "performance" | undefined;
@@ -36,8 +42,10 @@ export declare const CompiledRuleSchema: z.ZodObject<{
36
42
  lessonHeading: string;
37
43
  pattern: string;
38
44
  message: string;
39
- engine: "regex";
45
+ engine: "regex" | "ast" | "ast-grep";
40
46
  compiledAt: string;
47
+ astQuery?: string | undefined;
48
+ astGrepPattern?: string | Record<string, unknown> | undefined;
41
49
  createdAt?: string | undefined;
42
50
  fileGlobs?: string[] | undefined;
43
51
  category?: "security" | "architecture" | "style" | "performance" | undefined;
@@ -55,8 +63,12 @@ export declare const CompiledRulesFileSchema: z.ZodObject<{
55
63
  pattern: z.ZodString;
56
64
  /** Human-readable violation message shown when the pattern matches */
57
65
  message: z.ZodString;
58
- /** Engine type — only 'regex' for MVP */
59
- engine: z.ZodLiteral<"regex">;
66
+ /** Engine type — 'regex' for line-level matching, 'ast' for Tree-sitter S-expression queries, 'ast-grep' for ast-grep structural patterns */
67
+ engine: z.ZodEnum<["regex", "ast", "ast-grep"]>;
68
+ /** Tree-sitter S-expression query (required when engine is 'ast') */
69
+ astQuery: z.ZodOptional<z.ZodString>;
70
+ /** ast-grep pattern — string for simple patterns, object for compound rules (has/inside/not) */
71
+ astGrepPattern: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
60
72
  /** ISO timestamp of when this rule was compiled */
61
73
  compiledAt: z.ZodString;
62
74
  /** ISO timestamp of when this rule was first created (survives recompilation) */
@@ -72,8 +84,10 @@ export declare const CompiledRulesFileSchema: z.ZodObject<{
72
84
  lessonHeading: string;
73
85
  pattern: string;
74
86
  message: string;
75
- engine: "regex";
87
+ engine: "regex" | "ast" | "ast-grep";
76
88
  compiledAt: string;
89
+ astQuery?: string | undefined;
90
+ astGrepPattern?: string | Record<string, unknown> | undefined;
77
91
  createdAt?: string | undefined;
78
92
  fileGlobs?: string[] | undefined;
79
93
  category?: "security" | "architecture" | "style" | "performance" | undefined;
@@ -83,8 +97,10 @@ export declare const CompiledRulesFileSchema: z.ZodObject<{
83
97
  lessonHeading: string;
84
98
  pattern: string;
85
99
  message: string;
86
- engine: "regex";
100
+ engine: "regex" | "ast" | "ast-grep";
87
101
  compiledAt: string;
102
+ astQuery?: string | undefined;
103
+ astGrepPattern?: string | Record<string, unknown> | undefined;
88
104
  createdAt?: string | undefined;
89
105
  fileGlobs?: string[] | undefined;
90
106
  category?: "security" | "architecture" | "style" | "performance" | undefined;
@@ -99,8 +115,10 @@ export declare const CompiledRulesFileSchema: z.ZodObject<{
99
115
  lessonHeading: string;
100
116
  pattern: string;
101
117
  message: string;
102
- engine: "regex";
118
+ engine: "regex" | "ast" | "ast-grep";
103
119
  compiledAt: string;
120
+ astQuery?: string | undefined;
121
+ astGrepPattern?: string | Record<string, unknown> | undefined;
104
122
  createdAt?: string | undefined;
105
123
  fileGlobs?: string[] | undefined;
106
124
  category?: "security" | "architecture" | "style" | "performance" | undefined;
@@ -114,8 +132,10 @@ export declare const CompiledRulesFileSchema: z.ZodObject<{
114
132
  lessonHeading: string;
115
133
  pattern: string;
116
134
  message: string;
117
- engine: "regex";
135
+ engine: "regex" | "ast" | "ast-grep";
118
136
  compiledAt: string;
137
+ astQuery?: string | undefined;
138
+ astGrepPattern?: string | Record<string, unknown> | undefined;
119
139
  createdAt?: string | undefined;
120
140
  fileGlobs?: string[] | undefined;
121
141
  category?: "security" | "architecture" | "style" | "performance" | undefined;
@@ -175,6 +195,13 @@ export type RuleEventCallback = (event: 'trigger' | 'suppress', lessonHash: stri
175
195
  * Optional `onRuleEvent` callback enables observability metrics collection.
176
196
  */
177
197
  export declare function applyRulesToAdditions(rules: CompiledRule[], additions: DiffAddition[], onRuleEvent?: RuleEventCallback): Violation[];
198
+ /**
199
+ * Apply AST-engine compiled rules against pre-extracted diff additions.
200
+ * Handles both Tree-sitter S-expression ('ast') and ast-grep ('ast-grep') engines.
201
+ * Async because it reads files and runs Tree-sitter queries.
202
+ * Handles fileGlobs filtering and suppression same as regex rules.
203
+ */
204
+ export declare function applyAstRulesToAdditions(rules: CompiledRule[], additions: DiffAddition[], cwd: string, onRuleEvent?: RuleEventCallback): Promise<Violation[]>;
178
205
  /**
179
206
  * Apply compiled rules against added lines from a diff.
180
207
  * Returns all violations found.
@@ -195,15 +222,24 @@ export declare const CompilerOutputSchema: z.ZodObject<{
195
222
  pattern: z.ZodOptional<z.ZodString>;
196
223
  message: z.ZodOptional<z.ZodString>;
197
224
  fileGlobs: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
225
+ engine: z.ZodOptional<z.ZodEnum<["regex", "ast", "ast-grep"]>>;
226
+ astQuery: z.ZodOptional<z.ZodString>;
227
+ astGrepPattern: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
198
228
  }, "strip", z.ZodTypeAny, {
199
229
  compilable: boolean;
230
+ astQuery?: string | undefined;
200
231
  pattern?: string | undefined;
201
232
  message?: string | undefined;
233
+ engine?: "regex" | "ast" | "ast-grep" | undefined;
234
+ astGrepPattern?: string | Record<string, unknown> | undefined;
202
235
  fileGlobs?: string[] | undefined;
203
236
  }, {
204
237
  compilable: boolean;
238
+ astQuery?: string | undefined;
205
239
  pattern?: string | undefined;
206
240
  message?: string | undefined;
241
+ engine?: "regex" | "ast" | "ast-grep" | undefined;
242
+ astGrepPattern?: string | Record<string, unknown> | undefined;
207
243
  fileGlobs?: string[] | undefined;
208
244
  }>;
209
245
  export type CompilerOutput = z.infer<typeof CompilerOutputSchema>;
@@ -1 +1 @@
1
- {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,eAAO,MAAM,kBAAkB;IAC7B,0EAA0E;;IAE1E,+DAA+D;;IAE/D,sDAAsD;;IAEtD,sEAAsE;;IAEtE,6IAA6I;;IAE7I,qEAAqE;;IAErE,gGAAgG;;IAEhG,mDAAmD;;IAEnD,iFAAiF;;IAEjF,kGAAkG;;IAElG,mDAAmD;;IAEnD,yEAAyE;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEzE,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,eAAO,MAAM,uBAAuB;;;QA5BlC,0EAA0E;;QAE1E,+DAA+D;;QAE/D,sDAAsD;;QAEtD,sEAAsE;;QAEtE,6IAA6I;;QAE7I,qEAAqE;;QAErE,gGAAgG;;QAEhG,mDAAmD;;QAEnD,iFAAiF;;QAEjF,kGAAkG;;QAElG,mDAAmD;;QAEnD,yEAAyE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IASzE,2FAA2F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAE3F,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE,MAAM,WAAW,SAAS;IACxB,iCAAiC;IACjC,IAAI,EAAE,YAAY,CAAC;IACnB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,UAAU,EAAE,MAAM,CAAC;CACpB;AAMD,0EAA0E;AAC1E,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMhE;AAID,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAY9D;AAID,oEAAoE;AACpE,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAEjE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,8FAA8F;IAC9F,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,+FAA+F;IAC/F,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,CAkE9D;AAMD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAuCnE;AAsCD,mFAAmF;AACnF,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,SAAS,GAAG,UAAU,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;AAE5F;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,YAAY,EAAE,EACrB,SAAS,EAAE,YAAY,EAAE,EACzB,WAAW,CAAC,EAAE,iBAAiB,GAC9B,SAAS,EAAE,CA4Cb;AAED;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,YAAY,EAAE,EACrB,SAAS,EAAE,YAAY,EAAE,EACzB,GAAG,EAAE,MAAM,EACX,WAAW,CAAC,EAAE,iBAAiB,GAC9B,OAAO,CAAC,SAAS,EAAE,CAAC,CAiItB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,YAAY,EAAE,EACrB,IAAI,EAAE,MAAM,EACZ,YAAY,CAAC,EAAE,MAAM,EAAE,GACtB,SAAS,EAAE,CAUb;AAID,iFAAiF;AACjF,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC7B,YAAY,EAAE,CAmBhB;AAED,wEAAwE;AACxE,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC7B,iBAAiB,CAoBnB;AAED,0CAA0C;AAC1C,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,IAAI,CAMhF;AAED,wEAAwE;AACxE,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAKtF;AAID,8EAA8E;AAC9E,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;EAQ/B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAa7E"}