MCPcopy Create free account
hub / github.com/QodeXcli/QodeX / classifyCommit

Function classifyCommit

src/tools/git/classify-commits.ts:32–93  ·  view source on GitHub ↗
(c: RawCommit)

Source from the content-addressed store, hash-verified

30const CONV_RE = /^(?<type>[a-z]+)(?:\((?<scope>[^)]+)\))?(?<bang>!)?:\s*(?<desc>.+)$/i;
31
32export function classifyCommit(c: RawCommit): ClassifiedCommit {
33 const m = CONV_RE.exec(c.subject.trim());
34 const bodyLower = c.body.toLowerCase();
35 const hasBreakingTrailer = /\bbreaking[- ]change\b/i.test(c.body);
36
37 if (m?.groups) {
38 const type = m.groups.type!.toLowerCase();
39 const scope = m.groups.scope;
40 const bang = m.groups.bang === '!';
41 if (bang || hasBreakingTrailer) {
42 return { ...c, category: 'breaking', scope, reason: `conventional ${type}!${scope ? `(${scope})` : ''}` };
43 }
44 switch (type) {
45 case 'feat':
46 case 'feature':
47 return { ...c, category: 'features', scope, reason: `conventional feat` };
48 case 'fix':
49 case 'bugfix':
50 case 'hotfix':
51 return { ...c, category: 'fixes', scope, reason: `conventional fix` };
52 case 'perf':
53 return { ...c, category: 'perf', scope, reason: `conventional perf` };
54 case 'docs':
55 case 'doc':
56 return { ...c, category: 'docs', scope, reason: `conventional docs` };
57 case 'refactor':
58 case 'chore':
59 case 'test':
60 case 'tests':
61 case 'ci':
62 case 'build':
63 case 'style':
64 return { ...c, category: 'internal', scope, reason: `conventional ${type}` };
65 }
66 }
67
68 if (hasBreakingTrailer) {
69 return { ...c, category: 'breaking', reason: 'BREAKING CHANGE trailer in body' };
70 }
71
72 // Free-form heuristic fallback. Order matters — earlier wins.
73 const subj = c.subject.toLowerCase();
74 if (/\b(add|new|introduce|implement|support)\b/.test(subj)) {
75 return { ...c, category: 'features', reason: 'subject suggests addition' };
76 }
77 if (/\b(fix|resolve|correct|patch|repair|prevent)\b/.test(subj)) {
78 return { ...c, category: 'fixes', reason: 'subject suggests fix' };
79 }
80 if (/\b(refactor|cleanup|rename|reorganize|move|extract)\b/.test(subj)) {
81 return { ...c, category: 'internal', reason: 'subject suggests refactor' };
82 }
83 if (/\b(doc|docs|readme|comment)\b/.test(subj)) {
84 return { ...c, category: 'docs', reason: 'subject suggests docs' };
85 }
86 if (/\b(perf|performance|optimi[sz]e|speed)\b/.test(subj)) {
87 return { ...c, category: 'perf', reason: 'subject suggests perf' };
88 }
89 if (bodyLower.includes('breaking')) {

Callers 2

bucketFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected