@generacy-ai/orchestrator 0.5.1 → 0.7.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 (182) hide show
  1. package/dist/config/loader.d.ts.map +1 -1
  2. package/dist/config/loader.js +25 -0
  3. package/dist/config/loader.js.map +1 -1
  4. package/dist/config/schema.d.ts +54 -7
  5. package/dist/config/schema.d.ts.map +1 -1
  6. package/dist/index.d.ts +3 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +4 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/routes/health.d.ts.map +1 -1
  11. package/dist/routes/health.js +5 -0
  12. package/dist/routes/health.js.map +1 -1
  13. package/dist/server.d.ts.map +1 -1
  14. package/dist/server.js +130 -26
  15. package/dist/server.js.map +1 -1
  16. package/dist/services/base-advance-monitor-service.d.ts +78 -0
  17. package/dist/services/base-advance-monitor-service.d.ts.map +1 -0
  18. package/dist/services/base-advance-monitor-service.js +233 -0
  19. package/dist/services/base-advance-monitor-service.js.map +1 -0
  20. package/dist/services/boot-resume-service.d.ts +19 -0
  21. package/dist/services/boot-resume-service.d.ts.map +1 -0
  22. package/dist/services/boot-resume-service.js +87 -0
  23. package/dist/services/boot-resume-service.js.map +1 -0
  24. package/dist/services/epic-completion-monitor-service.d.ts.map +1 -1
  25. package/dist/services/epic-completion-monitor-service.js +2 -0
  26. package/dist/services/epic-completion-monitor-service.js.map +1 -1
  27. package/dist/services/in-memory-queue-adapter.d.ts +4 -0
  28. package/dist/services/in-memory-queue-adapter.d.ts.map +1 -1
  29. package/dist/services/in-memory-queue-adapter.js +30 -3
  30. package/dist/services/in-memory-queue-adapter.js.map +1 -1
  31. package/dist/services/label-monitor-service.d.ts +3 -3
  32. package/dist/services/label-monitor-service.d.ts.map +1 -1
  33. package/dist/services/label-monitor-service.js +58 -41
  34. package/dist/services/label-monitor-service.js.map +1 -1
  35. package/dist/services/label-sync-service.d.ts.map +1 -1
  36. package/dist/services/label-sync-service.js +45 -10
  37. package/dist/services/label-sync-service.js.map +1 -1
  38. package/dist/services/merge-conflict-monitor-service.d.ts +73 -0
  39. package/dist/services/merge-conflict-monitor-service.d.ts.map +1 -0
  40. package/dist/services/merge-conflict-monitor-service.js +295 -0
  41. package/dist/services/merge-conflict-monitor-service.js.map +1 -0
  42. package/dist/services/orchestrator-version.d.ts +2 -0
  43. package/dist/services/orchestrator-version.d.ts.map +1 -0
  44. package/dist/services/orchestrator-version.js +23 -0
  45. package/dist/services/orchestrator-version.js.map +1 -0
  46. package/dist/services/phase-tracker-service.d.ts +10 -0
  47. package/dist/services/phase-tracker-service.d.ts.map +1 -1
  48. package/dist/services/phase-tracker-service.js +38 -0
  49. package/dist/services/phase-tracker-service.js.map +1 -1
  50. package/dist/services/post-activation-dispatch.d.ts +18 -0
  51. package/dist/services/post-activation-dispatch.d.ts.map +1 -0
  52. package/dist/services/post-activation-dispatch.js +30 -0
  53. package/dist/services/post-activation-dispatch.js.map +1 -0
  54. package/dist/services/pr-feedback-monitor-service.d.ts +13 -4
  55. package/dist/services/pr-feedback-monitor-service.d.ts.map +1 -1
  56. package/dist/services/pr-feedback-monitor-service.js +212 -26
  57. package/dist/services/pr-feedback-monitor-service.js.map +1 -1
  58. package/dist/services/redis-queue-adapter.d.ts +4 -0
  59. package/dist/services/redis-queue-adapter.d.ts.map +1 -1
  60. package/dist/services/redis-queue-adapter.js +90 -10
  61. package/dist/services/redis-queue-adapter.js.map +1 -1
  62. package/dist/services/worker-dispatcher.d.ts +14 -2
  63. package/dist/services/worker-dispatcher.d.ts.map +1 -1
  64. package/dist/services/worker-dispatcher.js +55 -2
  65. package/dist/services/worker-dispatcher.js.map +1 -1
  66. package/dist/types/api.d.ts +3 -0
  67. package/dist/types/api.d.ts.map +1 -1
  68. package/dist/types/api.js +1 -0
  69. package/dist/types/api.js.map +1 -1
  70. package/dist/types/index.d.ts +1 -1
  71. package/dist/types/index.d.ts.map +1 -1
  72. package/dist/types/index.js.map +1 -1
  73. package/dist/types/monitor.d.ts +72 -4
  74. package/dist/types/monitor.d.ts.map +1 -1
  75. package/dist/worker/base-merge.d.ts +54 -0
  76. package/dist/worker/base-merge.d.ts.map +1 -0
  77. package/dist/worker/base-merge.js +99 -0
  78. package/dist/worker/base-merge.js.map +1 -0
  79. package/dist/worker/clarification-markers.d.ts +29 -0
  80. package/dist/worker/clarification-markers.d.ts.map +1 -0
  81. package/dist/worker/clarification-markers.js +44 -0
  82. package/dist/worker/clarification-markers.js.map +1 -0
  83. package/dist/worker/clarification-poster.d.ts.map +1 -1
  84. package/dist/worker/clarification-poster.js +266 -25
  85. package/dist/worker/clarification-poster.js.map +1 -1
  86. package/dist/worker/claude-cli-worker.d.ts +21 -2
  87. package/dist/worker/claude-cli-worker.d.ts.map +1 -1
  88. package/dist/worker/claude-cli-worker.js +149 -4
  89. package/dist/worker/claude-cli-worker.js.map +1 -1
  90. package/dist/worker/cli-spawner.d.ts +4 -0
  91. package/dist/worker/cli-spawner.d.ts.map +1 -1
  92. package/dist/worker/cli-spawner.js +51 -7
  93. package/dist/worker/cli-spawner.js.map +1 -1
  94. package/dist/worker/config.d.ts +101 -9
  95. package/dist/worker/config.d.ts.map +1 -1
  96. package/dist/worker/config.js +75 -4
  97. package/dist/worker/config.js.map +1 -1
  98. package/dist/worker/evidence-hash.d.ts +32 -0
  99. package/dist/worker/evidence-hash.d.ts.map +1 -0
  100. package/dist/worker/evidence-hash.js +139 -0
  101. package/dist/worker/evidence-hash.js.map +1 -0
  102. package/dist/worker/handler-outcome-assertion.d.ts +38 -0
  103. package/dist/worker/handler-outcome-assertion.d.ts.map +1 -0
  104. package/dist/worker/handler-outcome-assertion.js +58 -0
  105. package/dist/worker/handler-outcome-assertion.js.map +1 -0
  106. package/dist/worker/handler-outcome.d.ts +50 -0
  107. package/dist/worker/handler-outcome.d.ts.map +1 -0
  108. package/dist/worker/handler-outcome.js +2 -0
  109. package/dist/worker/handler-outcome.js.map +1 -0
  110. package/dist/worker/label-manager.d.ts +58 -2
  111. package/dist/worker/label-manager.d.ts.map +1 -1
  112. package/dist/worker/label-manager.js +225 -27
  113. package/dist/worker/label-manager.js.map +1 -1
  114. package/dist/worker/merge-conflict-handler.d.ts +141 -0
  115. package/dist/worker/merge-conflict-handler.d.ts.map +1 -0
  116. package/dist/worker/merge-conflict-handler.js +642 -0
  117. package/dist/worker/merge-conflict-handler.js.map +1 -0
  118. package/dist/worker/merge-conflict-prompt.d.ts +35 -0
  119. package/dist/worker/merge-conflict-prompt.d.ts.map +1 -0
  120. package/dist/worker/merge-conflict-prompt.js +71 -0
  121. package/dist/worker/merge-conflict-prompt.js.map +1 -0
  122. package/dist/worker/merge-conflict-remedy.d.ts +42 -0
  123. package/dist/worker/merge-conflict-remedy.d.ts.map +1 -0
  124. package/dist/worker/merge-conflict-remedy.js +28 -0
  125. package/dist/worker/merge-conflict-remedy.js.map +1 -0
  126. package/dist/worker/output-tail-synthesis.d.ts +15 -0
  127. package/dist/worker/output-tail-synthesis.d.ts.map +1 -0
  128. package/dist/worker/output-tail-synthesis.js +25 -0
  129. package/dist/worker/output-tail-synthesis.js.map +1 -0
  130. package/dist/worker/output-tail.d.ts +13 -0
  131. package/dist/worker/output-tail.d.ts.map +1 -0
  132. package/dist/worker/output-tail.js +31 -0
  133. package/dist/worker/output-tail.js.map +1 -0
  134. package/dist/worker/pause-context.d.ts +30 -0
  135. package/dist/worker/pause-context.d.ts.map +1 -0
  136. package/dist/worker/pause-context.js +98 -0
  137. package/dist/worker/pause-context.js.map +1 -0
  138. package/dist/worker/phase-loop.d.ts +66 -0
  139. package/dist/worker/phase-loop.d.ts.map +1 -1
  140. package/dist/worker/phase-loop.js +299 -31
  141. package/dist/worker/phase-loop.js.map +1 -1
  142. package/dist/worker/pr-feedback-handler.d.ts +46 -46
  143. package/dist/worker/pr-feedback-handler.d.ts.map +1 -1
  144. package/dist/worker/pr-feedback-handler.js +276 -105
  145. package/dist/worker/pr-feedback-handler.js.map +1 -1
  146. package/dist/worker/pr-manager.d.ts +5 -0
  147. package/dist/worker/pr-manager.d.ts.map +1 -1
  148. package/dist/worker/pr-manager.js +7 -0
  149. package/dist/worker/pr-manager.js.map +1 -1
  150. package/dist/worker/product-diff.d.ts +39 -0
  151. package/dist/worker/product-diff.d.ts.map +1 -0
  152. package/dist/worker/product-diff.js +43 -0
  153. package/dist/worker/product-diff.js.map +1 -0
  154. package/dist/worker/provisioning-failure.d.ts +14 -0
  155. package/dist/worker/provisioning-failure.d.ts.map +1 -0
  156. package/dist/worker/provisioning-failure.js +2 -0
  157. package/dist/worker/provisioning-failure.js.map +1 -0
  158. package/dist/worker/repo-checkout.d.ts +14 -0
  159. package/dist/worker/repo-checkout.d.ts.map +1 -1
  160. package/dist/worker/repo-checkout.js +19 -1
  161. package/dist/worker/repo-checkout.js.map +1 -1
  162. package/dist/worker/stage-comment-manager.d.ts +42 -1
  163. package/dist/worker/stage-comment-manager.d.ts.map +1 -1
  164. package/dist/worker/stage-comment-manager.js +205 -1
  165. package/dist/worker/stage-comment-manager.js.map +1 -1
  166. package/dist/worker/terminal-label-op-error.d.ts +23 -0
  167. package/dist/worker/terminal-label-op-error.d.ts.map +1 -0
  168. package/dist/worker/terminal-label-op-error.js +27 -0
  169. package/dist/worker/terminal-label-op-error.js.map +1 -0
  170. package/dist/worker/types.d.ts +161 -2
  171. package/dist/worker/types.d.ts.map +1 -1
  172. package/dist/worker/types.js +11 -0
  173. package/dist/worker/types.js.map +1 -1
  174. package/dist/worker/validate-fix-handler.d.ts +79 -0
  175. package/dist/worker/validate-fix-handler.d.ts.map +1 -0
  176. package/dist/worker/validate-fix-handler.js +320 -0
  177. package/dist/worker/validate-fix-handler.js.map +1 -0
  178. package/dist/worker/worker-result.d.ts +39 -0
  179. package/dist/worker/worker-result.d.ts.map +1 -0
  180. package/dist/worker/worker-result.js +10 -0
  181. package/dist/worker/worker-result.js.map +1 -0
  182. package/package.json +7 -6
@@ -1,4 +1,6 @@
1
1
  import { z } from 'zod';
2
+ import type { OrchestratorSettings } from '@generacy-ai/config';
3
+ import type { WorkflowPhase } from './types.js';
2
4
  /**
3
5
  * Gate definition schema for pausing workflow at review checkpoints
4
6
  */
@@ -8,22 +10,78 @@ export declare const GateDefinitionSchema: z.ZodObject<{
8
10
  /** Label to add when gate is active */
9
11
  gateLabel: z.ZodString;
10
12
  /** When to activate the gate */
11
- condition: z.ZodEnum<["always", "on-request", "on-questions", "on-failure", "on-sibling-review"]>;
13
+ condition: z.ZodEnum<["always", "on-request", "on-questions", "on-failure", "on-sibling-review", "on-merge-conflict"]>;
12
14
  }, "strip", z.ZodTypeAny, {
13
15
  phase: "specify" | "clarify" | "plan" | "tasks" | "implement" | "validate";
14
16
  gateLabel: string;
15
- condition: "always" | "on-request" | "on-questions" | "on-failure" | "on-sibling-review";
17
+ condition: "always" | "on-request" | "on-questions" | "on-failure" | "on-sibling-review" | "on-merge-conflict";
16
18
  }, {
17
19
  phase: "specify" | "clarify" | "plan" | "tasks" | "implement" | "validate";
18
20
  gateLabel: string;
19
- condition: "always" | "on-request" | "on-questions" | "on-failure" | "on-sibling-review";
21
+ condition: "always" | "on-request" | "on-questions" | "on-failure" | "on-sibling-review" | "on-merge-conflict";
20
22
  }>;
23
+ /**
24
+ * Per-phase wall-clock timeout overrides (milliseconds).
25
+ *
26
+ * Each CLI phase is killed (SIGTERM → grace → SIGKILL) once its wall-clock
27
+ * runtime exceeds its timeout. The `plan` and `implement` phases are
28
+ * structurally heavier than the others — `plan` fans out research subagents,
29
+ * `implement` writes code — so they default to a larger budget than the flat
30
+ * `phaseTimeoutMs`. Any phase without an override falls back to `phaseTimeoutMs`.
31
+ *
32
+ * Defined per-field (rather than as a `z.record`) so that overriding one phase
33
+ * via config/env does not drop the defaults for the others — Zod applies the
34
+ * remaining field defaults when the object is present but partial.
35
+ *
36
+ * `validate` is intentionally excluded: that phase runs a shell command via a
37
+ * separate code path with its own timeout, not `phaseTimeoutMs`.
38
+ */
39
+ export declare const PhaseTimeoutOverridesSchema: z.ZodDefault<z.ZodObject<{
40
+ specify: z.ZodOptional<z.ZodNumber>;
41
+ clarify: z.ZodOptional<z.ZodNumber>;
42
+ plan: z.ZodDefault<z.ZodNumber>;
43
+ tasks: z.ZodOptional<z.ZodNumber>;
44
+ implement: z.ZodDefault<z.ZodNumber>;
45
+ }, "strip", z.ZodTypeAny, {
46
+ plan: number;
47
+ implement: number;
48
+ specify?: number | undefined;
49
+ clarify?: number | undefined;
50
+ tasks?: number | undefined;
51
+ }, {
52
+ specify?: number | undefined;
53
+ clarify?: number | undefined;
54
+ plan?: number | undefined;
55
+ tasks?: number | undefined;
56
+ implement?: number | undefined;
57
+ }>>;
58
+ export type PhaseTimeoutOverrides = z.infer<typeof PhaseTimeoutOverridesSchema>;
21
59
  /**
22
60
  * Worker configuration schema
23
61
  */
24
62
  export declare const WorkerConfigSchema: z.ZodObject<{
25
- /** Timeout per phase in milliseconds */
63
+ /** Fallback timeout per phase in milliseconds (used when no per-phase override applies) */
26
64
  phaseTimeoutMs: z.ZodDefault<z.ZodNumber>;
65
+ /** Per-phase timeout overrides keyed by phase name */
66
+ phaseTimeoutOverrides: z.ZodDefault<z.ZodObject<{
67
+ specify: z.ZodOptional<z.ZodNumber>;
68
+ clarify: z.ZodOptional<z.ZodNumber>;
69
+ plan: z.ZodDefault<z.ZodNumber>;
70
+ tasks: z.ZodOptional<z.ZodNumber>;
71
+ implement: z.ZodDefault<z.ZodNumber>;
72
+ }, "strip", z.ZodTypeAny, {
73
+ plan: number;
74
+ implement: number;
75
+ specify?: number | undefined;
76
+ clarify?: number | undefined;
77
+ tasks?: number | undefined;
78
+ }, {
79
+ specify?: number | undefined;
80
+ clarify?: number | undefined;
81
+ plan?: number | undefined;
82
+ tasks?: number | undefined;
83
+ implement?: number | undefined;
84
+ }>>;
27
85
  /** Base directory for repo checkouts */
28
86
  workspaceDir: z.ZodDefault<z.ZodString>;
29
87
  /** Grace period for shutdown in milliseconds */
@@ -43,18 +101,25 @@ export declare const WorkerConfigSchema: z.ZodObject<{
43
101
  /** Label to add when gate is active */
44
102
  gateLabel: z.ZodString;
45
103
  /** When to activate the gate */
46
- condition: z.ZodEnum<["always", "on-request", "on-questions", "on-failure", "on-sibling-review"]>;
104
+ condition: z.ZodEnum<["always", "on-request", "on-questions", "on-failure", "on-sibling-review", "on-merge-conflict"]>;
47
105
  }, "strip", z.ZodTypeAny, {
48
106
  phase: "specify" | "clarify" | "plan" | "tasks" | "implement" | "validate";
49
107
  gateLabel: string;
50
- condition: "always" | "on-request" | "on-questions" | "on-failure" | "on-sibling-review";
108
+ condition: "always" | "on-request" | "on-questions" | "on-failure" | "on-sibling-review" | "on-merge-conflict";
51
109
  }, {
52
110
  phase: "specify" | "clarify" | "plan" | "tasks" | "implement" | "validate";
53
111
  gateLabel: string;
54
- condition: "always" | "on-request" | "on-questions" | "on-failure" | "on-sibling-review";
112
+ condition: "always" | "on-request" | "on-questions" | "on-failure" | "on-sibling-review" | "on-merge-conflict";
55
113
  }>, "many">>>;
56
114
  }, "strip", z.ZodTypeAny, {
57
115
  phaseTimeoutMs: number;
116
+ phaseTimeoutOverrides: {
117
+ plan: number;
118
+ implement: number;
119
+ specify?: number | undefined;
120
+ clarify?: number | undefined;
121
+ tasks?: number | undefined;
122
+ };
58
123
  workspaceDir: string;
59
124
  shutdownGracePeriodMs: number;
60
125
  validateCommand: string;
@@ -63,11 +128,18 @@ export declare const WorkerConfigSchema: z.ZodObject<{
63
128
  gates: Record<string, {
64
129
  phase: "specify" | "clarify" | "plan" | "tasks" | "implement" | "validate";
65
130
  gateLabel: string;
66
- condition: "always" | "on-request" | "on-questions" | "on-failure" | "on-sibling-review";
131
+ condition: "always" | "on-request" | "on-questions" | "on-failure" | "on-sibling-review" | "on-merge-conflict";
67
132
  }[]>;
68
133
  credentialRole?: string | undefined;
69
134
  }, {
70
135
  phaseTimeoutMs?: number | undefined;
136
+ phaseTimeoutOverrides?: {
137
+ specify?: number | undefined;
138
+ clarify?: number | undefined;
139
+ plan?: number | undefined;
140
+ tasks?: number | undefined;
141
+ implement?: number | undefined;
142
+ } | undefined;
71
143
  workspaceDir?: string | undefined;
72
144
  shutdownGracePeriodMs?: number | undefined;
73
145
  validateCommand?: string | undefined;
@@ -77,8 +149,28 @@ export declare const WorkerConfigSchema: z.ZodObject<{
77
149
  gates?: Record<string, {
78
150
  phase: "specify" | "clarify" | "plan" | "tasks" | "implement" | "validate";
79
151
  gateLabel: string;
80
- condition: "always" | "on-request" | "on-questions" | "on-failure" | "on-sibling-review";
152
+ condition: "always" | "on-request" | "on-questions" | "on-failure" | "on-sibling-review" | "on-merge-conflict";
81
153
  }[]> | undefined;
82
154
  }>;
83
155
  export type WorkerConfig = z.infer<typeof WorkerConfigSchema>;
156
+ /**
157
+ * Merge per-repo validate-command overrides onto the global worker config.
158
+ *
159
+ * The target repo's `.generacy/config.yaml` `orchestrator` block may set
160
+ * `validateCommand` / `preValidateCommand`. The global defaults are
161
+ * monorepo-shaped (`pnpm test && pnpm build`); single-package repos (e.g. an
162
+ * Astro site with only a `build` script) override them so the validate phase
163
+ * doesn't fail on a missing `test` script before it can reach the build.
164
+ *
165
+ * Only those two fields are overridable per-repo. An explicit empty
166
+ * `preValidateCommand` is preserved (it means "skip the install step"). Returns
167
+ * the original config object unchanged when there are no applicable overrides,
168
+ * so callers can cheaply detect "no override" via reference equality.
169
+ */
170
+ export declare function applyRepoValidateOverrides(config: WorkerConfig, settings: OrchestratorSettings | null | undefined): WorkerConfig;
171
+ /**
172
+ * Resolve the wall-clock timeout (ms) for a CLI phase: the per-phase override
173
+ * if one is configured, otherwise the flat `phaseTimeoutMs` fallback.
174
+ */
175
+ export declare function resolvePhaseTimeoutMs(config: WorkerConfig, phase: Exclude<WorkflowPhase, 'validate'>): number;
84
176
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/worker/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;GAEG;AACH,eAAO,MAAM,oBAAoB;IAC/B,qCAAqC;;IAErC,uCAAuC;;IAEvC,gCAAgC;;;;;;;;;;EAEhC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,kBAAkB;IAC7B,wCAAwC;;IAExC,wCAAwC;;IAExC,gDAAgD;;IAEhD,+CAA+C;;IAE/C,sFAAsF;;IAEtF,4EAA4E;;IAE5E,wHAAwH;;IAExH,4CAA4C;;QA1B5C,qCAAqC;;QAErC,uCAAuC;;QAEvC,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsChC,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/worker/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;GAEG;AACH,eAAO,MAAM,oBAAoB;IAC/B,qCAAqC;;IAErC,uCAAuC;;IAEvC,gCAAgC;;;;;;;;;;EAEhC,CAAC;AAEH;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;GAQ1B,CAAC;AACf,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF;;GAEG;AACH,eAAO,MAAM,kBAAkB;IAC7B,2FAA2F;;IAE3F,sDAAsD;;;;;;;;;;;;;;;;;;;;IAEtD,wCAAwC;;IAExC,gDAAgD;;IAEhD,+CAA+C;;IAE/C,sFAAsF;;IAMtF,4EAA4E;;IAE5E,wHAAwH;;IAExH,4CAA4C;;QA3D5C,qCAAqC;;QAErC,uCAAuC;;QAEvC,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2EhC,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,oBAAoB,GAAG,IAAI,GAAG,SAAS,GAChD,YAAY,CAgBd;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,OAAO,CAAC,aAAa,EAAE,UAAU,CAAC,GACxC,MAAM,CAIR"}
@@ -8,14 +8,41 @@ export const GateDefinitionSchema = z.object({
8
8
  /** Label to add when gate is active */
9
9
  gateLabel: z.string(),
10
10
  /** When to activate the gate */
11
- condition: z.enum(['always', 'on-request', 'on-questions', 'on-failure', 'on-sibling-review']),
11
+ condition: z.enum(['always', 'on-request', 'on-questions', 'on-failure', 'on-sibling-review', 'on-merge-conflict']),
12
12
  });
13
+ /**
14
+ * Per-phase wall-clock timeout overrides (milliseconds).
15
+ *
16
+ * Each CLI phase is killed (SIGTERM → grace → SIGKILL) once its wall-clock
17
+ * runtime exceeds its timeout. The `plan` and `implement` phases are
18
+ * structurally heavier than the others — `plan` fans out research subagents,
19
+ * `implement` writes code — so they default to a larger budget than the flat
20
+ * `phaseTimeoutMs`. Any phase without an override falls back to `phaseTimeoutMs`.
21
+ *
22
+ * Defined per-field (rather than as a `z.record`) so that overriding one phase
23
+ * via config/env does not drop the defaults for the others — Zod applies the
24
+ * remaining field defaults when the object is present but partial.
25
+ *
26
+ * `validate` is intentionally excluded: that phase runs a shell command via a
27
+ * separate code path with its own timeout, not `phaseTimeoutMs`.
28
+ */
29
+ export const PhaseTimeoutOverridesSchema = z
30
+ .object({
31
+ specify: z.number().int().min(60_000).optional(),
32
+ clarify: z.number().int().min(60_000).optional(),
33
+ plan: z.number().int().min(60_000).default(3_600_000),
34
+ tasks: z.number().int().min(60_000).optional(),
35
+ implement: z.number().int().min(60_000).default(3_600_000),
36
+ })
37
+ .default({});
13
38
  /**
14
39
  * Worker configuration schema
15
40
  */
16
41
  export const WorkerConfigSchema = z.object({
17
- /** Timeout per phase in milliseconds */
18
- phaseTimeoutMs: z.number().int().min(60_000).default(600_000),
42
+ /** Fallback timeout per phase in milliseconds (used when no per-phase override applies) */
43
+ phaseTimeoutMs: z.number().int().min(60_000).default(1_200_000),
44
+ /** Per-phase timeout overrides keyed by phase name */
45
+ phaseTimeoutOverrides: PhaseTimeoutOverridesSchema,
19
46
  /** Base directory for repo checkouts */
20
47
  workspaceDir: z.string().default('/tmp/orchestrator-workspaces'),
21
48
  /** Grace period for shutdown in milliseconds */
@@ -23,7 +50,9 @@ export const WorkerConfigSchema = z.object({
23
50
  /** Command to run during the validate phase */
24
51
  validateCommand: z.string().default('pnpm test && pnpm build'),
25
52
  /** Command to run before validation to install dependencies (empty string to skip) */
26
- preValidateCommand: z.string().default("pnpm install && pnpm -r --filter './packages/*' build"),
53
+ preValidateCommand: z
54
+ .string()
55
+ .default("pnpm install && if [ -f pnpm-workspace.yaml ] && ls packages/*/package.json >/dev/null 2>&1; then pnpm -r --filter './packages/*' build; fi"),
27
56
  /** Maximum retries for implement phase when partial progress is detected */
28
57
  maxImplementRetries: z.number().int().min(0).max(5).default(2),
29
58
  /** Credential role from .generacy/config.yaml defaults.role — when set, credentials are populated on launch requests */
@@ -34,10 +63,14 @@ export const WorkerConfigSchema = z.object({
34
63
  { phase: 'clarify', gateLabel: 'waiting-for:clarification', condition: 'on-questions' },
35
64
  { phase: 'implement', gateLabel: 'waiting-for:implementation-review', condition: 'always' },
36
65
  { phase: 'implement', gateLabel: 'waiting-for:sibling-review', condition: 'on-sibling-review' },
66
+ { phase: 'implement', gateLabel: 'waiting-for:merge-conflicts', condition: 'on-merge-conflict' },
67
+ { phase: 'validate', gateLabel: 'waiting-for:merge-conflicts', condition: 'on-merge-conflict' },
37
68
  ],
38
69
  'speckit-bugfix': [
39
70
  { phase: 'clarify', gateLabel: 'waiting-for:clarification', condition: 'on-questions' },
40
71
  { phase: 'implement', gateLabel: 'waiting-for:implementation-review', condition: 'on-request' },
72
+ { phase: 'implement', gateLabel: 'waiting-for:merge-conflicts', condition: 'on-merge-conflict' },
73
+ { phase: 'validate', gateLabel: 'waiting-for:merge-conflicts', condition: 'on-merge-conflict' },
41
74
  ],
42
75
  'speckit-epic': [
43
76
  { phase: 'clarify', gateLabel: 'waiting-for:clarification', condition: 'on-questions' },
@@ -45,4 +78,42 @@ export const WorkerConfigSchema = z.object({
45
78
  ],
46
79
  }),
47
80
  });
81
+ /**
82
+ * Merge per-repo validate-command overrides onto the global worker config.
83
+ *
84
+ * The target repo's `.generacy/config.yaml` `orchestrator` block may set
85
+ * `validateCommand` / `preValidateCommand`. The global defaults are
86
+ * monorepo-shaped (`pnpm test && pnpm build`); single-package repos (e.g. an
87
+ * Astro site with only a `build` script) override them so the validate phase
88
+ * doesn't fail on a missing `test` script before it can reach the build.
89
+ *
90
+ * Only those two fields are overridable per-repo. An explicit empty
91
+ * `preValidateCommand` is preserved (it means "skip the install step"). Returns
92
+ * the original config object unchanged when there are no applicable overrides,
93
+ * so callers can cheaply detect "no override" via reference equality.
94
+ */
95
+ export function applyRepoValidateOverrides(config, settings) {
96
+ if (settings == null ||
97
+ (settings.validateCommand === undefined && settings.preValidateCommand === undefined)) {
98
+ return config;
99
+ }
100
+ return {
101
+ ...config,
102
+ ...(settings.validateCommand !== undefined
103
+ ? { validateCommand: settings.validateCommand }
104
+ : {}),
105
+ ...(settings.preValidateCommand !== undefined
106
+ ? { preValidateCommand: settings.preValidateCommand }
107
+ : {}),
108
+ };
109
+ }
110
+ /**
111
+ * Resolve the wall-clock timeout (ms) for a CLI phase: the per-phase override
112
+ * if one is configured, otherwise the flat `phaseTimeoutMs` fallback.
113
+ */
114
+ export function resolvePhaseTimeoutMs(config, phase) {
115
+ // Optional-chained: configs built by hand (tests, direct construction) bypass
116
+ // Zod and may omit phaseTimeoutOverrides entirely.
117
+ return config.phaseTimeoutOverrides?.[phase] ?? config.phaseTimeoutMs;
118
+ }
48
119
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/worker/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,qCAAqC;IACrC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,CAA6C,CAAC;IAC3H,uCAAuC;IACvC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,gCAAgC;IAChC,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,mBAAmB,CAAC,CAAC;CAC/F,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,wCAAwC;IACxC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IAC7D,wCAAwC;IACxC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,8BAA8B,CAAC;IAChE,gDAAgD;IAChD,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;IAC/D,+CAA+C;IAC/C,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,yBAAyB,CAAC;IAC9D,sFAAsF;IACtF,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,uDAAuD,CAAC;IAC/F,4EAA4E;IAC5E,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC9D,wHAAwH;IACxH,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACrC,4CAA4C;IAC5C,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,OAAO,CAAC;QACjE,iBAAiB,EAAE;YACjB,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,2BAA2B,EAAE,SAAS,EAAE,cAAc,EAAE;YACvF,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,mCAAmC,EAAE,SAAS,EAAE,QAAQ,EAAE;YAC3F,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,4BAA4B,EAAE,SAAS,EAAE,mBAAmB,EAAE;SAChG;QACD,gBAAgB,EAAE;YAChB,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,2BAA2B,EAAE,SAAS,EAAE,cAAc,EAAE;YACvF,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,mCAAmC,EAAE,SAAS,EAAE,YAAY,EAAE;SAChG;QACD,cAAc,EAAE;YACd,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,2BAA2B,EAAE,SAAS,EAAE,cAAc,EAAE;YACvF,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,0BAA0B,EAAE,SAAS,EAAE,QAAQ,EAAE;SAC/E;KACF,CAAC;CACH,CAAC,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/worker/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Structured extract from failing validate CLI stdout.
3
+ * Sorted by `id` (lexicographic) for hash stability.
4
+ * See specs/892-found-during-cockpit-v1/contracts/evidence-hash.md.
5
+ */
6
+ export interface EvidenceExtract {
7
+ failures: Array<{
8
+ id: string;
9
+ firstError: string;
10
+ }>;
11
+ }
12
+ /**
13
+ * Result of hashing validate CLI stdout — SHA-256 hex identity plus the
14
+ * canonical `extract` that was hashed (surfaces in prompt + logs).
15
+ */
16
+ export interface EvidenceHashResult {
17
+ /** 64-character lower-case hex SHA-256. */
18
+ hash: string;
19
+ /** Canonical input to the hash; included in the fix prompt for debuggability. */
20
+ extract: EvidenceExtract;
21
+ }
22
+ /**
23
+ * Hash validate CLI stdout into a stable identity (#892).
24
+ *
25
+ * Extract categories are tried in order: next-build missing-module, next-build
26
+ * type-error, vitest failures. If none match, falls back to a whole-transcript
27
+ * hash so every stdout produces a well-defined result.
28
+ *
29
+ * See specs/892-found-during-cockpit-v1/contracts/evidence-hash.md.
30
+ */
31
+ export declare function hashValidationEvidence(stdout: string): EvidenceHashResult;
32
+ //# sourceMappingURL=evidence-hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence-hash.d.ts","sourceRoot":"","sources":["../../src/worker/evidence-hash.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrD;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,OAAO,EAAE,eAAe,CAAC;CAC1B;AA+HD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,CAmBzE"}
@@ -0,0 +1,139 @@
1
+ import { createHash } from 'node:crypto';
2
+ /**
3
+ * Normalization pipeline applied to raw stdout before extraction (#892).
4
+ *
5
+ * Idempotent by construction — running the pipeline on already-normalized
6
+ * text yields the same output. Ordering matters: ANSI first (so downstream
7
+ * regexes see clean text), timestamps before paths (so ISO-8601 doesn't
8
+ * partially match path regex), paths before PIDs (so bracket sequences in
9
+ * paths aren't mistaken for PIDs).
10
+ */
11
+ function normalize(stdout) {
12
+ let out = stdout;
13
+ // 1. ANSI escapes (CSI + OSC). Matching the ESC/BEL control chars is the
14
+ // whole point here, so the no-control-regex rule is intentionally disabled.
15
+ // eslint-disable-next-line no-control-regex
16
+ out = out.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '');
17
+ // eslint-disable-next-line no-control-regex
18
+ out = out.replace(/\x1b\][^\x07]*\x07/g, '');
19
+ // 2. ISO-8601 timestamps → <TS>.
20
+ out = out.replace(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})?/g, '<TS>');
21
+ // 3. Absolute paths → <PATH>. Only strip paths whose leading '/' is at a
22
+ // non-alphanumeric boundary — this preserves import specifiers like
23
+ // `@/components/CopyButton` and relative paths like `src/app/foo.ts` /
24
+ // `./src/foo.ts` while normalizing true absolute paths like
25
+ // `/home/node/workspaces/sniplink/src/app/foo.ts`.
26
+ out = out.replace(/(?<![\w@.])(\/[a-zA-Z0-9._-]+)+/g, '<PATH>');
27
+ // 4. PIDs → <PID>. Three forms: pid=<n>, PID: <n>, [<n>] where n >= 4 digits.
28
+ out = out.replace(/\bpid=\d+\b/g, 'pid=<PID>');
29
+ out = out.replace(/\bPID:\s*\d+\b/g, 'PID: <PID>');
30
+ out = out.replace(/\[\d{4,}\]/g, '[<PID>]');
31
+ // 5. Test-runner tmp identifiers → <TMP>. Absolute /tmp/... already
32
+ // reduced by step 3; T-<hex>{8+} form is the vitest/jest one.
33
+ out = out.replace(/T-[a-zA-Z0-9]{8,}/g, '<TMP>');
34
+ // 6. Ports on localhost/127.0.0.1 → <PORT>.
35
+ out = out.replace(/\b(localhost|127\.0\.0\.1):\d+\b/g, '$1:<PORT>');
36
+ return out;
37
+ }
38
+ /**
39
+ * Extract next-build "Cannot find module" failures.
40
+ */
41
+ function extractNextBuildMissingModule(normalized) {
42
+ const failures = [];
43
+ const re = /Cannot find module '([^']+)'/g;
44
+ let m;
45
+ while ((m = re.exec(normalized)) !== null) {
46
+ const modulePath = m[1];
47
+ failures.push({
48
+ id: `module:${modulePath}`,
49
+ firstError: m[0],
50
+ });
51
+ }
52
+ return failures;
53
+ }
54
+ /**
55
+ * Extract next-build "Type error" failures.
56
+ */
57
+ function extractNextBuildTypeError(normalized) {
58
+ const failures = [];
59
+ // Type error line followed (within the same block) by a File: <path> line.
60
+ const re = /Type error: (.+?)(?:\r?\n)[\s\S]{0,200}?File: (\S+)/g;
61
+ let m;
62
+ while ((m = re.exec(normalized)) !== null) {
63
+ const summary = m[1].trim();
64
+ const filePath = m[2];
65
+ failures.push({
66
+ id: `type:${filePath}:${summary.slice(0, 80)}`,
67
+ firstError: `Type error: ${summary}`,
68
+ });
69
+ }
70
+ return failures;
71
+ }
72
+ /**
73
+ * Extract vitest failing test lines (` × <name>`).
74
+ * `firstError` is the first indented (≥2 space) line following the × line.
75
+ */
76
+ function extractVitestFailures(normalized) {
77
+ const failures = [];
78
+ const lines = normalized.split('\n');
79
+ const failedLineRe = /^\s*×\s+(.+?)(?:\s+\d+ms)?$/;
80
+ for (let i = 0; i < lines.length; i++) {
81
+ const m = failedLineRe.exec(lines[i]);
82
+ if (!m)
83
+ continue;
84
+ const testName = m[1].trim();
85
+ let firstError = '';
86
+ for (let j = i + 1; j < Math.min(lines.length, i + 11); j++) {
87
+ const l = lines[j];
88
+ if (/^\s{2,}\S/.test(l)) {
89
+ firstError = l.trim();
90
+ break;
91
+ }
92
+ }
93
+ failures.push({
94
+ id: `test:${testName}`,
95
+ firstError,
96
+ });
97
+ }
98
+ return failures;
99
+ }
100
+ /**
101
+ * Fallback path when no known pattern matches.
102
+ * `id` = `hash:<first 16 hex of SHA-256 of full normalized transcript>`.
103
+ * `firstError` = first non-empty line of normalized transcript.
104
+ */
105
+ function fallbackExtract(normalized) {
106
+ const digest = createHash('sha256').update(normalized, 'utf8').digest('hex');
107
+ const firstLine = normalized.split('\n').find((l) => l.length > 0) ?? '';
108
+ return [
109
+ {
110
+ id: `hash:${digest.slice(0, 16)}`,
111
+ firstError: firstLine,
112
+ },
113
+ ];
114
+ }
115
+ /**
116
+ * Hash validate CLI stdout into a stable identity (#892).
117
+ *
118
+ * Extract categories are tried in order: next-build missing-module, next-build
119
+ * type-error, vitest failures. If none match, falls back to a whole-transcript
120
+ * hash so every stdout produces a well-defined result.
121
+ *
122
+ * See specs/892-found-during-cockpit-v1/contracts/evidence-hash.md.
123
+ */
124
+ export function hashValidationEvidence(stdout) {
125
+ const normalized = normalize(stdout);
126
+ const raw = [
127
+ ...extractNextBuildMissingModule(normalized),
128
+ ...extractNextBuildTypeError(normalized),
129
+ ...extractVitestFailures(normalized),
130
+ ];
131
+ const failures = raw.length > 0 ? raw : fallbackExtract(normalized);
132
+ // Sort by id for determinism (localeCompare with 'variant' avoids locale drift).
133
+ failures.sort((a, b) => a.id.localeCompare(b.id, undefined, { sensitivity: 'variant' }));
134
+ const extract = { failures };
135
+ const canonical = JSON.stringify({ failures: extract.failures });
136
+ const hash = createHash('sha256').update(canonical, 'utf8').digest('hex');
137
+ return { hash, extract };
138
+ }
139
+ //# sourceMappingURL=evidence-hash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence-hash.js","sourceRoot":"","sources":["../../src/worker/evidence-hash.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * `assertHandlerOutcomeMatchesWorld` (#902 FR-006).
3
+ *
4
+ * Post-exit runtime assertion that reads a snapshot of the *real* world
5
+ * (labels + queue state) and refuses to accept "the handler said X" as
6
+ * evidence. Load-bearing enforcement half of the terminal-outcome invariant.
7
+ *
8
+ * Compile-time exhaustiveness would have passed the broken #898 handler
9
+ * (which had a `void` return that ran through the success path without
10
+ * setting anything). The type alone cannot catch this bug class.
11
+ *
12
+ * Pure function — fixture code snapshots the world, then calls the helper.
13
+ * Callable from prod code as a dev-mode assertion (not enabled by default).
14
+ */
15
+ import type { HandlerOutcome } from './handler-outcome.js';
16
+ import type { QueueItem } from '../types/index.js';
17
+ export interface QueueSnapshot {
18
+ readonly inFlight: boolean;
19
+ readonly pendingItems: readonly Pick<QueueItem, 'command' | 'metadata' | 'workflowName'>[];
20
+ }
21
+ export type AssertionResult = {
22
+ readonly ok: true;
23
+ } | {
24
+ readonly ok: false;
25
+ readonly mismatch: string;
26
+ };
27
+ /**
28
+ * Assert the returned `HandlerOutcome` matches the real world.
29
+ *
30
+ * Rules per variant:
31
+ * - `re-armed`: `queueSnapshot.pendingItems` contains an entry with
32
+ * `command === 'continue'` and `metadata?.startPhase === outcome.startPhase`.
33
+ * - `gated`: `labels` contains a matching `waiting-for:*` label.
34
+ * - `failed`: `labels` contains a `blocked:*` or `failed:*` marker.
35
+ * - `done`: `labels` contains no `waiting-for:*` and no `blocked:*` / `failed:*`.
36
+ */
37
+ export declare function assertHandlerOutcomeMatchesWorld(outcome: HandlerOutcome, labels: readonly string[], queueSnapshot: QueueSnapshot): AssertionResult;
38
+ //# sourceMappingURL=handler-outcome-assertion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler-outcome-assertion.d.ts","sourceRoot":"","sources":["../../src/worker/handler-outcome-assertion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,SAAS,IAAI,CAAC,SAAS,EAAE,SAAS,GAAG,UAAU,GAAG,cAAc,CAAC,EAAE,CAAC;CAC5F;AAED,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;CAAE,GACrB;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtD;;;;;;;;;GASG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,aAAa,EAAE,aAAa,GAC3B,eAAe,CAwDjB"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Assert the returned `HandlerOutcome` matches the real world.
3
+ *
4
+ * Rules per variant:
5
+ * - `re-armed`: `queueSnapshot.pendingItems` contains an entry with
6
+ * `command === 'continue'` and `metadata?.startPhase === outcome.startPhase`.
7
+ * - `gated`: `labels` contains a matching `waiting-for:*` label.
8
+ * - `failed`: `labels` contains a `blocked:*` or `failed:*` marker.
9
+ * - `done`: `labels` contains no `waiting-for:*` and no `blocked:*` / `failed:*`.
10
+ */
11
+ export function assertHandlerOutcomeMatchesWorld(outcome, labels, queueSnapshot) {
12
+ switch (outcome.outcome) {
13
+ case 're-armed': {
14
+ const match = queueSnapshot.pendingItems.find((i) => i.command === 'continue' &&
15
+ i.metadata?.startPhase === outcome.startPhase);
16
+ if (!match) {
17
+ return {
18
+ ok: false,
19
+ mismatch: `re-armed(${outcome.startPhase}): no matching pending item found in queue`,
20
+ };
21
+ }
22
+ return { ok: true };
23
+ }
24
+ case 'gated': {
25
+ const hasMatchingWaitingFor = labels.some((l) => l === outcome.gateLabel && l.startsWith('waiting-for:'));
26
+ if (!hasMatchingWaitingFor) {
27
+ return {
28
+ ok: false,
29
+ mismatch: `gated(${outcome.gateLabel}): no matching waiting-for:* label on issue`,
30
+ };
31
+ }
32
+ return { ok: true };
33
+ }
34
+ case 'failed': {
35
+ const hasBlockedOrFailed = labels.some((l) => l.startsWith('blocked:') || l.startsWith('failed:'));
36
+ if (!hasBlockedOrFailed) {
37
+ return {
38
+ ok: false,
39
+ mismatch: `failed: no blocked:* or failed:* marker on issue`,
40
+ };
41
+ }
42
+ return { ok: true };
43
+ }
44
+ case 'done': {
45
+ const terminalBlockers = labels.filter((l) => l.startsWith('waiting-for:') ||
46
+ l.startsWith('blocked:') ||
47
+ l.startsWith('failed:'));
48
+ if (terminalBlockers.length > 0) {
49
+ return {
50
+ ok: false,
51
+ mismatch: `done: unexpected terminal-blocker label(s): ${terminalBlockers.join(', ')}`,
52
+ };
53
+ }
54
+ return { ok: true };
55
+ }
56
+ }
57
+ }
58
+ //# sourceMappingURL=handler-outcome-assertion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler-outcome-assertion.js","sourceRoot":"","sources":["../../src/worker/handler-outcome-assertion.ts"],"names":[],"mappings":"AA0BA;;;;;;;;;GASG;AACH,MAAM,UAAU,gCAAgC,CAC9C,OAAuB,EACvB,MAAyB,EACzB,aAA4B;IAE5B,QAAQ,OAAO,CAAC,OAAO,EAAE,CAAC;QACxB,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,MAAM,KAAK,GAAG,aAAa,CAAC,YAAY,CAAC,IAAI,CAC3C,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,OAAO,KAAK,UAAU;gBACvB,CAAC,CAAC,QAAgD,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CACzF,CAAC;YACF,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO;oBACL,EAAE,EAAE,KAAK;oBACT,QAAQ,EAAE,YAAY,OAAO,CAAC,UAAU,4CAA4C;iBACrF,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACtB,CAAC;QACD,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,qBAAqB,GAAG,MAAM,CAAC,IAAI,CACvC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC,UAAU,CAAC,cAAc,CAAC,CAC/D,CAAC;YACF,IAAI,CAAC,qBAAqB,EAAE,CAAC;gBAC3B,OAAO;oBACL,EAAE,EAAE,KAAK;oBACT,QAAQ,EAAE,SAAS,OAAO,CAAC,SAAS,6CAA6C;iBAClF,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACtB,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,kBAAkB,GAAG,MAAM,CAAC,IAAI,CACpC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAC3D,CAAC;YACF,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBACxB,OAAO;oBACL,EAAE,EAAE,KAAK;oBACT,QAAQ,EAAE,kDAAkD;iBAC7D,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACtB,CAAC;QACD,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,CACpC,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,UAAU,CAAC,cAAc,CAAC;gBAC5B,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC;gBACxB,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAC1B,CAAC;YACF,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChC,OAAO;oBACL,EAAE,EAAE,KAAK;oBACT,QAAQ,EAAE,+CAA+C,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;iBACvF,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * `HandlerOutcome` discriminated union (#902 FR-005).
3
+ *
4
+ * The only legal return shape for `MergeConflictHandler.handle`. Every
5
+ * terminal exit path in the handler maps to exactly one variant; compile-time
6
+ * exhaustiveness enforces this at the type layer.
7
+ *
8
+ * The load-bearing enforcement half is the runtime helper
9
+ * `assertHandlerOutcomeMatchesWorld` in `./handler-outcome-assertion.ts`.
10
+ *
11
+ * Semantics:
12
+ * - `re-armed` — the interrupted phase must be re-entered. Dispatcher enqueues
13
+ * `{command: 'continue', startPhase}` for the same itemKey after
14
+ * `queue.complete()` fires on the current handler item.
15
+ * - `gated` — the issue is now sitting at a `waiting-for:*` label matching
16
+ * `gateLabel`. Detector will pick it up naturally.
17
+ * - `failed` — the issue is now sitting at a `blocked:*` or `failed:*` marker.
18
+ * Operator intervention required.
19
+ * - `done` — the issue is terminal (closed / merged / withdrawn). No detector
20
+ * pickup expected.
21
+ */
22
+ import type { WorkflowPhase } from './types.js';
23
+ import type { BlockedStuckMergeConflictsEvidence } from './merge-conflict-handler.js';
24
+ export interface ReArmedOutcome {
25
+ readonly outcome: 're-armed';
26
+ /** Phase the interrupted worker should resume at. Threaded to enqueue. */
27
+ readonly startPhase: WorkflowPhase;
28
+ }
29
+ export interface GatedOutcome {
30
+ readonly outcome: 'gated';
31
+ /**
32
+ * The `waiting-for:*` label that MUST be present on the issue at return.
33
+ * Enforced by `assertHandlerOutcomeMatchesWorld`.
34
+ */
35
+ readonly gateLabel: string;
36
+ }
37
+ export interface FailedOutcome {
38
+ readonly outcome: 'failed';
39
+ /**
40
+ * Evidence blob rendered into the operator-facing stage comment.
41
+ * Shape is handler-specific; `MergeConflictHandler` uses
42
+ * `BlockedStuckMergeConflictsEvidence`.
43
+ */
44
+ readonly evidence: BlockedStuckMergeConflictsEvidence;
45
+ }
46
+ export interface DoneOutcome {
47
+ readonly outcome: 'done';
48
+ }
49
+ export type HandlerOutcome = ReArmedOutcome | GatedOutcome | FailedOutcome | DoneOutcome;
50
+ //# sourceMappingURL=handler-outcome.d.ts.map