@generacy-ai/generacy 0.3.4 → 0.4.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 (219) hide show
  1. package/README.md +153 -0
  2. package/dist/cli/commands/cluster/scaffolder.d.ts.map +1 -1
  3. package/dist/cli/commands/cluster/scaffolder.js +2 -0
  4. package/dist/cli/commands/cluster/scaffolder.js.map +1 -1
  5. package/dist/cli/commands/cockpit/advance.d.ts +42 -0
  6. package/dist/cli/commands/cockpit/advance.d.ts.map +1 -0
  7. package/dist/cli/commands/cockpit/advance.js +136 -0
  8. package/dist/cli/commands/cockpit/advance.js.map +1 -0
  9. package/dist/cli/commands/cockpit/clarification-comment-finder.d.ts +13 -0
  10. package/dist/cli/commands/cockpit/clarification-comment-finder.d.ts.map +1 -0
  11. package/dist/cli/commands/cockpit/clarification-comment-finder.js +31 -0
  12. package/dist/cli/commands/cockpit/clarification-comment-finder.js.map +1 -0
  13. package/dist/cli/commands/cockpit/code-references.d.ts +27 -0
  14. package/dist/cli/commands/cockpit/code-references.d.ts.map +1 -0
  15. package/dist/cli/commands/cockpit/code-references.js +48 -0
  16. package/dist/cli/commands/cockpit/code-references.js.map +1 -0
  17. package/dist/cli/commands/cockpit/context.d.ts +90 -0
  18. package/dist/cli/commands/cockpit/context.d.ts.map +1 -0
  19. package/dist/cli/commands/cockpit/context.js +280 -0
  20. package/dist/cli/commands/cockpit/context.js.map +1 -0
  21. package/dist/cli/commands/cockpit/exit.d.ts +12 -0
  22. package/dist/cli/commands/cockpit/exit.d.ts.map +1 -0
  23. package/dist/cli/commands/cockpit/exit.js +18 -0
  24. package/dist/cli/commands/cockpit/exit.js.map +1 -0
  25. package/dist/cli/commands/cockpit/gate-vocabulary.d.ts +48 -0
  26. package/dist/cli/commands/cockpit/gate-vocabulary.d.ts.map +1 -0
  27. package/dist/cli/commands/cockpit/gate-vocabulary.js +96 -0
  28. package/dist/cli/commands/cockpit/gate-vocabulary.js.map +1 -0
  29. package/dist/cli/commands/cockpit/index.d.ts +20 -0
  30. package/dist/cli/commands/cockpit/index.d.ts.map +1 -0
  31. package/dist/cli/commands/cockpit/index.js +40 -0
  32. package/dist/cli/commands/cockpit/index.js.map +1 -0
  33. package/dist/cli/commands/cockpit/manual-advance-marker.d.ts +18 -0
  34. package/dist/cli/commands/cockpit/manual-advance-marker.d.ts.map +1 -0
  35. package/dist/cli/commands/cockpit/manual-advance-marker.js +43 -0
  36. package/dist/cli/commands/cockpit/manual-advance-marker.js.map +1 -0
  37. package/dist/cli/commands/cockpit/mcp/errors.d.ts +54 -0
  38. package/dist/cli/commands/cockpit/mcp/errors.d.ts.map +1 -0
  39. package/dist/cli/commands/cockpit/mcp/errors.js +190 -0
  40. package/dist/cli/commands/cockpit/mcp/errors.js.map +1 -0
  41. package/dist/cli/commands/cockpit/mcp/event-bus-registry.d.ts +59 -0
  42. package/dist/cli/commands/cockpit/mcp/event-bus-registry.d.ts.map +1 -0
  43. package/dist/cli/commands/cockpit/mcp/event-bus-registry.js +305 -0
  44. package/dist/cli/commands/cockpit/mcp/event-bus-registry.js.map +1 -0
  45. package/dist/cli/commands/cockpit/mcp/event-bus.d.ts +82 -0
  46. package/dist/cli/commands/cockpit/mcp/event-bus.d.ts.map +1 -0
  47. package/dist/cli/commands/cockpit/mcp/event-bus.js +230 -0
  48. package/dist/cli/commands/cockpit/mcp/event-bus.js.map +1 -0
  49. package/dist/cli/commands/cockpit/mcp/index.d.ts +17 -0
  50. package/dist/cli/commands/cockpit/mcp/index.d.ts.map +1 -0
  51. package/dist/cli/commands/cockpit/mcp/index.js +37 -0
  52. package/dist/cli/commands/cockpit/mcp/index.js.map +1 -0
  53. package/dist/cli/commands/cockpit/mcp/ref-input.d.ts +52 -0
  54. package/dist/cli/commands/cockpit/mcp/ref-input.d.ts.map +1 -0
  55. package/dist/cli/commands/cockpit/mcp/ref-input.js +132 -0
  56. package/dist/cli/commands/cockpit/mcp/ref-input.js.map +1 -0
  57. package/dist/cli/commands/cockpit/mcp/schemas.d.ts +287 -0
  58. package/dist/cli/commands/cockpit/mcp/schemas.d.ts.map +1 -0
  59. package/dist/cli/commands/cockpit/mcp/schemas.js +84 -0
  60. package/dist/cli/commands/cockpit/mcp/schemas.js.map +1 -0
  61. package/dist/cli/commands/cockpit/mcp/server.d.ts +17 -0
  62. package/dist/cli/commands/cockpit/mcp/server.d.ts.map +1 -0
  63. package/dist/cli/commands/cockpit/mcp/server.js +62 -0
  64. package/dist/cli/commands/cockpit/mcp/server.js.map +1 -0
  65. package/dist/cli/commands/cockpit/mcp/tools/cockpit_advance.d.ts +42 -0
  66. package/dist/cli/commands/cockpit/mcp/tools/cockpit_advance.d.ts.map +1 -0
  67. package/dist/cli/commands/cockpit/mcp/tools/cockpit_advance.js +73 -0
  68. package/dist/cli/commands/cockpit/mcp/tools/cockpit_advance.js.map +1 -0
  69. package/dist/cli/commands/cockpit/mcp/tools/cockpit_await_events.d.ts +34 -0
  70. package/dist/cli/commands/cockpit/mcp/tools/cockpit_await_events.d.ts.map +1 -0
  71. package/dist/cli/commands/cockpit/mcp/tools/cockpit_await_events.js +115 -0
  72. package/dist/cli/commands/cockpit/mcp/tools/cockpit_await_events.js.map +1 -0
  73. package/dist/cli/commands/cockpit/mcp/tools/cockpit_context.d.ts +21 -0
  74. package/dist/cli/commands/cockpit/mcp/tools/cockpit_context.d.ts.map +1 -0
  75. package/dist/cli/commands/cockpit/mcp/tools/cockpit_context.js +35 -0
  76. package/dist/cli/commands/cockpit/mcp/tools/cockpit_context.js.map +1 -0
  77. package/dist/cli/commands/cockpit/mcp/tools/cockpit_merge.d.ts +43 -0
  78. package/dist/cli/commands/cockpit/mcp/tools/cockpit_merge.d.ts.map +1 -0
  79. package/dist/cli/commands/cockpit/mcp/tools/cockpit_merge.js +99 -0
  80. package/dist/cli/commands/cockpit/mcp/tools/cockpit_merge.js.map +1 -0
  81. package/dist/cli/commands/cockpit/mcp/tools/cockpit_queue.d.ts +43 -0
  82. package/dist/cli/commands/cockpit/mcp/tools/cockpit_queue.d.ts.map +1 -0
  83. package/dist/cli/commands/cockpit/mcp/tools/cockpit_queue.js +68 -0
  84. package/dist/cli/commands/cockpit/mcp/tools/cockpit_queue.js.map +1 -0
  85. package/dist/cli/commands/cockpit/mcp/tools/cockpit_resume.d.ts +38 -0
  86. package/dist/cli/commands/cockpit/mcp/tools/cockpit_resume.d.ts.map +1 -0
  87. package/dist/cli/commands/cockpit/mcp/tools/cockpit_resume.js +79 -0
  88. package/dist/cli/commands/cockpit/mcp/tools/cockpit_resume.js.map +1 -0
  89. package/dist/cli/commands/cockpit/mcp/tools/cockpit_status.d.ts +21 -0
  90. package/dist/cli/commands/cockpit/mcp/tools/cockpit_status.d.ts.map +1 -0
  91. package/dist/cli/commands/cockpit/mcp/tools/cockpit_status.js +59 -0
  92. package/dist/cli/commands/cockpit/mcp/tools/cockpit_status.js.map +1 -0
  93. package/dist/cli/commands/cockpit/merge.d.ts +42 -0
  94. package/dist/cli/commands/cockpit/merge.d.ts.map +1 -0
  95. package/dist/cli/commands/cockpit/merge.js +360 -0
  96. package/dist/cli/commands/cockpit/merge.js.map +1 -0
  97. package/dist/cli/commands/cockpit/plan-dependency-extractor.d.ts +30 -0
  98. package/dist/cli/commands/cockpit/plan-dependency-extractor.d.ts.map +1 -0
  99. package/dist/cli/commands/cockpit/plan-dependency-extractor.js +135 -0
  100. package/dist/cli/commands/cockpit/plan-dependency-extractor.js.map +1 -0
  101. package/dist/cli/commands/cockpit/queue.d.ts +85 -0
  102. package/dist/cli/commands/cockpit/queue.d.ts.map +1 -0
  103. package/dist/cli/commands/cockpit/queue.js +438 -0
  104. package/dist/cli/commands/cockpit/queue.js.map +1 -0
  105. package/dist/cli/commands/cockpit/resolver.d.ts +70 -0
  106. package/dist/cli/commands/cockpit/resolver.d.ts.map +1 -0
  107. package/dist/cli/commands/cockpit/resolver.js +117 -0
  108. package/dist/cli/commands/cockpit/resolver.js.map +1 -0
  109. package/dist/cli/commands/cockpit/resume.d.ts +38 -0
  110. package/dist/cli/commands/cockpit/resume.d.ts.map +1 -0
  111. package/dist/cli/commands/cockpit/resume.js +167 -0
  112. package/dist/cli/commands/cockpit/resume.js.map +1 -0
  113. package/dist/cli/commands/cockpit/shared/classify-issue.d.ts +12 -0
  114. package/dist/cli/commands/cockpit/shared/classify-issue.d.ts.map +1 -0
  115. package/dist/cli/commands/cockpit/shared/classify-issue.js +10 -0
  116. package/dist/cli/commands/cockpit/shared/classify-issue.js.map +1 -0
  117. package/dist/cli/commands/cockpit/shared/failing-check-json.d.ts +53 -0
  118. package/dist/cli/commands/cockpit/shared/failing-check-json.d.ts.map +1 -0
  119. package/dist/cli/commands/cockpit/shared/failing-check-json.js +170 -0
  120. package/dist/cli/commands/cockpit/shared/failing-check-json.js.map +1 -0
  121. package/dist/cli/commands/cockpit/shared/identity.d.ts +54 -0
  122. package/dist/cli/commands/cockpit/shared/identity.d.ts.map +1 -0
  123. package/dist/cli/commands/cockpit/shared/identity.js +65 -0
  124. package/dist/cli/commands/cockpit/shared/identity.js.map +1 -0
  125. package/dist/cli/commands/cockpit/shared/is-done-snapshot.d.ts +16 -0
  126. package/dist/cli/commands/cockpit/shared/is-done-snapshot.d.ts.map +1 -0
  127. package/dist/cli/commands/cockpit/shared/is-done-snapshot.js +17 -0
  128. package/dist/cli/commands/cockpit/shared/is-done-snapshot.js.map +1 -0
  129. package/dist/cli/commands/cockpit/shared/pagination.d.ts +17 -0
  130. package/dist/cli/commands/cockpit/shared/pagination.d.ts.map +1 -0
  131. package/dist/cli/commands/cockpit/shared/pagination.js +50 -0
  132. package/dist/cli/commands/cockpit/shared/pagination.js.map +1 -0
  133. package/dist/cli/commands/cockpit/shared/pr-link.d.ts +8 -0
  134. package/dist/cli/commands/cockpit/shared/pr-link.d.ts.map +1 -0
  135. package/dist/cli/commands/cockpit/shared/pr-link.js +15 -0
  136. package/dist/cli/commands/cockpit/shared/pr-link.js.map +1 -0
  137. package/dist/cli/commands/cockpit/shared/required-checks.d.ts +17 -0
  138. package/dist/cli/commands/cockpit/shared/required-checks.d.ts.map +1 -0
  139. package/dist/cli/commands/cockpit/shared/required-checks.js +38 -0
  140. package/dist/cli/commands/cockpit/shared/required-checks.js.map +1 -0
  141. package/dist/cli/commands/cockpit/shared/review-context-json.d.ts +29 -0
  142. package/dist/cli/commands/cockpit/shared/review-context-json.d.ts.map +1 -0
  143. package/dist/cli/commands/cockpit/shared/review-context-json.js +28 -0
  144. package/dist/cli/commands/cockpit/shared/review-context-json.js.map +1 -0
  145. package/dist/cli/commands/cockpit/status/color.d.ts +11 -0
  146. package/dist/cli/commands/cockpit/status/color.d.ts.map +1 -0
  147. package/dist/cli/commands/cockpit/status/color.js +33 -0
  148. package/dist/cli/commands/cockpit/status/color.js.map +1 -0
  149. package/dist/cli/commands/cockpit/status/group.d.ts +8 -0
  150. package/dist/cli/commands/cockpit/status/group.d.ts.map +1 -0
  151. package/dist/cli/commands/cockpit/status/group.js +35 -0
  152. package/dist/cli/commands/cockpit/status/group.js.map +1 -0
  153. package/dist/cli/commands/cockpit/status/render-table.d.ts +24 -0
  154. package/dist/cli/commands/cockpit/status/render-table.d.ts.map +1 -0
  155. package/dist/cli/commands/cockpit/status/render-table.js +71 -0
  156. package/dist/cli/commands/cockpit/status/render-table.js.map +1 -0
  157. package/dist/cli/commands/cockpit/status/row.d.ts +18 -0
  158. package/dist/cli/commands/cockpit/status/row.d.ts.map +1 -0
  159. package/dist/cli/commands/cockpit/status/row.js +17 -0
  160. package/dist/cli/commands/cockpit/status/row.js.map +1 -0
  161. package/dist/cli/commands/cockpit/status.d.ts +18 -0
  162. package/dist/cli/commands/cockpit/status.d.ts.map +1 -0
  163. package/dist/cli/commands/cockpit/status.js +138 -0
  164. package/dist/cli/commands/cockpit/status.js.map +1 -0
  165. package/dist/cli/commands/cockpit/watch/actionable.d.ts +15 -0
  166. package/dist/cli/commands/cockpit/watch/actionable.d.ts.map +1 -0
  167. package/dist/cli/commands/cockpit/watch/actionable.js +32 -0
  168. package/dist/cli/commands/cockpit/watch/actionable.js.map +1 -0
  169. package/dist/cli/commands/cockpit/watch/aggregate-emit.d.ts +107 -0
  170. package/dist/cli/commands/cockpit/watch/aggregate-emit.d.ts.map +1 -0
  171. package/dist/cli/commands/cockpit/watch/aggregate-emit.js +41 -0
  172. package/dist/cli/commands/cockpit/watch/aggregate-emit.js.map +1 -0
  173. package/dist/cli/commands/cockpit/watch/aggregate.d.ts +25 -0
  174. package/dist/cli/commands/cockpit/watch/aggregate.d.ts.map +1 -0
  175. package/dist/cli/commands/cockpit/watch/aggregate.js +67 -0
  176. package/dist/cli/commands/cockpit/watch/aggregate.js.map +1 -0
  177. package/dist/cli/commands/cockpit/watch/check-rollup.d.ts +9 -0
  178. package/dist/cli/commands/cockpit/watch/check-rollup.d.ts.map +1 -0
  179. package/dist/cli/commands/cockpit/watch/check-rollup.js +22 -0
  180. package/dist/cli/commands/cockpit/watch/check-rollup.js.map +1 -0
  181. package/dist/cli/commands/cockpit/watch/diff.d.ts +29 -0
  182. package/dist/cli/commands/cockpit/watch/diff.d.ts.map +1 -0
  183. package/dist/cli/commands/cockpit/watch/diff.js +85 -0
  184. package/dist/cli/commands/cockpit/watch/diff.js.map +1 -0
  185. package/dist/cli/commands/cockpit/watch/emit.d.ts +58 -0
  186. package/dist/cli/commands/cockpit/watch/emit.d.ts.map +1 -0
  187. package/dist/cli/commands/cockpit/watch/emit.js +30 -0
  188. package/dist/cli/commands/cockpit/watch/emit.js.map +1 -0
  189. package/dist/cli/commands/cockpit/watch/poll-loop.d.ts +29 -0
  190. package/dist/cli/commands/cockpit/watch/poll-loop.d.ts.map +1 -0
  191. package/dist/cli/commands/cockpit/watch/poll-loop.js +81 -0
  192. package/dist/cli/commands/cockpit/watch/poll-loop.js.map +1 -0
  193. package/dist/cli/commands/cockpit/watch/pr-state.d.ts +17 -0
  194. package/dist/cli/commands/cockpit/watch/pr-state.d.ts.map +1 -0
  195. package/dist/cli/commands/cockpit/watch/pr-state.js +33 -0
  196. package/dist/cli/commands/cockpit/watch/pr-state.js.map +1 -0
  197. package/dist/cli/commands/cockpit/watch/snapshot.d.ts +33 -0
  198. package/dist/cli/commands/cockpit/watch/snapshot.d.ts.map +1 -0
  199. package/dist/cli/commands/cockpit/watch/snapshot.js +30 -0
  200. package/dist/cli/commands/cockpit/watch/snapshot.js.map +1 -0
  201. package/dist/cli/commands/cockpit/watch/stream-event.d.ts +82 -0
  202. package/dist/cli/commands/cockpit/watch/stream-event.d.ts.map +1 -0
  203. package/dist/cli/commands/cockpit/watch/stream-event.js +9 -0
  204. package/dist/cli/commands/cockpit/watch/stream-event.js.map +1 -0
  205. package/dist/cli/commands/cockpit/watch.d.ts +22 -0
  206. package/dist/cli/commands/cockpit/watch.d.ts.map +1 -0
  207. package/dist/cli/commands/cockpit/watch.js +186 -0
  208. package/dist/cli/commands/cockpit/watch.js.map +1 -0
  209. package/dist/cli/commands/setup/build.d.ts.map +1 -1
  210. package/dist/cli/commands/setup/build.js +59 -0
  211. package/dist/cli/commands/setup/build.js.map +1 -1
  212. package/dist/cli/index.d.ts.map +1 -1
  213. package/dist/cli/index.js +2 -0
  214. package/dist/cli/index.js.map +1 -1
  215. package/dist/index.d.ts +2 -0
  216. package/dist/index.d.ts.map +1 -1
  217. package/dist/index.js +2 -0
  218. package/dist/index.js.map +1 -1
  219. package/package.json +11 -5
@@ -0,0 +1,360 @@
1
+ import { Command } from 'commander';
2
+ import { getLogger } from '../../utils/logger.js';
3
+ import { CockpitExit } from './exit.js';
4
+ import { resolveIssueContext } from './resolver.js';
5
+ import { classifyChecks } from './shared/required-checks.js';
6
+ import { buildFailingCheckPayload, serializeFailingCheckJson, } from './shared/failing-check-json.js';
7
+ function toPrCandidates(refs) {
8
+ return refs.map((r) => ({
9
+ number: r.number,
10
+ url: r.url,
11
+ isDraft: r.draft,
12
+ headRefName: r.headRefName,
13
+ }));
14
+ }
15
+ // Workflow labels (`waiting-for:*`, `completed:*`) are issue-scoped per the
16
+ // #807-Q2 label protocol. runMerge reads `completed:validate` from
17
+ // IssueStateResult.labels, never from PullRequestDetail.labels.
18
+ const COMPLETED_VALIDATE_LABEL = 'completed:validate';
19
+ /**
20
+ * FR-005 — Commander parser for `--pr <number>`. See contracts/pr-flag-cli.md §2.
21
+ * Throws `CockpitExit(2)` on any malformed input.
22
+ */
23
+ export function parsePrFlag(input) {
24
+ const trimmed = input.trim();
25
+ if (trimmed.length === 0 || !/^\d+$/.test(trimmed)) {
26
+ throw new CockpitExit(2, `merge: --pr must be a positive integer, got: "${input}"`);
27
+ }
28
+ const n = Number.parseInt(trimmed, 10);
29
+ if (!Number.isSafeInteger(n) || n <= 0) {
30
+ throw new CockpitExit(2, `merge: --pr must be a positive integer, got: "${input}"`);
31
+ }
32
+ return n;
33
+ }
34
+ function parseIssueRef(repo, issue) {
35
+ const [owner, name] = repo.split('/');
36
+ if (!owner || !name) {
37
+ throw new Error(`runMerge: repo must be "owner/name", got: ${repo}`);
38
+ }
39
+ return { owner, repo: name, number: issue };
40
+ }
41
+ async function classifyAndDeleteBranch(ctx) {
42
+ const { gh, pr, issueRef, logger } = ctx;
43
+ if (pr.headRepositoryOwner != null &&
44
+ pr.headRepositoryOwner !== issueRef.owner) {
45
+ logger.info({ pr: pr.number, headRef: pr.head, headOwner: pr.headRepositoryOwner }, 'branch deletion skipped: cross-fork PR');
46
+ return 'merged (branch delete skipped: cross-fork PR)\n';
47
+ }
48
+ const repo = `${issueRef.owner}/${issueRef.repo}`;
49
+ const result = await gh.deleteHeadRef(repo, pr.head);
50
+ switch (result.outcome) {
51
+ case 'deleted':
52
+ return 'merged and branch deleted\n';
53
+ case 'already-gone':
54
+ logger.info({ pr: pr.number, headRef: pr.head }, 'branch was already deleted');
55
+ return 'merged (branch was already deleted)\n';
56
+ case 'delete-failed':
57
+ logger.warn({ pr: pr.number, repo, headRef: pr.head, stderr: result.stderr }, 'branch deletion failed');
58
+ return `merged (branch delete failed: ${result.stderr ?? ''})\n`;
59
+ }
60
+ }
61
+ /**
62
+ * Shared merge-tail helper. Fetches issue state, checks completed:validate,
63
+ * fetches required checks, classifies, merges, deletes branch. Extracted from
64
+ * runMerge for reuse by runMergeWithExplicitPr per contracts/pr-flag-cli.md §5.
65
+ */
66
+ async function assertCompletedValidateAndMerge(input) {
67
+ const { gh, repo, issue, issueRef, prNumber, logger, exitPolicy, linkMethod, } = input;
68
+ const refuseExit = exitPolicy === 'pr-flag' ? 3 : 1;
69
+ const pr = await gh.getPullRequestDetail(repo, prNumber);
70
+ let issueState;
71
+ try {
72
+ issueState = await gh.fetchIssueState(repo, issue);
73
+ }
74
+ catch (err) {
75
+ logger.error({ issue, repo, err }, 'Failed to fetch issue state');
76
+ return {
77
+ exitCode: 1,
78
+ stdout: serializeFailingCheckJson(buildFailingCheckPayload({
79
+ reason: 'unresolved',
80
+ pr: null,
81
+ issue: issueRef,
82
+ })),
83
+ };
84
+ }
85
+ if (issueState.state === 'CLOSED') {
86
+ logger.error({
87
+ issue,
88
+ repo,
89
+ state: issueState.state,
90
+ stateReason: issueState.stateReason,
91
+ }, 'Issue is CLOSED');
92
+ return {
93
+ exitCode: refuseExit,
94
+ stdout: serializeFailingCheckJson(buildFailingCheckPayload({
95
+ reason: 'unresolved',
96
+ pr: { number: pr.number, url: pr.url },
97
+ issue: {
98
+ ...issueRef,
99
+ state: issueState.state,
100
+ stateReason: issueState.stateReason,
101
+ },
102
+ })),
103
+ };
104
+ }
105
+ if (!issueState.labels.includes(COMPLETED_VALIDATE_LABEL)) {
106
+ logger.error({ issue, repo, missingLabel: COMPLETED_VALIDATE_LABEL }, 'Issue missing completed:validate label');
107
+ const prPayload = linkMethod !== undefined
108
+ ? { number: pr.number, url: pr.url, linkMethod }
109
+ : // `missing-label` builder invariant I-9 requires linkMethod. Use the
110
+ // dedicated pr-flag `missing-label` payload variant: since the shared
111
+ // builder requires linkMethod for `missing-label`, we synthesize a
112
+ // sentinel for the pr-flag path so both share the schema shape.
113
+ { number: pr.number, url: pr.url, linkMethod: 'closing-refs' };
114
+ return {
115
+ exitCode: refuseExit,
116
+ stdout: serializeFailingCheckJson(buildFailingCheckPayload({
117
+ reason: 'missing-label',
118
+ pr: prPayload,
119
+ issue: issueRef,
120
+ })),
121
+ };
122
+ }
123
+ const [required, actualChecks] = await Promise.all([
124
+ gh.getRequiredCheckNames(repo, pr.base),
125
+ gh.getPullRequestCheckRuns(repo, pr.number),
126
+ ]);
127
+ if (required.source === 'fallback-pr-checks') {
128
+ logger.warn('required-check set derived from PR check list; token cannot read branch protection');
129
+ }
130
+ const noActual = actualChecks.length === 0;
131
+ const noRequired = required.source === 'branch-protection'
132
+ ? (required.names?.length ?? 0) === 0
133
+ : true;
134
+ if (noActual && noRequired) {
135
+ await gh.mergePullRequest(repo, pr.number, { squash: true });
136
+ logger.info({ pr: pr.number }, 'PR merged');
137
+ const deletionSuffix = await classifyAndDeleteBranch({
138
+ gh,
139
+ pr,
140
+ issueRef,
141
+ logger,
142
+ });
143
+ return {
144
+ exitCode: 0,
145
+ stdout: 'no checks configured and none required — proceeding on completed:validate\n' +
146
+ deletionSuffix,
147
+ prNumber: pr.number,
148
+ };
149
+ }
150
+ const { failingChecks, ok } = classifyChecks({ required, actual: actualChecks });
151
+ if (!ok) {
152
+ logger.error({ pr: pr.number, failing: failingChecks.length }, 'PR has failing or pending required checks');
153
+ const prPayload = linkMethod !== undefined
154
+ ? { number: pr.number, url: pr.url, linkMethod }
155
+ : { number: pr.number, url: pr.url, linkMethod: 'closing-refs' };
156
+ return {
157
+ exitCode: refuseExit,
158
+ stdout: serializeFailingCheckJson(buildFailingCheckPayload({
159
+ reason: 'checks-failing',
160
+ pr: prPayload,
161
+ failingChecks,
162
+ issue: issueRef,
163
+ })),
164
+ };
165
+ }
166
+ await gh.mergePullRequest(repo, pr.number, { squash: true });
167
+ logger.info({ pr: pr.number }, 'PR merged');
168
+ const deletionSuffix = await classifyAndDeleteBranch({
169
+ gh,
170
+ pr,
171
+ issueRef,
172
+ logger,
173
+ });
174
+ return { exitCode: 0, stdout: deletionSuffix, prNumber: pr.number };
175
+ }
176
+ export async function runMerge(input) {
177
+ const { gh, issue, repo, logger } = input;
178
+ const issueRef = parseIssueRef(repo, issue);
179
+ const resolution = await gh.resolveIssueToPRRef(repo, issue);
180
+ if (resolution.kind === 'unresolved') {
181
+ logger.error({ issue, repo }, 'No PR resolved for issue');
182
+ return {
183
+ exitCode: 1,
184
+ stdout: serializeFailingCheckJson(buildFailingCheckPayload({
185
+ reason: 'unresolved',
186
+ pr: null,
187
+ issue: issueRef,
188
+ })),
189
+ };
190
+ }
191
+ // #928 — the caller's `<issue>` argument is itself a PR node. Emit a
192
+ // typed refusal at exit-2 with guidance copy; the MCP envelope maps this
193
+ // reason to `class: 'wrong-kind'`. Closes #906 on the CLI at the same time.
194
+ if (resolution.kind === 'pr-number') {
195
+ logger.error({ issue, repo }, `#${issue} is a pull request, not an issue`);
196
+ return {
197
+ exitCode: 2,
198
+ stdout: serializeFailingCheckJson(buildFailingCheckPayload({
199
+ reason: 'pr-number',
200
+ pr: null,
201
+ issue: issueRef,
202
+ hint: `#${issue} is a pull request; pass the issue number ` +
203
+ `(e.g. the issue whose closing PR is #${issue}).`,
204
+ })),
205
+ };
206
+ }
207
+ if (resolution.kind === 'pr-is-draft') {
208
+ logger.error({
209
+ issue,
210
+ repo,
211
+ linkMethod: resolution.linkMethod,
212
+ candidates: resolution.candidates.map((c) => c.number),
213
+ }, 'Resolved PRs are drafts');
214
+ return {
215
+ exitCode: 1,
216
+ stdout: serializeFailingCheckJson(buildFailingCheckPayload({
217
+ reason: 'pr-is-draft',
218
+ pr: null,
219
+ candidates: toPrCandidates(resolution.candidates),
220
+ linkMethod: resolution.linkMethod,
221
+ issue: issueRef,
222
+ })),
223
+ };
224
+ }
225
+ if (resolution.kind === 'ambiguous') {
226
+ logger.error({
227
+ issue,
228
+ repo,
229
+ linkMethod: resolution.linkMethod,
230
+ candidates: resolution.candidates.map((c) => c.number),
231
+ }, 'Multiple PRs resolved for issue');
232
+ return {
233
+ exitCode: 1,
234
+ stdout: serializeFailingCheckJson(buildFailingCheckPayload({
235
+ reason: 'ambiguous-resolution',
236
+ pr: null,
237
+ candidates: toPrCandidates(resolution.candidates),
238
+ linkMethod: resolution.linkMethod,
239
+ issue: issueRef,
240
+ })),
241
+ };
242
+ }
243
+ // Exhaustiveness guard — after the branches above, resolution.kind is
244
+ // 'resolved'. Adding a new arm to PullRequestRefResolution surfaces here
245
+ // at build time.
246
+ const _exhaustive = resolution.kind;
247
+ void _exhaustive;
248
+ const prRef = resolution.ref;
249
+ const linkMethod = resolution.linkMethod;
250
+ // FR-004: log the resolved PR + tier BEFORE any subsequent gh call so a
251
+ // later failure never erases the evidence of which PR was targeted.
252
+ logger.info({ pr: prRef.number, linkMethod }, `resolved PR #${prRef.number} via ${linkMethod}`);
253
+ return assertCompletedValidateAndMerge({
254
+ gh,
255
+ repo,
256
+ issue,
257
+ issueRef,
258
+ prNumber: prRef.number,
259
+ logger,
260
+ exitPolicy: 'resolver',
261
+ linkMethod,
262
+ });
263
+ }
264
+ /**
265
+ * FR-005..FR-008 — `--pr <number>` escape hatch. Skips the tier-1/2/3 resolver
266
+ * chain but keeps every safety precondition. Gate order per contracts/pr-flag-cli.md §3.
267
+ */
268
+ export async function runMergeWithExplicitPr(input) {
269
+ const { gh, issue, repo, prNumber, logger } = input;
270
+ const issueRef = parseIssueRef(repo, issue);
271
+ const pr = await gh.getPullRequestGraphqlDetail(repo, prNumber);
272
+ // Gate 1 — FR-006a linkage.
273
+ const declares = pr.closingIssuesReferences.some((l) => l.nameWithOwner === repo && l.number === issue);
274
+ if (!declares) {
275
+ const kind = pr.closingIssuesReferences.length === 0 ? 'empty-refs' : 'mismatch';
276
+ const message = kind === 'empty-refs'
277
+ ? `--pr ${prNumber} refused: PR #${prNumber} declares no closing issues. Add ${repo}#${issue} via the PR's Development sidebar link, then re-run.`
278
+ : `--pr ${prNumber} refused: PR #${prNumber} does not declare ${repo}#${issue} as a closing issue. Add ${repo}#${issue} via the PR's Development sidebar link, then re-run.`;
279
+ logger.error({ pr: prNumber, issue, repo, kind }, `--pr linkage refused: ${kind}`);
280
+ return {
281
+ exitCode: 3,
282
+ stdout: serializeFailingCheckJson(buildFailingCheckPayload({
283
+ reason: 'pr-flag-linkage-refused',
284
+ pr: { number: prNumber, url: '' },
285
+ kind,
286
+ message,
287
+ issue: issueRef,
288
+ })),
289
+ };
290
+ }
291
+ // Gate 2 — FR-006b state classifier.
292
+ if (pr.state === 'MERGED') {
293
+ logger.info({ pr: prNumber }, `PR #${prNumber} already merged, no-op`);
294
+ return {
295
+ exitCode: 0,
296
+ stdout: `PR #${prNumber} already merged, no-op\n`,
297
+ prNumber,
298
+ };
299
+ }
300
+ if (pr.state === 'CLOSED') {
301
+ logger.error({ pr: prNumber }, 'PR is closed without merge');
302
+ return {
303
+ exitCode: 3,
304
+ stdout: serializeFailingCheckJson(buildFailingCheckPayload({
305
+ reason: 'pr-flag-closed-unmerged',
306
+ pr: { number: prNumber, url: '' },
307
+ message: `--pr ${prNumber} refused: PR #${prNumber} is closed without merge.`,
308
+ issue: issueRef,
309
+ })),
310
+ };
311
+ }
312
+ // state === 'OPEN' → continue.
313
+ // Gates 3 & 4 — delegate to shared tail with pr-flag exitPolicy.
314
+ return assertCompletedValidateAndMerge({
315
+ gh,
316
+ repo,
317
+ issue,
318
+ issueRef,
319
+ prNumber,
320
+ logger,
321
+ exitPolicy: 'pr-flag',
322
+ });
323
+ }
324
+ export function cockpitMergeCommand() {
325
+ const cmd = new Command('merge');
326
+ cmd
327
+ .description('Squash-merge the PR for <issue> iff it carries completed:validate and every required check is green')
328
+ .argument('<issue>', 'GitHub issue number')
329
+ .option('--repo <repo>', 'Owner/name (inferred from cwd if absent)')
330
+ .option('--pr <number>', 'Escape hatch — target this PR directly, skipping issue→PR resolution. ' +
331
+ '<issue> remains required as the authorization source for completed:validate. ' +
332
+ 'Enforces linkage verification and all safety preconditions; never bypasses safety.', parsePrFlag)
333
+ .action(async (issueArg, opts) => {
334
+ const logger = getLogger();
335
+ const ctx = await resolveIssueContext({
336
+ issue: issueArg,
337
+ repo: opts.repo,
338
+ });
339
+ const result = opts.pr != null
340
+ ? await runMergeWithExplicitPr({
341
+ gh: ctx.gh,
342
+ issue: ctx.ref.number,
343
+ repo: ctx.repo,
344
+ prNumber: opts.pr,
345
+ logger,
346
+ })
347
+ : await runMerge({
348
+ gh: ctx.gh,
349
+ issue: ctx.ref.number,
350
+ repo: ctx.repo,
351
+ logger,
352
+ });
353
+ if (result.stdout.length > 0) {
354
+ process.stdout.write(result.stdout);
355
+ }
356
+ process.exit(result.exitCode);
357
+ });
358
+ return cmd;
359
+ }
360
+ //# sourceMappingURL=merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.js","sourceRoot":"","sources":["../../../../src/cli/commands/cockpit/merge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Extracts declared cross-issue dependencies from a spec's `plan.md` file.
3
+ *
4
+ * v1 heuristic (contracts/plan-dependency-warning.md §Extractor):
5
+ * - Trigger verbs: `must be merged`, `must merge first`, `depends on`, `depends-on`,
6
+ * `requires`, `extends`, `blocked by`, `prerequisite`.
7
+ * - Extract `#\d+` (bare) → `{ defaultOwner, defaultRepo, N }`
8
+ * - Extract `[\w-]+/[\w-]+#\d+` → cross-repo
9
+ * - Search the trigger line PLUS the immediately-following line (wrapping tolerance).
10
+ * - Skip fenced code blocks (` ``` `) and inline code (backticks).
11
+ * - De-duplicate by `owner/repo/number`, preserving first-occurrence order.
12
+ *
13
+ * `originatingText` is derived from the trigger line, bounded to 120 chars.
14
+ */
15
+ export interface DependencyRef {
16
+ owner: string;
17
+ repo: string;
18
+ number: number;
19
+ /** The originating span from the plan.md line (bounded to 120 chars). */
20
+ originatingText: string;
21
+ }
22
+ /**
23
+ * Extract dependency refs from `plan.md` markdown.
24
+ *
25
+ * @param planMarkdown Raw markdown body.
26
+ * @param defaultOwner Owner for bare `#N` refs (typically the current issue's owner).
27
+ * @param defaultRepo Repo for bare `#N` refs (typically the current issue's repo).
28
+ */
29
+ export declare function extractPlanDependencies(planMarkdown: string, defaultOwner: string, defaultRepo: string): DependencyRef[];
30
+ //# sourceMappingURL=plan-dependency-extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-dependency-extractor.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/cockpit/plan-dependency-extractor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,eAAe,EAAE,MAAM,CAAC;CACzB;AAsCD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,GAClB,aAAa,EAAE,CAuFjB"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Extracts declared cross-issue dependencies from a spec's `plan.md` file.
3
+ *
4
+ * v1 heuristic (contracts/plan-dependency-warning.md §Extractor):
5
+ * - Trigger verbs: `must be merged`, `must merge first`, `depends on`, `depends-on`,
6
+ * `requires`, `extends`, `blocked by`, `prerequisite`.
7
+ * - Extract `#\d+` (bare) → `{ defaultOwner, defaultRepo, N }`
8
+ * - Extract `[\w-]+/[\w-]+#\d+` → cross-repo
9
+ * - Search the trigger line PLUS the immediately-following line (wrapping tolerance).
10
+ * - Skip fenced code blocks (` ``` `) and inline code (backticks).
11
+ * - De-duplicate by `owner/repo/number`, preserving first-occurrence order.
12
+ *
13
+ * `originatingText` is derived from the trigger line, bounded to 120 chars.
14
+ */
15
+ const TRIGGER_VERBS = [
16
+ 'must be merged',
17
+ 'must merge first',
18
+ 'depends on',
19
+ 'depends-on',
20
+ 'requires',
21
+ 'extends',
22
+ 'blocked by',
23
+ 'prerequisite',
24
+ ];
25
+ const CROSS_REPO_REF = /([A-Za-z0-9][\w-]*)\/([A-Za-z0-9][\w-]*)#(\d+)/g;
26
+ const BARE_REF = /#(\d+)/g;
27
+ const ORIGINATING_TEXT_MAX = 120;
28
+ /**
29
+ * Strip inline code spans (`...`) from a line so bare-ref regex doesn't match inside them.
30
+ *
31
+ * Handles the simple case of paired backticks; unpaired backticks are preserved.
32
+ */
33
+ function stripInlineCode(line) {
34
+ return line.replace(/`[^`\n]*`/g, '');
35
+ }
36
+ function boundOriginatingText(line) {
37
+ const trimmed = line.trim();
38
+ if (trimmed.length <= ORIGINATING_TEXT_MAX)
39
+ return trimmed;
40
+ return trimmed.slice(0, ORIGINATING_TEXT_MAX);
41
+ }
42
+ function lineHasTrigger(line) {
43
+ const lower = line.toLowerCase();
44
+ return TRIGGER_VERBS.some((v) => lower.includes(v));
45
+ }
46
+ /**
47
+ * Extract dependency refs from `plan.md` markdown.
48
+ *
49
+ * @param planMarkdown Raw markdown body.
50
+ * @param defaultOwner Owner for bare `#N` refs (typically the current issue's owner).
51
+ * @param defaultRepo Repo for bare `#N` refs (typically the current issue's repo).
52
+ */
53
+ export function extractPlanDependencies(planMarkdown, defaultOwner, defaultRepo) {
54
+ const lines = planMarkdown.split('\n');
55
+ const results = [];
56
+ const seen = new Set();
57
+ let inFence = false;
58
+ for (let i = 0; i < lines.length; i++) {
59
+ const rawLine = lines[i];
60
+ const trimmed = rawLine.trim();
61
+ // Toggle fenced-code-block state on ``` boundaries.
62
+ if (trimmed.startsWith('```')) {
63
+ inFence = !inFence;
64
+ continue;
65
+ }
66
+ if (inFence)
67
+ continue;
68
+ if (!lineHasTrigger(rawLine))
69
+ continue;
70
+ // Wrap tolerance: also scan the following non-fence line (if any).
71
+ const triggerLine = stripInlineCode(rawLine);
72
+ let followingLine = '';
73
+ if (i + 1 < lines.length) {
74
+ const nextRaw = lines[i + 1];
75
+ // Stop before a fenced-code boundary.
76
+ if (!nextRaw.trim().startsWith('```')) {
77
+ followingLine = stripInlineCode(nextRaw);
78
+ }
79
+ }
80
+ const searchSpan = `${triggerLine}\n${followingLine}`;
81
+ const originatingText = boundOriginatingText(rawLine);
82
+ // Cross-repo mentions first (they consume the trailing `#N`).
83
+ const crossRepoMatches = [];
84
+ CROSS_REPO_REF.lastIndex = 0;
85
+ let m;
86
+ while ((m = CROSS_REPO_REF.exec(searchSpan)) !== null) {
87
+ const num = Number.parseInt(m[3], 10);
88
+ if (Number.isFinite(num) && num > 0) {
89
+ crossRepoMatches.push({
90
+ owner: m[1],
91
+ repo: m[2],
92
+ number: num,
93
+ matchStart: m.index,
94
+ matchEnd: m.index + m[0].length,
95
+ });
96
+ }
97
+ }
98
+ for (const cr of crossRepoMatches) {
99
+ const key = `${cr.owner}/${cr.repo}#${cr.number}`;
100
+ if (!seen.has(key)) {
101
+ seen.add(key);
102
+ results.push({
103
+ owner: cr.owner,
104
+ repo: cr.repo,
105
+ number: cr.number,
106
+ originatingText,
107
+ });
108
+ }
109
+ }
110
+ // Bare `#N` — must not be part of a cross-repo match already consumed.
111
+ BARE_REF.lastIndex = 0;
112
+ while ((m = BARE_REF.exec(searchSpan)) !== null) {
113
+ const matchStart = m.index;
114
+ const matchEnd = matchStart + m[0].length;
115
+ const insideCrossRepo = crossRepoMatches.some((cr) => matchStart >= cr.matchStart && matchEnd <= cr.matchEnd);
116
+ if (insideCrossRepo)
117
+ continue;
118
+ const num = Number.parseInt(m[1], 10);
119
+ if (!Number.isFinite(num) || num <= 0)
120
+ continue;
121
+ const key = `${defaultOwner}/${defaultRepo}#${num}`;
122
+ if (seen.has(key))
123
+ continue;
124
+ seen.add(key);
125
+ results.push({
126
+ owner: defaultOwner,
127
+ repo: defaultRepo,
128
+ number: num,
129
+ originatingText,
130
+ });
131
+ }
132
+ }
133
+ return results;
134
+ }
135
+ //# sourceMappingURL=plan-dependency-extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-dependency-extractor.js","sourceRoot":"","sources":["../../../../src/cli/commands/cockpit/plan-dependency-extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * `generacy cockpit queue <epic-ref> <phase>` — enqueue every eligible ref
3
+ * listed under the matched `### <phase>` heading in the epic body.
4
+ *
5
+ * Pipeline:
6
+ * 1. resolveEpic(epicRef) → matchPhaseHeading(phase).
7
+ * 2. Per ref in the matched phase: gh issue view → classifyRow → eligible or [SKIP: …].
8
+ * 3. Print preview; if !--yes, prompt; on confirm, assign + label best-effort.
9
+ */
10
+ import { Command } from 'commander';
11
+ import { loadCockpitConfig, type CommandRunner, type GhWrapper, type IssueRef, type ParsedPhase, type ResolvedEpic } from '@generacy-ai/cockpit';
12
+ import { type DependencyRef } from './plan-dependency-extractor.js';
13
+ export interface QueueOptions {
14
+ label?: string;
15
+ repo?: string;
16
+ assignee?: string;
17
+ yes?: boolean;
18
+ }
19
+ export type EligibilityStatus = {
20
+ kind: 'eligible';
21
+ workflowLabel: string;
22
+ } | {
23
+ kind: 'skip';
24
+ reason: 'closed' | 'cross-repo' | 'already-labeled' | 'not-found';
25
+ };
26
+ export type MutationOutcome = {
27
+ kind: 'ok';
28
+ } | {
29
+ kind: 'already';
30
+ } | {
31
+ kind: 'error';
32
+ reason: string;
33
+ };
34
+ /** Warning state observed at queue time for a plan.md-declared dependency (#864). */
35
+ export type DependencyWarningState = 'unresolved' | 'closed-unmerged';
36
+ export interface DependencyWarning {
37
+ ref: DependencyRef;
38
+ state: DependencyWarningState;
39
+ }
40
+ export interface QueueRow {
41
+ ref: IssueRef;
42
+ title: string;
43
+ labels: string[];
44
+ assignees: string[];
45
+ eligibility: EligibilityStatus;
46
+ /**
47
+ * Present only when eligibility.kind === 'eligible', the phase heading matches
48
+ * /implement/i, and plan.md-declared prerequisites are not yet merged (#864).
49
+ */
50
+ dependencyWarnings?: DependencyWarning[];
51
+ assignResult?: MutationOutcome;
52
+ labelResult?: MutationOutcome;
53
+ }
54
+ export interface QueueResult {
55
+ epic: ResolvedEpic;
56
+ phase: ParsedPhase;
57
+ targetRepo: string;
58
+ workflowLabel: string;
59
+ assignee: string;
60
+ rows: QueueRow[];
61
+ confirmed: boolean;
62
+ exitCode: 0 | 1 | 2;
63
+ }
64
+ /**
65
+ * Fetches the raw `plan.md` for a given issue via the GitHub API.
66
+ * Returns `null` when the file (or spec directory) doesn't exist yet.
67
+ */
68
+ export type PlanFetcher = (ref: IssueRef) => Promise<string | null>;
69
+ export interface QueueCommandDeps {
70
+ runner?: CommandRunner;
71
+ gh?: GhWrapper;
72
+ cockpitGh?: GhWrapper;
73
+ loadConfig?: typeof loadCockpitConfig;
74
+ env?: NodeJS.ProcessEnv;
75
+ prompt?: (message: string) => Promise<boolean>;
76
+ stdout?: (line: string) => void;
77
+ stderr?: (line: string) => void;
78
+ /** Optional plan.md fetcher — defaults to a `gh api` call via `deps.runner`. */
79
+ fetchPlan?: PlanFetcher;
80
+ }
81
+ export declare function renderPreview(epic: ResolvedEpic, phase: ParsedPhase, targetRepo: string, workflowLabel: string, assignee: string, rows: QueueRow[]): string[];
82
+ export declare function renderSummary(rows: QueueRow[]): string[];
83
+ export declare function runQueue(epicRef: string | undefined, phaseArg: string | undefined, opts: QueueOptions, deps: QueueCommandDeps): Promise<QueueResult>;
84
+ export declare function queueCommand(deps?: QueueCommandDeps): Command;
85
+ //# sourceMappingURL=queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/cockpit/queue.ts"],"names":[],"mappings":"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"}