git-smart-flow 0.3.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 (190) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/LICENSE +21 -0
  3. package/README.md +130 -0
  4. package/bin/git-smart-flow.js +2 -0
  5. package/bin/gsf.js +2 -0
  6. package/bin/gsfc.js +3 -0
  7. package/bin/gsfm.js +3 -0
  8. package/bin/gsfp.js +3 -0
  9. package/bin/gsfpr.js +3 -0
  10. package/dist/cli.d.ts +2 -0
  11. package/dist/cli.js +214 -0
  12. package/dist/cli.js.map +1 -0
  13. package/dist/commands/aliases.d.ts +2 -0
  14. package/dist/commands/aliases.js +37 -0
  15. package/dist/commands/aliases.js.map +1 -0
  16. package/dist/commands/branch.d.ts +2 -0
  17. package/dist/commands/branch.js +414 -0
  18. package/dist/commands/branch.js.map +1 -0
  19. package/dist/commands/commit-message.d.ts +7 -0
  20. package/dist/commands/commit-message.js +95 -0
  21. package/dist/commands/commit-message.js.map +1 -0
  22. package/dist/commands/commit.d.ts +3 -0
  23. package/dist/commands/commit.js +597 -0
  24. package/dist/commands/commit.js.map +1 -0
  25. package/dist/commands/config.d.ts +2 -0
  26. package/dist/commands/config.js +88 -0
  27. package/dist/commands/config.js.map +1 -0
  28. package/dist/commands/doctor.d.ts +2 -0
  29. package/dist/commands/doctor.js +246 -0
  30. package/dist/commands/doctor.js.map +1 -0
  31. package/dist/commands/info.d.ts +2 -0
  32. package/dist/commands/info.js +155 -0
  33. package/dist/commands/info.js.map +1 -0
  34. package/dist/commands/install-hooks.d.ts +2 -0
  35. package/dist/commands/install-hooks.js +66 -0
  36. package/dist/commands/install-hooks.js.map +1 -0
  37. package/dist/commands/log.d.ts +2 -0
  38. package/dist/commands/log.js +101 -0
  39. package/dist/commands/log.js.map +1 -0
  40. package/dist/commands/menu.d.ts +2 -0
  41. package/dist/commands/menu.js +297 -0
  42. package/dist/commands/menu.js.map +1 -0
  43. package/dist/commands/merge.d.ts +6 -0
  44. package/dist/commands/merge.js +128 -0
  45. package/dist/commands/merge.js.map +1 -0
  46. package/dist/commands/pr.d.ts +2 -0
  47. package/dist/commands/pr.js +731 -0
  48. package/dist/commands/pr.js.map +1 -0
  49. package/dist/commands/push.d.ts +7 -0
  50. package/dist/commands/push.js +225 -0
  51. package/dist/commands/push.js.map +1 -0
  52. package/dist/commands/reflog.d.ts +2 -0
  53. package/dist/commands/reflog.js +162 -0
  54. package/dist/commands/reflog.js.map +1 -0
  55. package/dist/commands/repo-init.d.ts +2 -0
  56. package/dist/commands/repo-init.js +466 -0
  57. package/dist/commands/repo-init.js.map +1 -0
  58. package/dist/commands/revert.d.ts +7 -0
  59. package/dist/commands/revert.js +694 -0
  60. package/dist/commands/revert.js.map +1 -0
  61. package/dist/commands/setup.d.ts +2 -0
  62. package/dist/commands/setup.js +86 -0
  63. package/dist/commands/setup.js.map +1 -0
  64. package/dist/commands/stash.d.ts +2 -0
  65. package/dist/commands/stash.js +130 -0
  66. package/dist/commands/stash.js.map +1 -0
  67. package/dist/commands/sync.d.ts +2 -0
  68. package/dist/commands/sync.js +335 -0
  69. package/dist/commands/sync.js.map +1 -0
  70. package/dist/commands/tag.d.ts +2 -0
  71. package/dist/commands/tag.js +163 -0
  72. package/dist/commands/tag.js.map +1 -0
  73. package/dist/commands/validate.d.ts +2 -0
  74. package/dist/commands/validate.js +203 -0
  75. package/dist/commands/validate.js.map +1 -0
  76. package/dist/config/config.d.ts +10 -0
  77. package/dist/config/config.js +126 -0
  78. package/dist/config/config.js.map +1 -0
  79. package/dist/git/ai-context-builder.d.ts +11 -0
  80. package/dist/git/ai-context-builder.js +112 -0
  81. package/dist/git/ai-context-builder.js.map +1 -0
  82. package/dist/git/convention-detector.d.ts +3 -0
  83. package/dist/git/convention-detector.js +211 -0
  84. package/dist/git/convention-detector.js.map +1 -0
  85. package/dist/git/ensure-repo.d.ts +7 -0
  86. package/dist/git/ensure-repo.js +141 -0
  87. package/dist/git/ensure-repo.js.map +1 -0
  88. package/dist/git/gitignore.d.ts +8 -0
  89. package/dist/git/gitignore.js +261 -0
  90. package/dist/git/gitignore.js.map +1 -0
  91. package/dist/git/remote-setup.d.ts +2 -0
  92. package/dist/git/remote-setup.js +129 -0
  93. package/dist/git/remote-setup.js.map +1 -0
  94. package/dist/git/repo.d.ts +73 -0
  95. package/dist/git/repo.js +308 -0
  96. package/dist/git/repo.js.map +1 -0
  97. package/dist/git/validate.d.ts +36 -0
  98. package/dist/git/validate.js +113 -0
  99. package/dist/git/validate.js.map +1 -0
  100. package/dist/providers/base.provider.d.ts +10 -0
  101. package/dist/providers/base.provider.js +40 -0
  102. package/dist/providers/base.provider.js.map +1 -0
  103. package/dist/providers/claude.provider.d.ts +14 -0
  104. package/dist/providers/claude.provider.js +85 -0
  105. package/dist/providers/claude.provider.js.map +1 -0
  106. package/dist/providers/copilot.provider.d.ts +12 -0
  107. package/dist/providers/copilot.provider.js +88 -0
  108. package/dist/providers/copilot.provider.js.map +1 -0
  109. package/dist/providers/heuristic.provider.d.ts +9 -0
  110. package/dist/providers/heuristic.provider.js +163 -0
  111. package/dist/providers/heuristic.provider.js.map +1 -0
  112. package/dist/providers/ollama.provider.d.ts +14 -0
  113. package/dist/providers/ollama.provider.js +83 -0
  114. package/dist/providers/ollama.provider.js.map +1 -0
  115. package/dist/providers/openai.provider.d.ts +14 -0
  116. package/dist/providers/openai.provider.js +84 -0
  117. package/dist/providers/openai.provider.js.map +1 -0
  118. package/dist/providers/provider.factory.d.ts +5 -0
  119. package/dist/providers/provider.factory.js +51 -0
  120. package/dist/providers/provider.factory.js.map +1 -0
  121. package/dist/security/scanner.d.ts +13 -0
  122. package/dist/security/scanner.js +138 -0
  123. package/dist/security/scanner.js.map +1 -0
  124. package/dist/types/index.d.ts +146 -0
  125. package/dist/types/index.js +2 -0
  126. package/dist/types/index.js.map +1 -0
  127. package/dist/ux/components/BranchTree.d.ts +8 -0
  128. package/dist/ux/components/BranchTree.js +57 -0
  129. package/dist/ux/components/BranchTree.js.map +1 -0
  130. package/dist/ux/components/CommitProposal.d.ts +13 -0
  131. package/dist/ux/components/CommitProposal.js +127 -0
  132. package/dist/ux/components/CommitProposal.js.map +1 -0
  133. package/dist/ux/components/DiagnosticReport.d.ts +18 -0
  134. package/dist/ux/components/DiagnosticReport.js +19 -0
  135. package/dist/ux/components/DiagnosticReport.js.map +1 -0
  136. package/dist/ux/components/ErrorBox.d.ts +7 -0
  137. package/dist/ux/components/ErrorBox.js +9 -0
  138. package/dist/ux/components/ErrorBox.js.map +1 -0
  139. package/dist/ux/components/FileSelector.d.ts +14 -0
  140. package/dist/ux/components/FileSelector.js +87 -0
  141. package/dist/ux/components/FileSelector.js.map +1 -0
  142. package/dist/ux/components/Logo.d.ts +6 -0
  143. package/dist/ux/components/Logo.js +21 -0
  144. package/dist/ux/components/Logo.js.map +1 -0
  145. package/dist/ux/components/RepoContext.d.ts +8 -0
  146. package/dist/ux/components/RepoContext.js +17 -0
  147. package/dist/ux/components/RepoContext.js.map +1 -0
  148. package/dist/ux/components/SecurityAlert.d.ts +9 -0
  149. package/dist/ux/components/SecurityAlert.js +16 -0
  150. package/dist/ux/components/SecurityAlert.js.map +1 -0
  151. package/dist/ux/components/StatusDashboard.d.ts +14 -0
  152. package/dist/ux/components/StatusDashboard.js +36 -0
  153. package/dist/ux/components/StatusDashboard.js.map +1 -0
  154. package/dist/ux/components/SuccessBox.d.ts +7 -0
  155. package/dist/ux/components/SuccessBox.js +9 -0
  156. package/dist/ux/components/SuccessBox.js.map +1 -0
  157. package/dist/ux/components/ValidationReport.d.ts +16 -0
  158. package/dist/ux/components/ValidationReport.js +19 -0
  159. package/dist/ux/components/ValidationReport.js.map +1 -0
  160. package/dist/ux/components/WarningBox.d.ts +7 -0
  161. package/dist/ux/components/WarningBox.js +9 -0
  162. package/dist/ux/components/WarningBox.js.map +1 -0
  163. package/dist/ux/display.d.ts +21 -0
  164. package/dist/ux/display.js +96 -0
  165. package/dist/ux/display.js.map +1 -0
  166. package/dist/ux/hooks/useActivation.d.ts +8 -0
  167. package/dist/ux/hooks/useActivation.js +16 -0
  168. package/dist/ux/hooks/useActivation.js.map +1 -0
  169. package/dist/ux/hooks/useSpinner.d.ts +2 -0
  170. package/dist/ux/hooks/useSpinner.js +13 -0
  171. package/dist/ux/hooks/useSpinner.js.map +1 -0
  172. package/dist/ux/menu.d.ts +7 -0
  173. package/dist/ux/menu.js +56 -0
  174. package/dist/ux/menu.js.map +1 -0
  175. package/dist/ux/prompt.d.ts +7 -0
  176. package/dist/ux/prompt.js +361 -0
  177. package/dist/ux/prompt.js.map +1 -0
  178. package/dist/ux/renderer.d.ts +9 -0
  179. package/dist/ux/renderer.js +45 -0
  180. package/dist/ux/renderer.js.map +1 -0
  181. package/dist/ux/spinner.d.ts +6 -0
  182. package/dist/ux/spinner.js +42 -0
  183. package/dist/ux/spinner.js.map +1 -0
  184. package/dist/ux/statusbar.d.ts +2 -0
  185. package/dist/ux/statusbar.js +44 -0
  186. package/dist/ux/statusbar.js.map +1 -0
  187. package/dist/ux/theme.d.ts +37 -0
  188. package/dist/ux/theme.js +55 -0
  189. package/dist/ux/theme.js.map +1 -0
  190. package/package.json +125 -0
@@ -0,0 +1,112 @@
1
+ import { basename, extname } from 'path';
2
+ export function buildAIContext(params) {
3
+ const { repoName, branch, ticket, convention, stagedFiles, diff, allowRawDiff } = params;
4
+ const changedFiles = stagedFiles.map((f) => ({ path: f.path, status: f.status }));
5
+ const localSummary = buildLocalSummary(stagedFiles);
6
+ const sanitizedFragments = allowRawDiff && diff
7
+ ? buildRawFragments(stagedFiles, diff)
8
+ : buildHeuristicFragments(stagedFiles);
9
+ return {
10
+ repository: repoName,
11
+ branch,
12
+ ticket,
13
+ detectedCommitConvention: convention,
14
+ changedFiles,
15
+ localSummary,
16
+ sanitizedFragments,
17
+ };
18
+ }
19
+ function buildLocalSummary(files) {
20
+ const summary = [];
21
+ const byStatus = groupByStatus(files);
22
+ if (byStatus['added']?.length)
23
+ summary.push(`Added: ${byStatus['added'].map((f) => f.path).join(', ')}`);
24
+ if (byStatus['modified']?.length)
25
+ summary.push(`Modified: ${byStatus['modified'].map((f) => f.path).join(', ')}`);
26
+ if (byStatus['deleted']?.length)
27
+ summary.push(`Deleted: ${byStatus['deleted'].map((f) => f.path).join(', ')}`);
28
+ if (byStatus['renamed']?.length)
29
+ summary.push(`Renamed: ${byStatus['renamed'].map((f) => f.path).join(', ')}`);
30
+ return summary;
31
+ }
32
+ function buildHeuristicFragments(files) {
33
+ return files.map((file) => ({
34
+ file: file.path,
35
+ summary: heuristicSummary(file),
36
+ }));
37
+ }
38
+ function buildRawFragments(files, diff) {
39
+ return files.map((file) => {
40
+ const fileDiff = extractFileDiff(diff, file.path);
41
+ return {
42
+ file: file.path,
43
+ summary: fileDiff || heuristicSummary(file),
44
+ };
45
+ });
46
+ }
47
+ function heuristicSummary(file) {
48
+ const path = file.path;
49
+ const ext = extname(path).slice(1);
50
+ const name = basename(path, extname(path));
51
+ const dirHints = {
52
+ test: 'test file',
53
+ tests: 'test file',
54
+ __tests__: 'test file',
55
+ spec: 'test file',
56
+ docs: 'documentation',
57
+ doc: 'documentation',
58
+ ci: 'CI configuration',
59
+ '.github': 'GitHub configuration',
60
+ '.husky': 'Git hooks',
61
+ scripts: 'build/release script',
62
+ migrations: 'database migration',
63
+ config: 'configuration',
64
+ types: 'type definitions',
65
+ interfaces: 'interface definitions',
66
+ models: 'data model',
67
+ controllers: 'controller',
68
+ routes: 'route definition',
69
+ services: 'service module',
70
+ utils: 'utility function',
71
+ helpers: 'helper function',
72
+ };
73
+ const parts = path.split('/');
74
+ for (const part of parts) {
75
+ const hint = dirHints[part.toLowerCase()];
76
+ if (hint)
77
+ return `${file.status} ${hint}: ${name}.${ext}`;
78
+ }
79
+ const extHints = {
80
+ md: 'documentation file',
81
+ yml: 'configuration file',
82
+ yaml: 'configuration file',
83
+ json: 'configuration/data file',
84
+ ts: 'TypeScript module',
85
+ js: 'JavaScript module',
86
+ tsx: 'React component',
87
+ jsx: 'React component',
88
+ css: 'stylesheet',
89
+ scss: 'stylesheet',
90
+ sql: 'database script',
91
+ sh: 'shell script',
92
+ ps1: 'PowerShell script',
93
+ };
94
+ const extHint = extHints[ext] ?? 'file';
95
+ return `${file.status} ${extHint}: ${name}.${ext}`;
96
+ }
97
+ function extractFileDiff(diff, filePath) {
98
+ const lines = diff.split('\n');
99
+ const startIdx = lines.findIndex((l) => l.startsWith('diff --git') && l.includes(filePath));
100
+ if (startIdx === -1)
101
+ return '';
102
+ const endIdx = lines.findIndex((l, i) => i > startIdx && l.startsWith('diff --git'));
103
+ const chunk = endIdx === -1 ? lines.slice(startIdx) : lines.slice(startIdx, endIdx);
104
+ return chunk.slice(0, 50).join('\n');
105
+ }
106
+ function groupByStatus(files) {
107
+ return files.reduce((acc, file) => {
108
+ (acc[file.status] = acc[file.status] ?? []).push(file);
109
+ return acc;
110
+ }, {});
111
+ }
112
+ //# sourceMappingURL=ai-context-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-context-builder.js","sourceRoot":"","sources":["../../src/git/ai-context-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAGzC,MAAM,UAAU,cAAc,CAAC,MAQ9B;IACC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC;IAEzF,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAClF,MAAM,YAAY,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACpD,MAAM,kBAAkB,GACtB,YAAY,IAAI,IAAI;QAClB,CAAC,CAAC,iBAAiB,CAAC,WAAW,EAAE,IAAI,CAAC;QACtC,CAAC,CAAC,uBAAuB,CAAC,WAAW,CAAC,CAAC;IAE3C,OAAO;QACL,UAAU,EAAE,QAAQ;QACpB,MAAM;QACN,MAAM;QACN,wBAAwB,EAAE,UAAU;QACpC,YAAY;QACZ,YAAY;QACZ,kBAAkB;KACnB,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAmB;IAC5C,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAEtC,IAAI,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM;QAC3B,OAAO,CAAC,IAAI,CAAC,UAAU,QAAQ,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5E,IAAI,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM;QAC9B,OAAO,CAAC,IAAI,CAAC,aAAa,QAAQ,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClF,IAAI,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM;QAC7B,OAAO,CAAC,IAAI,CAAC,YAAY,QAAQ,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChF,IAAI,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM;QAC7B,OAAO,CAAC,IAAI,CAAC,YAAY,QAAQ,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEhF,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,uBAAuB,CAAC,KAAmB;IAClD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC1B,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO,EAAE,gBAAgB,CAAC,IAAI,CAAC;KAChC,CAAC,CAAC,CAAC;AACN,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAmB,EAAE,IAAY;IAC1D,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACxB,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,QAAQ,IAAI,gBAAgB,CAAC,IAAI,CAAC;SAC5C,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAgB;IACxC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IACvB,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAE3C,MAAM,QAAQ,GAA2B;QACvC,IAAI,EAAE,WAAW;QACjB,KAAK,EAAE,WAAW;QAClB,SAAS,EAAE,WAAW;QACtB,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,eAAe;QACrB,GAAG,EAAE,eAAe;QACpB,EAAE,EAAE,kBAAkB;QACtB,SAAS,EAAE,sBAAsB;QACjC,QAAQ,EAAE,WAAW;QACrB,OAAO,EAAE,sBAAsB;QAC/B,UAAU,EAAE,oBAAoB;QAChC,MAAM,EAAE,eAAe;QACvB,KAAK,EAAE,kBAAkB;QACzB,UAAU,EAAE,uBAAuB;QACnC,MAAM,EAAE,YAAY;QACpB,WAAW,EAAE,YAAY;QACzB,MAAM,EAAE,kBAAkB;QAC1B,QAAQ,EAAE,gBAAgB;QAC1B,KAAK,EAAE,kBAAkB;QACzB,OAAO,EAAE,iBAAiB;KAC3B,CAAC;IAEF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QAC1C,IAAI,IAAI;YAAE,OAAO,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,KAAK,IAAI,IAAI,GAAG,EAAE,CAAC;IAC5D,CAAC;IAED,MAAM,QAAQ,GAA2B;QACvC,EAAE,EAAE,oBAAoB;QACxB,GAAG,EAAE,oBAAoB;QACzB,IAAI,EAAE,oBAAoB;QAC1B,IAAI,EAAE,yBAAyB;QAC/B,EAAE,EAAE,mBAAmB;QACvB,EAAE,EAAE,mBAAmB;QACvB,GAAG,EAAE,iBAAiB;QACtB,GAAG,EAAE,iBAAiB;QACtB,GAAG,EAAE,YAAY;QACjB,IAAI,EAAE,YAAY;QAClB,GAAG,EAAE,iBAAiB;QACtB,EAAE,EAAE,cAAc;QAClB,GAAG,EAAE,mBAAmB;KACzB,CAAC;IAEF,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC;IACxC,OAAO,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,KAAK,IAAI,IAAI,GAAG,EAAE,CAAC;AACrD,CAAC;AAED,SAAS,eAAe,CAAC,IAAY,EAAE,QAAgB;IACrD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC5F,IAAI,QAAQ,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,QAAQ,IAAI,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;IACrF,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACpF,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,aAAa,CAAC,KAAmB;IACxC,OAAO,KAAK,CAAC,MAAM,CACjB,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;QACZ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,OAAO,GAAG,CAAC;IACb,CAAC,EACD,EAAkC,CACnC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { CommitConvention } from '../types/index.js';
2
+ export declare function detectConvention(cwd?: string): Promise<CommitConvention>;
3
+ //# sourceMappingURL=convention-detector.d.ts.map
@@ -0,0 +1,211 @@
1
+ import { execSync, spawnSync } from 'child_process';
2
+ import { existsSync, readdirSync, readFileSync } from 'fs';
3
+ import { join } from 'path';
4
+ const CONVENTIONAL_TYPES = [
5
+ 'feat',
6
+ 'fix',
7
+ 'docs',
8
+ 'style',
9
+ 'refactor',
10
+ 'perf',
11
+ 'test',
12
+ 'build',
13
+ 'ci',
14
+ 'chore',
15
+ 'revert',
16
+ ];
17
+ const DEFAULT_CONVENTION = {
18
+ type: 'conventional',
19
+ allowedTypes: CONVENTIONAL_TYPES,
20
+ allowedScopes: undefined,
21
+ scopeRequired: false,
22
+ maxHeaderLength: 100,
23
+ requireTicket: 'auto',
24
+ ticketPattern: '[A-Z][A-Z0-9]+-[0-9]+',
25
+ subjectCase: 'lower-case',
26
+ hasCommitlint: false,
27
+ hasHusky: false,
28
+ };
29
+ // eslint-disable-next-line @typescript-eslint/require-await
30
+ export async function detectConvention(cwd = process.cwd()) {
31
+ const convention = { ...DEFAULT_CONVENTION };
32
+ const commitlintResult = readCommitlint(cwd);
33
+ if (commitlintResult) {
34
+ Object.assign(convention, commitlintResult);
35
+ convention.hasCommitlint = true;
36
+ }
37
+ convention.hasHusky = detectHusky(cwd);
38
+ const monorepoScopes = detectMonorepoScopes(cwd);
39
+ if (monorepoScopes.length > 0) {
40
+ convention.allowedScopes = [...(convention.allowedScopes ?? []), ...monorepoScopes];
41
+ }
42
+ if (!commitlintResult) {
43
+ const historyConvention = inferFromHistory(cwd);
44
+ if (historyConvention) {
45
+ convention.type = historyConvention;
46
+ }
47
+ }
48
+ return convention;
49
+ }
50
+ function readCommitlint(cwd) {
51
+ const candidates = [
52
+ 'commitlint.config.js',
53
+ 'commitlint.config.cjs',
54
+ 'commitlint.config.mjs',
55
+ '.commitlintrc',
56
+ '.commitlintrc.json',
57
+ '.commitlintrc.yaml',
58
+ '.commitlintrc.yml',
59
+ ];
60
+ for (const candidate of candidates) {
61
+ const fullPath = join(cwd, candidate);
62
+ if (!existsSync(fullPath))
63
+ continue;
64
+ try {
65
+ if (candidate.endsWith('.json') || candidate === '.commitlintrc') {
66
+ const raw = readFileSync(fullPath, 'utf-8');
67
+ return parseCommitlintJson(JSON.parse(raw));
68
+ }
69
+ if (candidate.endsWith('.yaml') || candidate.endsWith('.yml')) {
70
+ const raw = readFileSync(fullPath, 'utf-8');
71
+ return parseCommitlintYaml(raw);
72
+ }
73
+ }
74
+ catch {
75
+ // skip unparseable files
76
+ }
77
+ }
78
+ const pkgPath = join(cwd, 'package.json');
79
+ if (existsSync(pkgPath)) {
80
+ try {
81
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
82
+ if (pkg.commitlint)
83
+ return parseCommitlintJson(pkg.commitlint);
84
+ }
85
+ catch {
86
+ // skip
87
+ }
88
+ }
89
+ return null;
90
+ }
91
+ function parseCommitlintJson(config) {
92
+ const result = {};
93
+ const rules = (config.rules ?? {});
94
+ if (rules['type-enum']) {
95
+ const typeRule = rules['type-enum'];
96
+ if (Array.isArray(typeRule) && typeRule.length >= 3 && Array.isArray(typeRule[2])) {
97
+ result.allowedTypes = typeRule[2];
98
+ }
99
+ }
100
+ if (rules['scope-enum']) {
101
+ const scopeRule = rules['scope-enum'];
102
+ if (Array.isArray(scopeRule) && scopeRule.length >= 3 && Array.isArray(scopeRule[2])) {
103
+ result.allowedScopes = scopeRule[2];
104
+ }
105
+ }
106
+ if (rules['scope-empty']) {
107
+ const scopeEmptyRule = rules['scope-empty'];
108
+ if (Array.isArray(scopeEmptyRule) &&
109
+ scopeEmptyRule[0] === 2 &&
110
+ scopeEmptyRule[1] === 'always') {
111
+ result.scopeRequired = true;
112
+ }
113
+ }
114
+ if (rules['header-max-length']) {
115
+ const headerRule = rules['header-max-length'];
116
+ if (Array.isArray(headerRule) && typeof headerRule[2] === 'number') {
117
+ result.maxHeaderLength = headerRule[2];
118
+ }
119
+ }
120
+ if (rules['subject-case']) {
121
+ const caseRule = rules['subject-case'];
122
+ if (Array.isArray(caseRule) && typeof caseRule[2] === 'string') {
123
+ result.subjectCase = caseRule[2];
124
+ }
125
+ }
126
+ const preset = (config.extends ?? '');
127
+ const presetStr = Array.isArray(preset) ? preset.join(',') : preset;
128
+ if (presetStr.includes('conventional') || presetStr.includes('angular')) {
129
+ result.type = 'conventional';
130
+ if (!result.allowedTypes)
131
+ result.allowedTypes = CONVENTIONAL_TYPES;
132
+ }
133
+ return result;
134
+ }
135
+ function parseCommitlintYaml(raw) {
136
+ // Minimal YAML parser for the rules we care about — avoids adding js-yaml as a required dep here
137
+ const result = {};
138
+ if (raw.includes('conventional') || raw.includes('angular')) {
139
+ result.type = 'conventional';
140
+ result.allowedTypes = CONVENTIONAL_TYPES;
141
+ }
142
+ const headerMatch = raw.match(/header-max-length[^:]*:[^[]*\[\s*\d+,\s*[^,]+,\s*(\d+)/);
143
+ if (headerMatch)
144
+ result.maxHeaderLength = parseInt(headerMatch[1] ?? '0', 10);
145
+ return result;
146
+ }
147
+ function detectHusky(cwd) {
148
+ return (existsSync(join(cwd, '.husky')) ||
149
+ existsSync(join(cwd, '.husky/commit-msg')) ||
150
+ existsSync(join(cwd, '.husky/pre-commit')));
151
+ }
152
+ function detectMonorepoScopes(cwd) {
153
+ const scopes = [];
154
+ // nx.json
155
+ if (existsSync(join(cwd, 'nx.json'))) {
156
+ try {
157
+ const output = execSync('ls packages/ 2>/dev/null || ls apps/ 2>/dev/null || true', {
158
+ cwd,
159
+ encoding: 'utf-8',
160
+ });
161
+ scopes.push(...output.split('\n').filter(Boolean));
162
+ }
163
+ catch {
164
+ /* */
165
+ }
166
+ }
167
+ // package.json workspaces
168
+ const pkgPath = join(cwd, 'package.json');
169
+ if (existsSync(pkgPath)) {
170
+ try {
171
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
172
+ if (pkg.workspaces) {
173
+ const ws = Array.isArray(pkg.workspaces) ? pkg.workspaces : (pkg.workspaces.packages ?? []);
174
+ for (const pattern of ws) {
175
+ const dir = pattern.replace(/\/\*$/, '').replace(/\*$/, '');
176
+ const dirPath = join(cwd, dir);
177
+ if (existsSync(dirPath)) {
178
+ try {
179
+ const entries = readdirSync(dirPath);
180
+ scopes.push(...entries.filter((e) => !e.startsWith('.')));
181
+ }
182
+ catch {
183
+ /* */
184
+ }
185
+ }
186
+ }
187
+ }
188
+ }
189
+ catch {
190
+ /* */
191
+ }
192
+ }
193
+ return [...new Set(scopes)];
194
+ }
195
+ function inferFromHistory(cwd) {
196
+ try {
197
+ const result = spawnSync('git', ['log', '--oneline', '-20'], { cwd, encoding: 'utf-8' });
198
+ if (result.status !== 0)
199
+ return null;
200
+ const lines = result.stdout.split('\n').filter(Boolean);
201
+ const conventionalPattern = /^[a-f0-9]+ (feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?!?:/;
202
+ const matches = lines.filter((l) => conventionalPattern.test(l));
203
+ if (matches.length / lines.length >= 0.5)
204
+ return 'conventional';
205
+ }
206
+ catch {
207
+ /* */
208
+ }
209
+ return null;
210
+ }
211
+ //# sourceMappingURL=convention-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convention-detector.js","sourceRoot":"","sources":["../../src/git/convention-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Ensures the cwd is a Git repository.
3
+ * If not, runs the full interactive onboarding wizard and returns true when ready.
4
+ * Returns false if the user declined to initialize.
5
+ */
6
+ export declare function ensureGitRepo(cwd?: string): Promise<boolean>;
7
+ //# sourceMappingURL=ensure-repo.d.ts.map
@@ -0,0 +1,141 @@
1
+ import { basename } from 'path';
2
+ import { getGitUserConfig, initRepo, isGitRepo, setDefaultBranch, setGitUserConfig, } from './repo.js';
3
+ import { detectProjectType, getTemplate, hasGitignore, PROJECT_TYPE_LABELS, readGitignore, writeGitignore, } from './gitignore.js';
4
+ import { runRemoteSetup } from './remote-setup.js';
5
+ import { blank, divider, info, section, success, warning } from '../ux/display.js';
6
+ import { confirmPrompt, inputPrompt, selectPrompt } from '../ux/prompt.js';
7
+ /**
8
+ * Ensures the cwd is a Git repository.
9
+ * If not, runs the full interactive onboarding wizard and returns true when ready.
10
+ * Returns false if the user declined to initialize.
11
+ */
12
+ export async function ensureGitRepo(cwd = process.cwd()) {
13
+ if (isGitRepo(cwd))
14
+ return true;
15
+ const dirName = basename(cwd);
16
+ warning(`"${dirName}" is not a Git repository.`);
17
+ blank();
18
+ const init = await confirmPrompt('Initialize a Git repository here?', true);
19
+ if (!init) {
20
+ info('No Git repository initialized. Exiting.');
21
+ return false;
22
+ }
23
+ initRepo(cwd);
24
+ success(`Initialized empty Git repository in ${cwd}/.git/`);
25
+ blank();
26
+ await wizardDefaultBranch(cwd);
27
+ await wizardGitIdentity(cwd);
28
+ await wizardGitignore(cwd);
29
+ await runRemoteSetup(cwd);
30
+ blank();
31
+ divider();
32
+ success('Repository is ready. You can now stage files and make your first commit.');
33
+ divider();
34
+ blank();
35
+ return true;
36
+ }
37
+ // ── Step 1: Default branch name ────────────────────────────────────────────
38
+ async function wizardDefaultBranch(cwd) {
39
+ section('Default Branch Name');
40
+ const choice = await selectPrompt('Choose the default branch name:', [
41
+ 'main (recommended)',
42
+ 'master',
43
+ 'develop',
44
+ 'Custom…',
45
+ ]);
46
+ let branchName = 'main';
47
+ if (choice.startsWith('master'))
48
+ branchName = 'master';
49
+ else if (choice.startsWith('develop'))
50
+ branchName = 'develop';
51
+ else if (choice.startsWith('Custom')) {
52
+ branchName = await inputPrompt('Branch name', 'main');
53
+ if (!branchName.trim())
54
+ branchName = 'main';
55
+ }
56
+ setDefaultBranch(branchName.trim(), cwd);
57
+ success(`Default branch set to "${branchName.trim()}".`);
58
+ blank();
59
+ }
60
+ // ── Step 2: Git identity ────────────────────────────────────────────────────
61
+ async function wizardGitIdentity(cwd) {
62
+ const local = getGitUserConfig(cwd);
63
+ if (local.name && local.email)
64
+ return; // already configured locally
65
+ section('Git Identity');
66
+ info('Git needs a name and email to create commits.');
67
+ const global = getGitUserConfig(); // global config (no cwd)
68
+ if (global.name && global.email) {
69
+ const useGlobal = await confirmPrompt(`Use global identity "${global.name} <${global.email}>"?`, true);
70
+ if (useGlobal) {
71
+ success(`Using global identity: ${global.name} <${global.email}>`);
72
+ blank();
73
+ return;
74
+ }
75
+ }
76
+ const name = await inputPrompt('Your name', global.name || '');
77
+ const email = await inputPrompt('Your email', global.email || '');
78
+ if (name.trim() && email.trim()) {
79
+ setGitUserConfig(name.trim(), email.trim(), cwd);
80
+ success(`Git identity set: ${name.trim()} <${email.trim()}>`);
81
+ }
82
+ else {
83
+ warning('Identity not set — you can configure it later with:\n git config user.name "Your Name"\n git config user.email "you@example.com"');
84
+ }
85
+ blank();
86
+ }
87
+ // ── Step 3: .gitignore ─────────────────────────────────────────────────────
88
+ async function wizardGitignore(cwd) {
89
+ section('.gitignore');
90
+ const detected = detectProjectType(cwd);
91
+ const detectedLabel = PROJECT_TYPE_LABELS[detected];
92
+ if (hasGitignore(cwd)) {
93
+ info('.gitignore already exists.');
94
+ const append = await confirmPrompt(`Append recommended ${detectedLabel} entries?`, false);
95
+ if (!append) {
96
+ blank();
97
+ return;
98
+ }
99
+ const existing = readGitignore(cwd);
100
+ const template = getTemplate(detected);
101
+ writeGitignore(existing + '\n# --- Added by git-smart-flow ---\n' + template, cwd);
102
+ success('.gitignore updated.');
103
+ blank();
104
+ return;
105
+ }
106
+ info(`Detected project type: ${detectedLabel}`);
107
+ const typeOptions = [
108
+ `${detectedLabel} (detected)`,
109
+ 'Node.js / TypeScript / JavaScript',
110
+ 'Python',
111
+ 'Java / Kotlin (Maven / Gradle)',
112
+ 'Go',
113
+ 'Rust',
114
+ 'Generic (editor files, env, logs)',
115
+ 'Skip — I will create it manually',
116
+ ];
117
+ const typeChoice = await selectPrompt('Choose .gitignore template:', typeOptions);
118
+ if (typeChoice.startsWith('Skip')) {
119
+ info('Skipped — create .gitignore manually or run "gsf setup" later.');
120
+ blank();
121
+ return;
122
+ }
123
+ // Resolve chosen type from label
124
+ let chosenType = detected;
125
+ if (typeChoice.includes('Node.js'))
126
+ chosenType = 'node';
127
+ else if (typeChoice.includes('Python'))
128
+ chosenType = 'python';
129
+ else if (typeChoice.includes('Java'))
130
+ chosenType = 'java';
131
+ else if (typeChoice.includes('Go'))
132
+ chosenType = 'go';
133
+ else if (typeChoice.includes('Rust'))
134
+ chosenType = 'rust';
135
+ else if (typeChoice.includes('Generic'))
136
+ chosenType = 'generic';
137
+ writeGitignore(getTemplate(chosenType), cwd);
138
+ success(`.gitignore created (${PROJECT_TYPE_LABELS[chosenType]} template).`);
139
+ blank();
140
+ }
141
+ //# sourceMappingURL=ensure-repo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ensure-repo.js","sourceRoot":"","sources":["../../src/git/ensure-repo.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export type ProjectType = 'node' | 'python' | 'java' | 'go' | 'rust' | 'generic';
2
+ export declare function detectProjectType(cwd: string): ProjectType;
3
+ export declare const PROJECT_TYPE_LABELS: Record<ProjectType, string>;
4
+ export declare function hasGitignore(cwd: string): boolean;
5
+ export declare function readGitignore(cwd: string): string;
6
+ export declare function writeGitignore(content: string, cwd: string): void;
7
+ export declare function getTemplate(type: ProjectType): string;
8
+ //# sourceMappingURL=gitignore.d.ts.map