@generacy-ai/generacy 0.3.3 → 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,38 @@
1
+ /**
2
+ * `generacy cockpit resume <issue>` — re-arm a failed phase in place.
3
+ *
4
+ * Engine-owned label surgery: on an issue carrying `failed:<phase>` (with or
5
+ * without `agent:error`), applies the additions `waiting-for:<preceding-gate>`
6
+ * + `completed:<preceding-gate>` + `agent:paused` FIRST, then removes
7
+ * `failed:<phase>` plus defensive `agent:error` / `phase:<phase>` when
8
+ * present. The terminal on-issue state is byte-identical to a
9
+ * naturally-paused-then-completed gate — the label monitor's next poll emits
10
+ * a resume event, and the worker's `PhaseResolver.resolveFromContinue` walks
11
+ * the preserved `completed:<earlier-phase>` chain to pick `<phase>` as the
12
+ * start phase.
13
+ *
14
+ * Side effects (in order):
15
+ * 1. gh addLabels [waiting-for:<G>, completed:<G>, agent:paused]
16
+ * 2. gh removeLabels [failed:<phase>, ...conditional]
17
+ *
18
+ * Idempotent (FR-003): no `failed:*` → no-op with single-line stdout, exit 0.
19
+ * Refuses (FR-004) with evidence and zero mutations when the state is
20
+ * ambiguous or non-re-armable. No `--force` in v1 (parity with `advance`).
21
+ */
22
+ import { Command } from 'commander';
23
+ import { loadCockpitConfig, type CommandRunner, type GhWrapper } from '@generacy-ai/cockpit';
24
+ export interface ResumeCommandDeps {
25
+ runner?: CommandRunner;
26
+ gh?: GhWrapper;
27
+ loadConfig?: typeof loadCockpitConfig;
28
+ env?: NodeJS.ProcessEnv;
29
+ now?: () => Date;
30
+ stdout?: (line: string) => void;
31
+ stderr?: (line: string) => void;
32
+ }
33
+ export interface ResumeOptions {
34
+ workflow?: string;
35
+ }
36
+ export declare function resumeCommand(deps?: ResumeCommandDeps): Command;
37
+ export declare function runResume(issue: string | undefined, opts: ResumeOptions, deps: ResumeCommandDeps): Promise<void>;
38
+ //# sourceMappingURL=resume.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/cockpit/resume.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,iBAAiB,EACjB,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,sBAAsB,CAAC;AAO9B,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,EAAE,CAAC,EAAE,SAAS,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,iBAAiB,CAAC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAwFD,wBAAgB,aAAa,CAAC,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAmBnE;AAED,wBAAsB,SAAS,CAC7B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,IAAI,EAAE,aAAa,EACnB,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,IAAI,CAAC,CA2Ff"}
@@ -0,0 +1,167 @@
1
+ /**
2
+ * `generacy cockpit resume <issue>` — re-arm a failed phase in place.
3
+ *
4
+ * Engine-owned label surgery: on an issue carrying `failed:<phase>` (with or
5
+ * without `agent:error`), applies the additions `waiting-for:<preceding-gate>`
6
+ * + `completed:<preceding-gate>` + `agent:paused` FIRST, then removes
7
+ * `failed:<phase>` plus defensive `agent:error` / `phase:<phase>` when
8
+ * present. The terminal on-issue state is byte-identical to a
9
+ * naturally-paused-then-completed gate — the label monitor's next poll emits
10
+ * a resume event, and the worker's `PhaseResolver.resolveFromContinue` walks
11
+ * the preserved `completed:<earlier-phase>` chain to pick `<phase>` as the
12
+ * start phase.
13
+ *
14
+ * Side effects (in order):
15
+ * 1. gh addLabels [waiting-for:<G>, completed:<G>, agent:paused]
16
+ * 2. gh removeLabels [failed:<phase>, ...conditional]
17
+ *
18
+ * Idempotent (FR-003): no `failed:*` → no-op with single-line stdout, exit 0.
19
+ * Refuses (FR-004) with evidence and zero mutations when the state is
20
+ * ambiguous or non-re-armable. No `--force` in v1 (parity with `advance`).
21
+ */
22
+ import { Command } from 'commander';
23
+ import { loadCockpitConfig, } from '@generacy-ai/cockpit';
24
+ import { getLogger } from '../../utils/logger.js';
25
+ import { resolveIssueContext } from './resolver.js';
26
+ import { resolvePrecedingGate } from './gate-vocabulary.js';
27
+ import { CockpitExit, isCockpitExit } from './exit.js';
28
+ const KNOWN_PHASES = [
29
+ 'specify',
30
+ 'clarify',
31
+ 'plan',
32
+ 'tasks',
33
+ 'implement',
34
+ 'validate',
35
+ ];
36
+ function isKnownPhase(candidate) {
37
+ return KNOWN_PHASES.includes(candidate);
38
+ }
39
+ function resolveWorkflowFromLabels(labels) {
40
+ const workflowLabel = labels.find((l) => l.startsWith('workflow:'));
41
+ if (workflowLabel) {
42
+ return workflowLabel.slice('workflow:'.length);
43
+ }
44
+ return 'speckit-feature';
45
+ }
46
+ function classify(labels, workflowOverride) {
47
+ const failedLabels = labels.filter((l) => l.startsWith('failed:')).sort();
48
+ if (failedLabels.length === 0) {
49
+ return { kind: 'no-op' };
50
+ }
51
+ if (failedLabels.length > 1) {
52
+ return { kind: 'refuse-multiple-failed', failedLabels };
53
+ }
54
+ const failedLabel = failedLabels[0];
55
+ const phaseSuffix = failedLabel.slice('failed:'.length);
56
+ if (!isKnownPhase(phaseSuffix)) {
57
+ return { kind: 'refuse-unknown-phase', failedLabel, phaseSuffix };
58
+ }
59
+ const failedPhase = phaseSuffix;
60
+ const workflowName = workflowOverride ?? resolveWorkflowFromLabels(labels);
61
+ const gateResult = resolvePrecedingGate(failedPhase, workflowName);
62
+ if (gateResult.kind === 'no-preceding-gate') {
63
+ return { kind: 'refuse-no-preceding-gate', failedPhase, workflowName };
64
+ }
65
+ const gate = gateResult.gate;
66
+ const conflictingWaiting = labels.find((l) => l.startsWith('waiting-for:') && l !== gate.waitingLabel);
67
+ if (conflictingWaiting) {
68
+ return {
69
+ kind: 'refuse-conflicting-waiting',
70
+ failedPhase,
71
+ conflictingLabel: conflictingWaiting,
72
+ expectedLabel: gate.waitingLabel,
73
+ };
74
+ }
75
+ const labelsToAdd = [gate.waitingLabel, gate.completedLabel, 'agent:paused'];
76
+ const labelsToRemove = [failedLabel];
77
+ if (labels.includes('agent:error'))
78
+ labelsToRemove.push('agent:error');
79
+ const phaseLabel = `phase:${failedPhase}`;
80
+ if (labels.includes(phaseLabel))
81
+ labelsToRemove.push(phaseLabel);
82
+ return { kind: 'happy-path', failedPhase, gate, labelsToAdd, labelsToRemove };
83
+ }
84
+ export function resumeCommand(deps = {}) {
85
+ const cmd = new Command('resume');
86
+ cmd
87
+ .description('Re-arm a failed phase in place so the next poll re-runs it.')
88
+ .argument('[issue]', 'Issue ref — <number>, <owner>/<repo>#<n>, or full URL.')
89
+ .option('--workflow <name>', 'Workflow name override (defaults to the issue\'s workflow:<name> label).')
90
+ .action(async (issue, opts) => {
91
+ try {
92
+ await runResume(issue, opts, deps);
93
+ }
94
+ catch (err) {
95
+ if (isCockpitExit(err)) {
96
+ const stderr = deps.stderr ?? ((line) => process.stderr.write(`${line}\n`));
97
+ stderr(err.message);
98
+ process.exit(err.code);
99
+ }
100
+ throw err;
101
+ }
102
+ });
103
+ return cmd;
104
+ }
105
+ export async function runResume(issue, opts, deps) {
106
+ const log = getLogger();
107
+ const print = deps.stdout ?? ((line) => process.stdout.write(`${line}\n`));
108
+ if (issue == null || issue.trim() === '') {
109
+ throw new CockpitExit(2, 'Error: cockpit resume: missing required argument <issue>');
110
+ }
111
+ const loaded = await (deps.loadConfig ?? loadCockpitConfig)({});
112
+ for (const w of loaded.warnings)
113
+ log.warn(w);
114
+ let ref;
115
+ let gh;
116
+ try {
117
+ const resolvedCtx = await resolveIssueContext({ issue, runner: deps.runner });
118
+ ref = resolvedCtx.ref;
119
+ gh = deps.gh ?? resolvedCtx.gh;
120
+ }
121
+ catch (err) {
122
+ throw new CockpitExit(2, `Error: cockpit resume: ${err.message}`);
123
+ }
124
+ let labels;
125
+ try {
126
+ labels = (await gh.fetchIssueLabels(ref.nwo, ref.number)).labels;
127
+ }
128
+ catch (err) {
129
+ throw new CockpitExit(1, `Error: cockpit resume: gh issue view: ${err.message}`);
130
+ }
131
+ const decision = classify(labels, opts.workflow);
132
+ switch (decision.kind) {
133
+ case 'no-op':
134
+ print(`issue ${ref.nwo}#${ref.number} is not in a failed state (no failed:<phase> label); nothing to re-arm`);
135
+ return;
136
+ case 'refuse-multiple-failed':
137
+ throw new CockpitExit(3, `Error: cockpit resume: refusing to resume: multiple failed:* labels present: [${decision.failedLabels.join(', ')}]`);
138
+ case 'refuse-unknown-phase':
139
+ throw new CockpitExit(3, `Error: cockpit resume: refusing to resume: unknown phase "${decision.phaseSuffix}" in label "${decision.failedLabel}"`);
140
+ case 'refuse-no-preceding-gate':
141
+ throw new CockpitExit(3, `Error: cockpit resume: refusing to resume: phase "${decision.failedPhase}" has no preceding gate; ` +
142
+ `use \`process:${decision.workflowName}\` label to re-queue from the beginning instead`);
143
+ case 'refuse-conflicting-waiting':
144
+ throw new CockpitExit(3, `Error: cockpit resume: refusing to resume: conflicting ${decision.conflictingLabel} already present; ` +
145
+ `derived preceding-gate is ${decision.expectedLabel.slice('waiting-for:'.length)}`);
146
+ case 'happy-path': {
147
+ try {
148
+ await gh.addLabels(ref.nwo, ref.number, decision.labelsToAdd);
149
+ }
150
+ catch (err) {
151
+ throw new CockpitExit(1, `Error: cockpit resume: gh issue edit (add ${decision.labelsToAdd.join(',')}): ${err.message}`);
152
+ }
153
+ try {
154
+ await gh.removeLabels(ref.nwo, ref.number, decision.labelsToRemove);
155
+ }
156
+ catch (err) {
157
+ throw new CockpitExit(1, `Error: cockpit resume: gh issue edit (remove ${decision.labelsToRemove.join(',')}): ${err.message}`);
158
+ }
159
+ print(`resumed ${ref.nwo}#${ref.number}: re-armed phase=${decision.failedPhase} ` +
160
+ `via preceding-gate=${decision.gate.name}; ` +
161
+ `added=[${decision.labelsToAdd.join(',')}] ` +
162
+ `removed=[${decision.labelsToRemove.join(',')}]`);
163
+ return;
164
+ }
165
+ }
166
+ }
167
+ //# sourceMappingURL=resume.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume.js","sourceRoot":"","sources":["../../../../src/cli/commands/cockpit/resume.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { CockpitState } from '@generacy-ai/cockpit';
2
+ export interface ClassifiedIssue {
3
+ state: CockpitState;
4
+ sourceLabel: string;
5
+ labels: string[];
6
+ }
7
+ /**
8
+ * Thin wrapper over `classify(labels)` — always returns `{ state, sourceLabel, labels }`
9
+ * with `labels` preserved alongside the classification.
10
+ */
11
+ export declare function classifyIssue(labels: string[]): ClassifiedIssue;
12
+ //# sourceMappingURL=classify-issue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classify-issue.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/cockpit/shared/classify-issue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGzD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,YAAY,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,eAAe,CAG/D"}
@@ -0,0 +1,10 @@
1
+ import { classify } from '@generacy-ai/cockpit';
2
+ /**
3
+ * Thin wrapper over `classify(labels)` — always returns `{ state, sourceLabel, labels }`
4
+ * with `labels` preserved alongside the classification.
5
+ */
6
+ export function classifyIssue(labels) {
7
+ const { state, sourceLabel } = classify(labels);
8
+ return { state, sourceLabel, labels: [...labels] };
9
+ }
10
+ //# sourceMappingURL=classify-issue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classify-issue.js","sourceRoot":"","sources":["../../../../../src/cli/commands/cockpit/shared/classify-issue.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAQhD;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,MAAgB;IAC5C,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChD,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC;AACrD,CAAC"}
@@ -0,0 +1,53 @@
1
+ import type { LinkMethod, PrCandidate } from '@generacy-ai/cockpit';
2
+ import type { FailingCheck } from './required-checks.js';
3
+ export type { LinkMethod, PrCandidate } from '@generacy-ai/cockpit';
4
+ export type RedReason = 'checks-failing' | 'missing-label' | 'unresolved' | 'pr-is-draft' | 'ambiguous-resolution' | 'pr-flag-linkage-refused' | 'pr-flag-closed-unmerged' | 'pr-number';
5
+ /** FR-006a — sub-kind for `pr-flag-linkage-refused` refusals. */
6
+ export type PrFlagLinkageKind = 'empty-refs' | 'mismatch';
7
+ export interface IssueRefWithState {
8
+ owner: string;
9
+ repo: string;
10
+ number: number;
11
+ state?: 'OPEN' | 'CLOSED';
12
+ stateReason?: string | null;
13
+ }
14
+ export interface FailingCheckPayload {
15
+ status: 'red';
16
+ reason: RedReason;
17
+ pr: {
18
+ number: number;
19
+ url: string;
20
+ linkMethod?: LinkMethod;
21
+ } | null;
22
+ candidates?: PrCandidate[];
23
+ linkMethod?: LinkMethod;
24
+ failingChecks: FailingCheck[];
25
+ issue?: IssueRefWithState;
26
+ /** FR-006a — sub-kind for `pr-flag-linkage-refused` refusals. */
27
+ kind?: PrFlagLinkageKind;
28
+ /** Human-readable remediation string for pr-flag refusals. */
29
+ message?: string;
30
+ /** #928 — human-readable remediation string for `reason: 'pr-number'`. */
31
+ hint?: string;
32
+ }
33
+ export interface BuildFailingCheckInput {
34
+ reason: RedReason;
35
+ pr: {
36
+ number: number;
37
+ url: string;
38
+ linkMethod?: LinkMethod;
39
+ } | null;
40
+ candidates?: PrCandidate[];
41
+ linkMethod?: LinkMethod;
42
+ failingChecks?: FailingCheck[];
43
+ issue?: IssueRefWithState;
44
+ /** Only for `pr-flag-linkage-refused`. */
45
+ kind?: PrFlagLinkageKind;
46
+ /** Only for `pr-flag-linkage-refused` and `pr-flag-closed-unmerged`. */
47
+ message?: string;
48
+ /** #928 — required for `reason: 'pr-number'`. Guidance copy for the caller. */
49
+ hint?: string;
50
+ }
51
+ export declare function buildFailingCheckPayload(input: BuildFailingCheckInput): FailingCheckPayload;
52
+ export declare function serializeFailingCheckJson(payload: FailingCheckPayload): string;
53
+ //# sourceMappingURL=failing-check-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failing-check-json.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/cockpit/shared/failing-check-json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEpE,MAAM,MAAM,SAAS,GACjB,gBAAgB,GAChB,eAAe,GACf,YAAY,GACZ,aAAa,GACb,sBAAsB,GACtB,yBAAyB,GACzB,yBAAyB,GACzB,WAAW,CAAC;AAEhB,iEAAiE;AACjE,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,UAAU,CAAC;AAE1D,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,KAAK,CAAC;IACd,MAAM,EAAE,SAAS,CAAC;IAClB,EAAE,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,UAAU,CAAA;KAAE,GAAG,IAAI,CAAC;IACpE,UAAU,CAAC,EAAE,WAAW,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,iEAAiE;IACjE,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,SAAS,CAAC;IAClB,EAAE,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,UAAU,CAAA;KAAE,GAAG,IAAI,CAAC;IACpE,UAAU,CAAC,EAAE,WAAW,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,0CAA0C;IAC1C,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,sBAAsB,GAC5B,mBAAmB,CA2OrB;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,mBAAmB,GAC3B,MAAM,CAER"}
@@ -0,0 +1,170 @@
1
+ export function buildFailingCheckPayload(input) {
2
+ const { reason, pr, candidates, linkMethod, failingChecks = [], issue, kind, message, hint } = input;
3
+ if (issue !== undefined) {
4
+ // I-6: state and stateReason are paired — if state is set, stateReason
5
+ // must also be present (may be null). Guards against callers accidentally
6
+ // dropping stateReason when they intend to carry state.
7
+ const hasState = 'state' in issue;
8
+ const hasStateReason = 'stateReason' in issue;
9
+ if (hasState !== hasStateReason) {
10
+ throw new Error("FailingCheckPayload invariant I-6: issue.state and issue.stateReason must be set together");
11
+ }
12
+ }
13
+ const applyIssue = (payload) => issue === undefined ? payload : { ...payload, issue };
14
+ // I-10/I-11: `candidates` and top-level `linkMethod` MUST NOT be set for
15
+ // single-PR reasons.
16
+ const isSinglePrReason = reason === 'unresolved' ||
17
+ reason === 'missing-label' ||
18
+ reason === 'checks-failing' ||
19
+ reason === 'pr-flag-linkage-refused' ||
20
+ reason === 'pr-flag-closed-unmerged' ||
21
+ reason === 'pr-number';
22
+ if (isSinglePrReason && candidates !== undefined) {
23
+ throw new Error(`FailingCheckPayload invariant I-10: candidates MUST NOT be set for reason='${reason}'`);
24
+ }
25
+ if (isSinglePrReason && linkMethod !== undefined) {
26
+ throw new Error(`FailingCheckPayload invariant I-11: top-level linkMethod MUST NOT be set for reason='${reason}'`);
27
+ }
28
+ if (reason === 'unresolved') {
29
+ if (failingChecks.length !== 0) {
30
+ throw new Error("FailingCheckPayload invariant: reason='unresolved' must have empty failingChecks");
31
+ }
32
+ return applyIssue({ status: 'red', reason, pr, failingChecks: [] });
33
+ }
34
+ if (reason === 'missing-label') {
35
+ if (pr == null) {
36
+ throw new Error("FailingCheckPayload invariant: reason='missing-label' requires non-null pr");
37
+ }
38
+ if (pr.linkMethod === undefined) {
39
+ throw new Error("FailingCheckPayload invariant I-9: reason='missing-label' requires pr.linkMethod to be set");
40
+ }
41
+ if (failingChecks.length !== 0) {
42
+ throw new Error("FailingCheckPayload invariant: reason='missing-label' must have empty failingChecks");
43
+ }
44
+ return applyIssue({ status: 'red', reason, pr, failingChecks: [] });
45
+ }
46
+ if (reason === 'checks-failing') {
47
+ if (pr == null) {
48
+ throw new Error("FailingCheckPayload invariant: reason='checks-failing' requires non-null pr");
49
+ }
50
+ if (pr.linkMethod === undefined) {
51
+ throw new Error("FailingCheckPayload invariant I-9: reason='checks-failing' requires pr.linkMethod to be set");
52
+ }
53
+ if (failingChecks.length === 0) {
54
+ throw new Error("FailingCheckPayload invariant: reason='checks-failing' requires non-empty failingChecks");
55
+ }
56
+ return applyIssue({ status: 'red', reason, pr, failingChecks });
57
+ }
58
+ if (reason === 'pr-is-draft') {
59
+ if (pr !== null) {
60
+ throw new Error("FailingCheckPayload invariant I-7: reason='pr-is-draft' requires pr === null");
61
+ }
62
+ if (!candidates || candidates.length < 1) {
63
+ throw new Error("FailingCheckPayload invariant I-7: reason='pr-is-draft' requires candidates.length >= 1");
64
+ }
65
+ if (candidates.some((c) => c.isDraft !== true)) {
66
+ throw new Error("FailingCheckPayload invariant I-7: reason='pr-is-draft' requires every candidate.isDraft === true");
67
+ }
68
+ if (linkMethod === undefined) {
69
+ throw new Error("FailingCheckPayload invariant I-7: reason='pr-is-draft' requires top-level linkMethod");
70
+ }
71
+ if (failingChecks.length !== 0) {
72
+ throw new Error("FailingCheckPayload invariant I-7: reason='pr-is-draft' must have empty failingChecks");
73
+ }
74
+ return applyIssue({
75
+ status: 'red',
76
+ reason,
77
+ pr: null,
78
+ candidates,
79
+ linkMethod,
80
+ failingChecks: [],
81
+ });
82
+ }
83
+ if (reason === 'ambiguous-resolution') {
84
+ if (pr !== null) {
85
+ throw new Error("FailingCheckPayload invariant I-8: reason='ambiguous-resolution' requires pr === null");
86
+ }
87
+ if (!candidates || candidates.length < 2) {
88
+ throw new Error("FailingCheckPayload invariant I-8: reason='ambiguous-resolution' requires candidates.length >= 2");
89
+ }
90
+ if (candidates.some((c) => c.isDraft !== false)) {
91
+ throw new Error("FailingCheckPayload invariant I-8: reason='ambiguous-resolution' requires every candidate.isDraft === false");
92
+ }
93
+ if (linkMethod === undefined) {
94
+ throw new Error("FailingCheckPayload invariant I-8: reason='ambiguous-resolution' requires top-level linkMethod");
95
+ }
96
+ if (failingChecks.length !== 0) {
97
+ throw new Error("FailingCheckPayload invariant I-8: reason='ambiguous-resolution' must have empty failingChecks");
98
+ }
99
+ return applyIssue({
100
+ status: 'red',
101
+ reason,
102
+ pr: null,
103
+ candidates,
104
+ linkMethod,
105
+ failingChecks: [],
106
+ });
107
+ }
108
+ if (reason === 'pr-flag-linkage-refused') {
109
+ if (pr == null) {
110
+ throw new Error("FailingCheckPayload invariant: reason='pr-flag-linkage-refused' requires non-null pr");
111
+ }
112
+ if (kind !== 'empty-refs' && kind !== 'mismatch') {
113
+ throw new Error("FailingCheckPayload invariant: reason='pr-flag-linkage-refused' requires kind ∈ { 'empty-refs' | 'mismatch' }");
114
+ }
115
+ if (failingChecks.length !== 0) {
116
+ throw new Error("FailingCheckPayload invariant: reason='pr-flag-linkage-refused' must have empty failingChecks");
117
+ }
118
+ const base = {
119
+ status: 'red',
120
+ reason,
121
+ pr,
122
+ failingChecks: [],
123
+ kind,
124
+ };
125
+ if (message !== undefined)
126
+ base.message = message;
127
+ return applyIssue(base);
128
+ }
129
+ if (reason === 'pr-number') {
130
+ // #928 — the caller's `<issue>` argument is itself a PR node.
131
+ if (pr !== null) {
132
+ throw new Error("FailingCheckPayload invariant: reason='pr-number' requires pr === null");
133
+ }
134
+ if (typeof hint !== 'string' || hint.length === 0) {
135
+ throw new Error("FailingCheckPayload invariant: reason='pr-number' requires a non-empty hint");
136
+ }
137
+ if (failingChecks.length !== 0) {
138
+ throw new Error("FailingCheckPayload invariant: reason='pr-number' must have empty failingChecks");
139
+ }
140
+ return applyIssue({
141
+ status: 'red',
142
+ reason,
143
+ pr: null,
144
+ failingChecks: [],
145
+ hint,
146
+ });
147
+ }
148
+ if (reason === 'pr-flag-closed-unmerged') {
149
+ if (pr == null) {
150
+ throw new Error("FailingCheckPayload invariant: reason='pr-flag-closed-unmerged' requires non-null pr");
151
+ }
152
+ if (failingChecks.length !== 0) {
153
+ throw new Error("FailingCheckPayload invariant: reason='pr-flag-closed-unmerged' must have empty failingChecks");
154
+ }
155
+ const base = {
156
+ status: 'red',
157
+ reason,
158
+ pr,
159
+ failingChecks: [],
160
+ };
161
+ if (message !== undefined)
162
+ base.message = message;
163
+ return applyIssue(base);
164
+ }
165
+ throw new Error(`FailingCheckPayload: unknown reason ${reason}`);
166
+ }
167
+ export function serializeFailingCheckJson(payload) {
168
+ return JSON.stringify(payload) + '\n';
169
+ }
170
+ //# sourceMappingURL=failing-check-json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failing-check-json.js","sourceRoot":"","sources":["../../../../../src/cli/commands/cockpit/shared/failing-check-json.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * `resolveCockpitIdentity` — resolve the GitHub identity used by cockpit
3
+ * subcommands (queue, advance), mirroring `packages/orchestrator/src/services/
4
+ * identity.ts` precedence so App-credentialed clusters don't 403 on `gh api user`.
5
+ *
6
+ * Precedence (first non-null / non-empty / non-throwing tier wins):
7
+ * 1a. `flag` — `--assignee <login>` CLI flag
8
+ * 1b. `configAssignee` — `cockpit.assignee` in `.generacy/config.yaml`
9
+ * 2a. `env.CLUSTER_GITHUB_USERNAME` — cluster-wide env
10
+ * 2b. `env.GH_USERNAME` — cluster-wide env (wizard-delivered)
11
+ * 3. `gh.getCurrentUser()` — `gh api user`
12
+ *
13
+ * Two modes:
14
+ * - `required` — throws `LoudIdentityError` naming all four knobs on all-miss.
15
+ * - `optional` — logs a warning naming all four knobs and returns
16
+ * `{ login: undefined, source: 'none' }`.
17
+ */
18
+ import type { GhWrapper } from '@generacy-ai/cockpit';
19
+ export type IdentitySource = 'flag' | 'config' | 'CLUSTER_GITHUB_USERNAME' | 'GH_USERNAME' | 'gh-api' | 'none';
20
+ export interface ResolveCockpitIdentityInput {
21
+ flag?: string;
22
+ configAssignee?: string;
23
+ gh: Pick<GhWrapper, 'getCurrentUser'>;
24
+ logger: {
25
+ warn(msg: string): void;
26
+ info?(msg: string): void;
27
+ };
28
+ verb: string;
29
+ mode: 'required' | 'optional';
30
+ env?: NodeJS.ProcessEnv;
31
+ }
32
+ export type ResolveCockpitIdentityResult = {
33
+ login: string;
34
+ source: Exclude<IdentitySource, 'none'>;
35
+ } | {
36
+ login: undefined;
37
+ source: 'none';
38
+ };
39
+ export declare class LoudIdentityError extends Error {
40
+ readonly code: "IDENTITY_UNRESOLVED";
41
+ readonly verb: string;
42
+ constructor(verb: string, message: string);
43
+ }
44
+ export declare function resolveCockpitIdentity(input: ResolveCockpitIdentityInput & {
45
+ mode: 'required';
46
+ }): Promise<{
47
+ login: string;
48
+ source: Exclude<IdentitySource, 'none'>;
49
+ }>;
50
+ export declare function resolveCockpitIdentity(input: ResolveCockpitIdentityInput & {
51
+ mode: 'optional';
52
+ }): Promise<ResolveCockpitIdentityResult>;
53
+ export declare function resolveCockpitIdentity(input: ResolveCockpitIdentityInput): Promise<ResolveCockpitIdentityResult>;
54
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/cockpit/shared/identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,MAAM,cAAc,GACtB,MAAM,GACN,QAAQ,GACR,yBAAyB,GACzB,aAAa,GACb,QAAQ,GACR,MAAM,CAAC;AAEX,MAAM,WAAW,2BAA2B;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,EAAE,EAAE,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IACtC,MAAM,EAAE;QAAE,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,UAAU,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAED,MAAM,MAAM,4BAA4B,GACpC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;CAAE,GAC1D;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,EAAG,qBAAqB,CAAU;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBACV,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK1C;AAkBD,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,2BAA2B,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACxD,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC,CAAC;AACvE,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,2BAA2B,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACxD,OAAO,CAAC,4BAA4B,CAAC,CAAC;AACzC,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,2BAA2B,GACjC,OAAO,CAAC,4BAA4B,CAAC,CAAC"}
@@ -0,0 +1,65 @@
1
+ export class LoudIdentityError extends Error {
2
+ code = 'IDENTITY_UNRESOLVED';
3
+ verb;
4
+ constructor(verb, message) {
5
+ super(message);
6
+ this.name = 'LoudIdentityError';
7
+ this.verb = verb;
8
+ }
9
+ }
10
+ function buildFourKnobMessage(verb) {
11
+ return (`cockpit ${verb}: unable to resolve GitHub identity.\n` +
12
+ 'Set one of the following:\n' +
13
+ ' --assignee <login> (flag, per-invocation)\n' +
14
+ ' cockpit.assignee in .generacy/config.yaml (per-repo)\n' +
15
+ ' CLUSTER_GITHUB_USERNAME (env, cluster-wide)\n' +
16
+ ' GH_USERNAME (env, cluster-wide)\n' +
17
+ 'Or authenticate `gh` for a user-token (gh auth login) so `gh api user` can resolve.');
18
+ }
19
+ function nonEmpty(v) {
20
+ return typeof v === 'string' && v.length > 0;
21
+ }
22
+ export async function resolveCockpitIdentity(input) {
23
+ const env = input.env ?? process.env;
24
+ const { flag, configAssignee, gh, logger, verb, mode } = input;
25
+ if (nonEmpty(flag)) {
26
+ logger.info?.(`cockpit ${verb}: identity resolved from --assignee flag (${flag})`);
27
+ return { login: flag, source: 'flag' };
28
+ }
29
+ if (nonEmpty(configAssignee)) {
30
+ logger.info?.(`cockpit ${verb}: identity resolved from cockpit.assignee config (${configAssignee})`);
31
+ return { login: configAssignee, source: 'config' };
32
+ }
33
+ const clusterEnv = env['CLUSTER_GITHUB_USERNAME'];
34
+ if (nonEmpty(clusterEnv)) {
35
+ logger.info?.(`cockpit ${verb}: identity resolved from CLUSTER_GITHUB_USERNAME (${clusterEnv})`);
36
+ return { login: clusterEnv, source: 'CLUSTER_GITHUB_USERNAME' };
37
+ }
38
+ const ghEnv = env['GH_USERNAME'];
39
+ if (nonEmpty(ghEnv)) {
40
+ logger.info?.(`cockpit ${verb}: identity resolved from GH_USERNAME (${ghEnv})`);
41
+ return { login: ghEnv, source: 'GH_USERNAME' };
42
+ }
43
+ try {
44
+ const login = await gh.getCurrentUser();
45
+ if (nonEmpty(login)) {
46
+ logger.info?.(`cockpit ${verb}: identity resolved from gh api user (${login})`);
47
+ return { login, source: 'gh-api' };
48
+ }
49
+ }
50
+ catch (err) {
51
+ if (mode === 'optional') {
52
+ const msg = err instanceof Error ? err.message : String(err);
53
+ logger.info?.(`cockpit ${verb}: gh api user failed: ${msg}`);
54
+ }
55
+ // Fall through to the four-knob failure branch. The individual error is
56
+ // not surfaced in the loud message — the four knobs are the actionable fix.
57
+ }
58
+ const message = buildFourKnobMessage(verb);
59
+ if (mode === 'required') {
60
+ throw new LoudIdentityError(verb, message);
61
+ }
62
+ logger.warn(`warning: ${message}`);
63
+ return { login: undefined, source: 'none' };
64
+ }
65
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../../../../src/cli/commands/cockpit/shared/identity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { Snapshot } from '../watch/snapshot.js';
2
+ /**
3
+ * Issue state: closed dominates any label-derived actionability tier.
4
+ *
5
+ * A closed issue carrying `completed:validate` (or any other actionable-label
6
+ * residue) is done, not actionable. This helper is the single decision
7
+ * surface: both `isActionableSnapshot` (watch) and the status renderer route
8
+ * through it. If you need to expand actionability tiers, extend
9
+ * `isActionableSnapshot` — do not add a second done-gate.
10
+ *
11
+ * The predicate reads raw `snap.state`, NOT `snap.classified.state`. The
12
+ * classified `'terminal'` tier is exactly the label residue this fix stops
13
+ * trusting; reading it would perpetuate the bug pattern (#873).
14
+ */
15
+ export declare function isDoneSnapshot(snap: Snapshot): boolean;
16
+ //# sourceMappingURL=is-done-snapshot.d.ts.map