@renfeng/kiro-code-review 1.9.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 (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +69 -0
  3. package/dist/api/gitlab-api.d.ts +122 -0
  4. package/dist/api/gitlab-api.d.ts.map +1 -0
  5. package/dist/api/gitlab-api.js +334 -0
  6. package/dist/api/gitlab-api.js.map +1 -0
  7. package/dist/bin/index.d.ts +11 -0
  8. package/dist/bin/index.d.ts.map +1 -0
  9. package/dist/bin/index.js +67 -0
  10. package/dist/bin/index.js.map +1 -0
  11. package/dist/config/glab-config.loader.d.ts +14 -0
  12. package/dist/config/glab-config.loader.d.ts.map +1 -0
  13. package/dist/config/glab-config.loader.js +87 -0
  14. package/dist/config/glab-config.loader.js.map +1 -0
  15. package/dist/errors/error-handler.d.ts +45 -0
  16. package/dist/errors/error-handler.d.ts.map +1 -0
  17. package/dist/errors/error-handler.js +134 -0
  18. package/dist/errors/error-handler.js.map +1 -0
  19. package/dist/logging/index.d.ts +2 -0
  20. package/dist/logging/index.d.ts.map +1 -0
  21. package/dist/logging/index.js +2 -0
  22. package/dist/logging/index.js.map +1 -0
  23. package/dist/logging/logger.service.d.ts +34 -0
  24. package/dist/logging/logger.service.d.ts.map +1 -0
  25. package/dist/logging/logger.service.js +91 -0
  26. package/dist/logging/logger.service.js.map +1 -0
  27. package/dist/servers/general-server.d.ts +18 -0
  28. package/dist/servers/general-server.d.ts.map +1 -0
  29. package/dist/servers/general-server.js +73 -0
  30. package/dist/servers/general-server.js.map +1 -0
  31. package/dist/servers/git-server.d.ts +17 -0
  32. package/dist/servers/git-server.d.ts.map +1 -0
  33. package/dist/servers/git-server.js +74 -0
  34. package/dist/servers/git-server.js.map +1 -0
  35. package/dist/servers/gitlab-server.d.ts +18 -0
  36. package/dist/servers/gitlab-server.d.ts.map +1 -0
  37. package/dist/servers/gitlab-server.js +139 -0
  38. package/dist/servers/gitlab-server.js.map +1 -0
  39. package/dist/services/__tests__/batch-retro.service.test.d.ts +9 -0
  40. package/dist/services/__tests__/batch-retro.service.test.d.ts.map +1 -0
  41. package/dist/services/__tests__/batch-retro.service.test.js +235 -0
  42. package/dist/services/__tests__/batch-retro.service.test.js.map +1 -0
  43. package/dist/services/__tests__/general-save-diffs.test.d.ts +5 -0
  44. package/dist/services/__tests__/general-save-diffs.test.d.ts.map +1 -0
  45. package/dist/services/__tests__/general-save-diffs.test.js +99 -0
  46. package/dist/services/__tests__/general-save-diffs.test.js.map +1 -0
  47. package/dist/services/__tests__/git-diff-files.test.d.ts +8 -0
  48. package/dist/services/__tests__/git-diff-files.test.d.ts.map +1 -0
  49. package/dist/services/__tests__/git-diff-files.test.js +64 -0
  50. package/dist/services/__tests__/git-diff-files.test.js.map +1 -0
  51. package/dist/services/__tests__/review-tools.service.test.d.ts +8 -0
  52. package/dist/services/__tests__/review-tools.service.test.d.ts.map +1 -0
  53. package/dist/services/__tests__/review-tools.service.test.js +169 -0
  54. package/dist/services/__tests__/review-tools.service.test.js.map +1 -0
  55. package/dist/services/__tests__/review-utils.service.test.d.ts +8 -0
  56. package/dist/services/__tests__/review-utils.service.test.d.ts.map +1 -0
  57. package/dist/services/__tests__/review-utils.service.test.js +306 -0
  58. package/dist/services/__tests__/review-utils.service.test.js.map +1 -0
  59. package/dist/services/anchor-resolver.d.ts +29 -0
  60. package/dist/services/anchor-resolver.d.ts.map +1 -0
  61. package/dist/services/anchor-resolver.js +97 -0
  62. package/dist/services/anchor-resolver.js.map +1 -0
  63. package/dist/services/general.service.d.ts +42 -0
  64. package/dist/services/general.service.d.ts.map +1 -0
  65. package/dist/services/general.service.js +157 -0
  66. package/dist/services/general.service.js.map +1 -0
  67. package/dist/services/git-tools.service.d.ts +123 -0
  68. package/dist/services/git-tools.service.d.ts.map +1 -0
  69. package/dist/services/git-tools.service.js +231 -0
  70. package/dist/services/git-tools.service.js.map +1 -0
  71. package/dist/services/review-tools.service.d.ts +130 -0
  72. package/dist/services/review-tools.service.d.ts.map +1 -0
  73. package/dist/services/review-tools.service.js +902 -0
  74. package/dist/services/review-tools.service.js.map +1 -0
  75. package/dist/tools/general-tools.d.ts +9 -0
  76. package/dist/tools/general-tools.d.ts.map +1 -0
  77. package/dist/tools/general-tools.js +99 -0
  78. package/dist/tools/general-tools.js.map +1 -0
  79. package/dist/tools/git-tools.d.ts +8 -0
  80. package/dist/tools/git-tools.d.ts.map +1 -0
  81. package/dist/tools/git-tools.js +175 -0
  82. package/dist/tools/git-tools.js.map +1 -0
  83. package/dist/tools/gitlab-tools.d.ts +8 -0
  84. package/dist/tools/gitlab-tools.d.ts.map +1 -0
  85. package/dist/tools/gitlab-tools.js +348 -0
  86. package/dist/tools/gitlab-tools.js.map +1 -0
  87. package/dist/types.d.ts +294 -0
  88. package/dist/types.d.ts.map +1 -0
  89. package/dist/types.js +7 -0
  90. package/dist/types.js.map +1 -0
  91. package/package.json +51 -0
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Tests for GeneralService.savePerFileDiffs and GitToolsService.diff with files param.
3
+ */
4
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
5
+ import { readFileSync, mkdtempSync, rmSync, existsSync } from 'fs';
6
+ import { join } from 'path';
7
+ import { tmpdir } from 'os';
8
+ import { GeneralService } from '../general.service.js';
9
+ import { GitToolsService } from '../git-tools.service.js';
10
+ import { Logger, LogLevel } from '../../logging/logger.service.js';
11
+ describe('GeneralService.savePerFileDiffs', () => {
12
+ let service;
13
+ let gitTools;
14
+ let logger;
15
+ let tmpDir;
16
+ beforeEach(() => {
17
+ logger = new Logger('test', LogLevel.ERROR);
18
+ gitTools = new GitToolsService(logger);
19
+ service = new GeneralService(logger, gitTools);
20
+ tmpDir = mkdtempSync(join(tmpdir(), 'save-diffs-'));
21
+ });
22
+ afterEach(() => {
23
+ rmSync(tmpDir, { recursive: true, force: true });
24
+ vi.restoreAllMocks();
25
+ });
26
+ it('saves per-file diffs to disk', async () => {
27
+ const diffSpy = vi.spyOn(gitTools, 'diff');
28
+ // First call: name-only
29
+ diffSpy.mockResolvedValueOnce({ diff: 'src/a.ts\nsrc/b.ts\n' });
30
+ // Per-file diffs
31
+ diffSpy.mockResolvedValueOnce({ diff: 'diff --git a/src/a.ts b/src/a.ts\n+added line\n' });
32
+ diffSpy.mockResolvedValueOnce({ diff: 'diff --git a/src/b.ts b/src/b.ts\n-removed line\n' });
33
+ const outputDir = join(tmpDir, 'diffs');
34
+ const result = await service.savePerFileDiffs({
35
+ repoDir: '/fake/repo', mergeBase: 'abc123', outputDir,
36
+ });
37
+ expect(result.files).toEqual(['src/a.ts', 'src/b.ts']);
38
+ expect(result.totalFiles).toBe(2);
39
+ expect(result.errors).toEqual([]);
40
+ // Verify files on disk
41
+ expect(readFileSync(join(outputDir, 'src/a.ts.diff'), 'utf-8')).toContain('+added line');
42
+ expect(readFileSync(join(outputDir, 'src/b.ts.diff'), 'utf-8')).toContain('-removed line');
43
+ // Verify diff() was called with correct params
44
+ expect(diffSpy).toHaveBeenCalledWith({
45
+ repoDir: '/fake/repo', base: 'abc123', head: 'HEAD', mode: 'name-only',
46
+ });
47
+ expect(diffSpy).toHaveBeenCalledWith({
48
+ repoDir: '/fake/repo', base: 'abc123', head: 'HEAD', mode: 'full', files: ['src/a.ts'],
49
+ });
50
+ expect(diffSpy).toHaveBeenCalledWith({
51
+ repoDir: '/fake/repo', base: 'abc123', head: 'HEAD', mode: 'full', files: ['src/b.ts'],
52
+ });
53
+ });
54
+ it('handles empty diff (no changed files)', async () => {
55
+ vi.spyOn(gitTools, 'diff').mockResolvedValueOnce({ diff: '\n' });
56
+ const result = await service.savePerFileDiffs({
57
+ repoDir: '/fake/repo', mergeBase: 'abc123', outputDir: join(tmpDir, 'diffs'),
58
+ });
59
+ expect(result.files).toEqual([]);
60
+ expect(result.totalFiles).toBe(0);
61
+ expect(result.errors).toEqual([]);
62
+ });
63
+ it('continues on per-file error and reports failures', async () => {
64
+ const diffSpy = vi.spyOn(gitTools, 'diff');
65
+ // name-only returns 3 files
66
+ diffSpy.mockResolvedValueOnce({ diff: 'good.ts\nbad.bin\nalso-good.ts\n' });
67
+ // good.ts succeeds
68
+ diffSpy.mockResolvedValueOnce({ diff: 'diff for good.ts' });
69
+ // bad.bin fails
70
+ diffSpy.mockRejectedValueOnce(new Error('binary file'));
71
+ // also-good.ts succeeds
72
+ diffSpy.mockResolvedValueOnce({ diff: 'diff for also-good.ts' });
73
+ const outputDir = join(tmpDir, 'diffs');
74
+ const result = await service.savePerFileDiffs({
75
+ repoDir: '/fake/repo', mergeBase: 'abc123', outputDir,
76
+ });
77
+ expect(result.files).toEqual(['good.ts', 'also-good.ts']);
78
+ expect(result.totalFiles).toBe(2);
79
+ expect(result.errors).toEqual([{ file: 'bad.bin', error: 'binary file' }]);
80
+ // good files saved, bad file not
81
+ expect(existsSync(join(outputDir, 'good.ts.diff'))).toBe(true);
82
+ expect(existsSync(join(outputDir, 'bad.bin.diff'))).toBe(false);
83
+ expect(existsSync(join(outputDir, 'also-good.ts.diff'))).toBe(true);
84
+ });
85
+ it('creates nested directories for deep file paths', async () => {
86
+ const diffSpy = vi.spyOn(gitTools, 'diff');
87
+ diffSpy.mockResolvedValueOnce({ diff: 'libs/orders/store/src/effects.ts\n' });
88
+ diffSpy.mockResolvedValueOnce({ diff: 'deep nested diff content' });
89
+ const outputDir = join(tmpDir, 'diffs');
90
+ const result = await service.savePerFileDiffs({
91
+ repoDir: '/fake/repo', mergeBase: 'abc123', outputDir,
92
+ });
93
+ expect(result.files).toEqual(['libs/orders/store/src/effects.ts']);
94
+ const savedPath = join(outputDir, 'libs/orders/store/src/effects.ts.diff');
95
+ expect(existsSync(savedPath)).toBe(true);
96
+ expect(readFileSync(savedPath, 'utf-8')).toBe('deep nested diff content');
97
+ });
98
+ });
99
+ //# sourceMappingURL=general-save-diffs.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"general-save-diffs.test.js","sourceRoot":"","sources":["../../../src/services/__tests__/general-save-diffs.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Tests for GitToolsService.diff with the files parameter.
3
+ *
4
+ * Uses a real temp directory for repoDir (to pass path validation),
5
+ * then mocks runGit to verify correct argument construction.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=git-diff-files.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-diff-files.test.d.ts","sourceRoot":"","sources":["../../../src/services/__tests__/git-diff-files.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Tests for GitToolsService.diff with the files parameter.
3
+ *
4
+ * Uses a real temp directory for repoDir (to pass path validation),
5
+ * then mocks runGit to verify correct argument construction.
6
+ */
7
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
8
+ import { mkdtempSync, rmSync } from 'fs';
9
+ import { join } from 'path';
10
+ import { tmpdir } from 'os';
11
+ import { GitToolsService } from '../git-tools.service.js';
12
+ import { Logger, LogLevel } from '../../logging/logger.service.js';
13
+ describe('GitToolsService.diff files parameter', () => {
14
+ let gitTools;
15
+ let runGitSpy;
16
+ let repoDir;
17
+ beforeEach(() => {
18
+ const logger = new Logger('test', LogLevel.ERROR);
19
+ gitTools = new GitToolsService(logger);
20
+ repoDir = mkdtempSync(join(tmpdir(), 'git-diff-test-'));
21
+ runGitSpy = vi.spyOn(gitTools, 'runGit').mockResolvedValue('mock diff output');
22
+ });
23
+ afterEach(() => {
24
+ rmSync(repoDir, { recursive: true, force: true });
25
+ vi.restoreAllMocks();
26
+ });
27
+ it('appends -- and file paths when files param is provided', async () => {
28
+ await gitTools.diff({
29
+ repoDir, base: 'abc123', head: 'HEAD', mode: 'full', files: ['src/a.ts'],
30
+ });
31
+ expect(runGitSpy).toHaveBeenCalledWith(repoDir, ['diff', 'abc123', 'HEAD', '--', 'src/a.ts']);
32
+ });
33
+ it('appends multiple file paths', async () => {
34
+ await gitTools.diff({
35
+ repoDir, base: 'abc123', head: 'HEAD', mode: 'full', files: ['src/a.ts', 'src/b.ts'],
36
+ });
37
+ expect(runGitSpy).toHaveBeenCalledWith(repoDir, ['diff', 'abc123', 'HEAD', '--', 'src/a.ts', 'src/b.ts']);
38
+ });
39
+ it('does not append -- when files is empty', async () => {
40
+ await gitTools.diff({
41
+ repoDir, base: 'abc123', head: 'HEAD', mode: 'full', files: [],
42
+ });
43
+ expect(runGitSpy).toHaveBeenCalledWith(repoDir, ['diff', 'abc123', 'HEAD']);
44
+ });
45
+ it('does not append -- when files is undefined', async () => {
46
+ await gitTools.diff({
47
+ repoDir, base: 'abc123', head: 'HEAD', mode: 'full',
48
+ });
49
+ expect(runGitSpy).toHaveBeenCalledWith(repoDir, ['diff', 'abc123', 'HEAD']);
50
+ });
51
+ it('combines files with stat mode', async () => {
52
+ await gitTools.diff({
53
+ repoDir, base: 'abc123', mode: 'stat', files: ['src/a.ts'],
54
+ });
55
+ expect(runGitSpy).toHaveBeenCalledWith(repoDir, ['diff', 'abc123', '--stat', '--', 'src/a.ts']);
56
+ });
57
+ it('combines files with name-only mode', async () => {
58
+ await gitTools.diff({
59
+ repoDir, base: 'abc123', mode: 'name-only', files: ['src/a.ts'],
60
+ });
61
+ expect(runGitSpy).toHaveBeenCalledWith(repoDir, ['diff', 'abc123', '--name-only', '--', 'src/a.ts']);
62
+ });
63
+ });
64
+ //# sourceMappingURL=git-diff-files.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-diff-files.test.js","sourceRoot":"","sources":["../../../src/services/__tests__/git-diff-files.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Tests for ReviewToolsService.postDraftNotes inline anchor resolution.
3
+ *
4
+ * Verifies that when repoDir and mergeBase are provided, anchor-based
5
+ * findings are resolved to line numbers before posting to GitLab.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=review-tools.service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-tools.service.test.d.ts","sourceRoot":"","sources":["../../../src/services/__tests__/review-tools.service.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Tests for ReviewToolsService.postDraftNotes inline anchor resolution.
3
+ *
4
+ * Verifies that when repoDir and mergeBase are provided, anchor-based
5
+ * findings are resolved to line numbers before posting to GitLab.
6
+ */
7
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
8
+ import { ReviewToolsService } from '../review-tools.service.js';
9
+ import { Logger, LogLevel } from '../../logging/logger.service.js';
10
+ // Mock GitLabAPI to capture posted draft notes
11
+ const mockPostDraftNote = vi.fn().mockResolvedValue({ id: 1, line_code: 'abc' });
12
+ const mockDeleteDraftNote = vi.fn().mockResolvedValue({});
13
+ vi.mock('../../api/gitlab-api.js', () => ({
14
+ GitLabAPI: class MockGitLabAPI {
15
+ postDraftNote = mockPostDraftNote;
16
+ deleteDraftNote = mockDeleteDraftNote;
17
+ constructor() { }
18
+ },
19
+ }));
20
+ // Mock GitToolsService.runGit to supply synthetic diffs
21
+ vi.mock('../git-tools.service.js', () => ({
22
+ GitToolsService: class MockGitToolsService {
23
+ constructor() { }
24
+ runGit(_repoDir, args) {
25
+ const filePath = args[args.length - 1];
26
+ if (filePath === 'file.ts') {
27
+ return Promise.resolve([
28
+ 'diff --git a/file.ts b/file.ts',
29
+ 'index abc..def 100644',
30
+ '--- a/file.ts',
31
+ '+++ b/file.ts',
32
+ '@@ -10,4 +10,5 @@',
33
+ ' const existing = true;',
34
+ '+const added = false;',
35
+ '-const removed = "old";',
36
+ ' const kept = 42;',
37
+ ].join('\n'));
38
+ }
39
+ return Promise.reject(new Error('no diff'));
40
+ }
41
+ },
42
+ }));
43
+ describe('ReviewToolsService.postDraftNotes anchor resolution', () => {
44
+ let service;
45
+ beforeEach(() => {
46
+ vi.clearAllMocks();
47
+ const logger = new Logger('test', LogLevel.ERROR);
48
+ service = new ReviewToolsService(logger);
49
+ });
50
+ const baseParams = {
51
+ project: 'group/repo',
52
+ mergeRequestIid: 1,
53
+ headSha: 'head123',
54
+ baseSha: 'base123',
55
+ startSha: 'start123',
56
+ repoDir: '/fake/repo',
57
+ mergeBase: 'merge-base-sha',
58
+ };
59
+ it('resolves anchor-based finding to line number before posting', async () => {
60
+ const result = await service.postDraftNotes({
61
+ ...baseParams,
62
+ findings: {
63
+ comments: [{
64
+ file: 'file.ts',
65
+ anchor: 'const added = false;',
66
+ blocking: true,
67
+ note: 'Review this addition',
68
+ }],
69
+ summary: 'test',
70
+ verdict: 'request_changes',
71
+ },
72
+ }, 'https://gitlab.example.com', 'fake-token');
73
+ expect(result.posted).toBe(1);
74
+ expect(result.errors).toHaveLength(0);
75
+ // Verify the draft was posted with resolved position
76
+ const postedBody = mockPostDraftNote.mock.calls[0][2];
77
+ expect(postedBody.position).toBeDefined();
78
+ expect(postedBody.position.new_line).toBe(11);
79
+ expect(postedBody.position.old_line).toBeNull();
80
+ });
81
+ it('resolves OLD: anchor to old_line', async () => {
82
+ const result = await service.postDraftNotes({
83
+ ...baseParams,
84
+ findings: {
85
+ comments: [{
86
+ file: 'file.ts',
87
+ anchor: 'OLD:const removed = "old";',
88
+ blocking: true,
89
+ note: 'This was removed',
90
+ }],
91
+ summary: 'test',
92
+ verdict: 'request_changes',
93
+ },
94
+ }, 'https://gitlab.example.com', 'fake-token');
95
+ expect(result.posted).toBe(1);
96
+ const postedBody = mockPostDraftNote.mock.calls[0][2];
97
+ expect(postedBody.position).toBeDefined();
98
+ expect(postedBody.position.old_line).toBe(11);
99
+ expect(postedBody.position.new_line).toBeNull();
100
+ });
101
+ it('falls back to general when anchor cannot be resolved', async () => {
102
+ const result = await service.postDraftNotes({
103
+ ...baseParams,
104
+ findings: {
105
+ comments: [{
106
+ file: 'missing.ts',
107
+ anchor: 'nonexistent line',
108
+ blocking: true,
109
+ note: 'Cannot find this',
110
+ }],
111
+ summary: 'test',
112
+ verdict: 'request_changes',
113
+ },
114
+ }, 'https://gitlab.example.com', 'fake-token');
115
+ expect(result.posted).toBe(1);
116
+ // Should be posted as general (no position)
117
+ const postedBody = mockPostDraftNote.mock.calls[0][2];
118
+ expect(postedBody.position).toBeUndefined();
119
+ expect(postedBody.note).toBe('**`missing.ts`** ([link](https://gitlab.example.com/group/repo/-/blob/head123/missing.ts))\n\nCannot find this');
120
+ });
121
+ it('skips resolution for findings that already have line numbers', async () => {
122
+ const result = await service.postDraftNotes({
123
+ ...baseParams,
124
+ findings: {
125
+ comments: [{
126
+ file: 'file.ts',
127
+ anchor: 'const added = false;',
128
+ line: 99,
129
+ changed: 'new',
130
+ blocking: true,
131
+ note: 'Already resolved',
132
+ }],
133
+ summary: 'test',
134
+ verdict: 'request_changes',
135
+ },
136
+ }, 'https://gitlab.example.com', 'fake-token');
137
+ expect(result.posted).toBe(1);
138
+ // Should use the pre-existing line number, not re-resolve
139
+ const postedBody = mockPostDraftNote.mock.calls[0][2];
140
+ expect(postedBody.position.new_line).toBe(99);
141
+ });
142
+ it('does not resolve anchors when repoDir is not provided', async () => {
143
+ const result = await service.postDraftNotes({
144
+ project: 'group/repo',
145
+ mergeRequestIid: 1,
146
+ headSha: 'head123',
147
+ baseSha: 'base123',
148
+ startSha: 'start123',
149
+ // No repoDir or mergeBase
150
+ findings: {
151
+ comments: [{
152
+ file: 'file.ts',
153
+ anchor: 'const added = false;',
154
+ blocking: true,
155
+ note: 'No resolution',
156
+ }],
157
+ summary: 'test',
158
+ verdict: 'request_changes',
159
+ },
160
+ }, 'https://gitlab.example.com', 'fake-token');
161
+ expect(result.posted).toBe(1);
162
+ // Without repoDir, anchor is ignored — no line/old_line means general comment
163
+ const postedBody = mockPostDraftNote.mock.calls[0][2];
164
+ expect(postedBody.position).toBeUndefined();
165
+ // File-link fallback should prepend file context to the note body
166
+ expect(postedBody.note).toBe('**`file.ts`** ([link](https://gitlab.example.com/group/repo/-/blob/head123/file.ts))\n\nNo resolution');
167
+ });
168
+ });
169
+ //# sourceMappingURL=review-tools.service.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-tools.service.test.js","sourceRoot":"","sources":["../../../src/services/__tests__/review-tools.service.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Tests for ReviewService anchor resolution.
3
+ *
4
+ * These tests mock GitToolsService.runGit to supply synthetic diffs,
5
+ * then verify that resolveAnchors correctly maps anchors to line numbers.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=review-utils.service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-utils.service.test.d.ts","sourceRoot":"","sources":["../../../src/services/__tests__/review-utils.service.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}