grepmax 0.10.4 → 0.11.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.
@@ -0,0 +1,223 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.context = void 0;
46
+ const fs = __importStar(require("node:fs"));
47
+ const path = __importStar(require("node:path"));
48
+ const commander_1 = require("commander");
49
+ const searcher_1 = require("../lib/search/searcher");
50
+ const skeleton_1 = require("../lib/skeleton");
51
+ const vector_db_1 = require("../lib/store/vector-db");
52
+ const filter_builder_1 = require("../lib/utils/filter-builder");
53
+ const exit_1 = require("../lib/utils/exit");
54
+ const project_root_1 = require("../lib/utils/project-root");
55
+ const arrow_1 = require("../lib/utils/arrow");
56
+ function estimateTokens(text) {
57
+ return Math.ceil(text.length / 4);
58
+ }
59
+ exports.context = new commander_1.Command("context")
60
+ .description("Generate a token-budgeted topic summary (search + skeleton + extract)")
61
+ .argument("<topic>", "Natural language topic or directory path")
62
+ .option("--budget <tokens>", "Max tokens for output (default 4000)", "4000")
63
+ .option("-m, --max-results <n>", "Initial search result limit (default 10)", "10")
64
+ .option("--root <dir>", "Project root directory")
65
+ .option("--agent", "Compact output for AI agents", false)
66
+ .action((topic, opts) => __awaiter(void 0, void 0, void 0, function* () {
67
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
68
+ const budget = Number.parseInt(opts.budget || "4000", 10) || 4000;
69
+ const maxResults = Number.parseInt(opts.maxResults || "10", 10) || 10;
70
+ let vectorDb = null;
71
+ try {
72
+ const root = opts.root ? path.resolve(opts.root) : process.cwd();
73
+ const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
74
+ const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
75
+ vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
76
+ const searcher = new searcher_1.Searcher(vectorDb);
77
+ const rel = (p) => p.startsWith(`${projectRoot}/`) ? p.slice(projectRoot.length + 1) : p;
78
+ // Phase 1: Semantic search
79
+ const response = yield searcher.search(topic, maxResults, { rerank: true }, {}, projectRoot);
80
+ if (response.data.length === 0) {
81
+ console.log(`No results found for "${topic}".`);
82
+ return;
83
+ }
84
+ let tokensUsed = 0;
85
+ const sections = [];
86
+ // Header
87
+ const header = `=== Context: "${topic}" ===`;
88
+ sections.push(header);
89
+ tokensUsed += estimateTokens(header);
90
+ // Phase 2: Entry points (ORCHESTRATION role results)
91
+ const orchestrators = response.data.filter((r) => r.role === "ORCHESTRATION");
92
+ const entryPoints = orchestrators.length > 0 ? orchestrators : response.data.slice(0, 3);
93
+ const epSection = ["\n## Entry Points"];
94
+ for (const r of entryPoints.slice(0, 5)) {
95
+ const p = String(r.path || ((_b = r.metadata) === null || _b === void 0 ? void 0 : _b.path) || "");
96
+ const line = Number((_c = r.start_line) !== null && _c !== void 0 ? _c : 0);
97
+ const sym = (_e = (_d = (0, arrow_1.toArr)(r.defined_symbols)) === null || _d === void 0 ? void 0 : _d[0]) !== null && _e !== void 0 ? _e : "";
98
+ const role = String(r.role || "IMPLEMENTATION");
99
+ epSection.push(`${rel(p)}:${line + 1} ${sym} [${role}]`);
100
+ }
101
+ const epText = epSection.join("\n");
102
+ if (tokensUsed + estimateTokens(epText) <= budget) {
103
+ sections.push(epText);
104
+ tokensUsed += estimateTokens(epText);
105
+ }
106
+ // Phase 3: Key function bodies (top 2-3 results)
107
+ const topChunks = entryPoints.slice(0, 3);
108
+ const bodySection = ["\n## Key Functions"];
109
+ for (const r of topChunks) {
110
+ const absP = String(r.path || "");
111
+ const startLine = Number((_f = r.start_line) !== null && _f !== void 0 ? _f : 0);
112
+ const endLine = Number((_g = r.end_line) !== null && _g !== void 0 ? _g : startLine);
113
+ const sym = (_j = (_h = (0, arrow_1.toArr)(r.defined_symbols)) === null || _h === void 0 ? void 0 : _h[0]) !== null && _j !== void 0 ? _j : "";
114
+ try {
115
+ const content = fs.readFileSync(absP, "utf-8");
116
+ const allLines = content.split("\n");
117
+ const body = allLines
118
+ .slice(startLine, Math.min(endLine + 1, allLines.length))
119
+ .join("\n");
120
+ const blob = `\n--- ${rel(absP)}:${startLine + 1} ${sym} ---\n${body}`;
121
+ const blobTokens = estimateTokens(blob);
122
+ if (tokensUsed + blobTokens > budget)
123
+ break;
124
+ bodySection.push(blob);
125
+ tokensUsed += blobTokens;
126
+ }
127
+ catch (_k) {
128
+ // File not readable — skip
129
+ }
130
+ }
131
+ if (bodySection.length > 1) {
132
+ sections.push(bodySection.join(""));
133
+ }
134
+ // Phase 4: File skeletons for unique files
135
+ const uniqueFiles = [
136
+ ...new Set(response.data
137
+ .map((r) => String(r.path || ""))
138
+ .filter(Boolean)),
139
+ ].slice(0, 5);
140
+ const skelSection = ["\n## File Structure"];
141
+ const skeletonizer = new skeleton_1.Skeletonizer();
142
+ yield skeletonizer.init();
143
+ for (const absP of uniqueFiles) {
144
+ if (!skeletonizer.isSupported(absP).supported)
145
+ continue;
146
+ try {
147
+ const content = fs.readFileSync(absP, "utf-8");
148
+ const result = yield skeletonizer.skeletonizeFile(absP, content);
149
+ if (!result.success)
150
+ continue;
151
+ const blob = `\n--- ${rel(absP)} (skeleton, ~${result.tokenEstimate} tokens) ---\n${result.skeleton}`;
152
+ const blobTokens = estimateTokens(blob);
153
+ if (tokensUsed + blobTokens > budget)
154
+ break;
155
+ skelSection.push(blob);
156
+ tokensUsed += blobTokens;
157
+ }
158
+ catch (_l) {
159
+ // Skip unreadable files
160
+ }
161
+ }
162
+ if (skelSection.length > 1) {
163
+ sections.push(skelSection.join(""));
164
+ }
165
+ // Phase 5: Related files summary
166
+ const table = yield vectorDb.ensureTable();
167
+ const allSymbols = new Set();
168
+ for (const r of response.data) {
169
+ for (const s of (0, arrow_1.toArr)(r.defined_symbols))
170
+ allSymbols.add(s);
171
+ }
172
+ if (allSymbols.size > 0) {
173
+ const pathScope = `path LIKE '${(0, filter_builder_1.escapeSqlString)(projectRoot)}/%'`;
174
+ const relatedCounts = new Map();
175
+ const searchedFiles = new Set(uniqueFiles);
176
+ for (const sym of [...allSymbols].slice(0, 20)) {
177
+ const rows = yield table
178
+ .query()
179
+ .select(["path"])
180
+ .where(`array_contains(referenced_symbols, '${(0, filter_builder_1.escapeSqlString)(sym)}') AND ${pathScope}`)
181
+ .limit(5)
182
+ .toArray();
183
+ for (const row of rows) {
184
+ const p = String(row.path || "");
185
+ if (searchedFiles.has(p))
186
+ continue;
187
+ relatedCounts.set(p, (relatedCounts.get(p) || 0) + 1);
188
+ }
189
+ }
190
+ const topRelated = Array.from(relatedCounts.entries())
191
+ .sort((a, b) => b[1] - a[1])
192
+ .slice(0, 5);
193
+ if (topRelated.length > 0) {
194
+ const relSection = ["\n## Related Files"];
195
+ for (const [p, count] of topRelated) {
196
+ relSection.push(`${rel(p)} — ${count} shared symbol${count > 1 ? "s" : ""}`);
197
+ }
198
+ const relText = relSection.join("\n");
199
+ if (tokensUsed + estimateTokens(relText) <= budget) {
200
+ sections.push(relText);
201
+ tokensUsed += estimateTokens(relText);
202
+ }
203
+ }
204
+ }
205
+ // Footer
206
+ sections.push(`\n(~${tokensUsed}/${budget} tokens used)`);
207
+ console.log(sections.join("\n"));
208
+ }
209
+ catch (error) {
210
+ const msg = error instanceof Error ? error.message : "Unknown error";
211
+ console.error("Context generation failed:", msg);
212
+ process.exitCode = 1;
213
+ }
214
+ finally {
215
+ if (vectorDb) {
216
+ try {
217
+ yield vectorDb.close();
218
+ }
219
+ catch (_m) { }
220
+ }
221
+ yield (0, exit_1.gracefulExit)();
222
+ }
223
+ }));
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.diff = void 0;
46
+ const path = __importStar(require("node:path"));
47
+ const commander_1 = require("commander");
48
+ const searcher_1 = require("../lib/search/searcher");
49
+ const vector_db_1 = require("../lib/store/vector-db");
50
+ const filter_builder_1 = require("../lib/utils/filter-builder");
51
+ const exit_1 = require("../lib/utils/exit");
52
+ const git_1 = require("../lib/utils/git");
53
+ const project_root_1 = require("../lib/utils/project-root");
54
+ const arrow_1 = require("../lib/utils/arrow");
55
+ exports.diff = new commander_1.Command("diff")
56
+ .description("Search code scoped to git changes")
57
+ .argument("[ref]", "Git ref to diff against (e.g. main, HEAD~5)")
58
+ .option("-q, --query <query>", "Semantic search within changed files")
59
+ .option("-m, --max-count <n>", "Max results (default 10)", "10")
60
+ .option("--role <role>", "Filter by role: ORCHESTRATION, DEFINITION, IMPLEMENTATION")
61
+ .option("--root <dir>", "Project root directory")
62
+ .option("--agent", "Compact output for AI agents", false)
63
+ .action((ref, opts) => __awaiter(void 0, void 0, void 0, function* () {
64
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
65
+ const limit = Math.min(Math.max(Number.parseInt(opts.maxCount || "10", 10), 1), 50);
66
+ let vectorDb = null;
67
+ try {
68
+ const root = opts.root ? path.resolve(opts.root) : process.cwd();
69
+ const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
70
+ const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
71
+ vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
72
+ const changedFiles = (0, git_1.getChangedFiles)(ref, projectRoot);
73
+ if (changedFiles.length === 0) {
74
+ console.log(ref ? `No changes found relative to ${ref}.` : "No uncommitted changes found.");
75
+ return;
76
+ }
77
+ const rel = (p) => p.startsWith(`${projectRoot}/`) ? p.slice(projectRoot.length + 1) : p;
78
+ if (opts.query) {
79
+ // Semantic search scoped to changed files
80
+ const searcher = new searcher_1.Searcher(vectorDb);
81
+ const response = yield searcher.search(opts.query, limit, { rerank: true }, Object.assign({}, (opts.role ? { role: opts.role } : {})), projectRoot);
82
+ // Filter results to only changed files
83
+ const changedSet = new Set(changedFiles);
84
+ const filtered = response.data.filter((r) => {
85
+ var _a;
86
+ const p = ((_a = r.metadata) === null || _a === void 0 ? void 0 : _a.path) || r.path || "";
87
+ return changedSet.has(p);
88
+ });
89
+ if (filtered.length === 0) {
90
+ console.log("No indexed results found in changed files for that query.");
91
+ return;
92
+ }
93
+ if (opts.agent) {
94
+ for (const r of filtered.slice(0, limit)) {
95
+ const p = String(r.path || ((_b = r.metadata) === null || _b === void 0 ? void 0 : _b.path) || "");
96
+ const line = Number((_c = r.start_line) !== null && _c !== void 0 ? _c : 0);
97
+ const sym = (_e = (_d = (0, arrow_1.toArr)(r.defined_symbols)) === null || _d === void 0 ? void 0 : _d[0]) !== null && _e !== void 0 ? _e : "";
98
+ const role = String(r.role || "IMPL");
99
+ console.log(`${rel(p)}:${line + 1} ${sym} [${role}]`);
100
+ }
101
+ }
102
+ else {
103
+ console.log(`Changed files matching "${opts.query}":\n`);
104
+ for (const r of filtered.slice(0, limit)) {
105
+ const p = String(r.path || ((_f = r.metadata) === null || _f === void 0 ? void 0 : _f.path) || "");
106
+ const line = Number((_g = r.start_line) !== null && _g !== void 0 ? _g : 0);
107
+ const sym = (_j = (_h = (0, arrow_1.toArr)(r.defined_symbols)) === null || _h === void 0 ? void 0 : _h[0]) !== null && _j !== void 0 ? _j : "";
108
+ const role = String(r.role || "IMPLEMENTATION");
109
+ const score = (_l = (_k = r.score) === null || _k === void 0 ? void 0 : _k.toFixed(3)) !== null && _l !== void 0 ? _l : "?";
110
+ console.log(` ${rel(p)}:${line + 1} ${sym} [${role}] (${score})`);
111
+ }
112
+ }
113
+ }
114
+ else {
115
+ // No query — list changed files with their indexed symbols
116
+ const table = yield vectorDb.ensureTable();
117
+ if (opts.agent) {
118
+ for (const file of changedFiles) {
119
+ const chunks = yield table
120
+ .query()
121
+ .select(["path", "start_line", "defined_symbols", "role"])
122
+ .where(`path = '${(0, filter_builder_1.escapeSqlString)(file)}'`)
123
+ .limit(50)
124
+ .toArray();
125
+ if (chunks.length === 0) {
126
+ console.log(`${rel(file)}\t(not indexed)`);
127
+ }
128
+ else {
129
+ for (const chunk of chunks) {
130
+ const sym = (_o = (_m = (0, arrow_1.toArr)(chunk.defined_symbols)) === null || _m === void 0 ? void 0 : _m[0]) !== null && _o !== void 0 ? _o : "";
131
+ const line = (_p = chunk.start_line) !== null && _p !== void 0 ? _p : 0;
132
+ const role = (chunk.role || "IMPL").slice(0, 4);
133
+ if (sym) {
134
+ console.log(`${rel(file)}:${line + 1}\t${sym}\t[${role}]`);
135
+ }
136
+ }
137
+ }
138
+ }
139
+ }
140
+ else {
141
+ console.log(`${changedFiles.length} changed file${changedFiles.length === 1 ? "" : "s"}${ref ? ` (vs ${ref})` : ""}:\n`);
142
+ for (const file of changedFiles) {
143
+ const chunks = yield table
144
+ .query()
145
+ .select(["defined_symbols", "role"])
146
+ .where(`path = '${(0, filter_builder_1.escapeSqlString)(file)}'`)
147
+ .limit(50)
148
+ .toArray();
149
+ const symbols = chunks
150
+ .flatMap((c) => (0, arrow_1.toArr)(c.defined_symbols))
151
+ .filter(Boolean);
152
+ if (symbols.length > 0) {
153
+ console.log(` ${rel(file)} (${symbols.length} symbol${symbols.length === 1 ? "" : "s"}: ${symbols.slice(0, 5).join(", ")}${symbols.length > 5 ? "..." : ""})`);
154
+ }
155
+ else {
156
+ console.log(` ${rel(file)}`);
157
+ }
158
+ }
159
+ }
160
+ }
161
+ }
162
+ catch (error) {
163
+ const msg = error instanceof Error ? error.message : "Unknown error";
164
+ console.error("Diff failed:", msg);
165
+ process.exitCode = 1;
166
+ }
167
+ finally {
168
+ if (vectorDb) {
169
+ try {
170
+ yield vectorDb.close();
171
+ }
172
+ catch (_q) { }
173
+ }
174
+ yield (0, exit_1.gracefulExit)();
175
+ }
176
+ }));
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.impact = void 0;
46
+ const path = __importStar(require("node:path"));
47
+ const commander_1 = require("commander");
48
+ const impact_1 = require("../lib/graph/impact");
49
+ const vector_db_1 = require("../lib/store/vector-db");
50
+ const exit_1 = require("../lib/utils/exit");
51
+ const project_root_1 = require("../lib/utils/project-root");
52
+ exports.impact = new commander_1.Command("impact")
53
+ .description("Analyze change impact: dependents and affected tests")
54
+ .argument("<target>", "Symbol name or file path")
55
+ .option("-d, --depth <n>", "Caller traversal depth (default 1, max 3)", "1")
56
+ .option("--root <dir>", "Project root directory")
57
+ .option("--agent", "Compact output for AI agents", false)
58
+ .action((target, opts) => __awaiter(void 0, void 0, void 0, function* () {
59
+ var _a;
60
+ const depth = Math.min(Math.max(Number.parseInt(opts.depth || "1", 10), 1), 3);
61
+ let vectorDb = null;
62
+ try {
63
+ const root = opts.root ? path.resolve(opts.root) : process.cwd();
64
+ const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
65
+ const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
66
+ vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
67
+ const { symbols, resolvedAsFile } = yield (0, impact_1.resolveTargetSymbols)(target, vectorDb, projectRoot);
68
+ if (symbols.length === 0) {
69
+ console.log(resolvedAsFile
70
+ ? `No symbols found in file: ${target}`
71
+ : `Symbol not found: ${target}`);
72
+ process.exitCode = 1;
73
+ return;
74
+ }
75
+ // Resolve the target's own file path for exclusion
76
+ const targetPath = resolvedAsFile
77
+ ? (target.startsWith("/") ? target : path.resolve(projectRoot, target))
78
+ : undefined;
79
+ const excludePaths = targetPath ? new Set([targetPath]) : undefined;
80
+ // Run dependents and tests in parallel
81
+ const [dependents, tests] = yield Promise.all([
82
+ (0, impact_1.findDependents)(symbols, vectorDb, projectRoot, excludePaths),
83
+ (0, impact_1.findTests)(symbols, vectorDb, projectRoot, depth),
84
+ ]);
85
+ // Separate test files from non-test dependents
86
+ const nonTestDeps = dependents.filter((d) => !(0, impact_1.isTestPath)(d.file));
87
+ const rel = (p) => p.startsWith(`${projectRoot}/`) ? p.slice(projectRoot.length + 1) : p;
88
+ if (opts.agent) {
89
+ for (const d of nonTestDeps) {
90
+ console.log(`dep: ${rel(d.file)}\t${d.sharedSymbols}`);
91
+ }
92
+ for (const t of tests) {
93
+ const hopLabel = t.hops === 0 ? "direct" : `${t.hops}-hop`;
94
+ console.log(`test: ${rel(t.file)}:${t.line + 1}\t${t.symbol}\t${hopLabel}`);
95
+ }
96
+ if (!nonTestDeps.length && !tests.length) {
97
+ console.log("(no impact detected)");
98
+ }
99
+ }
100
+ else {
101
+ console.log(`Impact analysis for ${target}:\n`);
102
+ if (nonTestDeps.length > 0) {
103
+ console.log(`Direct dependents (${nonTestDeps.length}):`);
104
+ for (const d of nonTestDeps) {
105
+ console.log(` ${rel(d.file).padEnd(45)} (${d.sharedSymbols} shared symbol${d.sharedSymbols > 1 ? "s" : ""})`);
106
+ }
107
+ }
108
+ else {
109
+ console.log("Direct dependents: none found");
110
+ }
111
+ console.log("");
112
+ if (tests.length > 0) {
113
+ console.log(`Affected tests (${tests.length}):`);
114
+ for (const t of tests) {
115
+ const hopLabel = t.hops === 0 ? "calls directly" : `${t.hops} hop${t.hops > 1 ? "s" : ""} away`;
116
+ console.log(` ${rel(t.file)}:${t.line + 1} ${t.symbol} (${hopLabel})`);
117
+ }
118
+ }
119
+ else {
120
+ console.log("Affected tests: none found");
121
+ }
122
+ }
123
+ }
124
+ catch (error) {
125
+ const msg = error instanceof Error ? error.message : "Unknown error";
126
+ console.error("Impact analysis failed:", msg);
127
+ process.exitCode = 1;
128
+ }
129
+ finally {
130
+ if (vectorDb) {
131
+ try {
132
+ yield vectorDb.close();
133
+ }
134
+ catch (_b) { }
135
+ }
136
+ yield (0, exit_1.gracefulExit)();
137
+ }
138
+ }));