@m3hti/commit-genie 3.1.0 → 3.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.
Files changed (56) hide show
  1. package/dist/commands/generate.d.ts.map +1 -1
  2. package/dist/commands/generate.js +10 -0
  3. package/dist/commands/generate.js.map +1 -1
  4. package/dist/commands/generate.test.js +38 -0
  5. package/dist/commands/generate.test.js.map +1 -1
  6. package/dist/services/analyzerService.d.ts +0 -157
  7. package/dist/services/analyzerService.d.ts.map +1 -1
  8. package/dist/services/analyzerService.js +75 -2010
  9. package/dist/services/analyzerService.js.map +1 -1
  10. package/dist/services/analyzerService.test.js +66 -4
  11. package/dist/services/analyzerService.test.js.map +1 -1
  12. package/dist/services/breakingChangeDetector.d.ts +9 -0
  13. package/dist/services/breakingChangeDetector.d.ts.map +1 -0
  14. package/dist/services/breakingChangeDetector.js +76 -0
  15. package/dist/services/breakingChangeDetector.js.map +1 -0
  16. package/dist/services/commitTypeDetector.d.ts +39 -0
  17. package/dist/services/commitTypeDetector.d.ts.map +1 -0
  18. package/dist/services/commitTypeDetector.js +510 -0
  19. package/dist/services/commitTypeDetector.js.map +1 -0
  20. package/dist/services/descriptionGenerator.d.ts +58 -0
  21. package/dist/services/descriptionGenerator.d.ts.map +1 -0
  22. package/dist/services/descriptionGenerator.js +566 -0
  23. package/dist/services/descriptionGenerator.js.map +1 -0
  24. package/dist/services/gitService.test.js +242 -24
  25. package/dist/services/gitService.test.js.map +1 -1
  26. package/dist/services/hookService.test.d.ts +2 -0
  27. package/dist/services/hookService.test.d.ts.map +1 -0
  28. package/dist/services/hookService.test.js +182 -0
  29. package/dist/services/hookService.test.js.map +1 -0
  30. package/dist/services/lintService.test.d.ts +2 -0
  31. package/dist/services/lintService.test.d.ts.map +1 -0
  32. package/dist/services/lintService.test.js +288 -0
  33. package/dist/services/lintService.test.js.map +1 -0
  34. package/dist/services/messageBuilder.d.ts +16 -0
  35. package/dist/services/messageBuilder.d.ts.map +1 -0
  36. package/dist/services/messageBuilder.js +135 -0
  37. package/dist/services/messageBuilder.js.map +1 -0
  38. package/dist/services/scopeDetector.d.ts +6 -0
  39. package/dist/services/scopeDetector.d.ts.map +1 -0
  40. package/dist/services/scopeDetector.js +51 -0
  41. package/dist/services/scopeDetector.js.map +1 -0
  42. package/dist/services/semanticAnalyzer.d.ts +25 -0
  43. package/dist/services/semanticAnalyzer.d.ts.map +1 -0
  44. package/dist/services/semanticAnalyzer.js +713 -0
  45. package/dist/services/semanticAnalyzer.js.map +1 -0
  46. package/dist/services/splitService.test.d.ts +2 -0
  47. package/dist/services/splitService.test.d.ts.map +1 -0
  48. package/dist/services/splitService.test.js +190 -0
  49. package/dist/services/splitService.test.js.map +1 -0
  50. package/dist/services/statsService.test.d.ts +2 -0
  51. package/dist/services/statsService.test.d.ts.map +1 -0
  52. package/dist/services/statsService.test.js +211 -0
  53. package/dist/services/statsService.test.js.map +1 -0
  54. package/dist/types/index.d.ts +5 -0
  55. package/dist/types/index.d.ts.map +1 -1
  56. package/package.json +1 -1
@@ -0,0 +1,288 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const lintService_1 = require("./lintService");
4
+ const configService_1 = require("./configService");
5
+ jest.mock('./configService');
6
+ const mockedConfigService = configService_1.ConfigService;
7
+ function makeMessage(overrides = {}) {
8
+ return {
9
+ type: 'feat',
10
+ description: 'add new feature',
11
+ full: 'feat: add new feature',
12
+ ...overrides,
13
+ };
14
+ }
15
+ describe('LintService', () => {
16
+ beforeEach(() => {
17
+ jest.clearAllMocks();
18
+ // Default config: all rules enabled, default values
19
+ mockedConfigService.getConfig.mockReturnValue({
20
+ linting: {
21
+ enabled: true,
22
+ blockOnError: true,
23
+ rules: {
24
+ subjectMaxLength: { enabled: true, maxLength: 72 },
25
+ typeRequired: { enabled: true },
26
+ scopeFormat: { enabled: true },
27
+ imperativeMood: { enabled: true },
28
+ },
29
+ },
30
+ });
31
+ });
32
+ describe('lint()', () => {
33
+ it('should return valid when linting is disabled', () => {
34
+ mockedConfigService.getConfig.mockReturnValue({
35
+ linting: { enabled: false },
36
+ });
37
+ const result = lintService_1.LintService.lint(makeMessage());
38
+ expect(result.valid).toBe(true);
39
+ expect(result.violations).toEqual([]);
40
+ });
41
+ it('should pass a valid commit message with all rules enabled', () => {
42
+ const result = lintService_1.LintService.lint(makeMessage());
43
+ expect(result.valid).toBe(true);
44
+ expect(result.violations).toHaveLength(0);
45
+ });
46
+ it('should fail when subject exceeds 72 characters', () => {
47
+ const longDescription = 'a'.repeat(80);
48
+ const full = `feat: ${longDescription}`;
49
+ const result = lintService_1.LintService.lint(makeMessage({
50
+ description: longDescription,
51
+ full,
52
+ }));
53
+ expect(result.valid).toBe(false);
54
+ const violation = result.violations.find(v => v.ruleId === 'subject-max-length');
55
+ expect(violation).toBeDefined();
56
+ expect(violation.severity).toBe('error');
57
+ expect(violation.message).toContain(String(full.length));
58
+ expect(violation.message).toContain('72');
59
+ });
60
+ it('should pass when subject is exactly at max length (72)', () => {
61
+ // "feat: " is 6 chars, so description needs to be 66 chars for total of 72
62
+ const description = 'a'.repeat(66);
63
+ const full = `feat: ${description}`;
64
+ expect(full.length).toBe(72);
65
+ const result = lintService_1.LintService.lint(makeMessage({
66
+ description,
67
+ full,
68
+ }));
69
+ expect(result.valid).toBe(true);
70
+ expect(result.violations.find(v => v.ruleId === 'subject-max-length')).toBeUndefined();
71
+ });
72
+ it('should use custom max length from config', () => {
73
+ mockedConfigService.getConfig.mockReturnValue({
74
+ linting: {
75
+ enabled: true,
76
+ blockOnError: true,
77
+ rules: {
78
+ subjectMaxLength: { enabled: true, maxLength: 50 },
79
+ typeRequired: { enabled: true },
80
+ scopeFormat: { enabled: true },
81
+ imperativeMood: { enabled: true },
82
+ },
83
+ },
84
+ });
85
+ // 51 chars total should exceed custom max of 50
86
+ const description = 'a'.repeat(45);
87
+ const full = `feat: ${description}`; // 6 + 45 = 51
88
+ expect(full.length).toBe(51);
89
+ const result = lintService_1.LintService.lint(makeMessage({
90
+ description,
91
+ full,
92
+ }));
93
+ expect(result.valid).toBe(false);
94
+ const violation = result.violations.find(v => v.ruleId === 'subject-max-length');
95
+ expect(violation).toBeDefined();
96
+ expect(violation.message).toContain('50');
97
+ });
98
+ it('should fail when type is missing/undefined', () => {
99
+ const result = lintService_1.LintService.lint(makeMessage({
100
+ type: undefined,
101
+ full: 'add new feature',
102
+ }));
103
+ expect(result.valid).toBe(false);
104
+ const violation = result.violations.find(v => v.ruleId === 'type-required');
105
+ expect(violation).toBeDefined();
106
+ expect(violation.severity).toBe('error');
107
+ expect(violation.message).toContain('type prefix');
108
+ });
109
+ it('should fail when type is not in allowed list', () => {
110
+ const result = lintService_1.LintService.lint(makeMessage({
111
+ type: 'wip',
112
+ full: 'wip: work in progress',
113
+ }));
114
+ expect(result.valid).toBe(false);
115
+ const violation = result.violations.find(v => v.ruleId === 'type-invalid');
116
+ expect(violation).toBeDefined();
117
+ expect(violation.severity).toBe('error');
118
+ expect(violation.message).toContain('"wip"');
119
+ });
120
+ it('should accept custom allowed types list', () => {
121
+ mockedConfigService.getConfig.mockReturnValue({
122
+ linting: {
123
+ enabled: true,
124
+ blockOnError: true,
125
+ rules: {
126
+ subjectMaxLength: { enabled: true, maxLength: 72 },
127
+ typeRequired: { enabled: true, allowedTypes: ['feat', 'fix', 'wip'] },
128
+ scopeFormat: { enabled: true },
129
+ imperativeMood: { enabled: true },
130
+ },
131
+ },
132
+ });
133
+ const result = lintService_1.LintService.lint(makeMessage({
134
+ type: 'wip',
135
+ description: 'work in progress',
136
+ full: 'wip: work in progress',
137
+ }));
138
+ // No type-invalid violation because 'wip' is in the custom allowed list
139
+ const typeViolation = result.violations.find(v => v.ruleId === 'type-invalid');
140
+ expect(typeViolation).toBeUndefined();
141
+ });
142
+ it('should pass valid scope', () => {
143
+ const result = lintService_1.LintService.lint(makeMessage({
144
+ scope: 'auth',
145
+ full: 'feat(auth): add new feature',
146
+ }));
147
+ expect(result.valid).toBe(true);
148
+ expect(result.violations.find(v => v.ruleId === 'scope-format')).toBeUndefined();
149
+ });
150
+ it('should fail invalid scope', () => {
151
+ const result = lintService_1.LintService.lint(makeMessage({
152
+ scope: 'Invalid-SCOPE!',
153
+ full: 'feat(Invalid-SCOPE!): add new feature',
154
+ }));
155
+ expect(result.valid).toBe(false);
156
+ const violation = result.violations.find(v => v.ruleId === 'scope-format');
157
+ expect(violation).toBeDefined();
158
+ expect(violation.severity).toBe('warning');
159
+ expect(violation.message).toContain('Invalid-SCOPE!');
160
+ });
161
+ it('should skip scope check when no scope is provided', () => {
162
+ const result = lintService_1.LintService.lint(makeMessage({
163
+ scope: undefined,
164
+ full: 'feat: add new feature',
165
+ }));
166
+ expect(result.violations.find(v => v.ruleId === 'scope-format')).toBeUndefined();
167
+ });
168
+ it('should gracefully handle invalid regex pattern (skip check, no violation)', () => {
169
+ mockedConfigService.getConfig.mockReturnValue({
170
+ linting: {
171
+ enabled: true,
172
+ blockOnError: true,
173
+ rules: {
174
+ subjectMaxLength: { enabled: true, maxLength: 72 },
175
+ typeRequired: { enabled: true },
176
+ scopeFormat: { enabled: true, pattern: '[invalid(' },
177
+ imperativeMood: { enabled: true },
178
+ },
179
+ },
180
+ });
181
+ const result = lintService_1.LintService.lint(makeMessage({
182
+ scope: 'auth',
183
+ full: 'feat(auth): add new feature',
184
+ }));
185
+ // Invalid regex should be caught and scope check skipped
186
+ const scopeViolation = result.violations.find(v => v.ruleId === 'scope-format');
187
+ expect(scopeViolation).toBeUndefined();
188
+ });
189
+ it('should detect forbidden prefix and suggest imperative form', () => {
190
+ const result = lintService_1.LintService.lint(makeMessage({
191
+ description: 'added new feature',
192
+ full: 'feat: added new feature',
193
+ }));
194
+ expect(result.valid).toBe(false);
195
+ const violation = result.violations.find(v => v.ruleId === 'imperative-mood');
196
+ expect(violation).toBeDefined();
197
+ expect(violation.severity).toBe('warning');
198
+ expect(violation.message).toContain('added');
199
+ expect(violation.suggestion).toContain('add');
200
+ });
201
+ it('should pass imperative mood description', () => {
202
+ const result = lintService_1.LintService.lint(makeMessage({
203
+ description: 'add new feature',
204
+ full: 'feat: add new feature',
205
+ }));
206
+ expect(result.violations.find(v => v.ruleId === 'imperative-mood')).toBeUndefined();
207
+ });
208
+ it('should only check first line for subject max length', () => {
209
+ const full = 'feat: add feature\n\nThis is a very long body line that exceeds 72 characters but should not trigger the subject max length rule at all.';
210
+ const result = lintService_1.LintService.lint(makeMessage({
211
+ description: 'add feature',
212
+ body: 'This is a very long body line that exceeds 72 characters but should not trigger the subject max length rule at all.',
213
+ full,
214
+ }));
215
+ expect(result.violations.find(v => v.ruleId === 'subject-max-length')).toBeUndefined();
216
+ });
217
+ it('should detect gerund forbidden prefix (fixing)', () => {
218
+ const result = lintService_1.LintService.lint(makeMessage({
219
+ type: 'fix',
220
+ description: 'fixing the broken test',
221
+ full: 'fix: fixing the broken test',
222
+ }));
223
+ const violation = result.violations.find(v => v.ruleId === 'imperative-mood');
224
+ expect(violation).toBeDefined();
225
+ expect(violation.message).toContain('fixing');
226
+ expect(violation.suggestion).toContain('fix');
227
+ });
228
+ it('should collect multiple violations from different rules', () => {
229
+ const longDescription = 'added ' + 'a'.repeat(80);
230
+ const full = `wip: ${longDescription}`;
231
+ const result = lintService_1.LintService.lint(makeMessage({
232
+ type: 'wip',
233
+ description: longDescription,
234
+ full,
235
+ }));
236
+ expect(result.valid).toBe(false);
237
+ // Should have subject-max-length, type-invalid, and imperative-mood violations
238
+ expect(result.violations.find(v => v.ruleId === 'subject-max-length')).toBeDefined();
239
+ expect(result.violations.find(v => v.ruleId === 'type-invalid')).toBeDefined();
240
+ expect(result.violations.find(v => v.ruleId === 'imperative-mood')).toBeDefined();
241
+ });
242
+ });
243
+ describe('shouldBlockCommit()', () => {
244
+ it('should block on error violation', () => {
245
+ const result = {
246
+ valid: false,
247
+ violations: [{
248
+ ruleId: 'subject-max-length',
249
+ ruleName: 'Subject Max Length',
250
+ message: 'Subject too long',
251
+ severity: 'error',
252
+ }],
253
+ };
254
+ expect(lintService_1.LintService.shouldBlockCommit(result)).toBe(true);
255
+ });
256
+ it('should not block on warning-only violations', () => {
257
+ const result = {
258
+ valid: false,
259
+ violations: [{
260
+ ruleId: 'imperative-mood',
261
+ ruleName: 'Imperative Mood',
262
+ message: 'Should use imperative mood',
263
+ severity: 'warning',
264
+ }],
265
+ };
266
+ expect(lintService_1.LintService.shouldBlockCommit(result)).toBe(false);
267
+ });
268
+ it('should respect blockOnError: false config', () => {
269
+ mockedConfigService.getConfig.mockReturnValue({
270
+ linting: {
271
+ enabled: true,
272
+ blockOnError: false,
273
+ },
274
+ });
275
+ const result = {
276
+ valid: false,
277
+ violations: [{
278
+ ruleId: 'subject-max-length',
279
+ ruleName: 'Subject Max Length',
280
+ message: 'Subject too long',
281
+ severity: 'error',
282
+ }],
283
+ };
284
+ expect(lintService_1.LintService.shouldBlockCommit(result)).toBe(false);
285
+ });
286
+ });
287
+ });
288
+ //# sourceMappingURL=lintService.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lintService.test.js","sourceRoot":"","sources":["../../src/services/lintService.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { ChangeAnalysis, CommitType, TicketInfo } from '../types';
2
+ export declare const COMMIT_EMOJIS: Record<CommitType, string>;
3
+ /**
4
+ * Generate commit body for larger changes
5
+ * Includes semantic role context when available
6
+ */
7
+ export declare function generateBody(analysis: ChangeAnalysis): string | undefined;
8
+ /**
9
+ * Apply a template to build the commit message subject line
10
+ */
11
+ export declare function applyTemplate(template: string, type: CommitType, scope: string | undefined, description: string, includeEmoji: boolean, isBreaking?: boolean): string;
12
+ /**
13
+ * Build full commit message string
14
+ */
15
+ export declare function buildFullMessage(type: CommitType, scope: string | undefined, description: string, body: string | undefined, includeEmoji: boolean, ticketInfo?: TicketInfo | null, isBreaking?: boolean, breakingReasons?: string[]): string;
16
+ //# sourceMappingURL=messageBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messageBuilder.d.ts","sourceRoot":"","sources":["../../src/services/messageBuilder.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EACd,UAAU,EACV,UAAU,EACX,MAAM,UAAU,CAAC;AAElB,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CASpD,CAAC;AAGF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS,CAiDzE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,OAAO,EACrB,UAAU,CAAC,EAAE,OAAO,GACnB,MAAM,CAqBR;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,YAAY,EAAE,OAAO,EACrB,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,EAC9B,UAAU,CAAC,EAAE,OAAO,EACpB,eAAe,CAAC,EAAE,MAAM,EAAE,GACzB,MAAM,CAuDR"}
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.COMMIT_EMOJIS = void 0;
4
+ exports.generateBody = generateBody;
5
+ exports.applyTemplate = applyTemplate;
6
+ exports.buildFullMessage = buildFullMessage;
7
+ const configService_1 = require("./configService");
8
+ exports.COMMIT_EMOJIS = {
9
+ feat: '\u2728',
10
+ fix: '\ud83d\udc1b',
11
+ docs: '\ud83d\udcda',
12
+ style: '\ud83d\udc84',
13
+ refactor: '\u267b\ufe0f',
14
+ test: '\ud83e\uddea',
15
+ chore: '\ud83d\udd27',
16
+ perf: '\u26a1',
17
+ };
18
+ /**
19
+ * Generate commit body for larger changes
20
+ * Includes semantic role context when available
21
+ */
22
+ function generateBody(analysis) {
23
+ const lines = [];
24
+ const semantic = analysis.semanticAnalysis;
25
+ // Include semantic context (WHY the change was made) for multi-role changes
26
+ if (semantic && semantic.hasMultipleRoles) {
27
+ lines.push('Changes:');
28
+ for (const roleChange of semantic.roleChanges.filter(r => r.significance > 15).slice(0, 4)) {
29
+ const elements = roleChange.affectedElements.length > 0
30
+ ? ` (${roleChange.affectedElements.slice(0, 2).join(', ')})`
31
+ : '';
32
+ lines.push(`- ${roleChange.summary}${elements}`);
33
+ }
34
+ lines.push('');
35
+ }
36
+ // Only add file details for truly large changes
37
+ if (!analysis.isLargeChange && lines.length === 0) {
38
+ return undefined;
39
+ }
40
+ // Add file change details for large changes
41
+ if (analysis.isLargeChange) {
42
+ if (lines.length > 0) {
43
+ lines.push('Files:');
44
+ }
45
+ if (analysis.fileChanges.added.length > 0) {
46
+ lines.push(`- Add ${analysis.fileChanges.added.join(', ')}`);
47
+ }
48
+ if (analysis.fileChanges.modified.length > 0) {
49
+ const files = analysis.fileChanges.modified.slice(0, 5);
50
+ const suffix = analysis.fileChanges.modified.length > 5
51
+ ? ` and ${analysis.fileChanges.modified.length - 5} more`
52
+ : '';
53
+ lines.push(`- Update ${files.join(', ')}${suffix}`);
54
+ }
55
+ if (analysis.fileChanges.deleted.length > 0) {
56
+ lines.push(`- Remove ${analysis.fileChanges.deleted.join(', ')}`);
57
+ }
58
+ if (analysis.fileChanges.renamed.length > 0) {
59
+ lines.push(`- Rename ${analysis.fileChanges.renamed.join(', ')}`);
60
+ }
61
+ }
62
+ return lines.length > 0 ? lines.join('\n') : undefined;
63
+ }
64
+ /**
65
+ * Apply a template to build the commit message subject line
66
+ */
67
+ function applyTemplate(template, type, scope, description, includeEmoji, isBreaking) {
68
+ const emoji = includeEmoji ? exports.COMMIT_EMOJIS[type] : '';
69
+ const breakingIndicator = isBreaking ? '!' : '';
70
+ let result = template
71
+ .replace('{emoji}', emoji)
72
+ .replace('{type}', type + breakingIndicator)
73
+ .replace('{description}', description);
74
+ // Handle scope - if no scope, use noScope template or remove scope placeholder
75
+ if (scope) {
76
+ result = result.replace('{scope}', scope);
77
+ }
78
+ else {
79
+ // Remove scope and parentheses if no scope
80
+ result = result.replace('({scope})', '').replace('{scope}', '');
81
+ }
82
+ // Clean up extra spaces
83
+ result = result.replace(/\s+/g, ' ').trim();
84
+ return result;
85
+ }
86
+ /**
87
+ * Build full commit message string
88
+ */
89
+ function buildFullMessage(type, scope, description, body, includeEmoji, ticketInfo, isBreaking, breakingReasons) {
90
+ const config = configService_1.ConfigService.getConfig();
91
+ const includeBreakingFooter = config.breakingChangeDetection?.includeFooter !== false;
92
+ const templates = config.templates;
93
+ let full = '';
94
+ // Use template if available
95
+ if (templates) {
96
+ const template = scope
97
+ ? (templates.default || '{emoji} {type}({scope}): {description}')
98
+ : (templates.noScope || '{emoji} {type}: {description}');
99
+ full = applyTemplate(template, type, scope, description, includeEmoji, isBreaking);
100
+ }
101
+ else {
102
+ // Fallback to original logic
103
+ if (includeEmoji) {
104
+ full += `${exports.COMMIT_EMOJIS[type]} `;
105
+ }
106
+ full += type;
107
+ if (scope) {
108
+ full += `(${scope})`;
109
+ }
110
+ // Add breaking change indicator
111
+ if (isBreaking) {
112
+ full += '!';
113
+ }
114
+ full += `: ${description}`;
115
+ }
116
+ if (body) {
117
+ full += `\n\n${body}`;
118
+ }
119
+ // Add BREAKING CHANGE footer if enabled and breaking
120
+ if (isBreaking && includeBreakingFooter && breakingReasons && breakingReasons.length > 0) {
121
+ full += '\n\nBREAKING CHANGE: ' + breakingReasons[0];
122
+ if (breakingReasons.length > 1) {
123
+ for (let i = 1; i < breakingReasons.length; i++) {
124
+ full += `\n- ${breakingReasons[i]}`;
125
+ }
126
+ }
127
+ }
128
+ // Add ticket reference as footer
129
+ if (ticketInfo) {
130
+ const prefix = ticketInfo.prefix || 'Refs:';
131
+ full += `\n\n${prefix} ${ticketInfo.id}`;
132
+ }
133
+ return full;
134
+ }
135
+ //# sourceMappingURL=messageBuilder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messageBuilder.js","sourceRoot":"","sources":["../../src/services/messageBuilder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { FileChange } from '../types';
2
+ /**
3
+ * Determine scope from file paths
4
+ */
5
+ export declare function determineScope(stagedFiles: FileChange[]): string | undefined;
6
+ //# sourceMappingURL=scopeDetector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scopeDetector.d.ts","sourceRoot":"","sources":["../../src/services/scopeDetector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,MAAM,GAAG,SAAS,CA+C5E"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.determineScope = determineScope;
4
+ const configService_1 = require("./configService");
5
+ /**
6
+ * Determine scope from file paths
7
+ */
8
+ function determineScope(stagedFiles) {
9
+ if (stagedFiles.length === 0)
10
+ return undefined;
11
+ const config = configService_1.ConfigService.getConfig();
12
+ const paths = stagedFiles.map((f) => f.path);
13
+ // Check config-based scope mappings first
14
+ if (config.scopes && config.scopes.length > 0) {
15
+ for (const mapping of config.scopes) {
16
+ const matchingFiles = paths.filter((p) => p.includes(mapping.pattern));
17
+ if (matchingFiles.length === paths.length) {
18
+ return mapping.scope;
19
+ }
20
+ }
21
+ // If most files match a pattern, use that scope
22
+ for (const mapping of config.scopes) {
23
+ const matchingFiles = paths.filter((p) => p.includes(mapping.pattern));
24
+ if (matchingFiles.length > paths.length / 2) {
25
+ return mapping.scope;
26
+ }
27
+ }
28
+ }
29
+ // Fallback to default heuristic
30
+ const firstPath = paths[0];
31
+ const parts = firstPath.split('/');
32
+ if (parts.length > 1) {
33
+ const potentialScope = parts[0];
34
+ // Common scope names to look for
35
+ const validScopes = [
36
+ 'api',
37
+ 'ui',
38
+ 'auth',
39
+ 'db',
40
+ 'core',
41
+ 'utils',
42
+ 'components',
43
+ 'services',
44
+ ];
45
+ if (validScopes.includes(potentialScope.toLowerCase())) {
46
+ return potentialScope;
47
+ }
48
+ }
49
+ return undefined;
50
+ }
51
+ //# sourceMappingURL=scopeDetector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scopeDetector.js","sourceRoot":"","sources":["../../src/services/scopeDetector.ts"],"names":[],"mappings":";;AAMA,wCA+CC;AApDD,mDAAgD;AAEhD;;GAEG;AACH,SAAgB,cAAc,CAAC,WAAyB;IACtD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAE/C,MAAM,MAAM,GAAG,6BAAa,CAAC,SAAS,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAE7C,0CAA0C;IAC1C,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YACpC,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;YACvE,IAAI,aAAa,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC;gBAC1C,OAAO,OAAO,CAAC,KAAK,CAAC;YACvB,CAAC;QACH,CAAC;QACD,gDAAgD;QAChD,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YACpC,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;YACvE,IAAI,aAAa,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5C,OAAO,OAAO,CAAC,KAAK,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IAED,gCAAgC;IAChC,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAEhC,iCAAiC;QACjC,MAAM,WAAW,GAAG;YAClB,KAAK;YACL,IAAI;YACJ,MAAM;YACN,IAAI;YACJ,MAAM;YACN,OAAO;YACP,YAAY;YACZ,UAAU;SACX,CAAC;QAEF,IAAI,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YACvD,OAAO,cAAc,CAAC;QACxB,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { ChangeRole, FileChange, SemanticAnalysis, SemanticIntent } from '../types';
2
+ export declare const ROLE_DESCRIPTIONS: Record<ChangeRole, string>;
3
+ export declare const INTENT_VERBS: Record<SemanticIntent, {
4
+ past: string;
5
+ present: string;
6
+ }>;
7
+ /**
8
+ * Perform semantic analysis on the diff to understand the nature of changes
9
+ * This provides intent-based understanding rather than line-count metrics
10
+ */
11
+ export declare function analyzeSemanticChanges(diff: string, stagedFiles: FileChange[]): SemanticAnalysis;
12
+ /**
13
+ * Extract affected element names (components, functions, etc.) from the diff
14
+ */
15
+ export declare function extractAffectedElements(diff: string): string[];
16
+ /**
17
+ * Extract function/class/method names from git diff by analyzing both hunk headers
18
+ * and the actual context lines around changes.
19
+ *
20
+ * This method prioritizes function declarations found in context lines near the
21
+ * actual changes, which is more accurate than just using hunk headers (which may
22
+ * show preceding functions instead of the one being modified).
23
+ */
24
+ export declare function extractHunkContext(diff: string): string[];
25
+ //# sourceMappingURL=semanticAnalyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semanticAnalyzer.d.ts","sourceRoot":"","sources":["../../src/services/semanticAnalyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,UAAU,EAEV,gBAAgB,EAChB,cAAc,EACf,MAAM,UAAU,CAAC;AAoKlB,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CASxD,CAAC;AAGF,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAQlF,CAAC;AAEF;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,UAAU,EAAE,GACxB,gBAAgB,CA6BlB;AAuND;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAqE9D;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAiDzD"}