issue-flow 0.12.0 → 0.14.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 (197) hide show
  1. package/README.md +79 -274
  2. package/dist/agent-OX3KPHE4.js +30 -0
  3. package/dist/{analyze-OEET7KGE.js → analyze-WIND2SEB.js} +31 -16
  4. package/dist/analyze-WIND2SEB.js.map +1 -0
  5. package/dist/{apply-ZIA3C52S.js → apply-JNOI2LR4.js} +18 -7
  6. package/dist/{apply-ZIA3C52S.js.map → apply-JNOI2LR4.js.map} +1 -1
  7. package/dist/bench-B4VZON7E.js +910 -0
  8. package/dist/bench-B4VZON7E.js.map +1 -0
  9. package/dist/{chunk-FADTCQGM.js → chunk-2IQ6M4ZE.js} +94 -32
  10. package/dist/chunk-2IQ6M4ZE.js.map +1 -0
  11. package/dist/chunk-3BWZO4YI.js +141 -0
  12. package/dist/chunk-3BWZO4YI.js.map +1 -0
  13. package/dist/chunk-3WFZETIM.js +163 -0
  14. package/dist/chunk-3WFZETIM.js.map +1 -0
  15. package/dist/chunk-67YIU2VB.js +362 -0
  16. package/dist/chunk-67YIU2VB.js.map +1 -0
  17. package/dist/{chunk-QCPGHBSZ.js → chunk-6BENHR2I.js} +63 -21
  18. package/dist/chunk-6BENHR2I.js.map +1 -0
  19. package/dist/{chunk-BYZDPR7N.js → chunk-6QYMSNVA.js} +194 -235
  20. package/dist/chunk-6QYMSNVA.js.map +1 -0
  21. package/dist/{chunk-Y5ZDJ4PJ.js → chunk-76MMPJ53.js} +20 -10
  22. package/dist/chunk-76MMPJ53.js.map +1 -0
  23. package/dist/chunk-7Z4Y3VKM.js +26 -0
  24. package/dist/chunk-7Z4Y3VKM.js.map +1 -0
  25. package/dist/{chunk-3QHK4YQA.js → chunk-B72RQZBV.js} +346 -119
  26. package/dist/chunk-B72RQZBV.js.map +1 -0
  27. package/dist/chunk-BEZ5BA5U.js +625 -0
  28. package/dist/chunk-BEZ5BA5U.js.map +1 -0
  29. package/dist/chunk-BRCNQXYQ.js +74 -0
  30. package/dist/chunk-BRCNQXYQ.js.map +1 -0
  31. package/dist/chunk-CGKLE6WR.js +1203 -0
  32. package/dist/chunk-CGKLE6WR.js.map +1 -0
  33. package/dist/chunk-CRGIQFUQ.js +83 -0
  34. package/dist/chunk-CRGIQFUQ.js.map +1 -0
  35. package/dist/{chunk-NS6R37II.js → chunk-F6TOYSYY.js} +141 -12
  36. package/dist/chunk-F6TOYSYY.js.map +1 -0
  37. package/dist/chunk-G5EK2XRN.js +25 -0
  38. package/dist/chunk-G5EK2XRN.js.map +1 -0
  39. package/dist/chunk-HAKDLR6N.js +134 -0
  40. package/dist/chunk-HAKDLR6N.js.map +1 -0
  41. package/dist/chunk-J3SOTUVI.js +298 -0
  42. package/dist/chunk-J3SOTUVI.js.map +1 -0
  43. package/dist/chunk-JN6D3MY6.js +30 -0
  44. package/dist/chunk-JN6D3MY6.js.map +1 -0
  45. package/dist/{chunk-LAFNLLQP.js → chunk-KMRFRXIT.js} +5 -5
  46. package/dist/chunk-KT7JKOXB.js +72 -0
  47. package/dist/chunk-KT7JKOXB.js.map +1 -0
  48. package/dist/chunk-L6HSKTQE.js +77 -0
  49. package/dist/chunk-L6HSKTQE.js.map +1 -0
  50. package/dist/chunk-LBGHI4S2.js +1264 -0
  51. package/dist/chunk-LBGHI4S2.js.map +1 -0
  52. package/dist/chunk-LEW4QM74.js +180 -0
  53. package/dist/chunk-LEW4QM74.js.map +1 -0
  54. package/dist/{chunk-FJP3UQGD.js → chunk-LFEQIZLB.js} +115 -20
  55. package/dist/chunk-LFEQIZLB.js.map +1 -0
  56. package/dist/chunk-OOVG2KBY.js +77 -0
  57. package/dist/chunk-OOVG2KBY.js.map +1 -0
  58. package/dist/{chunk-56KS3TFQ.js → chunk-OR43364P.js} +115 -160
  59. package/dist/chunk-OR43364P.js.map +1 -0
  60. package/dist/chunk-P3LRUNC6.js +16 -0
  61. package/dist/chunk-P3LRUNC6.js.map +1 -0
  62. package/dist/{chunk-TSOLWK7Y.js → chunk-PBTA3QQX.js} +8 -7
  63. package/dist/{chunk-TSOLWK7Y.js.map → chunk-PBTA3QQX.js.map} +1 -1
  64. package/dist/{chunk-MJULIKQU.js → chunk-PHW2YV6N.js} +23 -47
  65. package/dist/chunk-PHW2YV6N.js.map +1 -0
  66. package/dist/{chunk-73ATPIYX.js → chunk-PZTWU277.js} +36 -71
  67. package/dist/chunk-PZTWU277.js.map +1 -0
  68. package/dist/{chunk-M5UCXTIT.js → chunk-QD4VOILZ.js} +22 -18
  69. package/dist/chunk-QD4VOILZ.js.map +1 -0
  70. package/dist/chunk-QJ5UZAH5.js +2718 -0
  71. package/dist/chunk-QJ5UZAH5.js.map +1 -0
  72. package/dist/chunk-QK7WUO7A.js +283 -0
  73. package/dist/chunk-QK7WUO7A.js.map +1 -0
  74. package/dist/{chunk-A4SLHOW7.js → chunk-QZVKRDJY.js} +27 -19
  75. package/dist/chunk-QZVKRDJY.js.map +1 -0
  76. package/dist/chunk-REO3PXXO.js +71 -0
  77. package/dist/chunk-REO3PXXO.js.map +1 -0
  78. package/dist/{chunk-EZATO3DW.js → chunk-RVO7L4FX.js} +594 -17
  79. package/dist/chunk-RVO7L4FX.js.map +1 -0
  80. package/dist/{chunk-XQUSIEKA.js → chunk-SZMHCEYV.js} +63 -14
  81. package/dist/chunk-SZMHCEYV.js.map +1 -0
  82. package/dist/chunk-TYRNTSPJ.js +243 -0
  83. package/dist/chunk-TYRNTSPJ.js.map +1 -0
  84. package/dist/chunk-UJ3L2MS7.js +238 -0
  85. package/dist/chunk-UJ3L2MS7.js.map +1 -0
  86. package/dist/chunk-V7MO5EDS.js +120 -0
  87. package/dist/chunk-V7MO5EDS.js.map +1 -0
  88. package/dist/chunk-WB2X37MO.js +415 -0
  89. package/dist/chunk-WB2X37MO.js.map +1 -0
  90. package/dist/{chunk-NTMMF5UD.js → chunk-X44FKNKP.js} +525 -252
  91. package/dist/chunk-X44FKNKP.js.map +1 -0
  92. package/dist/chunk-XEYH6ZZI.js +289 -0
  93. package/dist/chunk-XEYH6ZZI.js.map +1 -0
  94. package/dist/cli.js +267 -44
  95. package/dist/cli.js.map +1 -1
  96. package/dist/{config-PRJGWW7J.js → config-HMFMCY2M.js} +31 -5
  97. package/dist/contract-JH2WBIO6.js +8 -0
  98. package/dist/conventions-NJF2OPVQ.js +146 -0
  99. package/dist/conventions-NJF2OPVQ.js.map +1 -0
  100. package/dist/diagnostics-THH42ZMP.js +23 -0
  101. package/dist/execute-KFNNZZHI.js +35 -0
  102. package/dist/{generate-EGB4KV2B.js → generate-FW5C6NP7.js} +37 -20
  103. package/dist/{generate-EGB4KV2B.js.map → generate-FW5C6NP7.js.map} +1 -1
  104. package/dist/git-W72QQ6GT.js +33 -0
  105. package/dist/init-HTN4V67Q.js +24 -0
  106. package/dist/{operations-BYT626KQ.js → operations-BCFOBH42.js} +27 -15
  107. package/dist/{operations-BYT626KQ.js.map → operations-BCFOBH42.js.map} +1 -1
  108. package/dist/permissions-4AKNQZHK.js +18 -0
  109. package/dist/plan-SIZLGA4V.js +34 -0
  110. package/dist/{policy-6S4GFC76.js → policy-DT6Q6ZVM.js} +20 -6
  111. package/dist/policy-DT6Q6ZVM.js.map +1 -0
  112. package/dist/pr-OMWCGUOW.js +39 -0
  113. package/dist/pr-review-N24CZPKR.js +32 -0
  114. package/dist/pr-review-N24CZPKR.js.map +1 -0
  115. package/dist/prd-5OFTZAHJ.js +33 -0
  116. package/dist/prd-5OFTZAHJ.js.map +1 -0
  117. package/dist/ps-RFORTCUD.js +93 -0
  118. package/dist/ps-RFORTCUD.js.map +1 -0
  119. package/dist/recorder-KCCPMKQG.js +32 -0
  120. package/dist/recorder-KCCPMKQG.js.map +1 -0
  121. package/dist/registry-GLPXOMFG.js +15 -0
  122. package/dist/registry-GLPXOMFG.js.map +1 -0
  123. package/dist/{resume-PPCNQVVV.js → resume-M5RLKP4I.js} +55 -34
  124. package/dist/{resume-PPCNQVVV.js.map → resume-M5RLKP4I.js.map} +1 -1
  125. package/dist/review-YM4JAABY.js +35 -0
  126. package/dist/review-YM4JAABY.js.map +1 -0
  127. package/dist/routing-NNT5WKGX.js +94 -0
  128. package/dist/routing-NNT5WKGX.js.map +1 -0
  129. package/dist/run-PZUKHPQK.js +54 -0
  130. package/dist/run-PZUKHPQK.js.map +1 -0
  131. package/dist/session-publisher-T7EI3CIP.js +11 -0
  132. package/dist/session-publisher-T7EI3CIP.js.map +1 -0
  133. package/dist/{state-manager-2EDVDBAR.js → state-manager-GQH32C44.js} +4 -2
  134. package/dist/state-manager-GQH32C44.js.map +1 -0
  135. package/dist/usage-V2CHE5PY.js +177 -0
  136. package/dist/usage-V2CHE5PY.js.map +1 -0
  137. package/dist/{web-EF5WIIGG.js → web-EA3KGNFN.js} +45 -30
  138. package/dist/web-EA3KGNFN.js.map +1 -0
  139. package/package.json +6 -2
  140. package/prompts/execute.md +7 -8
  141. package/prompts/plan.md +4 -5
  142. package/prompts/pr.md +2 -2
  143. package/web/AGENTS.md +152 -13
  144. package/web/public/app.css +380 -109
  145. package/web/public/app.js +525 -25
  146. package/web/public/index.html +68 -1
  147. package/dist/analyze-OEET7KGE.js.map +0 -1
  148. package/dist/chunk-3QHK4YQA.js.map +0 -1
  149. package/dist/chunk-42PJFMAR.js +0 -605
  150. package/dist/chunk-42PJFMAR.js.map +0 -1
  151. package/dist/chunk-4JSOYE4G.js +0 -368
  152. package/dist/chunk-4JSOYE4G.js.map +0 -1
  153. package/dist/chunk-56KS3TFQ.js.map +0 -1
  154. package/dist/chunk-73ATPIYX.js.map +0 -1
  155. package/dist/chunk-A4SLHOW7.js.map +0 -1
  156. package/dist/chunk-BAUPQXPE.js +0 -173
  157. package/dist/chunk-BAUPQXPE.js.map +0 -1
  158. package/dist/chunk-BYZDPR7N.js.map +0 -1
  159. package/dist/chunk-CD5ULRVC.js +0 -615
  160. package/dist/chunk-CD5ULRVC.js.map +0 -1
  161. package/dist/chunk-DIDUVL6O.js +0 -1365
  162. package/dist/chunk-DIDUVL6O.js.map +0 -1
  163. package/dist/chunk-EZATO3DW.js.map +0 -1
  164. package/dist/chunk-FADTCQGM.js.map +0 -1
  165. package/dist/chunk-FJP3UQGD.js.map +0 -1
  166. package/dist/chunk-LWRSMTTZ.js +0 -18
  167. package/dist/chunk-LWRSMTTZ.js.map +0 -1
  168. package/dist/chunk-M5UCXTIT.js.map +0 -1
  169. package/dist/chunk-M66SJHQQ.js +0 -206
  170. package/dist/chunk-M66SJHQQ.js.map +0 -1
  171. package/dist/chunk-MJULIKQU.js.map +0 -1
  172. package/dist/chunk-NS6R37II.js.map +0 -1
  173. package/dist/chunk-NTMMF5UD.js.map +0 -1
  174. package/dist/chunk-QCPGHBSZ.js.map +0 -1
  175. package/dist/chunk-XQUSIEKA.js.map +0 -1
  176. package/dist/chunk-Y5ZDJ4PJ.js.map +0 -1
  177. package/dist/execute-XBNVL753.js +0 -18
  178. package/dist/init-AJHCXJBP.js +0 -10
  179. package/dist/plan-QOZ3RIO6.js +0 -21
  180. package/dist/policy-6S4GFC76.js.map +0 -1
  181. package/dist/pr-EBBHD2ZX.js +0 -26
  182. package/dist/pr-review-VVMW5PO4.js +0 -20
  183. package/dist/prd-JQSZF7PR.js +0 -21
  184. package/dist/review-3F6MARWH.js +0 -19
  185. package/dist/run-RXE5GDQO.js +0 -36
  186. package/dist/web-EF5WIIGG.js.map +0 -1
  187. /package/dist/{config-PRJGWW7J.js.map → agent-OX3KPHE4.js.map} +0 -0
  188. /package/dist/{chunk-LAFNLLQP.js.map → chunk-KMRFRXIT.js.map} +0 -0
  189. /package/dist/{execute-XBNVL753.js.map → config-HMFMCY2M.js.map} +0 -0
  190. /package/dist/{init-AJHCXJBP.js.map → contract-JH2WBIO6.js.map} +0 -0
  191. /package/dist/{plan-QOZ3RIO6.js.map → diagnostics-THH42ZMP.js.map} +0 -0
  192. /package/dist/{pr-EBBHD2ZX.js.map → execute-KFNNZZHI.js.map} +0 -0
  193. /package/dist/{pr-review-VVMW5PO4.js.map → git-W72QQ6GT.js.map} +0 -0
  194. /package/dist/{prd-JQSZF7PR.js.map → init-HTN4V67Q.js.map} +0 -0
  195. /package/dist/{review-3F6MARWH.js.map → permissions-4AKNQZHK.js.map} +0 -0
  196. /package/dist/{run-RXE5GDQO.js.map → plan-SIZLGA4V.js.map} +0 -0
  197. /package/dist/{state-manager-2EDVDBAR.js.map → pr-OMWCGUOW.js.map} +0 -0
@@ -2,14 +2,353 @@
2
2
  import {
3
3
  loadPolicyConfig,
4
4
  mergeConfigLayers
5
- } from "./chunk-42PJFMAR.js";
5
+ } from "./chunk-QJ5UZAH5.js";
6
+ import {
7
+ printWarning
8
+ } from "./chunk-TYRNTSPJ.js";
6
9
  import {
7
10
  getProjectRoot,
8
11
  run
9
- } from "./chunk-DIDUVL6O.js";
10
- import {
11
- printWarning
12
- } from "./chunk-BYZDPR7N.js";
12
+ } from "./chunk-BEZ5BA5U.js";
13
+
14
+ // src/conventions/git/types.ts
15
+ var CHANGE_TYPES = [
16
+ "feat",
17
+ "fix",
18
+ "docs",
19
+ "refactor",
20
+ "perf",
21
+ "test",
22
+ "build",
23
+ "ci",
24
+ "chore",
25
+ "style",
26
+ "revert"
27
+ ];
28
+ var DEFAULT_BRANCH_CONVENTION = "{type}/{N}-{slug}";
29
+ var SLUG_MAX_LENGTH = 40;
30
+ var BRANCH_MAX_LENGTH = 60;
31
+ var DEFAULT_LABEL_TYPE_MAP = {
32
+ bug: "fix",
33
+ documentation: "docs",
34
+ docs: "docs",
35
+ refactor: "refactor",
36
+ "tech-debt": "refactor",
37
+ infra: "ci",
38
+ "ci-cd": "ci",
39
+ enhancement: "feat",
40
+ architecture: "feat",
41
+ investigation: "chore"
42
+ };
43
+ var FORBIDDEN_PROVIDER_NAMES = ["claude", "codex", "cursor", "antigravity"];
44
+ function isChangeType(value) {
45
+ return CHANGE_TYPES.includes(value);
46
+ }
47
+ function isForbiddenProviderToken(value) {
48
+ return FORBIDDEN_PROVIDER_NAMES.includes(value.toLowerCase());
49
+ }
50
+
51
+ // src/conventions/git/slug.ts
52
+ var COMBINING = /[\u0300-\u036f]/g;
53
+ var NON_SLUG = /[^a-z0-9]+/g;
54
+ function slugify(title, maxLength = SLUG_MAX_LENGTH) {
55
+ const withoutLock = title.replace(/\.lock$/i, "");
56
+ const normalized = withoutLock.normalize("NFD").replace(COMBINING, "").toLowerCase();
57
+ let slug = normalized.replace(NON_SLUG, "-").replace(/^-+|-+$/g, "");
58
+ slug = slug.replace(/\.{2,}/g, ".").replace(/^\.+|\.+$/g, "");
59
+ slug = slug.replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "");
60
+ if (slug.length <= maxLength) return slug;
61
+ const cut = slug.slice(0, maxLength);
62
+ const lastHyphen = cut.lastIndexOf("-");
63
+ if (lastHyphen >= Math.floor(maxLength / 2)) {
64
+ return cut.slice(0, lastHyphen).replace(/-+$/g, "");
65
+ }
66
+ return cut.replace(/-+$/g, "");
67
+ }
68
+
69
+ // src/conventions/git/branch.ts
70
+ var LEGACY_PREFIX = "issue";
71
+ function branchType(type) {
72
+ return type === "style" || type === "revert" ? "chore" : type;
73
+ }
74
+ function applyConvention(convention, type, issueNumber, slug) {
75
+ const hasNumber = issueNumber !== void 0 && issueNumber !== null;
76
+ let result = convention.replaceAll("{type}", type).replaceAll("{N}", hasNumber ? String(issueNumber) : "").replaceAll("{slug}", slug);
77
+ result = result.replace(/\/{2,}/g, "/").replace(/-{2,}/g, "-");
78
+ result = result.replace(/\/-/g, "/").replace(/-\//g, "/");
79
+ result = result.replace(/^\/+|\/+$/g, "").replace(/^-+|-+$/g, "");
80
+ if (!hasNumber) {
81
+ result = result.replace(`${type}/-`, `${type}/`).replace(/\/$/g, "");
82
+ }
83
+ if (slug === "") {
84
+ result = result.replace(/\/-$/, "").replace(/-$/, "");
85
+ }
86
+ return result.replace(/\/{2,}/g, "/").replace(/^\/+|\/+$/g, "");
87
+ }
88
+ function truncateBranch(name, max) {
89
+ if (name.length <= max) return name;
90
+ const slash = name.indexOf("/");
91
+ const prefix = slash === -1 ? "" : name.slice(0, slash + 1);
92
+ const rest = slash === -1 ? name : name.slice(slash + 1);
93
+ const budget = max - prefix.length;
94
+ if (budget < 1) return name.slice(0, max);
95
+ const cut = rest.slice(0, budget);
96
+ const lastHyphen = cut.lastIndexOf("-");
97
+ const trimmed = lastHyphen >= Math.floor(budget / 2) ? cut.slice(0, lastHyphen) : cut;
98
+ return `${prefix}${trimmed.replace(/-+$/g, "")}`;
99
+ }
100
+ function collide(name, existingRefs, currentOid) {
101
+ if (existingRefs === void 0 || existingRefs.length === 0) return name;
102
+ const byName = new Map(existingRefs.map((ref) => [ref.name, ref.oid]));
103
+ const existing = byName.get(name);
104
+ if (existing === void 0) return name;
105
+ if (currentOid !== void 0 && existing === currentOid) return name;
106
+ for (let n = 2; n < 100; n += 1) {
107
+ const candidate = `${name}-${n}`;
108
+ const oid = byName.get(candidate);
109
+ if (oid === void 0 || currentOid !== void 0 && oid === currentOid) {
110
+ return candidate;
111
+ }
112
+ }
113
+ return `${name}-${Date.now()}`;
114
+ }
115
+ function branchName(input) {
116
+ const type = branchType(input.type);
117
+ const convention = input.convention ?? DEFAULT_BRANCH_CONVENTION;
118
+ const slug = slugify(input.title);
119
+ const raw = applyConvention(convention, type, input.issueNumber, slug);
120
+ const truncated = truncateBranch(raw, BRANCH_MAX_LENGTH);
121
+ return collide(truncated, input.existingRefs, input.currentOid);
122
+ }
123
+ function parseBranch(name) {
124
+ const raw = name.trim();
125
+ const match = raw.match(/^([^/]+)\/(?:(\d+)(?:-(.*))?|(.*))$/);
126
+ if (match === null) {
127
+ return { type: null, issueNumber: null, slug: raw, raw };
128
+ }
129
+ const prefix = match[1] ?? "";
130
+ const numbered = match[2];
131
+ const numberedSlug = match[3] ?? "";
132
+ const unnumberedSlug = match[4] ?? "";
133
+ const type = prefix === LEGACY_PREFIX ? "issue" : isChangeType(prefix) ? prefix : null;
134
+ if (numbered !== void 0) {
135
+ return { type, issueNumber: Number(numbered), slug: numberedSlug, raw };
136
+ }
137
+ return { type, issueNumber: null, slug: unnumberedSlug, raw };
138
+ }
139
+ function archiveFolderName(branch) {
140
+ const parsed = parseBranch(branch);
141
+ if (parsed.issueNumber !== null && parsed.slug !== "") {
142
+ return `${parsed.issueNumber}-${parsed.slug}`.replace(/[<>:"|?*\\]/g, "_");
143
+ }
144
+ if (parsed.issueNumber !== null) {
145
+ return String(parsed.issueNumber);
146
+ }
147
+ return branch.replace(/^[^/]+\//, "").replace(/[<>:"|?*\\]/g, "_");
148
+ }
149
+
150
+ // src/conventions/git/change-type.ts
151
+ var ISSUE_TYPE_MAP = {
152
+ bug: "fix",
153
+ feature: "feat",
154
+ task: "chore",
155
+ epic: "chore",
156
+ idea: "chore",
157
+ research: "chore",
158
+ documentation: "docs"
159
+ };
160
+ var TITLE_PREFIX_MAP = {
161
+ bug: "fix",
162
+ fix: "fix",
163
+ feature: "feat",
164
+ enhancement: "feat",
165
+ architecture: "feat",
166
+ refactor: "refactor",
167
+ docs: "docs",
168
+ documentation: "docs",
169
+ chore: "chore",
170
+ perf: "perf",
171
+ test: "test",
172
+ ci: "ci"
173
+ };
174
+ function normalizeKey(value) {
175
+ return value.trim().toLowerCase();
176
+ }
177
+ function typeFromIssueType(issueType) {
178
+ const key = normalizeKey(issueType);
179
+ if (isChangeType(key)) return key;
180
+ return ISSUE_TYPE_MAP[key] ?? null;
181
+ }
182
+ function mergedTypeMap(overlay) {
183
+ const merged = { ...DEFAULT_LABEL_TYPE_MAP };
184
+ if (overlay === void 0 || overlay === null) return merged;
185
+ for (const [label, type] of Object.entries(overlay)) {
186
+ if (isChangeType(type)) {
187
+ merged[normalizeKey(label)] = type;
188
+ }
189
+ }
190
+ return merged;
191
+ }
192
+ function typeFromLabels(labels, typeMap) {
193
+ for (const label of labels) {
194
+ const key = normalizeKey(label);
195
+ const mapped = typeMap[key] ?? typeMap[key.replace(/^type:/, "")];
196
+ if (mapped !== void 0) return mapped;
197
+ }
198
+ return null;
199
+ }
200
+ function typeFromTitle(title) {
201
+ const match = title.match(/^\s*\[([^\]]+)\]/);
202
+ if (match?.[1] === void 0) return null;
203
+ const key = normalizeKey(match[1]);
204
+ if (isChangeType(key)) return key;
205
+ return TITLE_PREFIX_MAP[key] ?? null;
206
+ }
207
+ function resolveChangeType(input) {
208
+ if (input.declaredType !== void 0 && input.declaredType !== null) {
209
+ return { type: input.declaredType, source: "declared" };
210
+ }
211
+ const labels = input.labels ?? [];
212
+ const typeMap = mergedTypeMap(input.typeMap);
213
+ const fromLabels = typeFromLabels(labels, typeMap);
214
+ const fromIssueType = input.issueType !== void 0 && input.issueType !== null && input.issueType !== "" ? typeFromIssueType(input.issueType) : null;
215
+ if (fromIssueType !== null) {
216
+ const issueKey = normalizeKey(input.issueType ?? "");
217
+ if (issueKey === "task" && fromLabels !== null) {
218
+ return { type: fromLabels, source: "label" };
219
+ }
220
+ if (fromLabels !== null && fromLabels !== fromIssueType) {
221
+ return {
222
+ type: fromIssueType,
223
+ source: "issue-type",
224
+ conflict: { issueType: fromIssueType, label: fromLabels }
225
+ };
226
+ }
227
+ return { type: fromIssueType, source: "issue-type" };
228
+ }
229
+ if (fromLabels !== null) {
230
+ return { type: fromLabels, source: "label" };
231
+ }
232
+ if (input.titleConvention !== null && input.title !== void 0) {
233
+ const fromTitle = typeFromTitle(input.title);
234
+ if (fromTitle !== null) {
235
+ return { type: fromTitle, source: "title" };
236
+ }
237
+ } else if (input.title !== void 0) {
238
+ const fromTitle = typeFromTitle(input.title);
239
+ if (fromTitle !== null) {
240
+ return { type: fromTitle, source: "title" };
241
+ }
242
+ }
243
+ return { type: "feat", source: "fallback" };
244
+ }
245
+
246
+ // src/conventions/git/commit.ts
247
+ var HEADER_MAX = 72;
248
+ var BODY_WIDTH = 72;
249
+ var STORY_ID = /^US-\d+$/i;
250
+ function wrap(text, width) {
251
+ const paragraphs = text.replace(/\r\n/g, "\n").split("\n");
252
+ return paragraphs.map((paragraph) => {
253
+ if (paragraph.trim() === "") return "";
254
+ const words = paragraph.split(/\s+/);
255
+ const lines = [];
256
+ let current = "";
257
+ for (const word of words) {
258
+ const next = current === "" ? word : `${current} ${word}`;
259
+ if (next.length > width && current !== "") {
260
+ lines.push(current);
261
+ current = word;
262
+ } else {
263
+ current = next;
264
+ }
265
+ }
266
+ if (current !== "") lines.push(current);
267
+ return lines.join("\n");
268
+ }).join("\n");
269
+ }
270
+ function sanitizeScope(scope) {
271
+ if (scope === void 0 || scope === null) return void 0;
272
+ const trimmed = scope.trim();
273
+ if (trimmed === "" || isForbiddenProviderToken(trimmed)) return void 0;
274
+ return trimmed;
275
+ }
276
+ function sanitizeType(type) {
277
+ return isForbiddenProviderToken(type) ? "chore" : type;
278
+ }
279
+ function headerLine(type, scope, breaking, subject) {
280
+ const bang = breaking ? "!" : "";
281
+ const scoped = scope === void 0 ? `${type}${bang}` : `${type}(${scope})${bang}`;
282
+ const cleaned = subject.replace(/\.$/, "").trim();
283
+ const prefix = `${scoped}: `;
284
+ const budget = HEADER_MAX - prefix.length;
285
+ const clipped = budget < 1 ? "" : cleaned.length > budget ? cleaned.slice(0, budget).trimEnd() : cleaned;
286
+ return `${prefix}${clipped}`;
287
+ }
288
+ function commitMessage(input) {
289
+ const type = sanitizeType(input.type);
290
+ const scope = sanitizeScope(input.scope);
291
+ const breaking = input.breaking !== void 0 && input.breaking !== null && input.breaking !== "";
292
+ const lines = [headerLine(type, scope, breaking, input.subject)];
293
+ if (input.body !== void 0 && input.body !== "") {
294
+ lines.push("", wrap(input.body, BODY_WIDTH));
295
+ }
296
+ const footers = [];
297
+ if (input.issueNumber !== void 0 && input.issueNumber !== null) {
298
+ footers.push(`Refs #${input.issueNumber}`);
299
+ }
300
+ if (input.storyId !== void 0 && input.storyId !== null && STORY_ID.test(input.storyId)) {
301
+ footers.push(`Story: ${input.storyId}`);
302
+ }
303
+ if (breaking) {
304
+ footers.push(`BREAKING CHANGE: ${input.breaking}`);
305
+ }
306
+ if (input.signoff === true) {
307
+ footers.push("Signed-off-by:");
308
+ } else if (typeof input.signoff === "string" && input.signoff !== "") {
309
+ footers.push(`Signed-off-by: ${input.signoff}`);
310
+ }
311
+ if (footers.length > 0) {
312
+ lines.push("", ...footers);
313
+ }
314
+ return lines.join("\n");
315
+ }
316
+
317
+ // src/conventions/git/pull-request.ts
318
+ var IMPACT = ["feat", "fix"];
319
+ function sanitizeScope2(scope) {
320
+ if (scope === void 0 || scope === null) return void 0;
321
+ const trimmed = scope.trim();
322
+ if (trimmed === "" || isForbiddenProviderToken(trimmed)) return void 0;
323
+ return trimmed;
324
+ }
325
+ function highestImpact(types) {
326
+ for (const type of IMPACT) {
327
+ if (types.includes(type)) return type;
328
+ }
329
+ return types[0] ?? "feat";
330
+ }
331
+ function scopesAgree(scopes) {
332
+ const unique2 = [
333
+ ...new Set(scopes.map((scope) => sanitizeScope2(scope)).filter((scope) => scope !== void 0))
334
+ ];
335
+ return unique2.length === 1 ? unique2[0] : void 0;
336
+ }
337
+ function pullRequestTitle(input) {
338
+ const type = input.types !== void 0 && input.types.length > 0 ? highestImpact(input.types) : input.type;
339
+ const scope = input.scopes !== void 0 && input.scopes.length > 0 ? scopesAgree(input.scopes) : sanitizeScope2(input.scope);
340
+ const subject = input.subject.replace(/\.$/, "").trim();
341
+ if (isForbiddenProviderToken(type)) {
342
+ return scope === void 0 ? `chore: ${subject}` : `chore(${scope}): ${subject}`;
343
+ }
344
+ return scope === void 0 ? `${type}: ${subject}` : `${type}(${scope}): ${subject}`;
345
+ }
346
+ function issueReferenceLines(input) {
347
+ return input.references.map((ref) => {
348
+ const closes = ref.container === true ? ref.allChildrenComplete === true : ref.complete;
349
+ return `${closes ? "Closes" : "Refs"} #${ref.number}`;
350
+ }).join("\n");
351
+ }
13
352
 
14
353
  // src/policy/resolve.ts
15
354
  import { isAbsolute, normalize, sep as sep2 } from "path";
@@ -58,6 +397,118 @@ function extractReferencedDocuments(content, fromPath) {
58
397
  return found;
59
398
  }
60
399
 
400
+ // src/policy/parsers/git.ts
401
+ var COMMITLINT_NAMES = [
402
+ ".commitlintrc",
403
+ ".commitlintrc.json",
404
+ ".commitlintrc.yaml",
405
+ ".commitlintrc.yml",
406
+ ".commitlintrc.js",
407
+ ".commitlintrc.cjs",
408
+ ".commitlintrc.mjs",
409
+ ".commitlintrc.ts",
410
+ "commitlint.config.js",
411
+ "commitlint.config.cjs",
412
+ "commitlint.config.mjs",
413
+ "commitlint.config.ts"
414
+ ];
415
+ function unique(values) {
416
+ return [...new Set(values)];
417
+ }
418
+ function extractQuotedStrings(block) {
419
+ const matches = block.match(/['"]([a-z][a-z0-9-]*)['"]/g) ?? [];
420
+ return matches.map((token) => token.slice(1, -1));
421
+ }
422
+ function extractEnum(source, rule) {
423
+ const escaped = rule.replace("-", "\\-");
424
+ const match = source.match(new RegExp(`${escaped}[\\s\\S]{0,800}?\\[([\\s\\S]*?)\\]`, "i"));
425
+ if (match?.[1] === void 0) return [];
426
+ return extractQuotedStrings(match[1]).filter((value) => value !== "always" && value !== "never");
427
+ }
428
+ function parseCommitlintSource(source, path) {
429
+ const types = extractEnum(source, "type-enum").filter(isChangeType);
430
+ const scopes = extractEnum(source, "scope-enum");
431
+ const conventional = /conventional|commitlint/i.test(source) || types.length > 0;
432
+ return {
433
+ commitConvention: conventional ? "conventional" : null,
434
+ pullRequestTitleConvention: null,
435
+ allowedTypes: types.length > 0 ? unique(types) : null,
436
+ scopes: scopes.length > 0 ? unique(scopes) : null,
437
+ sources: [{ path, detail: conventional ? "commitlint" : "commitlint (unrecognised)" }]
438
+ };
439
+ }
440
+ function parsePackageCommitlint(pkg) {
441
+ if (pkg === null || typeof pkg !== "object" || Array.isArray(pkg)) return null;
442
+ const commitlint = pkg.commitlint;
443
+ if (commitlint === void 0 || commitlint === null) return null;
444
+ const source = JSON.stringify(commitlint);
445
+ return parseCommitlintSource(source, "package.json#commitlint");
446
+ }
447
+ function parseSemanticPrWorkflow(source, path) {
448
+ if (!/amannn\/action-semantic-pull-request/.test(source)) return null;
449
+ const typesBlock = source.match(/types:\s*[|>]?\s*\n((?:\s{2,}[a-z][a-z0-9-]*\s*\n)+)/i);
450
+ const scopesBlock = source.match(/scopes:\s*[|>]?\s*\n((?:\s{2,}[a-z][a-z0-9-]*\s*\n)+)/i);
451
+ const types = typesBlock?.[1]?.split("\n").map((line) => line.trim()).filter((line) => isChangeType(line)) ?? [];
452
+ const scopes = scopesBlock?.[1]?.split("\n").map((line) => line.trim()).filter((line) => /^[a-z][a-z0-9-]*$/.test(line)) ?? [];
453
+ return {
454
+ commitConvention: "conventional",
455
+ pullRequestTitleConvention: "conventional",
456
+ allowedTypes: types.length > 0 ? unique(types) : null,
457
+ scopes: scopes.length > 0 ? unique(scopes) : null,
458
+ sources: [{ path, detail: "amannn/action-semantic-pull-request" }]
459
+ };
460
+ }
461
+ function parseCommitlintText(source, path) {
462
+ return parseCommitlintSource(source, path);
463
+ }
464
+ function parsePackageJsonCommitlint(raw) {
465
+ try {
466
+ return parsePackageCommitlint(JSON.parse(raw));
467
+ } catch {
468
+ return null;
469
+ }
470
+ }
471
+ function parseReleasePlease(_raw, path) {
472
+ return {
473
+ commitConvention: "conventional",
474
+ pullRequestTitleConvention: null,
475
+ allowedTypes: null,
476
+ scopes: null,
477
+ sources: [{ path, detail: "release-please (Conventional Commits)" }]
478
+ };
479
+ }
480
+ function parseSemanticRelease(path) {
481
+ return {
482
+ commitConvention: "conventional",
483
+ pullRequestTitleConvention: null,
484
+ allowedTypes: null,
485
+ scopes: null,
486
+ sources: [{ path, detail: "semantic-release" }]
487
+ };
488
+ }
489
+ function parseChangesetConfig(path) {
490
+ return {
491
+ commitConvention: null,
492
+ pullRequestTitleConvention: null,
493
+ allowedTypes: null,
494
+ scopes: null,
495
+ sources: [{ path, detail: "changesets release flow" }]
496
+ };
497
+ }
498
+ function parseHuskyCommitMsg(path) {
499
+ return {
500
+ commitConvention: null,
501
+ pullRequestTitleConvention: null,
502
+ allowedTypes: null,
503
+ scopes: null,
504
+ sources: [{ path, detail: "husky commit-msg hook" }]
505
+ };
506
+ }
507
+ function parseSemanticPullRequestWorkflow(source, path) {
508
+ return parseSemanticPrWorkflow(source, path);
509
+ }
510
+ var COMMITLINT_FILE_NAMES = COMMITLINT_NAMES;
511
+
61
512
  // src/policy/parsers/labels.ts
62
513
  function parseLabels(payload) {
63
514
  if (!Array.isArray(payload)) return [];
@@ -551,6 +1002,85 @@ async function discoverDocuments(root, scope) {
551
1002
  }
552
1003
  return { documents, sources };
553
1004
  }
1005
+ function asPolicySources(discovered) {
1006
+ return discovered.sources.map((entry) => ({
1007
+ kind: "git-conventions",
1008
+ origin: "filesystem",
1009
+ path: entry.path,
1010
+ status: "found",
1011
+ detail: entry.detail
1012
+ }));
1013
+ }
1014
+ async function discoverGitConventions(root) {
1015
+ let merged = {
1016
+ commitConvention: null,
1017
+ pullRequestTitleConvention: null,
1018
+ allowedTypes: null,
1019
+ scopes: null,
1020
+ sources: []
1021
+ };
1022
+ const take = (extra) => {
1023
+ if (extra === null) return;
1024
+ merged = {
1025
+ commitConvention: merged.commitConvention ?? extra.commitConvention,
1026
+ pullRequestTitleConvention: merged.pullRequestTitleConvention ?? extra.pullRequestTitleConvention,
1027
+ allowedTypes: merged.allowedTypes ?? extra.allowedTypes,
1028
+ scopes: merged.scopes ?? extra.scopes,
1029
+ sources: [...merged.sources, ...extra.sources]
1030
+ };
1031
+ };
1032
+ const pkg = await readCapped(join(root, "package.json"));
1033
+ if (pkg !== null) {
1034
+ take(parsePackageJsonCommitlint(pkg.content));
1035
+ }
1036
+ for (const name of COMMITLINT_FILE_NAMES) {
1037
+ const found = await findFile(root, [name]);
1038
+ if (found === null) continue;
1039
+ const file = await readCapped(join(root, found));
1040
+ if (file === null) continue;
1041
+ take(parseCommitlintText(file.content, found));
1042
+ }
1043
+ for (const name of ["release-please-config.json", ".release-please-manifest.json"]) {
1044
+ const found = await findFile(root, [name]);
1045
+ if (found === null) continue;
1046
+ const file = await readCapped(join(root, found));
1047
+ if (file === null) continue;
1048
+ take(parseReleasePlease(file.content, found));
1049
+ }
1050
+ for (const name of [
1051
+ ".releaserc",
1052
+ ".releaserc.json",
1053
+ ".releaserc.yaml",
1054
+ ".releaserc.yml",
1055
+ "release.config.js"
1056
+ ]) {
1057
+ const found = await findFile(root, [name]);
1058
+ if (found === null) continue;
1059
+ take(parseSemanticRelease(found));
1060
+ }
1061
+ const changeset = await findFile(join(root, ".changeset"), ["config.json"]);
1062
+ if (changeset !== null) {
1063
+ take(parseChangesetConfig(`.changeset/${changeset}`));
1064
+ }
1065
+ const husky = await findFile(join(root, ".husky"), ["commit-msg"]);
1066
+ if (husky !== null) {
1067
+ take(parseHuskyCommitMsg(`.husky/${husky}`));
1068
+ }
1069
+ const workflowDir = join(root, ".github", "workflows");
1070
+ for (const name of await listDirectory(workflowDir)) {
1071
+ if (!/\.ya?ml$/i.test(name)) continue;
1072
+ const file = await readCapped(join(workflowDir, name));
1073
+ if (file === null) continue;
1074
+ take(parseSemanticPullRequestWorkflow(file.content, `.github/workflows/${name}`));
1075
+ }
1076
+ return {
1077
+ commitConvention: merged.commitConvention,
1078
+ pullRequestTitleConvention: merged.pullRequestTitleConvention,
1079
+ allowedTypes: merged.allowedTypes,
1080
+ scopes: merged.scopes,
1081
+ sources: asPolicySources(merged)
1082
+ };
1083
+ }
554
1084
  async function discoverBaseBranch(root, exec = defaultExec) {
555
1085
  const options = { cwd: root, timeout: DISCOVERY_TIMEOUT_MS };
556
1086
  try {
@@ -836,7 +1366,15 @@ function emptyPolicy(root, scope, enabled, sources) {
836
1366
  enabled,
837
1367
  issues: { templates: [], types: [], labels: [], titleConvention: null },
838
1368
  pullRequests: { template: null, templates: [], baseBranch: null, titleConvention: null },
839
- git: { branchConvention: null, commitConvention: null },
1369
+ git: {
1370
+ branchConvention: null,
1371
+ commitConvention: null,
1372
+ pullRequestTitleConvention: null,
1373
+ issueReference: null,
1374
+ typeMap: null,
1375
+ allowedTypes: null,
1376
+ scopes: null
1377
+ },
840
1378
  docs: [],
841
1379
  codeowners: null,
842
1380
  sources
@@ -854,7 +1392,7 @@ function disabledSource(kind) {
854
1392
  var DECLARATION_KINDS = {
855
1393
  issues: "issue-templates",
856
1394
  pullRequests: "pull-request-template",
857
- git: "base-branch"
1395
+ git: "git-conventions"
858
1396
  };
859
1397
  async function resolvePolicy(root, scope, options) {
860
1398
  const warn = options.warn ?? printWarning;
@@ -870,12 +1408,15 @@ async function resolvePolicy(root, scope, options) {
870
1408
  ]);
871
1409
  }
872
1410
  const toggles = config.discovery;
873
- const [templateDiscovery, prTemplates, documents, codeowners] = await Promise.all([
874
- toggles.issueTemplates ? discoverIssueTemplates(root) : Promise.resolve({ templates: [], sources: [disabledSource("issue-templates")] }),
875
- toggles.pullRequestTemplate ? discoverPullRequestTemplates(root) : Promise.resolve({ templates: [], sources: [disabledSource("pull-request-template")] }),
876
- toggles.docs ? discoverDocuments(root, scope) : Promise.resolve({ documents: [], sources: [disabledSource("docs")] }),
877
- toggles.codeowners ? discoverCodeowners(root) : Promise.resolve({ content: null, sources: [disabledSource("codeowners")] })
878
- ]);
1411
+ const [templateDiscovery, prTemplates, documents, codeowners, gitConventions] = await Promise.all(
1412
+ [
1413
+ toggles.issueTemplates ? discoverIssueTemplates(root) : Promise.resolve({ templates: [], sources: [disabledSource("issue-templates")] }),
1414
+ toggles.pullRequestTemplate ? discoverPullRequestTemplates(root) : Promise.resolve({ templates: [], sources: [disabledSource("pull-request-template")] }),
1415
+ toggles.docs ? discoverDocuments(root, scope) : Promise.resolve({ documents: [], sources: [disabledSource("docs")] }),
1416
+ toggles.codeowners ? discoverCodeowners(root) : Promise.resolve({ content: null, sources: [disabledSource("codeowners")] }),
1417
+ discoverGitConventions(root)
1418
+ ]
1419
+ );
879
1420
  const wantsOrgTemplates = toggles.issueTemplates && templateDiscovery.templates.length === 0;
880
1421
  const [baseBranch, slug] = await Promise.all([
881
1422
  discoverBaseBranch(root, options.exec),
@@ -901,7 +1442,8 @@ async function resolvePolicy(root, scope, options) {
901
1442
  ...prTemplates.sources,
902
1443
  ...baseBranch.sources,
903
1444
  ...documents.sources,
904
- ...codeowners.sources
1445
+ ...codeowners.sources,
1446
+ ...gitConventions.sources
905
1447
  ];
906
1448
  const discoveredPullRequests = {};
907
1449
  if (baseBranch.baseBranch !== null) {
@@ -916,8 +1458,30 @@ async function resolvePolicy(root, scope, options) {
916
1458
  discovered: discoveredPullRequests,
917
1459
  project: config.pullRequests
918
1460
  });
1461
+ const discoveredGit = {};
1462
+ if (gitConventions.commitConvention !== null) {
1463
+ discoveredGit.commitConvention = gitConventions.commitConvention;
1464
+ }
1465
+ if (gitConventions.pullRequestTitleConvention !== null) {
1466
+ discoveredGit.pullRequestTitleConvention = gitConventions.pullRequestTitleConvention;
1467
+ }
1468
+ if (gitConventions.allowedTypes !== null) {
1469
+ discoveredGit.allowedTypes = gitConventions.allowedTypes;
1470
+ }
1471
+ if (gitConventions.scopes !== null) {
1472
+ discoveredGit.scopes = gitConventions.scopes;
1473
+ }
919
1474
  const git = mergeConfigLayers({
920
- defaults: { branchConvention: null, commitConvention: null },
1475
+ defaults: {
1476
+ branchConvention: null,
1477
+ commitConvention: null,
1478
+ pullRequestTitleConvention: null,
1479
+ issueReference: null,
1480
+ typeMap: null,
1481
+ allowedTypes: null,
1482
+ scopes: null
1483
+ },
1484
+ discovered: discoveredGit,
921
1485
  project: config.git
922
1486
  });
923
1487
  for (const group of ["issues", "pullRequests", "git"]) {
@@ -950,7 +1514,12 @@ async function resolvePolicy(root, scope, options) {
950
1514
  },
951
1515
  git: {
952
1516
  branchConvention: git.branchConvention ?? null,
953
- commitConvention: git.commitConvention ?? null
1517
+ commitConvention: git.commitConvention ?? null,
1518
+ pullRequestTitleConvention: git.pullRequestTitleConvention ?? null,
1519
+ issueReference: git.issueReference ?? null,
1520
+ typeMap: git.typeMap ?? null,
1521
+ allowedTypes: git.allowedTypes ?? gitConventions.allowedTypes,
1522
+ scopes: git.scopes ?? gitConventions.scopes
954
1523
  },
955
1524
  docs: documents.documents,
956
1525
  codeowners: codeowners.content,
@@ -980,6 +1549,14 @@ async function loadRepositoryPolicy(options = {}) {
980
1549
  }
981
1550
 
982
1551
  export {
1552
+ DEFAULT_BRANCH_CONVENTION,
1553
+ isChangeType,
1554
+ branchName,
1555
+ archiveFolderName,
1556
+ resolveChangeType,
1557
+ commitMessage,
1558
+ pullRequestTitle,
1559
+ issueReferenceLines,
983
1560
  loadRepositoryPolicy
984
1561
  };
985
- //# sourceMappingURL=chunk-EZATO3DW.js.map
1562
+ //# sourceMappingURL=chunk-RVO7L4FX.js.map