@telora/daemon 0.17.36 → 0.17.42

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 (266) hide show
  1. package/build-info.json +5 -3
  2. package/dist/assembly-engine.d.ts +6 -0
  3. package/dist/assembly-engine.d.ts.map +1 -1
  4. package/dist/assembly-engine.js +19 -0
  5. package/dist/assembly-engine.js.map +1 -1
  6. package/dist/assembly-resolvers.d.ts +17 -8
  7. package/dist/assembly-resolvers.d.ts.map +1 -1
  8. package/dist/assembly-resolvers.js +19 -8
  9. package/dist/assembly-resolvers.js.map +1 -1
  10. package/dist/cli/session-state.d.ts +10 -0
  11. package/dist/cli/session-state.d.ts.map +1 -1
  12. package/dist/cli/session-state.js +31 -0
  13. package/dist/cli/session-state.js.map +1 -1
  14. package/dist/completion/completion-decision.d.ts +83 -0
  15. package/dist/completion/completion-decision.d.ts.map +1 -0
  16. package/dist/completion/completion-decision.js +48 -0
  17. package/dist/completion/completion-decision.js.map +1 -0
  18. package/dist/completion/event-escalations.d.ts +97 -0
  19. package/dist/completion/event-escalations.d.ts.map +1 -0
  20. package/dist/completion/event-escalations.js +213 -0
  21. package/dist/completion/event-escalations.js.map +1 -0
  22. package/dist/completion/event.d.ts +1 -72
  23. package/dist/completion/event.d.ts.map +1 -1
  24. package/dist/completion/event.js +148 -322
  25. package/dist/completion/event.js.map +1 -1
  26. package/dist/completion/exit-classification.d.ts +82 -0
  27. package/dist/completion/exit-classification.d.ts.map +1 -0
  28. package/dist/completion/exit-classification.js +61 -0
  29. package/dist/completion/exit-classification.js.map +1 -0
  30. package/dist/completion/index.d.ts +14 -5
  31. package/dist/completion/index.d.ts.map +1 -1
  32. package/dist/completion/index.js +14 -5
  33. package/dist/completion/index.js.map +1 -1
  34. package/dist/completion/merge-phase.d.ts +114 -0
  35. package/dist/completion/merge-phase.d.ts.map +1 -0
  36. package/dist/completion/merge-phase.js +198 -0
  37. package/dist/completion/merge-phase.js.map +1 -0
  38. package/dist/completion/review-exit-phase.d.ts +82 -0
  39. package/dist/completion/review-exit-phase.d.ts.map +1 -0
  40. package/dist/completion/review-exit-phase.js +228 -0
  41. package/dist/completion/review-exit-phase.js.map +1 -0
  42. package/dist/completion/status-advance-phase.d.ts +61 -0
  43. package/dist/completion/status-advance-phase.d.ts.map +1 -0
  44. package/dist/completion/status-advance-phase.js +182 -0
  45. package/dist/completion/status-advance-phase.js.map +1 -0
  46. package/dist/completion/team-completion.d.ts +28 -269
  47. package/dist/completion/team-completion.d.ts.map +1 -1
  48. package/dist/completion/team-completion.js +145 -676
  49. package/dist/completion/team-completion.js.map +1 -1
  50. package/dist/daemon-process.d.ts +18 -2
  51. package/dist/daemon-process.d.ts.map +1 -1
  52. package/dist/daemon-process.js +7 -2
  53. package/dist/daemon-process.js.map +1 -1
  54. package/dist/directive/close-loop-stage.d.ts +50 -0
  55. package/dist/directive/close-loop-stage.d.ts.map +1 -0
  56. package/dist/directive/close-loop-stage.js +196 -0
  57. package/dist/directive/close-loop-stage.js.map +1 -0
  58. package/dist/directive/directive-assembly.d.ts +33 -0
  59. package/dist/directive/directive-assembly.d.ts.map +1 -0
  60. package/dist/directive/directive-assembly.js +77 -0
  61. package/dist/directive/directive-assembly.js.map +1 -0
  62. package/dist/directive/directive-dispatch.d.ts +103 -0
  63. package/dist/directive/directive-dispatch.d.ts.map +1 -0
  64. package/dist/directive/directive-dispatch.js +279 -0
  65. package/dist/directive/directive-dispatch.js.map +1 -0
  66. package/dist/directive/phase-sync.d.ts +89 -0
  67. package/dist/directive/phase-sync.d.ts.map +1 -0
  68. package/dist/directive/phase-sync.js +173 -0
  69. package/dist/directive/phase-sync.js.map +1 -0
  70. package/dist/directive-executor.d.ts +21 -223
  71. package/dist/directive-executor.d.ts.map +1 -1
  72. package/dist/directive-executor.js +28 -687
  73. package/dist/directive-executor.js.map +1 -1
  74. package/dist/focus-engine.d.ts.map +1 -1
  75. package/dist/focus-engine.js +8 -0
  76. package/dist/focus-engine.js.map +1 -1
  77. package/dist/focus-executor.d.ts +29 -8
  78. package/dist/focus-executor.d.ts.map +1 -1
  79. package/dist/focus-executor.js +29 -10
  80. package/dist/focus-executor.js.map +1 -1
  81. package/dist/focus-stage-lifecycle.d.ts +7 -5
  82. package/dist/focus-stage-lifecycle.d.ts.map +1 -1
  83. package/dist/focus-stage-lifecycle.js +11 -6
  84. package/dist/focus-stage-lifecycle.js.map +1 -1
  85. package/dist/index.js +8 -0
  86. package/dist/index.js.map +1 -1
  87. package/dist/pipeline-config.d.ts +13 -0
  88. package/dist/pipeline-config.d.ts.map +1 -1
  89. package/dist/pipeline-config.js +15 -0
  90. package/dist/pipeline-config.js.map +1 -1
  91. package/dist/resolvers/agent-escalations.d.ts +8 -1
  92. package/dist/resolvers/agent-escalations.d.ts.map +1 -1
  93. package/dist/resolvers/agent-escalations.js +25 -22
  94. package/dist/resolvers/agent-escalations.js.map +1 -1
  95. package/dist/resolvers/agent-session-summaries.d.ts +8 -1
  96. package/dist/resolvers/agent-session-summaries.d.ts.map +1 -1
  97. package/dist/resolvers/agent-session-summaries.js +21 -18
  98. package/dist/resolvers/agent-session-summaries.js.map +1 -1
  99. package/dist/resolvers/delivery-acceptance-criteria.d.ts +7 -1
  100. package/dist/resolvers/delivery-acceptance-criteria.d.ts.map +1 -1
  101. package/dist/resolvers/delivery-acceptance-criteria.js +14 -11
  102. package/dist/resolvers/delivery-acceptance-criteria.js.map +1 -1
  103. package/dist/resolvers/delivery-description.d.ts +7 -1
  104. package/dist/resolvers/delivery-description.d.ts.map +1 -1
  105. package/dist/resolvers/delivery-description.js +14 -11
  106. package/dist/resolvers/delivery-description.js.map +1 -1
  107. package/dist/resolvers/delivery-issues.d.ts +8 -1
  108. package/dist/resolvers/delivery-issues.d.ts.map +1 -1
  109. package/dist/resolvers/delivery-issues.js +51 -48
  110. package/dist/resolvers/delivery-issues.js.map +1 -1
  111. package/dist/resolvers/delivery-listing.d.ts +16 -1
  112. package/dist/resolvers/delivery-listing.d.ts.map +1 -1
  113. package/dist/resolvers/delivery-listing.js +36 -33
  114. package/dist/resolvers/delivery-listing.js.map +1 -1
  115. package/dist/resolvers/delivery-tech-context.d.ts +7 -1
  116. package/dist/resolvers/delivery-tech-context.d.ts.map +1 -1
  117. package/dist/resolvers/delivery-tech-context.js +14 -11
  118. package/dist/resolvers/delivery-tech-context.js.map +1 -1
  119. package/dist/resolvers/deployment-profile.d.ts +8 -1
  120. package/dist/resolvers/deployment-profile.d.ts.map +1 -1
  121. package/dist/resolvers/deployment-profile.js +20 -17
  122. package/dist/resolvers/deployment-profile.js.map +1 -1
  123. package/dist/resolvers/focus-anchoring-injections.d.ts +26 -1
  124. package/dist/resolvers/focus-anchoring-injections.d.ts.map +1 -1
  125. package/dist/resolvers/focus-anchoring-injections.js +91 -88
  126. package/dist/resolvers/focus-anchoring-injections.js.map +1 -1
  127. package/dist/resolvers/focus-context.d.ts +9 -1
  128. package/dist/resolvers/focus-context.d.ts.map +1 -1
  129. package/dist/resolvers/focus-context.js +38 -35
  130. package/dist/resolvers/focus-context.js.map +1 -1
  131. package/dist/resolvers/focus-injections.d.ts +13 -1
  132. package/dist/resolvers/focus-injections.d.ts.map +1 -1
  133. package/dist/resolvers/focus-injections.js +60 -57
  134. package/dist/resolvers/focus-injections.js.map +1 -1
  135. package/dist/resolvers/focus-last-review-report.d.ts +2 -1
  136. package/dist/resolvers/focus-last-review-report.d.ts.map +1 -1
  137. package/dist/resolvers/focus-last-review-report.js +33 -30
  138. package/dist/resolvers/focus-last-review-report.js.map +1 -1
  139. package/dist/resolvers/focus-reality-tree.d.ts +15 -1
  140. package/dist/resolvers/focus-reality-tree.d.ts.map +1 -1
  141. package/dist/resolvers/focus-reality-tree.js +35 -32
  142. package/dist/resolvers/focus-reality-tree.js.map +1 -1
  143. package/dist/resolvers/git-diff-against-base.d.ts +8 -1
  144. package/dist/resolvers/git-diff-against-base.d.ts.map +1 -1
  145. package/dist/resolvers/git-diff-against-base.js +33 -30
  146. package/dist/resolvers/git-diff-against-base.js.map +1 -1
  147. package/dist/resolvers/guards-evaluation-results.d.ts +7 -1
  148. package/dist/resolvers/guards-evaluation-results.d.ts.map +1 -1
  149. package/dist/resolvers/guards-evaluation-results.js +25 -22
  150. package/dist/resolvers/guards-evaluation-results.js.map +1 -1
  151. package/dist/resolvers/index.d.ts +22 -40
  152. package/dist/resolvers/index.d.ts.map +1 -1
  153. package/dist/resolvers/index.js +112 -41
  154. package/dist/resolvers/index.js.map +1 -1
  155. package/dist/resolvers/loop-context.d.ts +18 -1
  156. package/dist/resolvers/loop-context.d.ts.map +1 -1
  157. package/dist/resolvers/loop-context.js +21 -18
  158. package/dist/resolvers/loop-context.js.map +1 -1
  159. package/dist/resolvers/loop-delivery-index.d.ts +17 -1
  160. package/dist/resolvers/loop-delivery-index.d.ts.map +1 -1
  161. package/dist/resolvers/loop-delivery-index.js +51 -48
  162. package/dist/resolvers/loop-delivery-index.js.map +1 -1
  163. package/dist/resolvers/loop-documents.d.ts +9 -1
  164. package/dist/resolvers/loop-documents.d.ts.map +1 -1
  165. package/dist/resolvers/loop-documents.js +22 -19
  166. package/dist/resolvers/loop-documents.js.map +1 -1
  167. package/dist/resolvers/loop-expected-effects.d.ts +11 -1
  168. package/dist/resolvers/loop-expected-effects.d.ts.map +1 -1
  169. package/dist/resolvers/loop-expected-effects.js +53 -50
  170. package/dist/resolvers/loop-expected-effects.js.map +1 -1
  171. package/dist/resolvers/loop-frt-statement.d.ts +11 -1
  172. package/dist/resolvers/loop-frt-statement.d.ts.map +1 -1
  173. package/dist/resolvers/loop-frt-statement.js +28 -25
  174. package/dist/resolvers/loop-frt-statement.js.map +1 -1
  175. package/dist/resolvers/loop-injection.d.ts +10 -1
  176. package/dist/resolvers/loop-injection.d.ts.map +1 -1
  177. package/dist/resolvers/loop-injection.js +38 -35
  178. package/dist/resolvers/loop-injection.js.map +1 -1
  179. package/dist/resolvers/loop-persona.d.ts +20 -1
  180. package/dist/resolvers/loop-persona.d.ts.map +1 -1
  181. package/dist/resolvers/loop-persona.js +20 -17
  182. package/dist/resolvers/loop-persona.js.map +1 -1
  183. package/dist/resolvers/loop-questions.d.ts +8 -1
  184. package/dist/resolvers/loop-questions.d.ts.map +1 -1
  185. package/dist/resolvers/loop-questions.js +39 -36
  186. package/dist/resolvers/loop-questions.js.map +1 -1
  187. package/dist/resolvers/loop-upstream-udes.d.ts +11 -1
  188. package/dist/resolvers/loop-upstream-udes.d.ts.map +1 -1
  189. package/dist/resolvers/loop-upstream-udes.js +74 -71
  190. package/dist/resolvers/loop-upstream-udes.js.map +1 -1
  191. package/dist/resolvers/prd-context.d.ts +2 -0
  192. package/dist/resolvers/prd-context.d.ts.map +1 -1
  193. package/dist/resolvers/prd-context.js +16 -13
  194. package/dist/resolvers/prd-context.js.map +1 -1
  195. package/dist/resolvers/prd-persona.d.ts +2 -0
  196. package/dist/resolvers/prd-persona.d.ts.map +1 -1
  197. package/dist/resolvers/prd-persona.js +6 -3
  198. package/dist/resolvers/prd-persona.js.map +1 -1
  199. package/dist/resolvers/reality-metrics.d.ts +8 -1
  200. package/dist/resolvers/reality-metrics.d.ts.map +1 -1
  201. package/dist/resolvers/reality-metrics.js +73 -70
  202. package/dist/resolvers/reality-metrics.js.map +1 -1
  203. package/dist/resolvers/reality-projections.d.ts +7 -1
  204. package/dist/resolvers/reality-projections.d.ts.map +1 -1
  205. package/dist/resolvers/reality-projections.js +35 -32
  206. package/dist/resolvers/reality-projections.js.map +1 -1
  207. package/dist/resolvers/reality-tree-snapshot.d.ts +10 -1
  208. package/dist/resolvers/reality-tree-snapshot.d.ts.map +1 -1
  209. package/dist/resolvers/reality-tree-snapshot.js +34 -31
  210. package/dist/resolvers/reality-tree-snapshot.js.map +1 -1
  211. package/dist/resolvers/retired-injections.d.ts +10 -1
  212. package/dist/resolvers/retired-injections.d.ts.map +1 -1
  213. package/dist/resolvers/retired-injections.js +68 -65
  214. package/dist/resolvers/retired-injections.js.map +1 -1
  215. package/dist/resolvers/review-outcomes.d.ts +11 -1
  216. package/dist/resolvers/review-outcomes.d.ts.map +1 -1
  217. package/dist/resolvers/review-outcomes.js +27 -24
  218. package/dist/resolvers/review-outcomes.js.map +1 -1
  219. package/dist/resolvers/security-advisory.d.ts +2 -1
  220. package/dist/resolvers/security-advisory.d.ts.map +1 -1
  221. package/dist/resolvers/security-advisory.js +47 -44
  222. package/dist/resolvers/security-advisory.js.map +1 -1
  223. package/dist/resolvers/wiki-search.d.ts +8 -1
  224. package/dist/resolvers/wiki-search.d.ts.map +1 -1
  225. package/dist/resolvers/wiki-search.js +17 -14
  226. package/dist/resolvers/wiki-search.js.map +1 -1
  227. package/dist/resolvers/wiki-topic.d.ts +9 -1
  228. package/dist/resolvers/wiki-topic.d.ts.map +1 -1
  229. package/dist/resolvers/wiki-topic.js +21 -18
  230. package/dist/resolvers/wiki-topic.js.map +1 -1
  231. package/dist/resolvers/workflow-stages.d.ts +7 -1
  232. package/dist/resolvers/workflow-stages.d.ts.map +1 -1
  233. package/dist/resolvers/workflow-stages.js +20 -17
  234. package/dist/resolvers/workflow-stages.js.map +1 -1
  235. package/dist/self-update.d.ts +6 -0
  236. package/dist/self-update.d.ts.map +1 -1
  237. package/dist/self-update.js +6 -1
  238. package/dist/self-update.js.map +1 -1
  239. package/dist/spawner/index.d.ts +2 -1
  240. package/dist/spawner/index.d.ts.map +1 -1
  241. package/dist/spawner/index.js +2 -1
  242. package/dist/spawner/index.js.map +1 -1
  243. package/dist/spawner/spawn-team.d.ts +14 -52
  244. package/dist/spawner/spawn-team.d.ts.map +1 -1
  245. package/dist/spawner/spawn-team.js +14 -469
  246. package/dist/spawner/spawn-team.js.map +1 -1
  247. package/dist/staleness.d.ts +124 -0
  248. package/dist/staleness.d.ts.map +1 -0
  249. package/dist/staleness.js +215 -0
  250. package/dist/staleness.js.map +1 -0
  251. package/dist/state-cascade.d.ts +3 -2
  252. package/dist/state-cascade.d.ts.map +1 -1
  253. package/dist/state-cascade.js +7 -3
  254. package/dist/state-cascade.js.map +1 -1
  255. package/dist/types/focus.d.ts +5 -4
  256. package/dist/types/focus.d.ts.map +1 -1
  257. package/dist/types/session.d.ts +2 -3
  258. package/dist/types/session.d.ts.map +1 -1
  259. package/dist/unified-shell.d.ts.map +1 -1
  260. package/dist/unified-shell.js +21 -12
  261. package/dist/unified-shell.js.map +1 -1
  262. package/package.json +2 -2
  263. package/dist/session-lifecycle.d.ts +0 -78
  264. package/dist/session-lifecycle.d.ts.map +0 -1
  265. package/dist/session-lifecycle.js +0 -382
  266. package/dist/session-lifecycle.js.map +0 -1
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Exit classification phase: how did the team lead process exit?
3
+ *
4
+ * Pure, side-effect-free classification of a team exit into success /
5
+ * controlled stop / failure, plus the exit_category derivation recorded on
6
+ * the session row. First phase of the completion flow in team-completion.ts.
7
+ * Extracted from completion/team-completion.ts; bodies verbatim.
8
+ */
9
+ import type { FocusTeamState, FocusTeamPhase, ExitCategory } from '../types.js';
10
+ /** Result of classifying how a team lead process exited. */
11
+ export interface TeamExitClassification {
12
+ /** Normalized exit code (null -> 1). */
13
+ exitCode: number;
14
+ /** Node reports a SIGTERM as either signal='SIGTERM' or code=143 (128+15). */
15
+ wasSigterm: boolean;
16
+ /**
17
+ * True when the daemon itself terminated the team because its work was done
18
+ * (shutdownReason='work_complete') -- a lifecycle teardown, NOT a crash.
19
+ */
20
+ proactivelyTerminated: boolean;
21
+ /**
22
+ * True when the exit should be treated as a SUCCESSFUL completion: a clean
23
+ * code-0 exit, or a proactive lifecycle termination. This is the signal the
24
+ * review-exit handler keys off to auto-approve a clean review's verify
25
+ * delivery -- so a review team that the daemon SIGTERMs as part of normal
26
+ * teardown is NOT mistaken for a failed review.
27
+ *
28
+ * IMPORTANT: `succeeded` is NARROW on purpose -- it stays false for a benign
29
+ * daemon-initiated SIGTERM whose reason is NOT work_complete (deactivated /
30
+ * handoff / teardown / user_stopped). The review auto-approve path depends on
31
+ * that. To label such a controlled stop as a non-error terminal status, use
32
+ * `controlledStop` / `disposition` instead of widening `succeeded`.
33
+ */
34
+ succeeded: boolean;
35
+ /**
36
+ * True when the daemon itself drove this exit: the team was in the
37
+ * 'shutting_down' phase and the process exited via SIGTERM -- for ANY
38
+ * shutdownReason (work_complete, deactivated, handoff, teardown,
39
+ * user_stopped, or none). Distinguishes a deliberate daemon stop from a
40
+ * genuine crash, WITHOUT widening `succeeded`.
41
+ */
42
+ controlledStop: boolean;
43
+ /**
44
+ * Terminal disposition for the session status label:
45
+ * - 'completed' -- a successful exit (`succeeded`).
46
+ * - 'stopped' -- a controlled daemon stop that was not a success
47
+ * (`controlledStop && !succeeded`).
48
+ * - 'failed' -- a genuine crash / unexpected exit.
49
+ * Maps 1:1 to the agent_sessions status the daemon writes.
50
+ */
51
+ disposition: 'completed' | 'stopped' | 'failed';
52
+ }
53
+ /**
54
+ * Classify how a team lead process exited.
55
+ *
56
+ * Pure and side-effect free so the "lifecycle SIGTERM is not a review failure"
57
+ * invariant is unit-testable in isolation. The crux: when the daemon proactively
58
+ * terminates a team because its work is complete, it sets phase='shutting_down'
59
+ * and shutdownReason='work_complete' BEFORE sending SIGTERM. We detect that
60
+ * teardown and classify it as succeeded -- otherwise a clean review team
61
+ * (which commits nothing of its own, then gets SIGTERMed once all deliveries
62
+ * are terminal) would look like a failed exit and its verify delivery would be
63
+ * stranded in `verify` instead of auto-approved to `done`.
64
+ */
65
+ export declare function classifyTeamExit(params: {
66
+ code: number | null;
67
+ signal: string | null;
68
+ teamPhase: FocusTeamPhase;
69
+ shutdownReason: FocusTeamState['shutdownReason'];
70
+ }): TeamExitClassification;
71
+ /**
72
+ * Derive the `exit_category` to record alongside the session status, given the
73
+ * classifier disposition and the team's shutdown reason.
74
+ *
75
+ * - 'completed' -> 'work_complete' when the daemon stopped the team because its
76
+ * work was done; otherwise null (a plain clean self-exit has no category).
77
+ * - 'stopped' -> the specific controlled-stop reason; any unknown/null reason
78
+ * falls back to 'handoff' (a benign daemon-initiated respawn).
79
+ * - 'failed' -> 'error' (genuine crash / unexpected exit).
80
+ */
81
+ export declare function deriveExitCategory(disposition: TeamExitClassification['disposition'], shutdownReason: FocusTeamState['shutdownReason']): ExitCategory | null;
82
+ //# sourceMappingURL=exit-classification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-classification.d.ts","sourceRoot":"","sources":["../../src/completion/exit-classification.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhF,4DAA4D;AAC5D,MAAM,WAAW,sBAAsB;IACrC,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,UAAU,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,qBAAqB,EAAE,OAAO,CAAC;IAC/B;;;;;;;;;;;;OAYG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;;;;;OAMG;IACH,cAAc,EAAE,OAAO,CAAC;IACxB;;;;;;;OAOG;IACH,WAAW,EAAE,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;CACjD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IACvC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,cAAc,CAAC;IAC1B,cAAc,EAAE,cAAc,CAAC,gBAAgB,CAAC,CAAC;CAClD,GAAG,sBAAsB,CAezB;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,sBAAsB,CAAC,aAAa,CAAC,EAClD,cAAc,EAAE,cAAc,CAAC,gBAAgB,CAAC,GAC/C,YAAY,GAAG,IAAI,CAerB"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Exit classification phase: how did the team lead process exit?
3
+ *
4
+ * Pure, side-effect-free classification of a team exit into success /
5
+ * controlled stop / failure, plus the exit_category derivation recorded on
6
+ * the session row. First phase of the completion flow in team-completion.ts.
7
+ * Extracted from completion/team-completion.ts; bodies verbatim.
8
+ */
9
+ /**
10
+ * Classify how a team lead process exited.
11
+ *
12
+ * Pure and side-effect free so the "lifecycle SIGTERM is not a review failure"
13
+ * invariant is unit-testable in isolation. The crux: when the daemon proactively
14
+ * terminates a team because its work is complete, it sets phase='shutting_down'
15
+ * and shutdownReason='work_complete' BEFORE sending SIGTERM. We detect that
16
+ * teardown and classify it as succeeded -- otherwise a clean review team
17
+ * (which commits nothing of its own, then gets SIGTERMed once all deliveries
18
+ * are terminal) would look like a failed exit and its verify delivery would be
19
+ * stranded in `verify` instead of auto-approved to `done`.
20
+ */
21
+ export function classifyTeamExit(params) {
22
+ const exitCode = params.code ?? 1;
23
+ const wasSigterm = params.signal === 'SIGTERM' || exitCode === 143;
24
+ const proactivelyTerminated = params.teamPhase === 'shutting_down' &&
25
+ wasSigterm &&
26
+ params.shutdownReason === 'work_complete';
27
+ const succeeded = exitCode === 0 || proactivelyTerminated;
28
+ // A controlled stop is any SIGTERM the daemon sent while the team was already
29
+ // shutting down -- regardless of reason. It is the signal that distinguishes
30
+ // a deliberate daemon teardown from a crash, without touching `succeeded`.
31
+ const controlledStop = params.teamPhase === 'shutting_down' && wasSigterm;
32
+ const disposition = succeeded ? 'completed' : controlledStop ? 'stopped' : 'failed';
33
+ return { exitCode, wasSigterm, proactivelyTerminated, succeeded, controlledStop, disposition };
34
+ }
35
+ /**
36
+ * Derive the `exit_category` to record alongside the session status, given the
37
+ * classifier disposition and the team's shutdown reason.
38
+ *
39
+ * - 'completed' -> 'work_complete' when the daemon stopped the team because its
40
+ * work was done; otherwise null (a plain clean self-exit has no category).
41
+ * - 'stopped' -> the specific controlled-stop reason; any unknown/null reason
42
+ * falls back to 'handoff' (a benign daemon-initiated respawn).
43
+ * - 'failed' -> 'error' (genuine crash / unexpected exit).
44
+ */
45
+ export function deriveExitCategory(disposition, shutdownReason) {
46
+ switch (disposition) {
47
+ case 'completed':
48
+ return shutdownReason === 'work_complete' ? 'work_complete' : null;
49
+ case 'stopped':
50
+ switch (shutdownReason) {
51
+ case 'deactivated': return 'deactivated';
52
+ case 'user_stopped': return 'user_stopped';
53
+ case 'handoff': return 'handoff';
54
+ case 'teardown': return 'teardown';
55
+ default: return 'handoff';
56
+ }
57
+ case 'failed':
58
+ return 'error';
59
+ }
60
+ }
61
+ //# sourceMappingURL=exit-classification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-classification.js","sourceRoot":"","sources":["../../src/completion/exit-classification.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAkDH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAKhC;IACC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;IAClC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,QAAQ,KAAK,GAAG,CAAC;IACnE,MAAM,qBAAqB,GACzB,MAAM,CAAC,SAAS,KAAK,eAAe;QACpC,UAAU;QACV,MAAM,CAAC,cAAc,KAAK,eAAe,CAAC;IAC5C,MAAM,SAAS,GAAG,QAAQ,KAAK,CAAC,IAAI,qBAAqB,CAAC;IAC1D,8EAA8E;IAC9E,6EAA6E;IAC7E,2EAA2E;IAC3E,MAAM,cAAc,GAAG,MAAM,CAAC,SAAS,KAAK,eAAe,IAAI,UAAU,CAAC;IAC1E,MAAM,WAAW,GACf,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;IAClE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,qBAAqB,EAAE,SAAS,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC;AACjG,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAChC,WAAkD,EAClD,cAAgD;IAEhD,QAAQ,WAAW,EAAE,CAAC;QACpB,KAAK,WAAW;YACd,OAAO,cAAc,KAAK,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC;QACrE,KAAK,SAAS;YACZ,QAAQ,cAAc,EAAE,CAAC;gBACvB,KAAK,aAAa,CAAC,CAAC,OAAO,aAAa,CAAC;gBACzC,KAAK,cAAc,CAAC,CAAC,OAAO,cAAc,CAAC;gBAC3C,KAAK,SAAS,CAAC,CAAC,OAAO,SAAS,CAAC;gBACjC,KAAK,UAAU,CAAC,CAAC,OAAO,UAAU,CAAC;gBACnC,OAAO,CAAC,CAAC,OAAO,SAAS,CAAC;YAC5B,CAAC;QACH,KAAK,QAAQ;YACX,OAAO,OAAO,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -6,16 +6,25 @@
6
6
  * directory) rather than reaching into individual modules.
7
7
  *
8
8
  * Modules:
9
- * - detector.ts -- CompletionDetector (interactive-session idle/complete detection)
10
- * - team-completion.ts -- handleTeamCompletion, focus merge, delivery advancement, review exit
11
- * - event.ts -- handleCompletionEvent (CompletionDetector event reactions, escalations)
12
- * - team-lifecycle.ts -- terminate/wait/detect-deactivated team lifecycle helpers
13
- * - agent-completion.ts -- legacy per-delivery handleAgentCompletion
9
+ * - detector.ts -- CompletionDetector (interactive-session idle/complete detection)
10
+ * - team-completion.ts -- handleTeamCompletion: the explicit PHASE SEQUENCER for team exit
11
+ * (classify -> git state -> guards -> status advance -> merge ->
12
+ * CI -> session finalize -> review exit -> terminate)
13
+ * - exit-classification.ts -- pure exit classification (success / controlled stop / crash)
14
+ * - merge-phase.ts -- merge gate, focus->integration merge, CI integration->main
15
+ * - status-advance-phase.ts -- delivery status advancement from issue completion
16
+ * - review-exit-phase.ts -- verify-delivery routing on review exit (auto-approve / verify_failed)
17
+ * - completion-decision.ts -- pure mid-focus handoff vs terminate decision tree
18
+ * - event.ts -- handleCompletionEvent (CompletionDetector event reactions, escalations)
19
+ * - team-lifecycle.ts -- terminate/wait/detect-deactivated team lifecycle helpers
20
+ * - agent-completion.ts -- legacy per-delivery handleAgentCompletion
14
21
  */
15
22
  export { CompletionDetector, } from './detector.js';
16
23
  export type { CompletionDetectorEvents, CompletionInfo, IdleInfo, } from './detector.js';
17
24
  export { isStatusTerminal, isStatusAgentActionable, shouldAttemptMerge, REPORTABLE_DELIVERY_STATUSES, selectWorkedDeliveryIds, attemptFocusMerge, runReviewExitHandler, classifyTeamExit, handleTeamCompletion, advanceDeliveryStatuses, } from './team-completion.js';
18
25
  export type { FocusMergeAttemptDeps, FocusMergeAttemptResult, ReviewExitDeps, ReviewExitParams, TeamCompletionParams, TeamExitClassification, AdvanceDeliveryDeps, } from './team-completion.js';
26
+ export { decideCompletionAction, shouldCheckNonAdvanceable, } from './completion-decision.js';
27
+ export type { CompletionAction, CompletionDecisionFacts, } from './completion-decision.js';
19
28
  export { PLANNING_NO_DELIVERIES_REASON, NO_PROGRESS_ESCALATION_REASON, NON_ADVANCEABLE_ESCALATION_REASON, NON_ADVANCEABLE_CAUSE, SCOPE_COVERAGE_NO_PROGRESS_LIMIT, escalatePlanningFailure, isDeliveryNonAdvanceable, findNonAdvanceableDelivery, handleCompletionEvent, isInReviewWindow, takeProgressSnapshot, snapshotsEqual, escalateNoProgress, escalateNonAdvanceable, } from './event.js';
20
29
  export type { CompletionEventContext, CompletionEventDeps, } from './event.js';
21
30
  export { terminateTeam, waitForTeamExit, terminateAllTeams, detectDeactivatedFocuses, checkAndMergeCompletedDeliveries, } from './team-lifecycle.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/completion/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EACL,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,wBAAwB,EACxB,cAAc,EACd,QAAQ,GACT,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAClB,4BAA4B,EAC5B,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,qBAAqB,EACrB,uBAAuB,EACvB,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,6BAA6B,EAC7B,6BAA6B,EAC7B,iCAAiC,EACjC,qBAAqB,EACrB,gCAAgC,EAChC,uBAAuB,EACvB,wBAAwB,EACxB,0BAA0B,EAC1B,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,gCAAgC,GACjC,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,uBAAuB,GACxB,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/completion/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,EACL,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,wBAAwB,EACxB,cAAc,EACd,QAAQ,GACT,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAClB,4BAA4B,EAC5B,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,qBAAqB,EACrB,uBAAuB,EACvB,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,6BAA6B,EAC7B,6BAA6B,EAC7B,iCAAiC,EACjC,qBAAqB,EACrB,gCAAgC,EAChC,uBAAuB,EACvB,wBAAwB,EACxB,0BAA0B,EAC1B,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,gCAAgC,GACjC,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,uBAAuB,GACxB,MAAM,uBAAuB,CAAC"}
@@ -6,16 +6,25 @@
6
6
  * directory) rather than reaching into individual modules.
7
7
  *
8
8
  * Modules:
9
- * - detector.ts -- CompletionDetector (interactive-session idle/complete detection)
10
- * - team-completion.ts -- handleTeamCompletion, focus merge, delivery advancement, review exit
11
- * - event.ts -- handleCompletionEvent (CompletionDetector event reactions, escalations)
12
- * - team-lifecycle.ts -- terminate/wait/detect-deactivated team lifecycle helpers
13
- * - agent-completion.ts -- legacy per-delivery handleAgentCompletion
9
+ * - detector.ts -- CompletionDetector (interactive-session idle/complete detection)
10
+ * - team-completion.ts -- handleTeamCompletion: the explicit PHASE SEQUENCER for team exit
11
+ * (classify -> git state -> guards -> status advance -> merge ->
12
+ * CI -> session finalize -> review exit -> terminate)
13
+ * - exit-classification.ts -- pure exit classification (success / controlled stop / crash)
14
+ * - merge-phase.ts -- merge gate, focus->integration merge, CI integration->main
15
+ * - status-advance-phase.ts -- delivery status advancement from issue completion
16
+ * - review-exit-phase.ts -- verify-delivery routing on review exit (auto-approve / verify_failed)
17
+ * - completion-decision.ts -- pure mid-focus handoff vs terminate decision tree
18
+ * - event.ts -- handleCompletionEvent (CompletionDetector event reactions, escalations)
19
+ * - team-lifecycle.ts -- terminate/wait/detect-deactivated team lifecycle helpers
20
+ * - agent-completion.ts -- legacy per-delivery handleAgentCompletion
14
21
  */
15
22
  // ── Completion detector ──────────────────────────────────────────────
16
23
  export { CompletionDetector, } from './detector.js';
17
24
  // ── Team completion ──────────────────────────────────────────────────
18
25
  export { isStatusTerminal, isStatusAgentActionable, shouldAttemptMerge, REPORTABLE_DELIVERY_STATUSES, selectWorkedDeliveryIds, attemptFocusMerge, runReviewExitHandler, classifyTeamExit, handleTeamCompletion, advanceDeliveryStatuses, } from './team-completion.js';
26
+ // ── Completion decision (pure handoff-vs-terminate tree) ─────────────
27
+ export { decideCompletionAction, shouldCheckNonAdvanceable, } from './completion-decision.js';
19
28
  // ── Completion event handler ─────────────────────────────────────────
20
29
  export { PLANNING_NO_DELIVERIES_REASON, NO_PROGRESS_ESCALATION_REASON, NON_ADVANCEABLE_ESCALATION_REASON, NON_ADVANCEABLE_CAUSE, SCOPE_COVERAGE_NO_PROGRESS_LIMIT, escalatePlanningFailure, isDeliveryNonAdvanceable, findNonAdvanceableDelivery, handleCompletionEvent, isInReviewWindow, takeProgressSnapshot, snapshotsEqual, escalateNoProgress, escalateNonAdvanceable, } from './event.js';
21
30
  // ── Team lifecycle ───────────────────────────────────────────────────
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/completion/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,wEAAwE;AACxE,OAAO,EACL,kBAAkB,GACnB,MAAM,eAAe,CAAC;AAOvB,wEAAwE;AACxE,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAClB,4BAA4B,EAC5B,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAW9B,wEAAwE;AACxE,OAAO,EACL,6BAA6B,EAC7B,6BAA6B,EAC7B,iCAAiC,EACjC,qBAAqB,EACrB,gCAAgC,EAChC,uBAAuB,EACvB,wBAAwB,EACxB,0BAA0B,EAC1B,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAMpB,wEAAwE;AACxE,OAAO,EACL,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,gCAAgC,GACjC,MAAM,qBAAqB,CAAC;AAE7B,wEAAwE;AACxE,OAAO,EACL,qBAAqB,GACtB,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/completion/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,wEAAwE;AACxE,OAAO,EACL,kBAAkB,GACnB,MAAM,eAAe,CAAC;AAOvB,wEAAwE;AACxE,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,EAClB,4BAA4B,EAC5B,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAW9B,wEAAwE;AACxE,OAAO,EACL,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,0BAA0B,CAAC;AAMlC,wEAAwE;AACxE,OAAO,EACL,6BAA6B,EAC7B,6BAA6B,EAC7B,iCAAiC,EACjC,qBAAqB,EACrB,gCAAgC,EAChC,uBAAuB,EACvB,wBAAwB,EACxB,0BAA0B,EAC1B,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAMpB,wEAAwE;AACxE,OAAO,EACL,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,gCAAgC,GACjC,MAAM,qBAAqB,CAAC;AAE7B,wEAAwE;AACxE,OAAO,EACL,qBAAqB,GACtB,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Merge phase of the team completion flow.
3
+ *
4
+ * Decides whether the focus branch has clean committed work and merges it to
5
+ * integration, escalates per-delivery merge failures, and runs the CI
6
+ * integration -> main backstop merge (with optional CD push). Invoked by the
7
+ * phase sequencer in team-completion.ts after status advancement. Extracted
8
+ * from completion/team-completion.ts; bodies verbatim.
9
+ */
10
+ import type { DaemonConfig, FocusTeamState } from '../types.js';
11
+ import { mergeFocusBranch } from '../focus-merge.js';
12
+ import { branchHasUnmergedCommits } from '../git.js';
13
+ /**
14
+ * Decide whether to attempt mergeFocusBranch on team exit.
15
+ *
16
+ * The gate asks "does the branch have clean committed work?" rather than
17
+ * "did the team session exit cleanly?" -- so a team that exits via review-
18
+ * cycle SIGTERM, role-clear, daemon crash, or manual termination still gets
19
+ * its committed work propagated to integration.
20
+ *
21
+ * Skip merge when:
22
+ * - The team is still in its planning phase (cancellation mid-planning --
23
+ * nothing scoped, nothing to merge), OR
24
+ * - The team is a read-only audit session (read-only violation; commits, if
25
+ * any, are surfaced separately by the existing readOnly guard), OR
26
+ * - The branch has no committed work ahead of integration (clean exit with
27
+ * no commits, e.g. audit team or planning-only team).
28
+ *
29
+ * Exported for unit testing the gate logic in isolation.
30
+ */
31
+ export declare function shouldAttemptMerge(teamState: Pick<FocusTeamState, 'planningPhase' | 'readOnly'>, branchHasCommits: boolean): boolean;
32
+ /**
33
+ * Statuses for deliveries whose git state should be reported on team
34
+ * completion. Includes 'done' so a focus whose deliveries all reached done
35
+ * before the branch was merged (review SIGTERM, role-clear, deferred merge,
36
+ * etc.) still attempts the merge instead of being short-circuited as
37
+ * "no worked deliveries". Excludes 'queued'/'planning'/'paused'/'cancelled'
38
+ * — those represent work that never started or was abandoned.
39
+ *
40
+ * Exported for unit testing.
41
+ */
42
+ export declare const REPORTABLE_DELIVERY_STATUSES: ReadonlySet<string>;
43
+ /**
44
+ * Filter delivery list to those whose git state should be reported on team
45
+ * completion. Excludes already-merged deliveries so we don't re-report them.
46
+ *
47
+ * Exported for unit testing the filter logic without invoking handleTeamCompletion.
48
+ */
49
+ export declare function selectWorkedDeliveryIds(deliveries: readonly {
50
+ id: string;
51
+ executionStatus: string | null;
52
+ }[], alreadyMerged: ReadonlySet<string>): string[];
53
+ export interface FocusMergeAttemptDeps {
54
+ branchHasUnmergedCommits: typeof branchHasUnmergedCommits;
55
+ mergeFocusBranch: typeof mergeFocusBranch;
56
+ }
57
+ export interface FocusMergeAttemptResult {
58
+ attempted: boolean;
59
+ mergeSucceeded: boolean;
60
+ exitReason: string | null;
61
+ }
62
+ /**
63
+ * Decide whether to merge the focus branch and, if so, run the merge.
64
+ *
65
+ * This is the integration of three separate concerns that the merge gate
66
+ * conflated before:
67
+ * 1. Branch state: does the focus branch actually have committed work?
68
+ * 2. Team gate: planningPhase + readOnly safety nets in shouldAttemptMerge.
69
+ * 3. Per-delivery telemetry: workedDeliveryIds is passed through for
70
+ * git-state reporting inside mergeFocusBranch.
71
+ *
72
+ * Returns attempted=false when the gate skips the merge (clean exit with
73
+ * nothing to merge, planning-phase, or read-only). Returns attempted=true
74
+ * with the merge result otherwise.
75
+ *
76
+ * Exported so tests can verify the threading from done-only deliveries +
77
+ * branch-with-commits to a real mergeFocusBranch invocation, without having
78
+ * to mock all of handleTeamCompletion's other side effects.
79
+ */
80
+ export declare function attemptFocusMerge(config: DaemonConfig, teamState: FocusTeamState, sessionId: string, workedDeliveryIds: string[], deps?: FocusMergeAttemptDeps): Promise<FocusMergeAttemptResult>;
81
+ /**
82
+ * Escalate a failed focus-branch merge for every worked delivery that has not
83
+ * already been merged mid-flight. Fire-and-forget per delivery (a failed
84
+ * escalation logs a warning and never blocks the completion flow).
85
+ */
86
+ export declare function escalateFailedMergeDeliveries(params: {
87
+ config: DaemonConfig;
88
+ teamState: FocusTeamState;
89
+ sessionId: string;
90
+ workedDeliveryIds: string[];
91
+ mergeExitReason: string | null;
92
+ }): void;
93
+ /**
94
+ * Run the CI integration -> main backstop merge for a completing team.
95
+ *
96
+ * When CI is enabled (default for legacy focuses without the field), always
97
+ * attempt the integration -> main merge at team exit. This is the
98
+ * unconditional backstop: the eager path in focus-team-lifecycle fires when a
99
+ * focus drains mid-flight, but if it didn't (or fired and integration has
100
+ * since moved), the exit path closes the gap. Independent of mergeSucceeded --
101
+ * even when this focus had no new commits, past focuses may have left
102
+ * integration ahead of main. mergeIntegrationToMain no-ops cleanly when
103
+ * integration is already at main. CD additionally pushes.
104
+ *
105
+ * Returns the suffix to append to the session exit reason (always non-empty).
106
+ */
107
+ export declare function runCiMergeToMain(params: {
108
+ config: DaemonConfig;
109
+ teamState: FocusTeamState;
110
+ sessionId: string;
111
+ mergeSucceeded: boolean;
112
+ workedDeliveryIds: string[];
113
+ }): Promise<string>;
114
+ //# sourceMappingURL=merge-phase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-phase.d.ts","sourceRoot":"","sources":["../../src/completion/merge-phase.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,gBAAgB,EAAyB,MAAM,mBAAmB,CAAC;AAI5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAIrD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,IAAI,CAAC,cAAc,EAAE,eAAe,GAAG,UAAU,CAAC,EAC7D,gBAAgB,EAAE,OAAO,GACxB,OAAO,CAIT;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,4BAA4B,EAAE,WAAW,CAAC,MAAM,CAI3D,CAAC;AAEH;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAAE,EACrE,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,GACjC,MAAM,EAAE,CAIV;AAID,MAAM,WAAW,qBAAqB;IACpC,wBAAwB,EAAE,OAAO,wBAAwB,CAAC;IAC1D,gBAAgB,EAAE,OAAO,gBAAgB,CAAC;CAC3C;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,cAAc,EACzB,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,MAAM,EAAE,EAC3B,IAAI,GAAE,qBAGL,GACA,OAAO,CAAC,uBAAuB,CAAC,CAqBlC;AAID;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE;IACpD,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,EAAE,cAAc,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,GAAG,IAAI,CAiBP;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAC7C,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,EAAE,cAAc,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IACxB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B,GAAG,OAAO,CAAC,MAAM,CAAC,CAmElB"}
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Merge phase of the team completion flow.
3
+ *
4
+ * Decides whether the focus branch has clean committed work and merges it to
5
+ * integration, escalates per-delivery merge failures, and runs the CI
6
+ * integration -> main backstop merge (with optional CD push). Invoked by the
7
+ * phase sequencer in team-completion.ts after status advancement. Extracted
8
+ * from completion/team-completion.ts; bodies verbatim.
9
+ */
10
+ import { reportGitState } from '../supabase.js';
11
+ import { mergeFocusBranch, escalateMergeConflict } from '../focus-merge.js';
12
+ import { mergeIntegrationToMain } from '../git-merge.js';
13
+ import { resolveCiDecision } from '../pipeline-config.js';
14
+ import { fileCdPushEscalation, shouldFileCdPushEscalation } from '../ci-escalation.js';
15
+ import { branchHasUnmergedCommits } from '../git.js';
16
+ // ── Merge gate ───────────────────────────────────────────────────────
17
+ /**
18
+ * Decide whether to attempt mergeFocusBranch on team exit.
19
+ *
20
+ * The gate asks "does the branch have clean committed work?" rather than
21
+ * "did the team session exit cleanly?" -- so a team that exits via review-
22
+ * cycle SIGTERM, role-clear, daemon crash, or manual termination still gets
23
+ * its committed work propagated to integration.
24
+ *
25
+ * Skip merge when:
26
+ * - The team is still in its planning phase (cancellation mid-planning --
27
+ * nothing scoped, nothing to merge), OR
28
+ * - The team is a read-only audit session (read-only violation; commits, if
29
+ * any, are surfaced separately by the existing readOnly guard), OR
30
+ * - The branch has no committed work ahead of integration (clean exit with
31
+ * no commits, e.g. audit team or planning-only team).
32
+ *
33
+ * Exported for unit testing the gate logic in isolation.
34
+ */
35
+ export function shouldAttemptMerge(teamState, branchHasCommits) {
36
+ if (teamState.planningPhase)
37
+ return false;
38
+ if (teamState.readOnly)
39
+ return false;
40
+ return branchHasCommits;
41
+ }
42
+ /**
43
+ * Statuses for deliveries whose git state should be reported on team
44
+ * completion. Includes 'done' so a focus whose deliveries all reached done
45
+ * before the branch was merged (review SIGTERM, role-clear, deferred merge,
46
+ * etc.) still attempts the merge instead of being short-circuited as
47
+ * "no worked deliveries". Excludes 'queued'/'planning'/'paused'/'cancelled'
48
+ * — those represent work that never started or was abandoned.
49
+ *
50
+ * Exported for unit testing.
51
+ */
52
+ export const REPORTABLE_DELIVERY_STATUSES = new Set([
53
+ 'coding',
54
+ 'verify',
55
+ 'done',
56
+ ]);
57
+ /**
58
+ * Filter delivery list to those whose git state should be reported on team
59
+ * completion. Excludes already-merged deliveries so we don't re-report them.
60
+ *
61
+ * Exported for unit testing the filter logic without invoking handleTeamCompletion.
62
+ */
63
+ export function selectWorkedDeliveryIds(deliveries, alreadyMerged) {
64
+ return deliveries
65
+ .filter(d => REPORTABLE_DELIVERY_STATUSES.has(d.executionStatus ?? '') && !alreadyMerged.has(d.id))
66
+ .map(d => d.id);
67
+ }
68
+ /**
69
+ * Decide whether to merge the focus branch and, if so, run the merge.
70
+ *
71
+ * This is the integration of three separate concerns that the merge gate
72
+ * conflated before:
73
+ * 1. Branch state: does the focus branch actually have committed work?
74
+ * 2. Team gate: planningPhase + readOnly safety nets in shouldAttemptMerge.
75
+ * 3. Per-delivery telemetry: workedDeliveryIds is passed through for
76
+ * git-state reporting inside mergeFocusBranch.
77
+ *
78
+ * Returns attempted=false when the gate skips the merge (clean exit with
79
+ * nothing to merge, planning-phase, or read-only). Returns attempted=true
80
+ * with the merge result otherwise.
81
+ *
82
+ * Exported so tests can verify the threading from done-only deliveries +
83
+ * branch-with-commits to a real mergeFocusBranch invocation, without having
84
+ * to mock all of handleTeamCompletion's other side effects.
85
+ */
86
+ export async function attemptFocusMerge(config, teamState, sessionId, workedDeliveryIds, deps = {
87
+ branchHasUnmergedCommits,
88
+ mergeFocusBranch,
89
+ }) {
90
+ const branchHasCommits = deps.branchHasUnmergedCommits(teamState.branchName, config.integrationBranch, config.repoPath);
91
+ if (!shouldAttemptMerge(teamState, branchHasCommits)) {
92
+ return { attempted: false, mergeSucceeded: false, exitReason: null };
93
+ }
94
+ const mergeResult = await deps.mergeFocusBranch(config, teamState, sessionId, teamState.branchName, workedDeliveryIds);
95
+ return {
96
+ attempted: true,
97
+ mergeSucceeded: mergeResult.mergeSucceeded,
98
+ exitReason: mergeResult.exitReason ?? null,
99
+ };
100
+ }
101
+ // ── Merge-failure escalation ─────────────────────────────────────────
102
+ /**
103
+ * Escalate a failed focus-branch merge for every worked delivery that has not
104
+ * already been merged mid-flight. Fire-and-forget per delivery (a failed
105
+ * escalation logs a warning and never blocks the completion flow).
106
+ */
107
+ export function escalateFailedMergeDeliveries(params) {
108
+ const { config, teamState, sessionId, workedDeliveryIds, mergeExitReason } = params;
109
+ for (const deliveryId of workedDeliveryIds) {
110
+ if (!teamState.mergedDeliveryIds.has(deliveryId)) {
111
+ escalateMergeConflict({
112
+ organizationId: teamState.organizationId,
113
+ sessionId,
114
+ deliveryId,
115
+ deliveryName: teamState.focusName,
116
+ branchName: teamState.branchName,
117
+ integrationBranch: config.integrationBranch,
118
+ mergeError: mergeExitReason ?? 'unknown',
119
+ }).catch(err => console.warn(`[focus-executor] escalateMergeConflict failed for ${deliveryId}:`, err.message));
120
+ }
121
+ }
122
+ }
123
+ // ── CI: merge integration → main ──────────────────────────────────────
124
+ /**
125
+ * Run the CI integration -> main backstop merge for a completing team.
126
+ *
127
+ * When CI is enabled (default for legacy focuses without the field), always
128
+ * attempt the integration -> main merge at team exit. This is the
129
+ * unconditional backstop: the eager path in focus-team-lifecycle fires when a
130
+ * focus drains mid-flight, but if it didn't (or fired and integration has
131
+ * since moved), the exit path closes the gap. Independent of mergeSucceeded --
132
+ * even when this focus had no new commits, past focuses may have left
133
+ * integration ahead of main. mergeIntegrationToMain no-ops cleanly when
134
+ * integration is already at main. CD additionally pushes.
135
+ *
136
+ * Returns the suffix to append to the session exit reason (always non-empty).
137
+ */
138
+ export async function runCiMergeToMain(params) {
139
+ const { config, teamState, sessionId, mergeSucceeded, workedDeliveryIds } = params;
140
+ const focusName = teamState.focusName;
141
+ const ciDecision = resolveCiDecision(teamState.pipelineConfig);
142
+ if (!ciDecision.shouldMerge) {
143
+ console.log(`[CI] Skipping integration→main merge for focus ${teamState.focusId} ("${focusName}"): ci.enabled=false`);
144
+ return ' CI skipped (ci.enabled=false).';
145
+ }
146
+ const { pushToRemote, mergeStrategy } = ciDecision;
147
+ const ciLabel = pushToRemote ? 'CI+CD' : 'CI';
148
+ console.log(`[${ciLabel}] Merging integration to main for "${focusName}" (strategy=${mergeStrategy})${pushToRemote ? ' (will push to remote)' : ''}`);
149
+ try {
150
+ const ciResult = await mergeIntegrationToMain({
151
+ config,
152
+ focusId: teamState.focusId,
153
+ focusName,
154
+ pushToRemote,
155
+ mergeStrategy,
156
+ });
157
+ if (ciResult.success) {
158
+ if (ciResult.pushedTo) {
159
+ console.log(`[${ciLabel}] Pushed main to ${ciResult.pushedTo.name} (${ciResult.pushedTo.url}) for focus ${teamState.focusId} ("${focusName}")`);
160
+ }
161
+ else {
162
+ console.log(`[${ciLabel}] Successfully merged integration to main for focus ${teamState.focusId} ("${focusName}")`);
163
+ }
164
+ // Report merged_to_main / pushed_to_remote for every delivery on
165
+ // integration. That's mid-flight-merged deliveries plus, if this
166
+ // exit's focus→integration merge succeeded, the just-merged ones.
167
+ // Failed focus merges leave workedDeliveryIds off integration —
168
+ // exclude them so we don't lie about where they landed.
169
+ const onIntegration = new Set(teamState.mergedDeliveryIds);
170
+ if (mergeSucceeded) {
171
+ for (const id of workedDeliveryIds)
172
+ onIntegration.add(id);
173
+ }
174
+ const newState = ciResult.pushedTo ? 'pushed_to_remote' : 'merged_to_main';
175
+ for (const deliveryId of onIntegration) {
176
+ reportGitState(deliveryId, newState).catch(err => console.warn(`[${ciLabel}] reportGitState ${newState} failed for ${deliveryId}:`, err.message));
177
+ }
178
+ return ` ${ciLabel}: merged to main${ciResult.pushedTo ? ' and pushed to remote' : ''}.`;
179
+ }
180
+ console.error(`[${ciLabel}] Failed to merge integration to main for "${focusName}": ${ciResult.error}`);
181
+ if (shouldFileCdPushEscalation(pushToRemote, ciResult)) {
182
+ await fileCdPushEscalation({
183
+ organizationId: teamState.organizationId,
184
+ sessionId,
185
+ focusId: teamState.focusId,
186
+ focusName,
187
+ integrationBranch: config.integrationBranch,
188
+ pushError: ciResult.error,
189
+ });
190
+ }
191
+ return ` ${ciLabel} failed: ${ciResult.error}`;
192
+ }
193
+ catch (err) {
194
+ console.error(`[${ciLabel}] Error merging integration to main for "${focusName}":`, err.message);
195
+ return ` ${ciLabel} error: ${err.message}`;
196
+ }
197
+ }
198
+ //# sourceMappingURL=merge-phase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-phase.js","sourceRoot":"","sources":["../../src/completion/merge-phase.ts"],"names":[],"mappings":"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"}