@telora/daemon 0.24.42 → 0.24.55

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 (343) hide show
  1. package/build-info.json +9 -3
  2. package/dist/completion/completion-event/unfinished-work.d.ts +3 -3
  3. package/dist/completion/review-cycle-budget/review-loop-detection.d.ts.map +1 -1
  4. package/dist/completion/review-cycle-budget/review-loop-detection.js +2 -1
  5. package/dist/completion/review-cycle-budget/review-loop-detection.js.map +1 -1
  6. package/dist/completion/review-exit-holds/review-exit-verdict-gate.d.ts +1 -1
  7. package/dist/completion/review-exit-holds/review-exit-verdict-gate.d.ts.map +1 -1
  8. package/dist/completion/review-exit-holds/review-exit-verdict-gate.js +2 -3
  9. package/dist/completion/review-exit-holds/review-exit-verdict-gate.js.map +1 -1
  10. package/dist/completion/state-cascade/focus-next-step-read.d.ts +38 -0
  11. package/dist/completion/state-cascade/focus-next-step-read.d.ts.map +1 -0
  12. package/dist/completion/state-cascade/focus-next-step-read.js +188 -0
  13. package/dist/completion/state-cascade/focus-next-step-read.js.map +1 -0
  14. package/dist/completion/state-cascade/review-request-gate.d.ts.map +1 -1
  15. package/dist/completion/state-cascade/review-request-gate.js +1 -0
  16. package/dist/completion/state-cascade/review-request-gate.js.map +1 -1
  17. package/dist/completion/state-cascade/review-request-next-step.d.ts +56 -0
  18. package/dist/completion/state-cascade/review-request-next-step.d.ts.map +1 -0
  19. package/dist/completion/state-cascade/review-request-next-step.js +47 -0
  20. package/dist/completion/state-cascade/review-request-next-step.js.map +1 -0
  21. package/dist/completion/state-cascade/review-verify-judgment-gate.d.ts +1 -1
  22. package/dist/completion/state-cascade/review-verify-judgment-gate.d.ts.map +1 -1
  23. package/dist/completion/state-cascade/review-verify-judgment-gate.js +1 -0
  24. package/dist/completion/state-cascade/review-verify-judgment-gate.js.map +1 -1
  25. package/dist/completion/state-cascade/state-cascade.d.ts +12 -7
  26. package/dist/completion/state-cascade/state-cascade.d.ts.map +1 -1
  27. package/dist/completion/state-cascade/state-cascade.js +36 -105
  28. package/dist/completion/state-cascade/state-cascade.js.map +1 -1
  29. package/dist/composition/commit-gate-context.d.ts.map +1 -1
  30. package/dist/composition/commit-gate-context.js +1 -0
  31. package/dist/composition/commit-gate-context.js.map +1 -1
  32. package/dist/composition/daemon-contexts.js +1 -1
  33. package/dist/composition/execution-migrations-context.d.ts.map +1 -1
  34. package/dist/composition/execution-migrations-context.js +3 -1
  35. package/dist/composition/execution-migrations-context.js.map +1 -1
  36. package/dist/composition/execution-process-context.js +1 -1
  37. package/dist/composition/execution-recovery-context.d.ts +4 -3
  38. package/dist/composition/execution-recovery-context.d.ts.map +1 -1
  39. package/dist/composition/execution-recovery-context.js +6 -3
  40. package/dist/composition/execution-recovery-context.js.map +1 -1
  41. package/dist/composition/execution-worktree-context.js +1 -1
  42. package/dist/composition/focus-next-step-context.d.ts +19 -0
  43. package/dist/composition/focus-next-step-context.d.ts.map +1 -0
  44. package/dist/composition/focus-next-step-context.js +51 -0
  45. package/dist/composition/focus-next-step-context.js.map +1 -0
  46. package/dist/composition/runtime-contexts.d.ts.map +1 -1
  47. package/dist/composition/runtime-contexts.js +6 -18
  48. package/dist/composition/runtime-contexts.js.map +1 -1
  49. package/dist/composition/runtime-poll-context.d.ts +8 -53
  50. package/dist/composition/runtime-poll-context.d.ts.map +1 -1
  51. package/dist/composition/runtime-poll-context.js +35 -94
  52. package/dist/composition/runtime-poll-context.js.map +1 -1
  53. package/dist/composition/runtime-prd-context.d.ts +8 -0
  54. package/dist/composition/runtime-prd-context.d.ts.map +1 -1
  55. package/dist/composition/runtime-prd-context.js +32 -0
  56. package/dist/composition/runtime-prd-context.js.map +1 -1
  57. package/dist/composition/runtime-spawn-pass-context.d.ts.map +1 -1
  58. package/dist/composition/runtime-spawn-pass-context.js +2 -3
  59. package/dist/composition/runtime-spawn-pass-context.js.map +1 -1
  60. package/dist/composition/state-cascade-context.d.ts +2 -0
  61. package/dist/composition/state-cascade-context.d.ts.map +1 -1
  62. package/dist/composition/state-cascade-context.js +9 -0
  63. package/dist/composition/state-cascade-context.js.map +1 -1
  64. package/dist/composition/verification-context.d.ts.map +1 -1
  65. package/dist/composition/verification-context.js +15 -3
  66. package/dist/composition/verification-context.js.map +1 -1
  67. package/dist/config/live-daemon-config.js +1 -1
  68. package/dist/daemon-state/branch-removal-record.d.ts +30 -0
  69. package/dist/daemon-state/branch-removal-record.d.ts.map +1 -0
  70. package/dist/daemon-state/branch-removal-record.js +103 -0
  71. package/dist/daemon-state/branch-removal-record.js.map +1 -0
  72. package/dist/delivery/advance-hold.d.ts +8 -19
  73. package/dist/delivery/advance-hold.d.ts.map +1 -1
  74. package/dist/delivery/advance-hold.js +11 -36
  75. package/dist/delivery/advance-hold.js.map +1 -1
  76. package/dist/delivery/commit-verdict-hold.d.ts +1 -1
  77. package/dist/delivery/commit-verdict-hold.js +1 -1
  78. package/dist/delivery/recorded-concerns.d.ts.map +1 -1
  79. package/dist/delivery/recorded-concerns.js +0 -2
  80. package/dist/delivery/recorded-concerns.js.map +1 -1
  81. package/dist/directive/directive-queue.d.ts +4 -16
  82. package/dist/directive/directive-queue.d.ts.map +1 -1
  83. package/dist/directive/directive-queue.js +5 -13
  84. package/dist/directive/directive-queue.js.map +1 -1
  85. package/dist/directive/phase-sync.d.ts +1 -1
  86. package/dist/directive/phase-sync.js +1 -1
  87. package/dist/focus/crash-recovery.d.ts +10 -32
  88. package/dist/focus/crash-recovery.d.ts.map +1 -1
  89. package/dist/focus/crash-recovery.js +55 -150
  90. package/dist/focus/crash-recovery.js.map +1 -1
  91. package/dist/focus/daemon-contexts-runtime.d.ts +3 -3
  92. package/dist/focus/daemon-contexts-runtime.d.ts.map +1 -1
  93. package/dist/focus/daemon-contexts.js +1 -1
  94. package/dist/focus/directive-executor.d.ts.map +1 -1
  95. package/dist/focus/directive-executor.js +3 -7
  96. package/dist/focus/directive-executor.js.map +1 -1
  97. package/dist/focus/failed-head-rework-start.d.ts +61 -0
  98. package/dist/focus/failed-head-rework-start.d.ts.map +1 -0
  99. package/dist/focus/failed-head-rework-start.js +52 -0
  100. package/dist/focus/failed-head-rework-start.js.map +1 -0
  101. package/dist/focus/focus-activity-record.d.ts +4 -2
  102. package/dist/focus/focus-activity-record.d.ts.map +1 -1
  103. package/dist/focus/focus-activity-record.js +4 -2
  104. package/dist/focus/focus-activity-record.js.map +1 -1
  105. package/dist/focus/focus-liveness-pass.d.ts +62 -0
  106. package/dist/focus/focus-liveness-pass.d.ts.map +1 -0
  107. package/dist/focus/focus-liveness-pass.js +197 -0
  108. package/dist/focus/focus-liveness-pass.js.map +1 -0
  109. package/dist/focus/focus-poller-spawn.js +1 -1
  110. package/dist/focus/focus-poller-state.js +1 -1
  111. package/dist/focus/live-branch-preservation.d.ts +123 -0
  112. package/dist/focus/live-branch-preservation.d.ts.map +1 -0
  113. package/dist/focus/live-branch-preservation.js +192 -0
  114. package/dist/focus/live-branch-preservation.js.map +1 -0
  115. package/dist/focus/migration-claim-pass.d.ts +2 -0
  116. package/dist/focus/migration-claim-pass.d.ts.map +1 -1
  117. package/dist/focus/migration-claim-pass.js +57 -22
  118. package/dist/focus/migration-claim-pass.js.map +1 -1
  119. package/dist/focus/migration-held-set-publish.d.ts +28 -2
  120. package/dist/focus/migration-held-set-publish.d.ts.map +1 -1
  121. package/dist/focus/migration-held-set-publish.js +14 -0
  122. package/dist/focus/migration-held-set-publish.js.map +1 -1
  123. package/dist/focus/pending-spawn-review-next-step.d.ts +5 -11
  124. package/dist/focus/pending-spawn-review-next-step.d.ts.map +1 -1
  125. package/dist/focus/pending-spawn-review-next-step.js +26 -72
  126. package/dist/focus/pending-spawn-review-next-step.js.map +1 -1
  127. package/dist/focus/review-refire-gate.d.ts +25 -0
  128. package/dist/focus/review-refire-gate.d.ts.map +1 -0
  129. package/dist/focus/review-refire-gate.js +68 -0
  130. package/dist/focus/review-refire-gate.js.map +1 -0
  131. package/dist/focus/verify-routing-passes.d.ts +8 -11
  132. package/dist/focus/verify-routing-passes.d.ts.map +1 -1
  133. package/dist/focus/verify-routing-passes.js +1 -2
  134. package/dist/focus/verify-routing-passes.js.map +1 -1
  135. package/dist/git/types.js +1 -1
  136. package/dist/prd/arm-refusal-streak.d.ts +102 -0
  137. package/dist/prd/arm-refusal-streak.d.ts.map +1 -0
  138. package/dist/prd/arm-refusal-streak.js +136 -0
  139. package/dist/prd/arm-refusal-streak.js.map +1 -0
  140. package/dist/prd/arm-refusal.d.ts.map +1 -1
  141. package/dist/prd/arm-refusal.js +7 -4
  142. package/dist/prd/arm-refusal.js.map +1 -1
  143. package/dist/prd/controller-shared.d.ts +40 -1
  144. package/dist/prd/controller-shared.d.ts.map +1 -1
  145. package/dist/prd/controller-shared.js +28 -2
  146. package/dist/prd/controller-shared.js.map +1 -1
  147. package/dist/prd/controller.d.ts.map +1 -1
  148. package/dist/prd/controller.js +3 -1
  149. package/dist/prd/controller.js.map +1 -1
  150. package/dist/prd/frontier-arming.d.ts +10 -2
  151. package/dist/prd/frontier-arming.d.ts.map +1 -1
  152. package/dist/prd/frontier-arming.js +91 -7
  153. package/dist/prd/frontier-arming.js.map +1 -1
  154. package/dist/prd/scoping-prompt.d.ts +8 -0
  155. package/dist/prd/scoping-prompt.d.ts.map +1 -1
  156. package/dist/prd/scoping-prompt.js +18 -0
  157. package/dist/prd/scoping-prompt.js.map +1 -1
  158. package/dist/prompt-sections/qa-failure-section.d.ts.map +1 -1
  159. package/dist/prompt-sections/qa-failure-section.js +3 -1
  160. package/dist/prompt-sections/qa-failure-section.js.map +1 -1
  161. package/dist/queries/api-client/shared.js +1 -1
  162. package/dist/queries/deliveries/deliveries.js +1 -1
  163. package/dist/queries/delivery-gate-state/delivery-gate-holds.d.ts +4 -3
  164. package/dist/queries/delivery-gate-state/delivery-gate-holds.d.ts.map +1 -1
  165. package/dist/queries/delivery-gate-state/delivery-gate-state.js +1 -1
  166. package/dist/queries/escalations/escalations.d.ts.map +1 -1
  167. package/dist/queries/escalations/escalations.js +0 -1
  168. package/dist/queries/escalations/escalations.js.map +1 -1
  169. package/dist/queries/escalations/incident-record.d.ts.map +1 -1
  170. package/dist/queries/escalations/incident-record.js +1 -0
  171. package/dist/queries/escalations/incident-record.js.map +1 -1
  172. package/dist/queries/focus-review/review-criterion-verdicts.d.ts.map +1 -1
  173. package/dist/queries/focus-review/review-criterion-verdicts.js +1 -0
  174. package/dist/queries/focus-review/review-criterion-verdicts.js.map +1 -1
  175. package/dist/queries/migrations/live-focus-branches.d.ts +23 -0
  176. package/dist/queries/migrations/live-focus-branches.d.ts.map +1 -1
  177. package/dist/queries/migrations/live-focus-branches.js +32 -1
  178. package/dist/queries/migrations/live-focus-branches.js.map +1 -1
  179. package/dist/queries/prd/prd.d.ts.map +1 -1
  180. package/dist/queries/prd/prd.js +1 -16
  181. package/dist/queries/prd/prd.js.map +1 -1
  182. package/dist/queries/qa-packets/focus-qa-failure.d.ts +18 -0
  183. package/dist/queries/qa-packets/focus-qa-failure.d.ts.map +1 -1
  184. package/dist/queries/qa-packets/focus-qa-failure.js +14 -1
  185. package/dist/queries/qa-packets/focus-qa-failure.js.map +1 -1
  186. package/dist/queries/tower-decisions/tower-decisions.d.ts.map +1 -1
  187. package/dist/queries/tower-decisions/tower-decisions.js +1 -0
  188. package/dist/queries/tower-decisions/tower-decisions.js.map +1 -1
  189. package/dist/queries/verification/verification.d.ts +10 -0
  190. package/dist/queries/verification/verification.d.ts.map +1 -1
  191. package/dist/queries/verification/verification.js +1 -1
  192. package/dist/queries/verification/verification.js.map +1 -1
  193. package/dist/supervision/escalation-suppression.js +1 -1
  194. package/dist/supervision/failed-head-rerun.d.ts +7 -0
  195. package/dist/supervision/failed-head-rerun.d.ts.map +1 -0
  196. package/dist/supervision/failed-head-rerun.js +41 -0
  197. package/dist/supervision/failed-head-rerun.js.map +1 -0
  198. package/dist/supervision/focus-delivery-aggregate-phase.js +1 -1
  199. package/dist/supervision/focus-delivery-aggregate-phase.js.map +1 -1
  200. package/dist/supervision/focus-liveness.d.ts +89 -0
  201. package/dist/supervision/focus-liveness.d.ts.map +1 -0
  202. package/dist/supervision/focus-liveness.js +94 -0
  203. package/dist/supervision/focus-liveness.js.map +1 -0
  204. package/dist/supervision/focus-next-step.d.ts +175 -0
  205. package/dist/supervision/focus-next-step.d.ts.map +1 -0
  206. package/dist/supervision/focus-next-step.js +129 -0
  207. package/dist/supervision/focus-next-step.js.map +1 -0
  208. package/dist/supervision/prd-frontier-rule.d.ts +52 -0
  209. package/dist/supervision/prd-frontier-rule.d.ts.map +1 -0
  210. package/dist/supervision/prd-frontier-rule.js +51 -0
  211. package/dist/supervision/prd-frontier-rule.js.map +1 -0
  212. package/dist/supervision/prt-frontier.d.ts +22 -7
  213. package/dist/supervision/prt-frontier.d.ts.map +1 -1
  214. package/dist/supervision/prt-frontier.js +17 -7
  215. package/dist/supervision/prt-frontier.js.map +1 -1
  216. package/dist/supervision/review-loop-detector.d.ts.map +1 -1
  217. package/dist/supervision/review-loop-detector.js +2 -1
  218. package/dist/supervision/review-loop-detector.js.map +1 -1
  219. package/dist/supervision/spawn-cooldown.js +1 -1
  220. package/dist/supervision/stop-registry.d.ts +1 -0
  221. package/dist/supervision/stop-registry.d.ts.map +1 -1
  222. package/dist/supervision/stop-rows-focus-health.d.ts +14 -0
  223. package/dist/supervision/stop-rows-focus-health.d.ts.map +1 -1
  224. package/dist/supervision/stop-rows-focus-health.js +32 -0
  225. package/dist/supervision/stop-rows-focus-health.js.map +1 -1
  226. package/dist/supervision/stop-rows-spawn.d.ts +3 -2
  227. package/dist/supervision/stop-rows-spawn.d.ts.map +1 -1
  228. package/dist/supervision/stop-rows-spawn.js +9 -6
  229. package/dist/supervision/stop-rows-spawn.js.map +1 -1
  230. package/dist/supervision/team-work.js +1 -1
  231. package/dist/supervision/team-work.js.map +1 -1
  232. package/dist/testing/fixtures/api-client.js +1 -1
  233. package/dist/testing/fixtures/index.js +1 -1
  234. package/dist/testing/fixtures/migration-namespace-repo.d.ts.map +1 -1
  235. package/dist/testing/fixtures/migration-namespace-repo.js +1 -0
  236. package/dist/testing/fixtures/migration-namespace-repo.js.map +1 -1
  237. package/dist/testing/fixtures/pending-spawn-world.d.ts +24 -0
  238. package/dist/testing/fixtures/pending-spawn-world.d.ts.map +1 -1
  239. package/dist/testing/fixtures/pending-spawn-world.js +46 -19
  240. package/dist/testing/fixtures/pending-spawn-world.js.map +1 -1
  241. package/dist/testing/fixtures/recording-api-client.js +1 -1
  242. package/dist/testing/fixtures/verification-deps.d.ts +27 -0
  243. package/dist/testing/fixtures/verification-deps.d.ts.map +1 -1
  244. package/dist/testing/fixtures/verification-deps.js +77 -1
  245. package/dist/testing/fixtures/verification-deps.js.map +1 -1
  246. package/dist/testing/fixtures/vitest-failure-log.d.ts.map +1 -1
  247. package/dist/testing/fixtures/vitest-failure-log.js +1 -0
  248. package/dist/testing/fixtures/vitest-failure-log.js.map +1 -1
  249. package/dist/tower/tower-supervisor-history.d.ts.map +1 -1
  250. package/dist/tower/tower-supervisor-history.js +2 -1
  251. package/dist/tower/tower-supervisor-history.js.map +1 -1
  252. package/dist/tower/tower-supervisor-prompt.d.ts.map +1 -1
  253. package/dist/tower/tower-supervisor-prompt.js +40 -8
  254. package/dist/tower/tower-supervisor-prompt.js.map +1 -1
  255. package/dist/tower/tower-supervisor-session.d.ts.map +1 -1
  256. package/dist/tower/tower-supervisor-session.js +1 -0
  257. package/dist/tower/tower-supervisor-session.js.map +1 -1
  258. package/dist/types/issue-status.d.ts.map +1 -1
  259. package/dist/types/issue-status.js +6 -1
  260. package/dist/types/issue-status.js.map +1 -1
  261. package/dist/verify/attribution/code-failure-evidence.d.ts +77 -0
  262. package/dist/verify/attribution/code-failure-evidence.d.ts.map +1 -0
  263. package/dist/verify/attribution/code-failure-evidence.js +92 -0
  264. package/dist/verify/attribution/code-failure-evidence.js.map +1 -0
  265. package/dist/verify/attribution/verification-attribution.d.ts +18 -0
  266. package/dist/verify/attribution/verification-attribution.d.ts.map +1 -1
  267. package/dist/verify/attribution/verification-attribution.js +49 -2
  268. package/dist/verify/attribution/verification-attribution.js.map +1 -1
  269. package/dist/verify/attribution/verification-baseline.d.ts.map +1 -1
  270. package/dist/verify/attribution/verification-baseline.js +1 -0
  271. package/dist/verify/attribution/verification-baseline.js.map +1 -1
  272. package/dist/verify/attribution/verification-diagnostics.d.ts +10 -0
  273. package/dist/verify/attribution/verification-diagnostics.d.ts.map +1 -1
  274. package/dist/verify/attribution/verification-diagnostics.js +39 -10
  275. package/dist/verify/attribution/verification-diagnostics.js.map +1 -1
  276. package/dist/verify/deterministic-gate/verification-deterministic.d.ts +19 -0
  277. package/dist/verify/deterministic-gate/verification-deterministic.d.ts.map +1 -1
  278. package/dist/verify/deterministic-gate/verification-deterministic.js +1 -1
  279. package/dist/verify/deterministic-gate/verification-deterministic.js.map +1 -1
  280. package/dist/verify/engine/verification-commit-sharing.d.ts.map +1 -1
  281. package/dist/verify/engine/verification-commit-sharing.js +36 -4
  282. package/dist/verify/engine/verification-commit-sharing.js.map +1 -1
  283. package/dist/verify/engine/verification-deps.d.ts +7 -0
  284. package/dist/verify/engine/verification-deps.d.ts.map +1 -1
  285. package/dist/verify/engine/verification-engine.d.ts.map +1 -1
  286. package/dist/verify/engine/verification-engine.js +6 -3
  287. package/dist/verify/engine/verification-engine.js.map +1 -1
  288. package/dist/verify/escaped-tests/escaped-test-run.d.ts +5 -1
  289. package/dist/verify/escaped-tests/escaped-test-run.d.ts.map +1 -1
  290. package/dist/verify/escaped-tests/escaped-test-run.js +24 -2
  291. package/dist/verify/escaped-tests/escaped-test-run.js.map +1 -1
  292. package/dist/verify/failing-test-rerun/failing-test-retry.d.ts +4 -1
  293. package/dist/verify/failing-test-rerun/failing-test-retry.d.ts.map +1 -1
  294. package/dist/verify/failing-test-rerun/failing-test-retry.js.map +1 -1
  295. package/dist/verify/gate-verdicts/commit-verdict-record.js +1 -1
  296. package/dist/verify/gate-verdicts/commit-verdict-record.js.map +1 -1
  297. package/dist/verify/gate-verdicts/no-verdict-record.d.ts +27 -3
  298. package/dist/verify/gate-verdicts/no-verdict-record.d.ts.map +1 -1
  299. package/dist/verify/gate-verdicts/no-verdict-record.js +36 -6
  300. package/dist/verify/gate-verdicts/no-verdict-record.js.map +1 -1
  301. package/dist/verify/outcome-routing/verification-rework-issue.d.ts.map +1 -1
  302. package/dist/verify/outcome-routing/verification-rework-issue.js +5 -4
  303. package/dist/verify/outcome-routing/verification-rework-issue.js.map +1 -1
  304. package/dist/verify/run-selection/default-on-guards.d.ts +15 -4
  305. package/dist/verify/run-selection/default-on-guards.d.ts.map +1 -1
  306. package/dist/verify/run-selection/default-on-guards.js +14 -4
  307. package/dist/verify/run-selection/default-on-guards.js.map +1 -1
  308. package/dist/verify/run-selection/explicit-next-step-gate.d.ts +39 -0
  309. package/dist/verify/run-selection/explicit-next-step-gate.d.ts.map +1 -0
  310. package/dist/verify/run-selection/explicit-next-step-gate.js +70 -0
  311. package/dist/verify/run-selection/explicit-next-step-gate.js.map +1 -0
  312. package/dist/verify/run-selection/pre-review-gate-dispatch.d.ts +0 -9
  313. package/dist/verify/run-selection/pre-review-gate-dispatch.d.ts.map +1 -1
  314. package/dist/verify/run-selection/pre-review-gate-dispatch.js +21 -62
  315. package/dist/verify/run-selection/pre-review-gate-dispatch.js.map +1 -1
  316. package/dist/verify/run-selection/reselection-log-line.d.ts +1 -1
  317. package/dist/verify/run-selection/reselection-log-line.d.ts.map +1 -1
  318. package/dist/verify/run-selection/reselection-log-line.js +2 -0
  319. package/dist/verify/run-selection/reselection-log-line.js.map +1 -1
  320. package/dist/verify/run-selection/verification-default-on.d.ts +32 -4
  321. package/dist/verify/run-selection/verification-default-on.d.ts.map +1 -1
  322. package/dist/verify/run-selection/verification-default-on.js +83 -19
  323. package/dist/verify/run-selection/verification-default-on.js.map +1 -1
  324. package/dist/verify/shortfalls/shortfall-park.js +1 -1
  325. package/dist/worktree/focus-worktree-state.js +1 -1
  326. package/dist/worktree/focus-worktree-state.js.map +1 -1
  327. package/package.json +3 -3
  328. package/dist/completion/state-cascade/review-next-step.d.ts +0 -107
  329. package/dist/completion/state-cascade/review-next-step.d.ts.map +0 -1
  330. package/dist/completion/state-cascade/review-next-step.js +0 -90
  331. package/dist/completion/state-cascade/review-next-step.js.map +0 -1
  332. package/dist/focus/failed-head-wedge.d.ts +0 -124
  333. package/dist/focus/failed-head-wedge.d.ts.map +0 -1
  334. package/dist/focus/failed-head-wedge.js +0 -120
  335. package/dist/focus/failed-head-wedge.js.map +0 -1
  336. package/dist/focus/stranded-review-reroute.d.ts +0 -70
  337. package/dist/focus/stranded-review-reroute.d.ts.map +0 -1
  338. package/dist/focus/stranded-review-reroute.js +0 -193
  339. package/dist/focus/stranded-review-reroute.js.map +0 -1
  340. package/dist/focus/uncommitted-work-backstop.d.ts +0 -115
  341. package/dist/focus/uncommitted-work-backstop.d.ts.map +0 -1
  342. package/dist/focus/uncommitted-work-backstop.js +0 -259
  343. package/dist/focus/uncommitted-work-backstop.js.map +0 -1
@@ -0,0 +1,197 @@
1
+ // PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
2
+ // Pinned by: packages/daemon/src/focus/focus-liveness-pass.test.ts,
3
+ // packages/daemon/src/integration/failed-verdict-review-exit-respawn-regression.test.ts,
4
+ // packages/daemon/src/integration/failed-verdict-review-loop-regression.test.ts
5
+ // PINNED-BY-END
6
+ /**
7
+ * The liveness pass: each poll, every ARMED focus of one product (role set, not
8
+ * operator-stopped, not read-only) has its one next step read
9
+ * (supervision/focus-next-step.ts) and counted by the liveness detector
10
+ * (supervision/focus-liveness.ts), and the pass does what the detector says:
11
+ * - start_coding: start the coding team the step names -- for a failed HEAD's
12
+ * rework, first make it startable: file the HEAD's rework Bug, or re-open the
13
+ * done or paused delivery carrying it (focus/failed-head-rework-start.ts), and
14
+ * close a review window still open over that HEAD (the decision says no review
15
+ * serves it, and the open-work pass routes nothing while it stays open) --
16
+ * and queue ONE daemon coding respawn of the focus's own lineage, naming the
17
+ * decided reason (and the uncommitted paths, when that is the reason), never
18
+ * over a spawn directive already queued. A rework that could not be made
19
+ * startable queues nothing and is asked for again next poll, until its Bug is
20
+ * filed or re-opened (the retired failed-head wedge retried the same way);
21
+ * - report: file ONE agent-resolvable observation for the stalled key, carrying
22
+ * a deterministic cause_key so incident correlation records it once; a filing
23
+ * that fails is reported again next poll.
24
+ * It replaces the per-shape backstops it was built over -- the failed-head wedge,
25
+ * the uncommitted-work backstop and the stranded-review reroute: each of their
26
+ * stalls is a decided actor that did not move the focus.
27
+ *
28
+ * A stranded-work record the retired uncommitted-work backstop left on a delivery
29
+ * (delivery/advance-hold.ts STRANDED_WORK_REASON) is cleared here once the
30
+ * worktree reads clean, so the dashboard's Waiting-on line does not keep it.
31
+ *
32
+ * Best-effort: every failure is logged and the next poll retries.
33
+ *
34
+ * @module focus/focus-liveness-pass
35
+ */
36
+ import { createHash } from 'node:crypto';
37
+ import { ESCALATION_REASONS } from '@telora/daemon-core';
38
+ import { focusPipelineModelForPass } from '../config/model-resolution.js';
39
+ import { DISPOSITION_AGENT_RESOLVABLE } from '../queries/escalations/escalation-dispositions.js';
40
+ import { computeCauseKey } from '../queries/escalations/cause-key.js';
41
+ import { describeFocusNextStep } from '../supervision/focus-next-step.js';
42
+ import { forgetFocusLiveness, observeFocusLiveness, unmarkFocusLivenessCodingStarted, unmarkFocusLivenessReported, LIVENESS_MERGE_STALL_POLLS, LIVENESS_STALL_POLLS, LIVENESS_STALL_STARTS, } from '../supervision/focus-liveness.js';
43
+ import { hasStrandedWorkRecord } from '../delivery/advance-hold.js';
44
+ import { createLogger } from '../log/daemon-log.js';
45
+ const log = createLogger({ module: 'focus-poller' });
46
+ /** metadata.cause on the stall observation. */
47
+ export const FOCUS_NEXT_ACTOR_STALLED_CAUSE = 'focus_next_actor_stalled';
48
+ /** At most this many uncommitted paths are named in a respawn; the count carries the rest. */
49
+ export const LIVENESS_PATH_CAP = 20;
50
+ const isArmed = (f) => !!f.assigned_agent_role_id && !f.operator_stopped_at && f.read_only !== true;
51
+ /** The respawn message: the decided step, and the paths when the reason is uncommitted work. */
52
+ export function buildLivenessRespawnMessage(focusName, next, paths) {
53
+ const lines = [
54
+ `The focus "${focusName}" has a coding team as its next step (${describeFocusNextStep(next)}), and none has started.`,
55
+ ];
56
+ if (next.step === 'coding' && next.reason === 'uncommitted_work' && paths.length > 0) {
57
+ const named = paths.slice(0, LIVENESS_PATH_CAP).map((p) => `- ${p}`);
58
+ const more = paths.length > LIVENESS_PATH_CAP ? [`- ... and ${paths.length - LIVENESS_PATH_CAP} more`] : [];
59
+ lines.push('', 'Its worktree holds uncommitted work -- the gate and the review judge commits, so nothing else can see it:', ...named, ...more, '', 'Finish it and commit it (with the Telora-Delivery trailer of the delivery it belongs to), or discard what is not wanted.');
60
+ }
61
+ else if (next.step === 'coding' && next.reason.startsWith('gate_rework')) {
62
+ lines.push('', 'The gate FAILED at the focus HEAD. Read the failure on the HEAD\'s rework Bug (title "Verify gate failed at <sha>:"), '
63
+ + 're-open it if it was closed with no commit, fix the failure and commit.');
64
+ }
65
+ return lines.join('\n');
66
+ }
67
+ /** The ONE observation a stalled key owes (agent-resolvable; its cause_key keys the stalled step and HEAD). */
68
+ export function buildFocusStallObservation(organizationId, focus, stall, next, head) {
69
+ const at = head ? head.slice(0, 12) : '<unreadable HEAD>';
70
+ return {
71
+ organizationId,
72
+ issueId: null,
73
+ reasonType: ESCALATION_REASONS.ERROR_ENCOUNTERED,
74
+ disposition: DISPOSITION_AGENT_RESOLVABLE,
75
+ anchor: { focusId: focus.focus_id },
76
+ metadata: {
77
+ cause: FOCUS_NEXT_ACTOR_STALLED_CAUSE,
78
+ cause_key: computeCauseKey(FOCUS_NEXT_ACTOR_STALLED_CAUSE, { focusId: focus.focus_id, step: stall.step, head: head ?? 'unreadable' }),
79
+ step: stall.step,
80
+ next_step: describeFocusNextStep(next),
81
+ head,
82
+ not_started_polls: stall.notStartedPolls,
83
+ starts: stall.starts,
84
+ },
85
+ description: `Armed focus "${focus.focus_name}" is not moving: its next step is ${describeFocusNextStep(next)} at HEAD ${at}, and ` +
86
+ (stall.starts >= LIVENESS_STALL_STARTS
87
+ ? `that actor started ${stall.starts} times without the focus moving (no new commit, no new step).`
88
+ : `that actor has not started for ${stall.notStartedPolls} polls (bound ${stall.step === 'merge' ? LIVENESS_MERGE_STALL_POLLS : LIVENESS_STALL_POLLS}).`),
89
+ whatWasTried: 'The liveness detector read the focus\'s one next step every poll (supervision/focus-next-step.ts); a coding step ' +
90
+ 'that did not start was given one daemon coding respawn.',
91
+ helpNeeded: 'Find what keeps that actor from starting or from moving the focus (daemon log: [focus-poller], [state-cascade], ' +
92
+ '[verification] lines for this focus) and clear it -- e.g. re-open or file the HEAD\'s rework Bug, commit or discard ' +
93
+ 'uncommitted work, or close a review window that cannot route (telora_product_focus update clearReviewRequest).',
94
+ };
95
+ }
96
+ async function fileStall(organizationId, focus, stall, next, head, deps) {
97
+ try {
98
+ await deps.createEscalation(buildFocusStallObservation(organizationId, focus, stall, next, head));
99
+ log.warn(`[focus-poller] "${focus.focus_name}" is not moving: ${describeFocusNextStep(next)} at ${head?.slice(0, 12) ?? '?'} -- observation filed`);
100
+ }
101
+ catch (err) {
102
+ unmarkFocusLivenessReported(focus.focus_id, stall.key);
103
+ log.warn(`[focus-poller] "${focus.focus_name}": liveness observation not recorded (retried next poll): ${err.message}`);
104
+ }
105
+ }
106
+ /**
107
+ * A failed HEAD's rework needs its Bug on a routable delivery, and no review window holding its delivery in verify,
108
+ * before a coding team has it to work. False when that could not be made so.
109
+ */
110
+ async function prepareRework(focus, next, head, deps) {
111
+ if (next.step !== 'coding' || !next.reason.startsWith('gate_rework'))
112
+ return true;
113
+ try {
114
+ if (focus.review_requested_at) {
115
+ await deps.closeReviewWindow(focus.focus_id);
116
+ log.info(`[focus-poller] "${focus.focus_name}": closed the review window over its failed HEAD -- its rework, not a review, is next`);
117
+ }
118
+ if (next.reason === 'gate_rework_unanswered' || !head || !focus.product_id)
119
+ return true;
120
+ const start = await deps.startFailedHeadRework({ focusId: focus.focus_id, productId: focus.product_id, head });
121
+ if (!start.ready) {
122
+ log.warn(`[focus-poller] "${focus.focus_name}": failed HEAD ${head.slice(0, 12)} -- ${start.did}; no coding team queued, retried next poll`);
123
+ return false;
124
+ }
125
+ log.info(`[focus-poller] "${focus.focus_name}": failed HEAD ${head.slice(0, 12)} -- ${start.did}`);
126
+ return true;
127
+ }
128
+ catch (err) {
129
+ log.warn(`[focus-poller] "${focus.focus_name}": failed HEAD rework not made startable -- no coding team queued; retried next poll: ${err.message}`);
130
+ return false;
131
+ }
132
+ }
133
+ async function startCoding(focus, next, head, key, deps) {
134
+ if (!(await prepareRework(focus, next, head, deps))) {
135
+ unmarkFocusLivenessCodingStarted(focus.focus_id, key);
136
+ return;
137
+ }
138
+ const paths = next.step === 'coding' && next.reason === 'uncommitted_work' ? deps.listUncommittedPaths(focus.focus_id) : [];
139
+ const message = buildLivenessRespawnMessage(focus.focus_name, next, paths);
140
+ const queued = deps.queueCodingRespawn({
141
+ focusId: focus.focus_id,
142
+ message,
143
+ contentHash: createHash('sha256').update(message).digest('hex'),
144
+ focusOverrideModel: focusPipelineModelForPass(focus.pipeline_config, 'coding'),
145
+ });
146
+ log.info(`[focus-poller] "${focus.focus_name}": ${describeFocusNextStep(next)} has not started -- ` +
147
+ (queued ? 'queued a coding respawn' : 'a spawn directive is already queued'));
148
+ }
149
+ /** Clear a stranded-work record left on a delivery once the worktree reads clean (module header). */
150
+ async function clearStaleStrandedWork(focus, deliveries, deps) {
151
+ for (const d of deliveries.filter((x) => hasStrandedWorkRecord(x.gateState))) {
152
+ await deps.clearStrandedWorkRecord(d.id).catch((err) => log.warn(`[focus-poller] "${focus.focus_name}": stranded-work record on ${d.id} not cleared (retried next poll): ${err.message}`));
153
+ }
154
+ }
155
+ async function observeFocus(organizationId, focus, deps) {
156
+ const read = await deps.readNextStep(focus);
157
+ if (!read.readable) {
158
+ forgetFocusLiveness(focus.focus_id);
159
+ return { act: 'none' };
160
+ }
161
+ if (!read.facts.uncommittedWork)
162
+ await clearStaleStrandedWork(focus, read.deliveries, deps);
163
+ const act = observeFocusLiveness({ focusId: focus.focus_id, next: read.next, head: read.head, reviewWindow: focus.review_requested_at });
164
+ if (act.act === 'start_coding')
165
+ await startCoding(focus, read.next, read.head, act.key, deps);
166
+ if (act.act === 'report')
167
+ await fileStall(organizationId, focus, act, read.next, read.head, deps);
168
+ return act;
169
+ }
170
+ /** The liveness pass over one product's active focuses (module header). Never throws. */
171
+ export async function detectFocusLivenessStalls(config, deps) {
172
+ let focuses;
173
+ try {
174
+ focuses = await deps.getActiveFocuses(config.organizationId, config.productId);
175
+ }
176
+ catch (err) {
177
+ log.warn(`[focus-poller] liveness pass: active focuses unreadable (retried next poll): ${err.message}`);
178
+ return [];
179
+ }
180
+ const acts = [];
181
+ for (const focus of focuses) {
182
+ if (!isArmed(focus)) {
183
+ forgetFocusLiveness(focus.focus_id);
184
+ continue;
185
+ }
186
+ try {
187
+ const act = await observeFocus(config.organizationId, focus, deps);
188
+ if (act.act !== 'none')
189
+ acts.push({ focusId: focus.focus_id, act });
190
+ }
191
+ catch (err) {
192
+ log.warn(`[focus-poller] liveness pass failed for "${focus.focus_name}" (retried next poll): ${err.message}`);
193
+ }
194
+ }
195
+ return acts;
196
+ }
197
+ //# sourceMappingURL=focus-liveness-pass.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"focus-liveness-pass.js","sourceRoot":"","sources":["../../src/focus/focus-liveness-pass.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  // PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
2
- // Pinned by: 29 tests -- run: npm run gen:pinned-by -- --list packages/daemon/src/focus/focus-poller-spawn.ts
2
+ // Pinned by: 28 tests -- run: npm run gen:pinned-by -- --list packages/daemon/src/focus/focus-poller-spawn.ts
3
3
  // PINNED-BY-END
4
4
  import { resolveReadyFocusSpawnAction } from './ready-focus-spawn-action.js';
5
5
  import { roles, pollState, idleLoggedFocuses, nullRoleSkipWarnedFocuses, lastRolesRefreshAt, healthCheckConsecutiveFailures, POLL_INTERVAL_MS, ROLES_REFRESH_INTERVAL_MS, setPollState, setLastRolesRefreshAt, setLastReadyFocusCount, } from './focus-poller-state.js';
@@ -1,5 +1,5 @@
1
1
  // PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
2
- // Pinned by: 27 tests -- run: npm run gen:pinned-by -- --list packages/daemon/src/focus/focus-poller-state.ts
2
+ // Pinned by: 26 tests -- run: npm run gen:pinned-by -- --list packages/daemon/src/focus/focus-poller-state.ts
3
3
  // PINNED-BY-END
4
4
  /** Polling interval in milliseconds (default: 30 seconds). */
5
5
  export const POLL_INTERVAL_MS = 30000;
@@ -0,0 +1,123 @@
1
+ /**
2
+ * What crash recovery must NOT remove, and the stale-branch pruner that obeys it.
3
+ *
4
+ * ONE RULE FOR WHICH FOCUS BRANCHES ARE LIVE. The migration allocator (the
5
+ * held-set publisher and the grant handler's coverage check) treats every focus
6
+ * with a branch and a status other than complete or cancelled as live -- armed
7
+ * or not -- and requires that branch in every held set. A merged branch is not
8
+ * a dead one: a finished focus still active (awaiting QA, its arm cleared at
9
+ * run end) has a branch fully contained in integration that the allocator still
10
+ * requires. Deleting it refuses every migration claim on the product.
11
+ *
12
+ * So recovery reads the SAME population (queries/migrations/live-focus-branches.ts,
13
+ * canonical src/lib/vocabulary/migration-branch-population.ts) plus every
14
+ * pending completion merge, once per pass, and both the classifier
15
+ * (focus/crash-recovery.ts) and the pruner here keep what it names. An
16
+ * unreadable population removes nothing.
17
+ *
18
+ * History: docs/daemon/history-platform.md (focus/live-branch-preservation.ts).
19
+ *
20
+ * @module focus/live-branch-preservation
21
+ */
22
+ import type { DaemonConfig } from '../types/index.js';
23
+ import type { LiveFocusBranch } from '../queries/migrations/live-focus-branches.js';
24
+ /** What the live population is read through (a subset of RecoveryDeps). */
25
+ export interface LiveBranchPreservationDeps {
26
+ /**
27
+ * The product's LIVE focus branches with their owning focuses: every focus
28
+ * with a branch whose status is not complete or cancelled, armed or not
29
+ * (queries/migrations/live-focus-branches.ts -- the rule the migration
30
+ * allocator and the grant handler read). Deliberately NOT getActiveFocuses,
31
+ * the spawn set. A rejection means the population is unknown, and nothing is
32
+ * removed.
33
+ */
34
+ listLiveFocusBranches: (productId: string) => Promise<LiveFocusBranch[]>;
35
+ /**
36
+ * The focus ids this host holds a pending completion merge for
37
+ * (merge/completion-hold-record.ts). Their worktrees are NOT orphans even when
38
+ * the focus has left the live set: the completed work still has to reach
39
+ * integration, and the merge-back loop drives it from that worktree.
40
+ */
41
+ listPendingCompletionFocusIds: (productId: string) => string[];
42
+ }
43
+ /**
44
+ * Extract the focus ID prefix (last 8 hex chars) from a worktree directory name.
45
+ * Focus worktree directories follow: agent-{role}-{name}-{8-char-id}
46
+ */
47
+ export declare function extractFocusIdPrefix(dirName: string): string | null;
48
+ /**
49
+ * Extract the 8-char focus-key suffix from an agent BRANCH name.
50
+ * Branch format: agent/<role>/<slug>-<8hexfocuskey>. The final path segment
51
+ * carries the same -<8hex> suffix that extractFocusIdPrefix parses off the
52
+ * worktree DIRECTORY name, so this is the branch-name analogue used to anchor a
53
+ * residual signal back to the owning focus.
54
+ */
55
+ export declare function extractFocusKeyFromBranch(branchName: string): string | null;
56
+ /**
57
+ * Parse `git worktree list --porcelain` to build a map of
58
+ * worktree path -> branch name for all registered worktrees.
59
+ */
60
+ export declare function parseWorktreeList(repoPath: string): Map<string, string>;
61
+ /**
62
+ * What crash recovery must not remove: the shared migration branch population
63
+ * (every focus with a branch and a status other than complete or cancelled,
64
+ * armed or not), plus every focus this host holds a pending completion merge
65
+ * for (RecoveryDeps.listPendingCompletionFocusIds) -- its completed work still
66
+ * has to reach integration from that worktree.
67
+ */
68
+ export interface LiveFocusPopulation {
69
+ /** 8-char focus-id prefixes whose worktrees are persistent. */
70
+ focusIdPrefixes: Set<string>;
71
+ /** Branch names live focuses name: never pruned, never removed as a merged orphan. */
72
+ branches: Set<string>;
73
+ /** The live focuses themselves, with the status that makes each live -- what the keep log names. */
74
+ liveFocuses: LiveFocusBranch[];
75
+ /**
76
+ * False when the live focus read failed (or the config names no product).
77
+ * Recovery then removes NOTHING a focus could own: a merged branch can be
78
+ * recreated by nobody once it is gone, and keeping one an extra restart costs
79
+ * a directory.
80
+ */
81
+ known: boolean;
82
+ }
83
+ /** Read the population recovery preserves. Never throws: a failed read is `known: false`. */
84
+ export declare function readLiveFocusPopulation(config: DaemonConfig, deps: LiveBranchPreservationDeps): Promise<LiveFocusPopulation>;
85
+ /**
86
+ * Why the population keeps a branch (or the worktree carrying `idPrefix`), or
87
+ * null when it does not. A LIVE focus is named with the status that makes it
88
+ * live, so a log reader sees the rule -- not complete or cancelled, armed or
89
+ * not -- rather than having to infer it; a pending completion merge is a
90
+ * different reason and says so.
91
+ */
92
+ export declare function keepReason(population: LiveFocusPopulation, idPrefix: string | null, branchName: string): string | null;
93
+ /**
94
+ * Whether the live population keeps a REGISTERED worktree: its directory
95
+ * carries a live (or pending-completion) focus's id prefix, or its branch is
96
+ * one a live focus names -- merged or not, since its focus can still commit and
97
+ * the allocator requires the branch in every held set. When the population
98
+ * could not be read every worktree is kept: whether it is live is unknown, and
99
+ * it is not removed on a guess.
100
+ */
101
+ export declare function populationKeepsWorktree(population: LiveFocusPopulation, dirName: string, worktreePath: string, branchName: string): boolean;
102
+ /**
103
+ * Prune stale agent branches that have no worktree, no unmerged commits, and
104
+ * that NO LIVE FOCUS NAMES.
105
+ *
106
+ * A merged branch is not a dead one: a finished focus that is still active
107
+ * (awaiting QA, its arm cleared at run end) has a branch fully contained in
108
+ * integration, and the migration allocator still requires it in every held
109
+ * set. So the live population (`LiveFocusPopulation`, the same rule the
110
+ * allocator reads) is consulted before anything is deleted, and an unknown
111
+ * population prunes nothing.
112
+ *
113
+ * Same housekeeping policy as the orphaned-worktree path: a branch with
114
+ * unmerged commits is PRESERVED and LOGGED (the commits are recoverable from
115
+ * the ref), never escalated. A merged branch with no worktree is safe to delete.
116
+ * No path here files a needs_operator escalation -- branch-only orphans are
117
+ * reality-side housekeeping the daemon owns.
118
+ */
119
+ export declare function pruneStaleAgentBranches(config: DaemonConfig, livePopulation: LiveFocusPopulation): {
120
+ pruned: string[];
121
+ preserved: string[];
122
+ };
123
+ //# sourceMappingURL=live-branch-preservation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-branch-preservation.d.ts","sourceRoot":"","sources":["../../src/focus/live-branch-preservation.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8CAA8C,CAAC;AAKpF,2EAA2E;AAC3E,MAAM,WAAW,0BAA0B;IACzC;;;;;;;OAOG;IACH,qBAAqB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IACzE;;;;;OAKG;IACH,6BAA6B,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;CAChE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGnE;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG3E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAiBvE;AAED;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,+DAA+D;IAC/D,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,sFAAsF;IACtF,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,oGAAoG;IACpG,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B;;;;;OAKG;IACH,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,6FAA6F;AAC7F,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,0BAA0B,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAuBlI;AAcD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYtH;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,mBAAmB,EAC/B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,OAAO,CAWT;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,YAAY,EACpB,cAAc,EAAE,mBAAmB,GAClC;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,CAyD3C"}
@@ -0,0 +1,192 @@
1
+ // PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
2
+ // Pinned by: packages/daemon/src/focus/crash-recovery.test.ts,
3
+ // packages/daemon/src/integration/finished-merged-active-focus-restart-regression.test.ts
4
+ // PINNED-BY-END
5
+ import { runGitSync } from '../git/types.js';
6
+ import { branchHasUnmergedCommits } from '../worktree/safety.js';
7
+ import { createLogger } from '../log/daemon-log.js';
8
+ const log = createLogger({ module: 'crash-recovery' });
9
+ /**
10
+ * Extract the focus ID prefix (last 8 hex chars) from a worktree directory name.
11
+ * Focus worktree directories follow: agent-{role}-{name}-{8-char-id}
12
+ */
13
+ export function extractFocusIdPrefix(dirName) {
14
+ const match = dirName.match(/-([0-9a-f]{8})$/);
15
+ return match ? match[1] : null;
16
+ }
17
+ /**
18
+ * Extract the 8-char focus-key suffix from an agent BRANCH name.
19
+ * Branch format: agent/<role>/<slug>-<8hexfocuskey>. The final path segment
20
+ * carries the same -<8hex> suffix that extractFocusIdPrefix parses off the
21
+ * worktree DIRECTORY name, so this is the branch-name analogue used to anchor a
22
+ * residual signal back to the owning focus.
23
+ */
24
+ export function extractFocusKeyFromBranch(branchName) {
25
+ const lastSegment = branchName.split('/').pop() ?? branchName;
26
+ return extractFocusIdPrefix(lastSegment);
27
+ }
28
+ /**
29
+ * Parse `git worktree list --porcelain` to build a map of
30
+ * worktree path -> branch name for all registered worktrees.
31
+ */
32
+ export function parseWorktreeList(repoPath) {
33
+ const result = runGitSync(['worktree', 'list', '--porcelain'], repoPath);
34
+ const map = new Map();
35
+ if (!result.success)
36
+ return map;
37
+ let currentPath = null;
38
+ for (const line of result.output.split('\n')) {
39
+ if (line.startsWith('worktree ')) {
40
+ currentPath = line.slice('worktree '.length);
41
+ }
42
+ else if (line.startsWith('branch refs/heads/') && currentPath) {
43
+ map.set(currentPath, line.slice('branch refs/heads/'.length));
44
+ currentPath = null;
45
+ }
46
+ else if (line === '') {
47
+ currentPath = null;
48
+ }
49
+ }
50
+ return map;
51
+ }
52
+ /** Read the population recovery preserves. Never throws: a failed read is `known: false`. */
53
+ export async function readLiveFocusPopulation(config, deps) {
54
+ const population = { focusIdPrefixes: new Set(), branches: new Set(), liveFocuses: [], known: false };
55
+ if (config.productId) {
56
+ try {
57
+ for (const live of await deps.listLiveFocusBranches(config.productId)) {
58
+ population.focusIdPrefixes.add(live.focusId.slice(0, 8));
59
+ population.branches.add(live.branchName);
60
+ population.liveFocuses.push(live);
61
+ }
62
+ population.known = true;
63
+ }
64
+ catch (err) {
65
+ log.warn(`[crash-recovery] Failed to read the live focus branches: ${err instanceof Error ? err.message : String(err)}. ` +
66
+ `No focus worktree or agent branch will be removed this pass.`);
67
+ }
68
+ }
69
+ else {
70
+ log.warn('[crash-recovery] No product in config: the live focus branches cannot be read, so nothing a focus owns is removed.');
71
+ }
72
+ for (const focusId of deps.listPendingCompletionFocusIds(config.productId)) {
73
+ population.focusIdPrefixes.add(focusId.slice(0, 8));
74
+ }
75
+ return population;
76
+ }
77
+ /**
78
+ * List all local branches matching the agent/* pattern.
79
+ */
80
+ function listAgentBranches(repoPath) {
81
+ const result = runGitSync(['branch', '--list', 'agent/*'], repoPath);
82
+ if (!result.success)
83
+ return [];
84
+ return result.output
85
+ .split('\n')
86
+ .map((line) => line.replace(/^[*+]?\s+/, '').trim())
87
+ .filter(Boolean);
88
+ }
89
+ /**
90
+ * Why the population keeps a branch (or the worktree carrying `idPrefix`), or
91
+ * null when it does not. A LIVE focus is named with the status that makes it
92
+ * live, so a log reader sees the rule -- not complete or cancelled, armed or
93
+ * not -- rather than having to infer it; a pending completion merge is a
94
+ * different reason and says so.
95
+ */
96
+ export function keepReason(population, idPrefix, branchName) {
97
+ const live = population.liveFocuses.find((f) => f.branchName === branchName || (idPrefix !== null && f.focusId.startsWith(idPrefix)));
98
+ if (live) {
99
+ return `focus ${live.focusId} is live (status '${live.status}', not complete or cancelled), so its branch ` +
100
+ 'is kept merged or not -- the migration allocator requires it in every held set';
101
+ }
102
+ if (idPrefix !== null && population.focusIdPrefixes.has(idPrefix)) {
103
+ return `focus-key ${idPrefix} has a pending completion merge on this host`;
104
+ }
105
+ return null;
106
+ }
107
+ /**
108
+ * Whether the live population keeps a REGISTERED worktree: its directory
109
+ * carries a live (or pending-completion) focus's id prefix, or its branch is
110
+ * one a live focus names -- merged or not, since its focus can still commit and
111
+ * the allocator requires the branch in every held set. When the population
112
+ * could not be read every worktree is kept: whether it is live is unknown, and
113
+ * it is not removed on a guess.
114
+ */
115
+ export function populationKeepsWorktree(population, dirName, worktreePath, branchName) {
116
+ const reason = keepReason(population, extractFocusIdPrefix(dirName), branchName);
117
+ if (reason) {
118
+ log.info(`[crash-recovery] Keeping worktree and branch: ${reason}: ${worktreePath} [${branchName}]`);
119
+ return true;
120
+ }
121
+ if (!population.known) {
122
+ log.warn(`[crash-recovery] Keeping worktree (live focus branches unknown this pass): ${worktreePath} [${branchName}]`);
123
+ return true;
124
+ }
125
+ return false;
126
+ }
127
+ /**
128
+ * Prune stale agent branches that have no worktree, no unmerged commits, and
129
+ * that NO LIVE FOCUS NAMES.
130
+ *
131
+ * A merged branch is not a dead one: a finished focus that is still active
132
+ * (awaiting QA, its arm cleared at run end) has a branch fully contained in
133
+ * integration, and the migration allocator still requires it in every held
134
+ * set. So the live population (`LiveFocusPopulation`, the same rule the
135
+ * allocator reads) is consulted before anything is deleted, and an unknown
136
+ * population prunes nothing.
137
+ *
138
+ * Same housekeeping policy as the orphaned-worktree path: a branch with
139
+ * unmerged commits is PRESERVED and LOGGED (the commits are recoverable from
140
+ * the ref), never escalated. A merged branch with no worktree is safe to delete.
141
+ * No path here files a needs_operator escalation -- branch-only orphans are
142
+ * reality-side housekeeping the daemon owns.
143
+ */
144
+ export function pruneStaleAgentBranches(config, livePopulation) {
145
+ const { repoPath, integrationBranch } = config;
146
+ const branches = listAgentBranches(repoPath);
147
+ const pruned = [];
148
+ const preserved = [];
149
+ if (branches.length === 0) {
150
+ log.info('No stale agent branches found');
151
+ return { pruned, preserved };
152
+ }
153
+ if (!livePopulation.known) {
154
+ log.warn(`[crash-recovery] Branch pruning skipped: the live focus branches are unknown this pass (${branches.length} agent branch(es) kept)`);
155
+ return { pruned, preserved };
156
+ }
157
+ // Get set of branches that have active worktrees
158
+ const worktreeMap = parseWorktreeList(repoPath);
159
+ const worktreeBranches = new Set(worktreeMap.values());
160
+ for (const branch of branches) {
161
+ // Skip branches with active worktrees
162
+ if (worktreeBranches.has(branch))
163
+ continue;
164
+ // A branch a live focus names is never pruned, merged or not; nor is the
165
+ // branch of a pending completion merge.
166
+ const focusKey = extractFocusKeyFromBranch(branch);
167
+ const keep = keepReason(livePopulation, focusKey, branch);
168
+ if (keep) {
169
+ log.info(`[crash-recovery] Keeping branch: ${keep}: ${branch}`);
170
+ continue;
171
+ }
172
+ // Check for unmerged commits
173
+ if (branchHasUnmergedCommits(branch, integrationBranch, repoPath)) {
174
+ log.info(`[crash-recovery] Housekeeping: preserving stale branch with unmerged commits: ${branch}` +
175
+ (focusKey ? ` (focus-key ${focusKey})` : ''));
176
+ preserved.push(branch);
177
+ continue;
178
+ }
179
+ // Safe to delete
180
+ const deleteResult = runGitSync(['branch', '-D', branch], repoPath);
181
+ if (deleteResult.success) {
182
+ log.info(`Pruned stale branch: ${branch}`);
183
+ pruned.push(branch);
184
+ }
185
+ else {
186
+ log.warn(`Failed to prune branch ${branch}: ${deleteResult.error}`);
187
+ }
188
+ }
189
+ log.info(`[crash-recovery] Branch pruning: ${pruned.length} pruned, ${preserved.length} preserved with unmerged work`);
190
+ return { pruned, preserved };
191
+ }
192
+ //# sourceMappingURL=live-branch-preservation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-branch-preservation.js","sourceRoot":"","sources":["../../src/focus/live-branch-preservation.ts"],"names":[],"mappings":"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"}
@@ -30,6 +30,8 @@ export interface MigrationClaimPassResult {
30
30
  skippedUnchanged: number;
31
31
  /** Focuses whose branch could not be read: nothing was applied for them. */
32
32
  unreadable: number;
33
+ /** Focuses whose unclaimed-file record or clear write failed: retried next tick. */
34
+ recordFailed: number;
33
35
  }
34
36
  /**
35
37
  * Run the confirm / release / unclaimed-file passes for one product.
@@ -1 +1 @@
1
- {"version":3,"file":"migration-claim-pass.d.ts","sourceRoot":"","sources":["../../src/focus/migration-claim-pass.ts"],"names":[],"mappings":"AAwCA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAKrF,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,EACvB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,yBAAyB,EACzB,wBAAwB,EAEzB,MAAM,+DAA+D,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6CAA6C,CAAC;AAIlF,gFAAgF;AAChF,MAAM,WAAW,sBAAsB;IACrC,wDAAwD;IACxD,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAC9D,UAAU,EAAE,OAAO,uBAAuB,CAAC;IAC3C,OAAO,EAAE,OAAO,sBAAsB,CAAC;IACvC,OAAO,EAAE,OAAO,sBAAsB,CAAC;IACvC,eAAe,EAAE,OAAO,yBAAyB,CAAC;IAClD,cAAc,EAAE,OAAO,wBAAwB,CAAC;IAChD,uEAAuE;IACvE,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC3D,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,wBAAwB,CAAC;IAC3E,sEAAsE;IACtE,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC7D,GAAG,EAAE,MAAM,MAAM,CAAC;CACnB;AAWD,sFAAsF;AACtF,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAED,6DAA6D;AAC7D,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,8EAA8E;IAC9E,gBAAgB,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,UAAU,EAAE,MAAM,CAAC;CACpB;AAuKD;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,wBAAwB,CAAC,CAsCnC"}
1
+ {"version":3,"file":"migration-claim-pass.d.ts","sourceRoot":"","sources":["../../src/focus/migration-claim-pass.ts"],"names":[],"mappings":"AA0CA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AAMrF,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,EACvB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,yBAAyB,EACzB,wBAAwB,EAEzB,MAAM,+DAA+D,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6CAA6C,CAAC;AAIlF,gFAAgF;AAChF,MAAM,WAAW,sBAAsB;IACrC,wDAAwD;IACxD,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAC9D,UAAU,EAAE,OAAO,uBAAuB,CAAC;IAC3C,OAAO,EAAE,OAAO,sBAAsB,CAAC;IACvC,OAAO,EAAE,OAAO,sBAAsB,CAAC;IACvC,eAAe,EAAE,OAAO,yBAAyB,CAAC;IAClD,cAAc,EAAE,OAAO,wBAAwB,CAAC;IAChD,uEAAuE;IACvE,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC3D,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,wBAAwB,CAAC;IAC3E,sEAAsE;IACtE,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC7D,GAAG,EAAE,MAAM,MAAM,CAAC;CACnB;AAWD,sFAAsF;AACtF,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAED,6DAA6D;AAC7D,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,8EAA8E;IAC9E,gBAAgB,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,UAAU,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,YAAY,EAAE,MAAM,CAAC;CACtB;AA+MD;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,wBAAwB,CAAC,CAsCnC"}