@eduardo-afonso/codebase-intelligence 0.1.0 → 2.0.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 (108) hide show
  1. package/README.md +82 -7
  2. package/README.pt-BR.md +84 -8
  3. package/dist/ai/CodebaseWithAI.d.ts +91 -0
  4. package/dist/ai/CodebaseWithAI.d.ts.map +1 -0
  5. package/dist/ai/CodebaseWithAI.js +149 -0
  6. package/dist/ai/CodebaseWithAI.js.map +1 -0
  7. package/dist/ai/RAGPipeline.d.ts +66 -0
  8. package/dist/ai/RAGPipeline.d.ts.map +1 -0
  9. package/dist/ai/RAGPipeline.js +102 -0
  10. package/dist/ai/RAGPipeline.js.map +1 -0
  11. package/dist/ai/index.d.ts +6 -0
  12. package/dist/ai/index.d.ts.map +1 -0
  13. package/dist/ai/index.js +5 -0
  14. package/dist/ai/index.js.map +1 -0
  15. package/dist/ai/providers/NoopAIProvider.d.ts +23 -0
  16. package/dist/ai/providers/NoopAIProvider.d.ts.map +1 -0
  17. package/dist/ai/providers/NoopAIProvider.js +24 -0
  18. package/dist/ai/providers/NoopAIProvider.js.map +1 -0
  19. package/dist/cli/index.js +168 -8
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/context/ContextEngine.d.ts +54 -0
  22. package/dist/context/ContextEngine.d.ts.map +1 -0
  23. package/dist/context/ContextEngine.js +179 -0
  24. package/dist/context/ContextEngine.js.map +1 -0
  25. package/dist/context/FileContextBuilder.d.ts +49 -0
  26. package/dist/context/FileContextBuilder.d.ts.map +1 -0
  27. package/dist/context/FileContextBuilder.js +124 -0
  28. package/dist/context/FileContextBuilder.js.map +1 -0
  29. package/dist/context/SemanticChunker.d.ts +105 -0
  30. package/dist/context/SemanticChunker.d.ts.map +1 -0
  31. package/dist/context/SemanticChunker.js +293 -0
  32. package/dist/context/SemanticChunker.js.map +1 -0
  33. package/dist/context/SignatureExtractor.d.ts +49 -0
  34. package/dist/context/SignatureExtractor.d.ts.map +1 -0
  35. package/dist/context/SignatureExtractor.js +167 -0
  36. package/dist/context/SignatureExtractor.js.map +1 -0
  37. package/dist/context/interfaces.d.ts +149 -0
  38. package/dist/context/interfaces.d.ts.map +1 -0
  39. package/dist/context/interfaces.js +13 -0
  40. package/dist/context/interfaces.js.map +1 -0
  41. package/dist/context/strategies/ContextBuildStrategy.d.ts +25 -0
  42. package/dist/context/strategies/ContextBuildStrategy.d.ts.map +1 -0
  43. package/dist/context/strategies/ContextBuildStrategy.js +3 -0
  44. package/dist/context/strategies/ContextBuildStrategy.js.map +1 -0
  45. package/dist/context/strategies/DeepStrategy.d.ts +18 -0
  46. package/dist/context/strategies/DeepStrategy.d.ts.map +1 -0
  47. package/dist/context/strategies/DeepStrategy.js +19 -0
  48. package/dist/context/strategies/DeepStrategy.js.map +1 -0
  49. package/dist/context/strategies/ShallowStrategy.d.ts +15 -0
  50. package/dist/context/strategies/ShallowStrategy.d.ts.map +1 -0
  51. package/dist/context/strategies/ShallowStrategy.js +15 -0
  52. package/dist/context/strategies/ShallowStrategy.js.map +1 -0
  53. package/dist/context/strategies/SignatureStrategy.d.ts +20 -0
  54. package/dist/context/strategies/SignatureStrategy.d.ts.map +1 -0
  55. package/dist/context/strategies/SignatureStrategy.js +59 -0
  56. package/dist/context/strategies/SignatureStrategy.js.map +1 -0
  57. package/dist/context/strategies/index.d.ts +5 -0
  58. package/dist/context/strategies/index.d.ts.map +1 -0
  59. package/dist/context/strategies/index.js +4 -0
  60. package/dist/context/strategies/index.js.map +1 -0
  61. package/dist/context/types.d.ts +136 -0
  62. package/dist/context/types.d.ts.map +1 -0
  63. package/dist/context/types.js +8 -0
  64. package/dist/context/types.js.map +1 -0
  65. package/dist/core/Codebase.d.ts +50 -0
  66. package/dist/core/Codebase.d.ts.map +1 -1
  67. package/dist/core/Codebase.js +104 -0
  68. package/dist/core/Codebase.js.map +1 -1
  69. package/dist/diff/ChangeSetImpactAnalyzer.d.ts +19 -0
  70. package/dist/diff/ChangeSetImpactAnalyzer.d.ts.map +1 -0
  71. package/dist/diff/ChangeSetImpactAnalyzer.js +121 -0
  72. package/dist/diff/ChangeSetImpactAnalyzer.js.map +1 -0
  73. package/dist/diff/GitChangeSetProvider.d.ts +86 -0
  74. package/dist/diff/GitChangeSetProvider.d.ts.map +1 -0
  75. package/dist/diff/GitChangeSetProvider.js +297 -0
  76. package/dist/diff/GitChangeSetProvider.js.map +1 -0
  77. package/dist/diff/errors.d.ts +48 -0
  78. package/dist/diff/errors.d.ts.map +1 -0
  79. package/dist/diff/errors.js +70 -0
  80. package/dist/diff/errors.js.map +1 -0
  81. package/dist/diff/types.d.ts +159 -0
  82. package/dist/diff/types.d.ts.map +1 -0
  83. package/dist/diff/types.js +8 -0
  84. package/dist/diff/types.js.map +1 -0
  85. package/dist/explorer/SnapshotBuilder.d.ts +22 -0
  86. package/dist/explorer/SnapshotBuilder.d.ts.map +1 -0
  87. package/dist/explorer/SnapshotBuilder.js +225 -0
  88. package/dist/explorer/SnapshotBuilder.js.map +1 -0
  89. package/dist/explorer/types.d.ts +88 -0
  90. package/dist/explorer/types.d.ts.map +1 -0
  91. package/dist/explorer/types.js +12 -0
  92. package/dist/explorer/types.js.map +1 -0
  93. package/dist/explorer/ui/App.d.ts +3 -0
  94. package/dist/explorer/ui/App.d.ts.map +1 -0
  95. package/dist/explorer/ui/App.js +43 -0
  96. package/dist/explorer/ui/App.js.map +1 -0
  97. package/dist/explorer/ui/main.d.ts +2 -0
  98. package/dist/explorer/ui/main.d.ts.map +1 -0
  99. package/dist/explorer/ui/main.js +8 -0
  100. package/dist/explorer/ui/main.js.map +1 -0
  101. package/dist/index.d.ts +17 -0
  102. package/dist/index.d.ts.map +1 -1
  103. package/dist/index.js +16 -0
  104. package/dist/index.js.map +1 -1
  105. package/dist/ui/assets/index-D4w3JVrv.css +1 -0
  106. package/dist/ui/assets/index-DBRKE5qL.js +52 -0
  107. package/dist/ui/index.html +13 -0
  108. package/package.json +50 -50
@@ -0,0 +1,297 @@
1
+ import { execFile as execFileCb } from 'node:child_process';
2
+ import { promisify } from 'node:util';
3
+ import * as path from 'node:path';
4
+ import * as fs from 'node:fs';
5
+ import { GitCommandError, GitNotAvailableError, InvalidGitRefError, NotAGitRepositoryError, } from './errors.js';
6
+ const execFile = promisify(execFileCb);
7
+ // ---------------------------------------------------------------------------
8
+ // GitChangeSetProvider
9
+ // ---------------------------------------------------------------------------
10
+ /**
11
+ * A `ChangeSetProvider` implementation that reads file changes from a local
12
+ * Git repository using the `git` CLI.
13
+ *
14
+ * **Safety guarantees**:
15
+ * - All git calls use `execFile` with an args array (never `exec` with a
16
+ * shell-interpolated string). This prevents shell injection.
17
+ * - Refs provided by callers are validated and rejected if they begin with
18
+ * `-` or cannot be resolved in the repository.
19
+ * - Output is parsed using NUL (`\0`) as the field separator (`-z` flag),
20
+ * which correctly handles file names containing spaces, tabs, or newlines.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * const provider = new GitChangeSetProvider('/path/to/codebase');
25
+ * const changes = await provider.getChanges({ since: 'main' });
26
+ * ```
27
+ */
28
+ export class GitChangeSetProvider {
29
+ codebaseRoot;
30
+ /**
31
+ * @param codebaseRoot - Absolute path to the codebase root as passed to
32
+ * `Codebase.load()`. May differ from the Git repository root (e.g. when
33
+ * the codebase is a sub-directory of a monorepo).
34
+ */
35
+ constructor(codebaseRoot) {
36
+ this.codebaseRoot = codebaseRoot;
37
+ }
38
+ async getChanges(options = {}) {
39
+ await this.ensureGitAvailable();
40
+ const gitRoot = await this.resolveGitRoot();
41
+ this.validateOptions(options);
42
+ if (options.since !== undefined)
43
+ await this.validateRef(options.since, gitRoot);
44
+ if (options.until !== undefined)
45
+ await this.validateRef(options.until, gitRoot);
46
+ let changes;
47
+ if (options.staged) {
48
+ changes = await this.getStagedChanges(gitRoot);
49
+ }
50
+ else if (options.uncommitted) {
51
+ changes = await this.getUncommittedChanges(gitRoot);
52
+ }
53
+ else if (options.since !== undefined) {
54
+ changes = await this.getChangesSince(gitRoot, options.since, options.until ?? 'HEAD');
55
+ }
56
+ else {
57
+ // Default: uncommitted (staged + working tree)
58
+ changes = await this.getUncommittedChanges(gitRoot);
59
+ }
60
+ // Normalise all paths to be relative to the codebase root and sort
61
+ return this.normaliseAndSort(changes, gitRoot);
62
+ }
63
+ // ---- Git modes ----------------------------------------------------------
64
+ /** Returns only staged (index) changes: `git diff --cached`. */
65
+ async getStagedChanges(gitRoot) {
66
+ const stdout = await this.runGit(['diff', '--name-status', '-M', '-z', '--cached'], gitRoot);
67
+ return this.parseDiffOutput(stdout);
68
+ }
69
+ /**
70
+ * Returns all uncommitted changes (staged + working tree) plus untracked
71
+ * files. This is the most useful default for local development.
72
+ */
73
+ async getUncommittedChanges(gitRoot) {
74
+ // Check whether HEAD exists (fresh repos before first commit have no HEAD)
75
+ const hasHead = await this.headExists(gitRoot);
76
+ let diffChanges = [];
77
+ if (hasHead) {
78
+ // staged + unstaged changes vs HEAD
79
+ const diffStdout = await this.runGit(['diff', '--name-status', '-M', '-z', 'HEAD'], gitRoot);
80
+ diffChanges = this.parseDiffOutput(diffStdout);
81
+ }
82
+ // untracked files (not ignored)
83
+ const untrackedStdout = await this.runGit(['ls-files', '--others', '--exclude-standard', '-z'], gitRoot);
84
+ const untrackedChanges = this.parseUntrackedOutput(untrackedStdout);
85
+ return [...diffChanges, ...untrackedChanges];
86
+ }
87
+ /**
88
+ * Returns changes introduced by the current branch relative to `since`.
89
+ * Uses three-dot merge-base semantics so only commits not in `since` are
90
+ * included.
91
+ */
92
+ async getChangesSince(gitRoot, since, until) {
93
+ // Verify merge-base is reachable (fails on shallow clones without full history)
94
+ try {
95
+ await this.runGit(['merge-base', '--is-ancestor', since, until], gitRoot);
96
+ }
97
+ catch {
98
+ // merge-base failure — check if this is a shallow clone
99
+ const isShallow = await this.isShallowRepository(gitRoot);
100
+ if (isShallow) {
101
+ throw new GitCommandError('git', ['merge-base', since, until], `Repository is a shallow clone. The merge-base between "${since}" and "${until}" cannot be determined.\n` +
102
+ 'In GitHub Actions, add `fetch-depth: 0` to the checkout step. ' +
103
+ 'Locally, run `git fetch --unshallow`.', 1);
104
+ }
105
+ // Not shallow — just proceed; three-dot diff handles this gracefully
106
+ }
107
+ const stdout = await this.runGit(['diff', '--name-status', '-M', '-z', `${since}...${until}`], gitRoot);
108
+ return this.parseDiffOutput(stdout);
109
+ }
110
+ // ---- Output parsers -----------------------------------------------------
111
+ /**
112
+ * Parses the NUL-delimited output of `git diff --name-status -M -z`.
113
+ *
114
+ * The `-z` flag makes git output fields separated by NUL bytes instead of
115
+ * newlines. For most statuses the format is:
116
+ * `<status> NUL <path> NUL`
117
+ * For renames and copies it is:
118
+ * `R<score> NUL <old-path> NUL <new-path> NUL`
119
+ */
120
+ parseDiffOutput(raw) {
121
+ if (!raw.trim())
122
+ return [];
123
+ const changes = [];
124
+ // Split on NUL; filter empty trailing entries
125
+ const tokens = raw.split('\0').filter((t, i, arr) => {
126
+ // The last token after a trailing NUL is always empty — drop it
127
+ return !(i === arr.length - 1 && t === '');
128
+ });
129
+ let i = 0;
130
+ while (i < tokens.length) {
131
+ const statusToken = tokens[i];
132
+ if (!statusToken) {
133
+ i++;
134
+ continue;
135
+ }
136
+ const statusCode = statusToken[0] ?? '';
137
+ i++;
138
+ if (statusCode === 'R' || statusCode === 'C') {
139
+ // rename / copy: next two tokens are old-path and new-path
140
+ const oldPath = tokens[i] ?? '';
141
+ const newPath = tokens[i + 1] ?? '';
142
+ i += 2;
143
+ changes.push({
144
+ path: newPath,
145
+ oldPath,
146
+ status: statusCode === 'R' ? 'renamed' : 'copied',
147
+ });
148
+ }
149
+ else {
150
+ const filePath = tokens[i] ?? '';
151
+ i++;
152
+ const status = this.mapStatusCode(statusCode);
153
+ if (status !== null) {
154
+ changes.push({ path: filePath, status });
155
+ }
156
+ }
157
+ }
158
+ return changes;
159
+ }
160
+ /** Parses NUL-delimited output of `git ls-files --others -z`. */
161
+ parseUntrackedOutput(raw) {
162
+ if (!raw.trim())
163
+ return [];
164
+ return raw
165
+ .split('\0')
166
+ .filter(p => p.length > 0)
167
+ .map(p => ({ path: p, status: 'added' }));
168
+ }
169
+ mapStatusCode(code) {
170
+ switch (code) {
171
+ case 'A': return 'added';
172
+ case 'M': return 'modified';
173
+ case 'D': return 'deleted';
174
+ case 'T': return 'typechange';
175
+ default: return null;
176
+ }
177
+ }
178
+ // ---- Path normalisation -------------------------------------------------
179
+ /**
180
+ * Converts absolute-or-git-root-relative paths to codebase-root-relative
181
+ * paths. Paths that fall outside the codebase root are kept with their
182
+ * original path so the analyser can mark them as `outside-codebase`.
183
+ */
184
+ normaliseAndSort(changes, gitRoot) {
185
+ // Resolve gitRoot and codebaseRoot to their real absolute paths
186
+ // This is crucial on Windows where git might return short paths (e.g. MIRANT~1)
187
+ let realGitRoot = path.resolve(gitRoot);
188
+ let realCbRoot = path.resolve(this.codebaseRoot);
189
+ try {
190
+ realGitRoot = fs.realpathSync.native(realGitRoot);
191
+ }
192
+ catch { /* ignore */ }
193
+ try {
194
+ realCbRoot = fs.realpathSync.native(realCbRoot);
195
+ }
196
+ catch { /* ignore */ }
197
+ const normalised = changes.map(change => {
198
+ // Resolve path using path.resolve (Windows-aware) relative to realGitRoot
199
+ const absolutePath = path.resolve(realGitRoot, change.path);
200
+ const relativeToCb = path.relative(realCbRoot, absolutePath).replace(/\\/g, '/');
201
+ const normalisedChange = { ...change, path: relativeToCb };
202
+ if (change.oldPath !== undefined) {
203
+ const absOld = path.resolve(realGitRoot, change.oldPath);
204
+ normalisedChange.oldPath = path.relative(realCbRoot, absOld).replace(/\\/g, '/');
205
+ }
206
+ return normalisedChange;
207
+ });
208
+ return normalised.sort((a, b) => a.path.localeCompare(b.path));
209
+ }
210
+ // ---- Validation ---------------------------------------------------------
211
+ validateOptions(options) {
212
+ const modes = [
213
+ options.since !== undefined,
214
+ options.staged === true,
215
+ options.uncommitted === true,
216
+ ].filter(Boolean).length;
217
+ if (modes > 1) {
218
+ throw new Error('GitChangeSetProvider: options `since`, `staged`, and `uncommitted` are mutually exclusive. ' +
219
+ 'Provide at most one.');
220
+ }
221
+ }
222
+ /**
223
+ * Validates a git ref string.
224
+ * Rejects empty strings and strings beginning with `-` (which could be
225
+ * interpreted as flags by git).
226
+ * Uses `git rev-parse --verify --quiet <ref>^{commit}` to confirm the ref
227
+ * resolves to a commit object in the repository.
228
+ */
229
+ async validateRef(ref, gitRoot) {
230
+ if (!ref || ref.startsWith('-')) {
231
+ throw new InvalidGitRefError(ref);
232
+ }
233
+ try {
234
+ await this.runGit(['rev-parse', '--verify', '--quiet', `${ref}^{commit}`], gitRoot);
235
+ }
236
+ catch {
237
+ throw new InvalidGitRefError(ref);
238
+ }
239
+ }
240
+ // ---- Git helpers --------------------------------------------------------
241
+ /** Resolves the root of the Git repository containing `codebaseRoot`. */
242
+ async resolveGitRoot() {
243
+ try {
244
+ const stdout = await this.runGit(['rev-parse', '--show-toplevel'], this.codebaseRoot);
245
+ return stdout.trim();
246
+ }
247
+ catch {
248
+ throw new NotAGitRepositoryError(this.codebaseRoot);
249
+ }
250
+ }
251
+ /** Returns `true` when the repository is a shallow clone. */
252
+ async isShallowRepository(gitRoot) {
253
+ try {
254
+ const stdout = await this.runGit(['rev-parse', '--is-shallow-repository'], gitRoot);
255
+ return stdout.trim() === 'true';
256
+ }
257
+ catch {
258
+ return false;
259
+ }
260
+ }
261
+ /** Returns `true` if HEAD resolves to a commit (repo has at least one commit). */
262
+ async headExists(gitRoot) {
263
+ try {
264
+ await this.runGit(['rev-parse', '--verify', 'HEAD'], gitRoot);
265
+ return true;
266
+ }
267
+ catch {
268
+ return false;
269
+ }
270
+ }
271
+ /** Throws `GitNotAvailableError` if `git --version` fails. */
272
+ async ensureGitAvailable() {
273
+ try {
274
+ await execFile('git', ['--version']);
275
+ }
276
+ catch {
277
+ throw new GitNotAvailableError();
278
+ }
279
+ }
280
+ /**
281
+ * Runs a git command in the given working directory.
282
+ * Always uses `execFile` with an args array — never `exec` with a string.
283
+ *
284
+ * @throws `GitCommandError` on non-zero exit.
285
+ */
286
+ async runGit(args, cwd) {
287
+ try {
288
+ const { stdout } = await execFile('git', args, { cwd, maxBuffer: 50 * 1024 * 1024 });
289
+ return stdout;
290
+ }
291
+ catch (err) {
292
+ const e = err;
293
+ throw new GitCommandError('git', args, e.stderr ?? e.message ?? '', typeof e.code === 'number' ? e.code : 1);
294
+ }
295
+ }
296
+ }
297
+ //# sourceMappingURL=GitChangeSetProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitChangeSetProvider.js","sourceRoot":"","sources":["../../src/diff/GitChangeSetProvider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Diff Impact — Git-specific Errors
3
+ *
4
+ * These errors are specific to the Git layer and should not be caught by
5
+ * general application code unless the caller is explicitly handling Git
6
+ * failures.
7
+ *
8
+ * Library consumers who inject a custom `ChangeSetProvider` will never see
9
+ * these errors unless their provider chooses to re-use them.
10
+ */
11
+ /**
12
+ * Thrown when `git` is not found in PATH or returns a non-zero exit code
13
+ * during the availability check.
14
+ */
15
+ export declare class GitNotAvailableError extends Error {
16
+ constructor(message?: string);
17
+ }
18
+ /**
19
+ * Thrown when the target directory (or any ancestor) is not a Git repository.
20
+ *
21
+ * Typically triggered when `git rev-parse --git-dir` fails.
22
+ */
23
+ export declare class NotAGitRepositoryError extends Error {
24
+ readonly directory: string;
25
+ constructor(directory: string);
26
+ }
27
+ /**
28
+ * Thrown when a Git ref (branch, tag, commit SHA) provided by the caller
29
+ * cannot be resolved in the current repository.
30
+ */
31
+ export declare class InvalidGitRefError extends Error {
32
+ readonly ref: string;
33
+ constructor(ref: string);
34
+ }
35
+ /**
36
+ * Thrown when a `git` sub-command exits with a non-zero status code.
37
+ *
38
+ * The `command` and `args` fields allow callers to log or display the
39
+ * exact invocation that failed.
40
+ */
41
+ export declare class GitCommandError extends Error {
42
+ readonly command: string;
43
+ readonly args: string[];
44
+ readonly stderr: string;
45
+ readonly exitCode: number;
46
+ constructor(command: string, args: string[], stderr: string, exitCode: number);
47
+ }
48
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/diff/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;GAGG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,OAAO,SAAkC,EAGpD;CACF;AAED;;;;GAIG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;aACnB,SAAS,EAAE,MAAM;IAA7C,YAA4B,SAAS,EAAE,MAAM,EAM5C;CACF;AAED;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;aACf,GAAG,EAAE,MAAM;IAAvC,YAA4B,GAAG,EAAE,MAAM,EAOtC;CACF;AAED;;;;;GAKG;AACH,qBAAa,eAAgB,SAAQ,KAAK;aAEtB,OAAO,EAAE,MAAM;aACf,IAAI,EAAE,MAAM,EAAE;aACd,MAAM,EAAE,MAAM;aACd,QAAQ,EAAE,MAAM;IAJlC,YACkB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAOjC;CACF"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Diff Impact — Git-specific Errors
3
+ *
4
+ * These errors are specific to the Git layer and should not be caught by
5
+ * general application code unless the caller is explicitly handling Git
6
+ * failures.
7
+ *
8
+ * Library consumers who inject a custom `ChangeSetProvider` will never see
9
+ * these errors unless their provider chooses to re-use them.
10
+ */
11
+ /**
12
+ * Thrown when `git` is not found in PATH or returns a non-zero exit code
13
+ * during the availability check.
14
+ */
15
+ export class GitNotAvailableError extends Error {
16
+ constructor(message = 'git is not available in PATH.') {
17
+ super(message);
18
+ this.name = 'GitNotAvailableError';
19
+ }
20
+ }
21
+ /**
22
+ * Thrown when the target directory (or any ancestor) is not a Git repository.
23
+ *
24
+ * Typically triggered when `git rev-parse --git-dir` fails.
25
+ */
26
+ export class NotAGitRepositoryError extends Error {
27
+ directory;
28
+ constructor(directory) {
29
+ super(`"${directory}" is not inside a Git repository. ` +
30
+ 'Run `git init` or specify a path that is part of a repository.');
31
+ this.directory = directory;
32
+ this.name = 'NotAGitRepositoryError';
33
+ }
34
+ }
35
+ /**
36
+ * Thrown when a Git ref (branch, tag, commit SHA) provided by the caller
37
+ * cannot be resolved in the current repository.
38
+ */
39
+ export class InvalidGitRefError extends Error {
40
+ ref;
41
+ constructor(ref) {
42
+ super(`Git ref "${ref}" could not be resolved. ` +
43
+ 'Make sure the ref exists and that the repository has been fetched. ' +
44
+ 'In CI environments, use `fetch-depth: 0` to include all history.');
45
+ this.ref = ref;
46
+ this.name = 'InvalidGitRefError';
47
+ }
48
+ }
49
+ /**
50
+ * Thrown when a `git` sub-command exits with a non-zero status code.
51
+ *
52
+ * The `command` and `args` fields allow callers to log or display the
53
+ * exact invocation that failed.
54
+ */
55
+ export class GitCommandError extends Error {
56
+ command;
57
+ args;
58
+ stderr;
59
+ exitCode;
60
+ constructor(command, args, stderr, exitCode) {
61
+ super(`git ${args.join(' ')} failed with exit code ${exitCode}.\n` +
62
+ (stderr ? `stderr: ${stderr}` : ''));
63
+ this.command = command;
64
+ this.args = args;
65
+ this.stderr = stderr;
66
+ this.exitCode = exitCode;
67
+ this.name = 'GitCommandError';
68
+ }
69
+ }
70
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/diff/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;GAGG;AACH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,OAAO,GAAG,+BAA+B;QACnD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IACnB,SAAS;IAArC,YAA4B,SAAiB;QAC3C,KAAK,CACH,IAAI,SAAS,oCAAoC;YAC/C,gEAAgE,CACnE,CAAC;yBAJwB,SAAS;QAKnC,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IACf,GAAG;IAA/B,YAA4B,GAAW;QACrC,KAAK,CACH,YAAY,GAAG,2BAA2B;YACxC,qEAAqE;YACrE,kEAAkE,CACrE,CAAC;mBALwB,GAAG;QAM7B,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAEtB,OAAO;IACP,IAAI;IACJ,MAAM;IACN,QAAQ;IAJ1B,YACkB,OAAe,EACf,IAAc,EACd,MAAc,EACd,QAAgB;QAEhC,KAAK,CACH,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,0BAA0B,QAAQ,KAAK;YAC1D,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CACtC,CAAC;uBARc,OAAO;oBACP,IAAI;sBACJ,MAAM;wBACN,QAAQ;QAMxB,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF"}
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Diff Impact — Core Types
3
+ *
4
+ * Defines all public-facing types for the git-diff-based impact analysis
5
+ * feature. No business logic lives here.
6
+ */
7
+ /**
8
+ * Git status codes mapped to a human-readable union.
9
+ * Mirrors the single-letter codes from `git diff --name-status`.
10
+ */
11
+ export type ChangeStatus = 'added' | 'modified' | 'deleted' | 'renamed' | 'copied' | 'typechange';
12
+ /**
13
+ * A single file change as reported by a `ChangeSetProvider`.
14
+ */
15
+ export interface FileChange {
16
+ /** Current path, relative to the codebase root. */
17
+ path: string;
18
+ /**
19
+ * Original path before a rename or copy.
20
+ * Only present when `status` is `'renamed'` or `'copied'`.
21
+ */
22
+ oldPath?: string;
23
+ status: ChangeStatus;
24
+ }
25
+ /**
26
+ * Options controlling how a `ChangeSetProvider` collects file changes.
27
+ *
28
+ * **Mutual exclusivity**:
29
+ * - `since` may be combined with `until` but not with `staged` or `uncommitted`.
30
+ * - `staged` and `uncommitted` are mutually exclusive with each other.
31
+ *
32
+ * **Default (no options)**:
33
+ * Returns uncommitted changes (staged + working tree vs HEAD), which is the
34
+ * most useful default for a local development workflow.
35
+ */
36
+ export interface ChangeSetOptions {
37
+ /**
38
+ * Base ref for a branch/PR comparison.
39
+ * The provider will use `git diff <since>...<until>` (three-dot, merge-base
40
+ * semantics) so only commits introduced by the branch are considered.
41
+ */
42
+ since?: string;
43
+ /**
44
+ * Head ref for the comparison.
45
+ * @default 'HEAD'
46
+ */
47
+ until?: string;
48
+ /**
49
+ * When `true`, return only staged (index) changes (`git diff --cached`).
50
+ */
51
+ staged?: boolean;
52
+ /**
53
+ * When `true`, return all uncommitted changes — staged and unstaged — plus
54
+ * untracked files. This is the equivalent of what a developer sees before
55
+ * committing.
56
+ */
57
+ uncommitted?: boolean;
58
+ }
59
+ /**
60
+ * Contract for any source of file changes.
61
+ *
62
+ * The core library ships `GitChangeSetProvider` as the default implementation.
63
+ * Alternative implementations (e.g. a GitHub PR API client, a Mercurial
64
+ * adapter, or a test stub) can be injected via `codebase.impactOfChanges()`.
65
+ */
66
+ export interface ChangeSetProvider {
67
+ /**
68
+ * Returns the list of changed files according to the provider's source.
69
+ * The returned list is ordered by `path` (deterministic).
70
+ */
71
+ getChanges(options?: ChangeSetOptions): Promise<FileChange[]>;
72
+ }
73
+ /**
74
+ * Explains why a changed file could not be traced through the dependency graph.
75
+ *
76
+ * The analyser is honest: it never invents relationships it cannot prove.
77
+ * Files that cannot be analysed are reported explicitly here instead of being
78
+ * silently omitted.
79
+ */
80
+ export type UnanalyzableReason =
81
+ /** The file path is outside the codebase root that was loaded. */
82
+ 'outside-codebase'
83
+ /** The file extension has no registered parser (e.g. `.md`, `.css`). */
84
+ | 'unsupported-language'
85
+ /**
86
+ * The file exists on disk but was not indexed (e.g. it was added after
87
+ * `codebase.analyze()` was called, or it is excluded by ignore rules).
88
+ */
89
+ | 'not-in-index'
90
+ /**
91
+ * The file was deleted and the graph cannot prove which files depended on
92
+ * it (no recorded `unresolved` edges matching the old path).
93
+ */
94
+ | 'deleted-unprovable';
95
+ /**
96
+ * The complete result of a change-set impact analysis.
97
+ *
98
+ * **Important — granularity**: the result operates at file granularity, not
99
+ * symbol granularity. A single line change in a file marks *all* dependents
100
+ * of that file as potentially affected. The result is therefore a
101
+ * **conservative upper bound**, not a minimal set.
102
+ */
103
+ export interface ChangeSetImpact {
104
+ /** The raw list of file changes as provided by the `ChangeSetProvider`. */
105
+ changed: FileChange[];
106
+ /**
107
+ * Files that directly import/depend on at least one changed file.
108
+ * The changed files themselves are excluded from this list.
109
+ *
110
+ * If a file is both a direct dependent of one change and an indirect
111
+ * dependent of another, it is classified as **direct** (highest priority).
112
+ */
113
+ direct: string[];
114
+ /**
115
+ * All transitive dependents, minus the files already in `direct`.
116
+ * Ordered alphabetically.
117
+ */
118
+ indirect: string[];
119
+ /**
120
+ * Test files related to any changed or dependent file, discovered by
121
+ * naming convention (e.g. `AuthService.test.ts`). Union across all changes.
122
+ * Ordered alphabetically.
123
+ */
124
+ tests: string[];
125
+ /**
126
+ * Configuration and infrastructure files that are outside the import graph
127
+ * but whose modification can affect the entire codebase.
128
+ *
129
+ * Examples: `package.json`, `tsconfig.json`, `vite.config.*`, lockfiles.
130
+ * These are reported separately because the graph cannot model their impact.
131
+ */
132
+ globalChanges: string[];
133
+ /**
134
+ * Files that could not be fully traced through the dependency graph,
135
+ * along with the reason why.
136
+ */
137
+ unanalyzable: {
138
+ path: string;
139
+ reason: UnanalyzableReason;
140
+ }[];
141
+ /**
142
+ * Specifiers that appear as `unresolved` edges in the dependency graph
143
+ * (i.e. imports whose absolute path the parser could not determine).
144
+ * Reported for transparency; not treated as errors.
145
+ */
146
+ unresolvedDependencies: string[];
147
+ metadata: {
148
+ /**
149
+ * The analyser operates at file granularity.
150
+ * Every dependent of every changed file is considered potentially affected.
151
+ */
152
+ granularity: 'file';
153
+ /** The base ref used for the comparison, if any. */
154
+ base?: string;
155
+ /** The head ref used for the comparison, if any. */
156
+ head?: string;
157
+ };
158
+ }
159
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/diff/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH;;;GAGG;AACH,MAAM,MAAM,YAAY,GACpB,OAAO,GACP,UAAU,GACV,SAAS,GACT,SAAS,GACT,QAAQ,GACR,YAAY,CAAC;AAEjB;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,YAAY,CAAC;CACtB;AAMD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAMD;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,UAAU,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;CAC/D;AAMD;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB;AAC5B,kEAAkE;AAChE,kBAAkB;AACpB,wEAAwE;GACtE,sBAAsB;AACxB;;;GAGG;GACD,cAAc;AAChB;;;GAGG;GACD,oBAAoB,CAAC;AAMzB;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,OAAO,EAAE,UAAU,EAAE,CAAC;IAEtB;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IAEjB;;;OAGG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;IAEnB;;;;OAIG;IACH,KAAK,EAAE,MAAM,EAAE,CAAC;IAEhB;;;;;;OAMG;IACH,aAAa,EAAE,MAAM,EAAE,CAAC;IAExB;;;OAGG;IACH,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,kBAAkB,CAAA;KAAE,EAAE,CAAC;IAE7D;;;;OAIG;IACH,sBAAsB,EAAE,MAAM,EAAE,CAAC;IAEjC,QAAQ,EAAE;QACR;;;WAGG;QACH,WAAW,EAAE,MAAM,CAAC;QACpB,oDAAoD;QACpD,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,oDAAoD;QACpD,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Diff Impact — Core Types
3
+ *
4
+ * Defines all public-facing types for the git-diff-based impact analysis
5
+ * feature. No business logic lives here.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/diff/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,22 @@
1
+ import type { Codebase } from '../core/Codebase.js';
2
+ import type { ExplorerSnapshot } from './types.js';
3
+ /**
4
+ * Builds an {@link ExplorerSnapshot} from an analysed {@link Codebase}.
5
+ *
6
+ * Rules:
7
+ * - The codebase MUST have been analysed (`analyze()` called) before calling
8
+ * `build()`. If not, edges will be empty because the graph will be empty.
9
+ * - IDs are stable POSIX relative paths (e.g. `src/auth/AuthService.ts`).
10
+ * - External / unresolved graph nodes (not present in `codebase.files()`)
11
+ * are silently skipped — we never invent nodes that the analysis cannot prove.
12
+ * - The resulting snapshot is fully JSON-serialisable with no circular refs.
13
+ */
14
+ export declare class SnapshotBuilder {
15
+ /**
16
+ * @param codebase The analysed codebase instance.
17
+ * @param rootPath The absolute path that was passed to `Codebase.load()`.
18
+ * Used as `ExplorerSnapshot.rootPath`.
19
+ */
20
+ static build(codebase: Codebase, rootPath: string): ExplorerSnapshot;
21
+ }
22
+ //# sourceMappingURL=SnapshotBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SnapshotBuilder.d.ts","sourceRoot":"","sources":["../../src/explorer/SnapshotBuilder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EACV,gBAAgB,EAKjB,MAAM,YAAY,CAAC;AAsDpB;;;;;;;;;;GAUG;AACH,qBAAa,eAAe;IAC1B;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CA6KnE;CACF"}