@telora/daemon 0.24.25 → 0.24.29

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 (433) hide show
  1. package/build-info.json +10 -3
  2. package/dist/audit/audit-prompt.d.ts.map +1 -1
  3. package/dist/audit/audit-prompt.js +15 -0
  4. package/dist/audit/audit-prompt.js.map +1 -1
  5. package/dist/completion/completion-event/event.d.ts +4 -3
  6. package/dist/completion/completion-event/event.d.ts.map +1 -1
  7. package/dist/completion/completion-event/event.js.map +1 -1
  8. package/dist/completion/review-cycle-budget/review-cycle-cap.d.ts +19 -11
  9. package/dist/completion/review-cycle-budget/review-cycle-cap.d.ts.map +1 -1
  10. package/dist/completion/review-cycle-budget/review-cycle-cap.js +36 -36
  11. package/dist/completion/review-cycle-budget/review-cycle-cap.js.map +1 -1
  12. package/dist/completion/review-cycle-budget/review-loop-detection.d.ts +101 -0
  13. package/dist/completion/review-cycle-budget/review-loop-detection.d.ts.map +1 -0
  14. package/dist/completion/review-cycle-budget/review-loop-detection.js +105 -0
  15. package/dist/completion/review-cycle-budget/review-loop-detection.js.map +1 -0
  16. package/dist/completion/review-cycle-budget/spent-budget-release.d.ts +70 -0
  17. package/dist/completion/review-cycle-budget/spent-budget-release.d.ts.map +1 -0
  18. package/dist/completion/review-cycle-budget/spent-budget-release.js +98 -0
  19. package/dist/completion/review-cycle-budget/spent-budget-release.js.map +1 -0
  20. package/dist/completion/review-exit/review-defect-detector.d.ts +71 -49
  21. package/dist/completion/review-exit/review-defect-detector.d.ts.map +1 -1
  22. package/dist/completion/review-exit/review-defect-detector.js +75 -69
  23. package/dist/completion/review-exit/review-defect-detector.js.map +1 -1
  24. package/dist/completion/review-exit/review-exit-attribution.d.ts +1 -1
  25. package/dist/completion/review-exit/review-exit-attribution.js +1 -1
  26. package/dist/completion/review-exit/review-exit-deps.d.ts +5 -2
  27. package/dist/completion/review-exit/review-exit-deps.d.ts.map +1 -1
  28. package/dist/completion/review-exit/review-exit-deps.js +1 -1
  29. package/dist/completion/review-exit/review-exit-evidence.d.ts +10 -1
  30. package/dist/completion/review-exit/review-exit-evidence.d.ts.map +1 -1
  31. package/dist/completion/review-exit/review-exit-evidence.js +17 -14
  32. package/dist/completion/review-exit/review-exit-evidence.js.map +1 -1
  33. package/dist/completion/review-exit/review-exit-foreign-findings.d.ts +1 -1
  34. package/dist/completion/review-exit/review-exit-foreign-findings.d.ts.map +1 -1
  35. package/dist/completion/review-exit/review-exit-phase.d.ts.map +1 -1
  36. package/dist/completion/review-exit/review-exit-phase.js +12 -8
  37. package/dist/completion/review-exit/review-exit-phase.js.map +1 -1
  38. package/dist/completion/state-cascade/review-next-step.d.ts +12 -3
  39. package/dist/completion/state-cascade/review-next-step.d.ts.map +1 -1
  40. package/dist/completion/state-cascade/review-next-step.js +10 -1
  41. package/dist/completion/state-cascade/review-next-step.js.map +1 -1
  42. package/dist/completion/state-cascade/standing-approval-convergence.d.ts +1 -1
  43. package/dist/completion/state-cascade/standing-approval-convergence.d.ts.map +1 -1
  44. package/dist/completion/state-cascade/standing-approval-convergence.js +10 -4
  45. package/dist/completion/state-cascade/standing-approval-convergence.js.map +1 -1
  46. package/dist/completion/state-cascade/state-cascade.d.ts +3 -0
  47. package/dist/completion/state-cascade/state-cascade.d.ts.map +1 -1
  48. package/dist/completion/state-cascade/state-cascade.js +16 -1
  49. package/dist/completion/state-cascade/state-cascade.js.map +1 -1
  50. package/dist/completion/team-exit/status-advance-phase.d.ts +1 -1
  51. package/dist/completion/team-exit/status-advance-phase.d.ts.map +1 -1
  52. package/dist/completion/team-exit/status-advance-phase.js +6 -4
  53. package/dist/completion/team-exit/status-advance-phase.js.map +1 -1
  54. package/dist/completion/team-outcome/apply-turn.d.ts.map +1 -1
  55. package/dist/completion/team-outcome/apply-turn.js +9 -4
  56. package/dist/completion/team-outcome/apply-turn.js.map +1 -1
  57. package/dist/completion/team-outcome/decide-turn-entry-rows.d.ts.map +1 -1
  58. package/dist/completion/team-outcome/decide-turn-entry-rows.js +28 -3
  59. package/dist/completion/team-outcome/decide-turn-entry-rows.js.map +1 -1
  60. package/dist/completion/team-outcome/decide.d.ts.map +1 -1
  61. package/dist/completion/team-outcome/decide.js +1 -0
  62. package/dist/completion/team-outcome/decide.js.map +1 -1
  63. package/dist/completion/team-outcome/exit-limits.d.ts +6 -0
  64. package/dist/completion/team-outcome/exit-limits.d.ts.map +1 -1
  65. package/dist/completion/team-outcome/exit-limits.js +6 -0
  66. package/dist/completion/team-outcome/exit-limits.js.map +1 -1
  67. package/dist/completion/team-outcome/exit-pipeline-state.d.ts +5 -0
  68. package/dist/completion/team-outcome/exit-pipeline-state.d.ts.map +1 -1
  69. package/dist/completion/team-outcome/exit-pipeline-state.js.map +1 -1
  70. package/dist/completion/team-teardown/session-hold-bounds.d.ts +10 -1
  71. package/dist/completion/team-teardown/session-hold-bounds.d.ts.map +1 -1
  72. package/dist/completion/team-teardown/session-hold-bounds.js +11 -0
  73. package/dist/completion/team-teardown/session-hold-bounds.js.map +1 -1
  74. package/dist/completion/team-teardown/session-hold.d.ts.map +1 -1
  75. package/dist/completion/team-teardown/session-hold.js +2 -0
  76. package/dist/completion/team-teardown/session-hold.js.map +1 -1
  77. package/dist/composition/engine-start-context.d.ts.map +1 -1
  78. package/dist/composition/engine-start-context.js +9 -1
  79. package/dist/composition/engine-start-context.js.map +1 -1
  80. package/dist/composition/execution-spawn-context.d.ts.map +1 -1
  81. package/dist/composition/execution-spawn-context.js +2 -0
  82. package/dist/composition/execution-spawn-context.js.map +1 -1
  83. package/dist/composition/judgement-contexts.d.ts.map +1 -1
  84. package/dist/composition/judgement-contexts.js +8 -2
  85. package/dist/composition/judgement-contexts.js.map +1 -1
  86. package/dist/composition/review-exit-context.d.ts.map +1 -1
  87. package/dist/composition/review-exit-context.js +2 -0
  88. package/dist/composition/review-exit-context.js.map +1 -1
  89. package/dist/composition/review-loop-context.d.ts +28 -0
  90. package/dist/composition/review-loop-context.d.ts.map +1 -0
  91. package/dist/composition/review-loop-context.js +147 -0
  92. package/dist/composition/review-loop-context.js.map +1 -0
  93. package/dist/composition/runtime-heartbeat-context.d.ts.map +1 -1
  94. package/dist/composition/runtime-heartbeat-context.js +8 -2
  95. package/dist/composition/runtime-heartbeat-context.js.map +1 -1
  96. package/dist/composition/spawn-pass-deps.d.ts.map +1 -1
  97. package/dist/composition/spawn-pass-deps.js +3 -0
  98. package/dist/composition/spawn-pass-deps.js.map +1 -1
  99. package/dist/composition/state-cascade-context.d.ts.map +1 -1
  100. package/dist/composition/state-cascade-context.js +3 -1
  101. package/dist/composition/state-cascade-context.js.map +1 -1
  102. package/dist/composition/tower-escalation-context.d.ts +12 -0
  103. package/dist/composition/tower-escalation-context.d.ts.map +1 -0
  104. package/dist/composition/tower-escalation-context.js +109 -0
  105. package/dist/composition/tower-escalation-context.js.map +1 -0
  106. package/dist/composition/workstation-intervals-context.d.ts +3 -0
  107. package/dist/composition/workstation-intervals-context.d.ts.map +1 -0
  108. package/dist/composition/workstation-intervals-context.js +33 -0
  109. package/dist/composition/workstation-intervals-context.js.map +1 -0
  110. package/dist/daemon-state/awaiting-slot.d.ts +18 -1
  111. package/dist/daemon-state/awaiting-slot.d.ts.map +1 -1
  112. package/dist/daemon-state/awaiting-slot.js +7 -0
  113. package/dist/daemon-state/awaiting-slot.js.map +1 -1
  114. package/dist/delivery/delivery-reconciler.d.ts +7 -7
  115. package/dist/delivery/recorded-concerns.d.ts +63 -28
  116. package/dist/delivery/recorded-concerns.d.ts.map +1 -1
  117. package/dist/delivery/recorded-concerns.js +72 -28
  118. package/dist/delivery/recorded-concerns.js.map +1 -1
  119. package/dist/directive/directive-queue.d.ts +8 -0
  120. package/dist/directive/directive-queue.d.ts.map +1 -1
  121. package/dist/directive/directive-queue.js +1 -1
  122. package/dist/directive/directive-queue.js.map +1 -1
  123. package/dist/focus/control-state.d.ts +6 -4
  124. package/dist/focus/control-state.d.ts.map +1 -1
  125. package/dist/focus/control-state.js +6 -4
  126. package/dist/focus/control-state.js.map +1 -1
  127. package/dist/focus/daemon-contexts-judgement.d.ts +6 -0
  128. package/dist/focus/daemon-contexts-judgement.d.ts.map +1 -1
  129. package/dist/focus/daemon-contexts.d.ts +6 -0
  130. package/dist/focus/daemon-contexts.d.ts.map +1 -1
  131. package/dist/focus/daemon-contexts.js.map +1 -1
  132. package/dist/focus/focus-engine.d.ts.map +1 -1
  133. package/dist/focus/focus-engine.js +3 -1
  134. package/dist/focus/focus-engine.js.map +1 -1
  135. package/dist/focus/focus-executor.d.ts.map +1 -1
  136. package/dist/focus/focus-executor.js +3 -2
  137. package/dist/focus/focus-executor.js.map +1 -1
  138. package/dist/focus/focus-loop-registry.d.ts.map +1 -1
  139. package/dist/focus/focus-loop-registry.js +42 -0
  140. package/dist/focus/focus-loop-registry.js.map +1 -1
  141. package/dist/focus/focus-poller-auto-advance.d.ts +4 -2
  142. package/dist/focus/focus-poller-auto-advance.d.ts.map +1 -1
  143. package/dist/focus/focus-poller-auto-advance.js +24 -18
  144. package/dist/focus/focus-poller-auto-advance.js.map +1 -1
  145. package/dist/focus/focus-poller-spawn.d.ts.map +1 -1
  146. package/dist/focus/focus-poller-spawn.js +8 -6
  147. package/dist/focus/focus-poller-spawn.js.map +1 -1
  148. package/dist/focus/heartbeat.d.ts +9 -2
  149. package/dist/focus/heartbeat.d.ts.map +1 -1
  150. package/dist/focus/heartbeat.js +9 -1
  151. package/dist/focus/heartbeat.js.map +1 -1
  152. package/dist/focus/pending-directive-gates.d.ts +14 -0
  153. package/dist/focus/pending-directive-gates.d.ts.map +1 -1
  154. package/dist/focus/pending-directive-gates.js +25 -1
  155. package/dist/focus/pending-directive-gates.js.map +1 -1
  156. package/dist/focus/pending-spawn-pass-deps.d.ts +7 -0
  157. package/dist/focus/pending-spawn-pass-deps.d.ts.map +1 -1
  158. package/dist/focus/pending-spawn-review-next-step.d.ts +1 -1
  159. package/dist/focus/pending-spawn-review-next-step.d.ts.map +1 -1
  160. package/dist/focus/pending-spawn-review-next-step.js +2 -0
  161. package/dist/focus/pending-spawn-review-next-step.js.map +1 -1
  162. package/dist/focus/ready-focus-team-work.d.ts +9 -4
  163. package/dist/focus/ready-focus-team-work.d.ts.map +1 -1
  164. package/dist/focus/ready-focus-team-work.js +14 -3
  165. package/dist/focus/ready-focus-team-work.js.map +1 -1
  166. package/dist/focus/verify-open-issues.d.ts +3 -2
  167. package/dist/focus/verify-open-issues.d.ts.map +1 -1
  168. package/dist/focus/verify-open-issues.js +6 -4
  169. package/dist/focus/verify-open-issues.js.map +1 -1
  170. package/dist/focus/workstation-intervals.d.ts +83 -0
  171. package/dist/focus/workstation-intervals.d.ts.map +1 -0
  172. package/dist/focus/workstation-intervals.js +81 -0
  173. package/dist/focus/workstation-intervals.js.map +1 -0
  174. package/dist/focus-stage-lifecycle/wedge-watchdog.d.ts +5 -2
  175. package/dist/focus-stage-lifecycle/wedge-watchdog.d.ts.map +1 -1
  176. package/dist/focus-stage-lifecycle/wedge-watchdog.js +2 -2
  177. package/dist/focus-stage-lifecycle/wedge-watchdog.js.map +1 -1
  178. package/dist/nexus/escalation-bridge.d.ts.map +1 -1
  179. package/dist/nexus/escalation-bridge.js +2 -1
  180. package/dist/nexus/escalation-bridge.js.map +1 -1
  181. package/dist/nexus/file-escalation.d.ts.map +1 -1
  182. package/dist/nexus/file-escalation.js +1 -0
  183. package/dist/nexus/file-escalation.js.map +1 -1
  184. package/dist/prompt-sections/persona-sections.d.ts.map +1 -1
  185. package/dist/prompt-sections/persona-sections.js +4 -1
  186. package/dist/prompt-sections/persona-sections.js.map +1 -1
  187. package/dist/prompt-sections/qa-author-section.d.ts.map +1 -1
  188. package/dist/prompt-sections/qa-author-section.js +18 -1
  189. package/dist/prompt-sections/qa-author-section.js.map +1 -1
  190. package/dist/prompt-sections/scoping-sections.d.ts +0 -12
  191. package/dist/prompt-sections/scoping-sections.d.ts.map +1 -1
  192. package/dist/prompt-sections/scoping-sections.js +16 -2
  193. package/dist/prompt-sections/scoping-sections.js.map +1 -1
  194. package/dist/prompts/bounded-universals.d.ts +13 -0
  195. package/dist/prompts/bounded-universals.d.ts.map +1 -0
  196. package/dist/prompts/bounded-universals.js +32 -0
  197. package/dist/prompts/bounded-universals.js.map +1 -0
  198. package/dist/queries/api-client/shared.d.ts +2 -1
  199. package/dist/queries/api-client/shared.d.ts.map +1 -1
  200. package/dist/queries/api-client/shared.js +31 -1
  201. package/dist/queries/api-client/shared.js.map +1 -1
  202. package/dist/queries/deliveries/deliveries.js +1 -1
  203. package/dist/queries/deliveries/issues.d.ts.map +1 -1
  204. package/dist/queries/deliveries/issues.js +1 -0
  205. package/dist/queries/deliveries/issues.js.map +1 -1
  206. package/dist/queries/delivery-gate-state/delivery-gate-state.js +1 -1
  207. package/dist/queries/delivery-gate-state/verify-own-holds.d.ts +24 -2
  208. package/dist/queries/delivery-gate-state/verify-own-holds.d.ts.map +1 -1
  209. package/dist/queries/delivery-gate-state/verify-own-holds.js.map +1 -1
  210. package/dist/queries/escalations/cause-key.d.ts.map +1 -1
  211. package/dist/queries/escalations/cause-key.js +1 -0
  212. package/dist/queries/escalations/cause-key.js.map +1 -1
  213. package/dist/queries/escalations/escalation-consumption.d.ts +13 -0
  214. package/dist/queries/escalations/escalation-consumption.d.ts.map +1 -1
  215. package/dist/queries/escalations/escalation-consumption.js +12 -2
  216. package/dist/queries/escalations/escalation-consumption.js.map +1 -1
  217. package/dist/queries/escalations/escalations.d.ts.map +1 -1
  218. package/dist/queries/escalations/escalations.js +2 -1
  219. package/dist/queries/escalations/escalations.js.map +1 -1
  220. package/dist/queries/escalations/tower-escalations.d.ts +82 -0
  221. package/dist/queries/escalations/tower-escalations.d.ts.map +1 -0
  222. package/dist/queries/escalations/tower-escalations.js +97 -0
  223. package/dist/queries/escalations/tower-escalations.js.map +1 -0
  224. package/dist/queries/focus-review/recorded-concern-ids.d.ts +48 -11
  225. package/dist/queries/focus-review/recorded-concern-ids.d.ts.map +1 -1
  226. package/dist/queries/focus-review/recorded-concern-ids.js +42 -12
  227. package/dist/queries/focus-review/recorded-concern-ids.js.map +1 -1
  228. package/dist/queries/focus-review/review-criterion-verdicts.d.ts +37 -0
  229. package/dist/queries/focus-review/review-criterion-verdicts.d.ts.map +1 -0
  230. package/dist/queries/focus-review/review-criterion-verdicts.js +64 -0
  231. package/dist/queries/focus-review/review-criterion-verdicts.js.map +1 -0
  232. package/dist/queries/focus-review/review-finding-facts.d.ts +18 -6
  233. package/dist/queries/focus-review/review-finding-facts.d.ts.map +1 -1
  234. package/dist/queries/focus-review/review-finding-facts.js +21 -8
  235. package/dist/queries/focus-review/review-finding-facts.js.map +1 -1
  236. package/dist/queries/focuses/ended-arm.d.ts +56 -13
  237. package/dist/queries/focuses/ended-arm.d.ts.map +1 -1
  238. package/dist/queries/focuses/ended-arm.js +40 -14
  239. package/dist/queries/focuses/ended-arm.js.map +1 -1
  240. package/dist/queries/focuses/focus-criteria-standing.d.ts +12 -0
  241. package/dist/queries/focuses/focus-criteria-standing.d.ts.map +1 -1
  242. package/dist/queries/focuses/focus-criteria-standing.js +13 -0
  243. package/dist/queries/focuses/focus-criteria-standing.js.map +1 -1
  244. package/dist/queries/focuses/focus-discovery.d.ts +14 -3
  245. package/dist/queries/focuses/focus-discovery.d.ts.map +1 -1
  246. package/dist/queries/focuses/focus-discovery.js +2 -19
  247. package/dist/queries/focuses/focus-discovery.js.map +1 -1
  248. package/dist/queries/focuses/focuses.d.ts +15 -12
  249. package/dist/queries/focuses/focuses.d.ts.map +1 -1
  250. package/dist/queries/focuses/focuses.js +15 -13
  251. package/dist/queries/focuses/focuses.js.map +1 -1
  252. package/dist/queries/sessions/sessions.d.ts.map +1 -1
  253. package/dist/queries/sessions/sessions.js +2 -1
  254. package/dist/queries/sessions/sessions.js.map +1 -1
  255. package/dist/queries/tower-decisions/tower-decisions.d.ts +103 -0
  256. package/dist/queries/tower-decisions/tower-decisions.d.ts.map +1 -0
  257. package/dist/queries/tower-decisions/tower-decisions.js +138 -0
  258. package/dist/queries/tower-decisions/tower-decisions.js.map +1 -0
  259. package/dist/queries/verification/verification.js +1 -1
  260. package/dist/queries/wire-schemas/schemas.d.ts +2 -0
  261. package/dist/queries/wire-schemas/schemas.d.ts.map +1 -1
  262. package/dist/queries/wire-schemas/schemas.js +8 -2
  263. package/dist/queries/wire-schemas/schemas.js.map +1 -1
  264. package/dist/queries/workstation-intervals/workstation-intervals.d.ts +52 -0
  265. package/dist/queries/workstation-intervals/workstation-intervals.d.ts.map +1 -0
  266. package/dist/queries/workstation-intervals/workstation-intervals.js +49 -0
  267. package/dist/queries/workstation-intervals/workstation-intervals.js.map +1 -0
  268. package/dist/resolvers/escalation-answers.d.ts +31 -0
  269. package/dist/resolvers/escalation-answers.d.ts.map +1 -1
  270. package/dist/resolvers/escalation-answers.js +31 -17
  271. package/dist/resolvers/escalation-answers.js.map +1 -1
  272. package/dist/resolvers/focus-criteria-standing.d.ts.map +1 -1
  273. package/dist/resolvers/focus-criteria-standing.js +20 -0
  274. package/dist/resolvers/focus-criteria-standing.js.map +1 -1
  275. package/dist/shell/unified-engine-lifecycle.d.ts +11 -1
  276. package/dist/shell/unified-engine-lifecycle.d.ts.map +1 -1
  277. package/dist/shell/unified-engine-lifecycle.js +10 -1
  278. package/dist/shell/unified-engine-lifecycle.js.map +1 -1
  279. package/dist/spawn/directive-dispatch.d.ts.map +1 -1
  280. package/dist/spawn/directive-dispatch.js +1 -0
  281. package/dist/spawn/directive-dispatch.js.map +1 -1
  282. package/dist/spawn/lead-continuation.d.ts +4 -3
  283. package/dist/spawn/lead-continuation.d.ts.map +1 -1
  284. package/dist/spawn/lead-continuation.js.map +1 -1
  285. package/dist/spawn/live-answer-delivery.d.ts +53 -0
  286. package/dist/spawn/live-answer-delivery.d.ts.map +1 -0
  287. package/dist/spawn/live-answer-delivery.js +26 -0
  288. package/dist/spawn/live-answer-delivery.js.map +1 -0
  289. package/dist/spawn/routing-decider-spawn.d.ts +64 -2
  290. package/dist/spawn/routing-decider-spawn.d.ts.map +1 -1
  291. package/dist/spawn/routing-decider-spawn.js +65 -20
  292. package/dist/spawn/routing-decider-spawn.js.map +1 -1
  293. package/dist/spawn/worktree-session.d.ts +7 -5
  294. package/dist/spawn/worktree-session.d.ts.map +1 -1
  295. package/dist/spawn/worktree-session.js +11 -7
  296. package/dist/spawn/worktree-session.js.map +1 -1
  297. package/dist/supervision/escalation-filing.js +1 -1
  298. package/dist/supervision/incident-correlation.d.ts +4 -1
  299. package/dist/supervision/incident-correlation.d.ts.map +1 -1
  300. package/dist/supervision/incident-correlation.js +7 -2
  301. package/dist/supervision/incident-correlation.js.map +1 -1
  302. package/dist/supervision/review-cycle-cap-hold.d.ts +11 -5
  303. package/dist/supervision/review-cycle-cap-hold.d.ts.map +1 -1
  304. package/dist/supervision/review-cycle-cap-hold.js +29 -11
  305. package/dist/supervision/review-cycle-cap-hold.js.map +1 -1
  306. package/dist/supervision/review-loop-detector.d.ts +48 -0
  307. package/dist/supervision/review-loop-detector.d.ts.map +1 -0
  308. package/dist/supervision/review-loop-detector.js +13 -0
  309. package/dist/supervision/review-loop-detector.js.map +1 -0
  310. package/dist/supervision/review-loop-hold.d.ts +29 -0
  311. package/dist/supervision/review-loop-hold.d.ts.map +1 -0
  312. package/dist/supervision/review-loop-hold.js +99 -0
  313. package/dist/supervision/review-loop-hold.js.map +1 -0
  314. package/dist/supervision/stall-detector-config.d.ts +8 -0
  315. package/dist/supervision/stall-detector-config.d.ts.map +1 -1
  316. package/dist/supervision/stall-detector-config.js +14 -3
  317. package/dist/supervision/stall-detector-config.js.map +1 -1
  318. package/dist/supervision/stop-registry.d.ts +4 -0
  319. package/dist/supervision/stop-registry.d.ts.map +1 -1
  320. package/dist/supervision/stop-registry.js +3 -1
  321. package/dist/supervision/stop-registry.js.map +1 -1
  322. package/dist/supervision/stop-rows-delivery.d.ts +10 -0
  323. package/dist/supervision/stop-rows-delivery.d.ts.map +1 -1
  324. package/dist/supervision/stop-rows-delivery.js +29 -0
  325. package/dist/supervision/stop-rows-delivery.js.map +1 -1
  326. package/dist/supervision/stop-rows-review-loop.d.ts +35 -0
  327. package/dist/supervision/stop-rows-review-loop.d.ts.map +1 -0
  328. package/dist/supervision/stop-rows-review-loop.js +150 -0
  329. package/dist/supervision/stop-rows-review-loop.js.map +1 -0
  330. package/dist/supervision/stop-rows-team-session.d.ts +1 -1
  331. package/dist/supervision/stop-rows-team-session.d.ts.map +1 -1
  332. package/dist/supervision/stop-rows-team-session.js.map +1 -1
  333. package/dist/supervision/unreviewed-settle-detector.d.ts +7 -2
  334. package/dist/supervision/unreviewed-settle-detector.d.ts.map +1 -1
  335. package/dist/supervision/unreviewed-settle-detector.js +15 -2
  336. package/dist/supervision/unreviewed-settle-detector.js.map +1 -1
  337. package/dist/templates/agents-md.d.ts.map +1 -1
  338. package/dist/templates/agents-md.js +1 -0
  339. package/dist/templates/agents-md.js.map +1 -1
  340. package/dist/templates/claude-md.d.ts +1 -1
  341. package/dist/templates/claude-md.d.ts.map +1 -1
  342. package/dist/templates/claude-md.js +12 -0
  343. package/dist/templates/claude-md.js.map +1 -1
  344. package/dist/testing/fixtures/api-client.js +1 -1
  345. package/dist/testing/fixtures/index.js +1 -1
  346. package/dist/testing/fixtures/pending-spawn-world.d.ts +4 -0
  347. package/dist/testing/fixtures/pending-spawn-world.d.ts.map +1 -1
  348. package/dist/testing/fixtures/pending-spawn-world.js +15 -2
  349. package/dist/testing/fixtures/pending-spawn-world.js.map +1 -1
  350. package/dist/testing/fixtures/recording-api-client.js +1 -1
  351. package/dist/testing/fixtures/review-exit-deps.d.ts.map +1 -1
  352. package/dist/testing/fixtures/review-exit-deps.js +3 -1
  353. package/dist/testing/fixtures/review-exit-deps.js.map +1 -1
  354. package/dist/testing/fixtures/review-loop.d.ts +19 -0
  355. package/dist/testing/fixtures/review-loop.d.ts.map +1 -0
  356. package/dist/testing/fixtures/review-loop.js +30 -0
  357. package/dist/testing/fixtures/review-loop.js.map +1 -0
  358. package/dist/testing/fixtures/shortfall-rework-hold-deps.d.ts.map +1 -1
  359. package/dist/testing/fixtures/shortfall-rework-hold-deps.js +1 -0
  360. package/dist/testing/fixtures/shortfall-rework-hold-deps.js.map +1 -1
  361. package/dist/testing/fixtures/tower-loop.d.ts +28 -0
  362. package/dist/testing/fixtures/tower-loop.d.ts.map +1 -0
  363. package/dist/testing/fixtures/tower-loop.js +83 -0
  364. package/dist/testing/fixtures/tower-loop.js.map +1 -0
  365. package/dist/tower/tower-escalation-gather.d.ts +33 -0
  366. package/dist/tower/tower-escalation-gather.d.ts.map +1 -0
  367. package/dist/tower/tower-escalation-gather.js +38 -0
  368. package/dist/tower/tower-escalation-gather.js.map +1 -0
  369. package/dist/tower/tower-escalation-prompt.d.ts +62 -0
  370. package/dist/tower/tower-escalation-prompt.d.ts.map +1 -0
  371. package/dist/tower/tower-escalation-prompt.js +130 -0
  372. package/dist/tower/tower-escalation-prompt.js.map +1 -0
  373. package/dist/tower/tower-escalation-routing.d.ts +49 -0
  374. package/dist/tower/tower-escalation-routing.d.ts.map +1 -0
  375. package/dist/tower/tower-escalation-routing.js +53 -0
  376. package/dist/tower/tower-escalation-routing.js.map +1 -0
  377. package/dist/tower/tower-escalation-session.d.ts +149 -0
  378. package/dist/tower/tower-escalation-session.d.ts.map +1 -0
  379. package/dist/tower/tower-escalation-session.js +238 -0
  380. package/dist/tower/tower-escalation-session.js.map +1 -0
  381. package/dist/tower/tower-supervisor-history.d.ts +129 -0
  382. package/dist/tower/tower-supervisor-history.d.ts.map +1 -0
  383. package/dist/tower/tower-supervisor-history.js +217 -0
  384. package/dist/tower/tower-supervisor-history.js.map +1 -0
  385. package/dist/tower/tower-supervisor-prompt.d.ts +21 -0
  386. package/dist/tower/tower-supervisor-prompt.d.ts.map +1 -0
  387. package/dist/tower/tower-supervisor-prompt.js +205 -0
  388. package/dist/tower/tower-supervisor-prompt.js.map +1 -0
  389. package/dist/tower/tower-supervisor-session.d.ts +220 -0
  390. package/dist/tower/tower-supervisor-session.d.ts.map +1 -0
  391. package/dist/tower/tower-supervisor-session.js +307 -0
  392. package/dist/tower/tower-supervisor-session.js.map +1 -0
  393. package/dist/tower/tower-supervisor.d.ts +86 -0
  394. package/dist/tower/tower-supervisor.d.ts.map +1 -0
  395. package/dist/tower/tower-supervisor.js +8 -0
  396. package/dist/tower/tower-supervisor.js.map +1 -0
  397. package/dist/types/index.js +1 -1
  398. package/dist/verify/deterministic-gate/verification-deterministic.js +1 -1
  399. package/dist/verify/effect-reconciliation/verify-reconciliation.d.ts +11 -0
  400. package/dist/verify/effect-reconciliation/verify-reconciliation.d.ts.map +1 -1
  401. package/dist/verify/effect-reconciliation/verify-reconciliation.js +35 -2
  402. package/dist/verify/effect-reconciliation/verify-reconciliation.js.map +1 -1
  403. package/dist/verify/effect-reconciliation/verify-restatement.d.ts +4 -0
  404. package/dist/verify/effect-reconciliation/verify-restatement.d.ts.map +1 -1
  405. package/dist/verify/effect-reconciliation/verify-restatement.js +3 -3
  406. package/dist/verify/effect-reconciliation/verify-restatement.js.map +1 -1
  407. package/dist/verify/engine/reconciliation-step.d.ts +9 -2
  408. package/dist/verify/engine/reconciliation-step.d.ts.map +1 -1
  409. package/dist/verify/engine/reconciliation-step.js +26 -3
  410. package/dist/verify/engine/reconciliation-step.js.map +1 -1
  411. package/dist/verify/outcome-routing/incurable-model-hold.d.ts +2 -0
  412. package/dist/verify/outcome-routing/incurable-model-hold.d.ts.map +1 -1
  413. package/dist/verify/outcome-routing/incurable-model-hold.js +21 -6
  414. package/dist/verify/outcome-routing/incurable-model-hold.js.map +1 -1
  415. package/dist/verify/outcome-routing/repeating-model-hold.d.ts.map +1 -1
  416. package/dist/verify/outcome-routing/repeating-model-hold.js +13 -7
  417. package/dist/verify/outcome-routing/repeating-model-hold.js.map +1 -1
  418. package/dist/verify/outcome-routing/unjudged-node-hold.d.ts +31 -0
  419. package/dist/verify/outcome-routing/unjudged-node-hold.d.ts.map +1 -0
  420. package/dist/verify/outcome-routing/unjudged-node-hold.js +134 -0
  421. package/dist/verify/outcome-routing/unjudged-node-hold.js.map +1 -0
  422. package/dist/verify/outcome-routing/verification-model-unavailable-hold.d.ts +4 -0
  423. package/dist/verify/outcome-routing/verification-model-unavailable-hold.d.ts.map +1 -1
  424. package/dist/verify/outcome-routing/verification-model-unavailable-hold.js +25 -8
  425. package/dist/verify/outcome-routing/verification-model-unavailable-hold.js.map +1 -1
  426. package/dist/verify/outcome-routing/verification-rework-issue.d.ts +4 -4
  427. package/dist/verify/outcome-routing/verification-rework-issue.d.ts.map +1 -1
  428. package/dist/verify/outcome-routing/verification-rework-issue.js +16 -6
  429. package/dist/verify/outcome-routing/verification-rework-issue.js.map +1 -1
  430. package/dist/verify/shortfalls/pre-judge-rulings.d.ts.map +1 -1
  431. package/dist/verify/shortfalls/pre-judge-rulings.js +1 -0
  432. package/dist/verify/shortfalls/pre-judge-rulings.js.map +1 -1
  433. package/package.json +3 -3
@@ -0,0 +1,130 @@
1
+ // PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
2
+ // Pinned by: packages/daemon/src/tower/tower-escalation-prompt.test.ts
3
+ // PINNED-BY-END
4
+ /** The last line the session prints (informational; the record decides). */
5
+ export const TOWER_ESCALATION_LINE_PREFIX = 'TOWER DECISION:';
6
+ function fence(text) {
7
+ return ['```', text.replace(/```/g, "'''"), '```'].join('\n');
8
+ }
9
+ function escalationSection(input) {
10
+ const e = input.escalation;
11
+ const out = [
12
+ '## The escalation',
13
+ '',
14
+ `escalationId ${e.escalationId}, filed ${e.createdAt} by a team on this focus` +
15
+ `${e.deliveryId ? ` (deliveryId ${e.deliveryId})` : ''}${e.issueId ? ` (issueId ${e.issueId})` : ''}.`,
16
+ `Reason: ${e.reasonType}; disposition: ${e.disposition ?? 'unset'}.`,
17
+ '',
18
+ 'What happened and why the team escalated:',
19
+ fence(e.description.trim() === '' ? '(no description)' : e.description),
20
+ ];
21
+ if (e.whatWasTried)
22
+ out.push('', 'What the team tried:', fence(e.whatWasTried));
23
+ if (e.helpNeeded)
24
+ out.push('', 'What the team asks for (its recommendation, when it made one, is usually here):', fence(e.helpNeeded));
25
+ out.push('');
26
+ return out;
27
+ }
28
+ function deliveryLine(d) {
29
+ const arm = d.covered === null ? '' : d.covered ? ', covered by the arm' : ', recorded as new intent after the arm (not covered)';
30
+ return `- "${d.name}" (deliveryId ${d.deliveryId}, ${d.executionStatus}${arm})`;
31
+ }
32
+ function contextSection(ctx) {
33
+ const out = ['## The focus, and the arm (the criteria it stamped and where they stand)', ''];
34
+ out.push(ctx.focusContext.trim() === '' ? '(The focus context could not be assembled.)' : ctx.focusContext.trim(), '');
35
+ out.push('### Deliveries', '');
36
+ if (ctx.deliveries.length === 0)
37
+ out.push('(none readable)');
38
+ for (const d of ctx.deliveries)
39
+ out.push(deliveryLine(d));
40
+ out.push('', '## The product\'s standing decisions', '');
41
+ const sd = ctx.standingDecisions;
42
+ if (sd.source === null)
43
+ out.push('This product keeps no decisions log the daemon could find. Decide from the focus alone.');
44
+ else {
45
+ out.push(`From ${sd.source}${sd.truncated ? ' (newest entries; cut at the size cap -- read the file for older ones)' : ''}. What is ruled here is not re-decided.`, '', sd.text);
46
+ }
47
+ out.push('');
48
+ if (ctx.readErrors.length > 0)
49
+ out.push('## What you were NOT given (a read failed)', '', ...ctx.readErrors.map((e) => `- ${e}`), '');
50
+ return out;
51
+ }
52
+ function instructionsSection(input) {
53
+ const { escalation: e, supervisorSessionId: sid } = input;
54
+ const ids = `escalationId "${e.escalationId}", agentSessionId "${sid}"`;
55
+ return [
56
+ '## What you do, in order',
57
+ '',
58
+ '1. **Read the ask.** What does the team need decided, and what does it recommend? Read the code it names in',
59
+ ' this worktree if that is how you judge it (read only).',
60
+ '2. **Judge it against the scope the team is solving for**: the focus\'s intent, the criteria its arm stamped, the',
61
+ ' deliveries the arm covers, and the standing decisions above. A path is within scope when it serves that intent',
62
+ ' inside those criteria and decisions -- most escalations are: a fork the team could act on but would not decide',
63
+ ' alone. Prefer the team\'s own recommendation when it is within scope; when two paths are, prefer the one that',
64
+ ' is reversible.',
65
+ '3. **When you can recommend a path within that scope, ANSWER it** with `telora_agent` action "escalation_answer":',
66
+ ` ${ids}, answer (addressed to the team, imperative: what to do, and any condition), summary (WHAT you`,
67
+ ' decided), rationale (WHY it is within scope), decisionEvidence { recommendation: "team" | "supervisor",',
68
+ ' criteria: [the criteria it rests on], standingDecisions: [the entries it cites], alternatives: [what you',
69
+ ' rejected and why] }. That one call resolves the escalation, records escalation_answered on the focus, and',
70
+ ' the daemon hands your answer to the team (its live session now, or its next spawn).',
71
+ '4. **DEFER it to the operator** with `telora_agent` action "escalation_defer" (' + ids + ', summary,',
72
+ ' rationale) -- the escalation then stands in the operator\'s inbox -- when any of these holds:',
73
+ ' - it asks for a MAJOR NEW BUILD: a new capability, product surface or focus beyond what the arm covers;',
74
+ ' - the intent is genuinely open: the focus and the standing decisions leave two readings that change the',
75
+ ' outcome, and neither is clearly the team\'s scope;',
76
+ ' - it needs a human act after all (something irreversible, outward, or a credential no agent reaches);',
77
+ ' - you feel a human is needed. When in doubt between answering and deferring, DEFER.',
78
+ '',
79
+ ];
80
+ }
81
+ function boundariesSection() {
82
+ return [
83
+ '## What you never do',
84
+ '',
85
+ '- You hold NO budget lever. You cannot grant review cycles, extend a budget, re-arm, un-arm or stop the',
86
+ ' focus; your Telora tools do not offer it. An answer never widens the arm: new intent is the operator\'s.',
87
+ '- You do not amend a criterion, write code, commit, or file a new escalation for this one: answering or',
88
+ ' deferring THIS escalation is the whole act.',
89
+ '- You do not lower the bar to unblock the team: an answer that drops a stamped criterion is a deferral.',
90
+ '- You decide exactly once: one escalation_answer OR one escalation_defer.',
91
+ '',
92
+ `End with one line: \`${TOWER_ESCALATION_LINE_PREFIX} answered\` or \`${TOWER_ESCALATION_LINE_PREFIX} deferred\`.`,
93
+ ];
94
+ }
95
+ /** Pure: the whole escalation prompt. */
96
+ export function buildTowerEscalationPrompt(input) {
97
+ const { focus } = input;
98
+ return [
99
+ `# Tower supervisor: answer a team escalation on "${focus.focusName}"`,
100
+ '',
101
+ 'You are the Tower supervisor. A team working this armed focus escalated a question. The operator ruled that',
102
+ 'you answer what lies within the scope the team is solving for -- usually by authorizing the team\'s own',
103
+ 'recommendation -- WITHOUT the operator, and that every decision you make is recorded on the focus (what, why,',
104
+ 'and the evidence), where the dashboard shows it. Only what you cannot answer, or a major new build, goes to',
105
+ 'the operator.',
106
+ '',
107
+ `Focus: "${focus.focusName}" (focusId ${focus.focusId}, productId ${focus.productId})`,
108
+ ...(focus.focusDescription ? ['', fence(focus.focusDescription)] : []),
109
+ '',
110
+ ...escalationSection(input),
111
+ ...contextSection(input.context),
112
+ ...instructionsSection(input),
113
+ ...boundariesSection(),
114
+ ].join('\n');
115
+ }
116
+ /** Pure: the decision the session's last line states, or null. Informational: the record decides. */
117
+ export function parseTowerEscalationLine(stdout) {
118
+ for (const line of stdout.trim().split('\n').reverse()) {
119
+ const at = line.indexOf(TOWER_ESCALATION_LINE_PREFIX);
120
+ if (at === -1)
121
+ continue;
122
+ const word = line.slice(at + TOWER_ESCALATION_LINE_PREFIX.length).trim().replace(/[`*.]/g, '').toLowerCase();
123
+ if (word.startsWith('answered'))
124
+ return 'answered';
125
+ if (word.startsWith('deferred'))
126
+ return 'deferred';
127
+ }
128
+ return null;
129
+ }
130
+ //# sourceMappingURL=tower-escalation-prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tower-escalation-prompt.js","sourceRoot":"","sources":["../../src/tower/tower-escalation-prompt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * THE ROUTING TABLE for a team escalation pending on the Tower supervisor: does
3
+ * the supervisor decide it, or does the daemon hand it straight to the
4
+ * operator? Pure; the one place the rule is written (product-api stamps the
5
+ * candidates -- a team filing on an armed focus -- and this decides each).
6
+ *
7
+ * -> the OPERATOR, with no supervisor session, when
8
+ * human_act the filing names a human-only act (metadata.human_act
9
+ * kind irreversible | outward | unreachable_capability):
10
+ * no agent can perform it, so no agent should hold it;
11
+ * external_wait the filing waits on a third party: not a judgement call;
12
+ * unarmed the focus is no longer armed (no assigned agent role):
13
+ * the supervisor decides within the scope an ARM authorised;
14
+ * focus_closed the focus is not active on a product this daemon runs.
15
+ * -> the SUPERVISOR otherwise. Whether it then answers (a path within the
16
+ * scope the team is solving for) or defers (a major new build, or it feels
17
+ * a human is needed) is its judgement, told in tower/tower-escalation-prompt.ts.
18
+ *
19
+ * @module tower/tower-escalation-routing
20
+ */
21
+ /** The human-only act kinds (mcp telora_agent humanAct.kind). */
22
+ export declare const HUMAN_ACT_KINDS: readonly string[];
23
+ /** Why an escalation goes straight to the operator. */
24
+ export type OperatorRouteReason = 'human_act' | 'external_wait' | 'unarmed' | 'focus_closed';
25
+ /** Where one pending escalation goes. */
26
+ export type TowerEscalationRoute = {
27
+ route: 'supervisor';
28
+ } | {
29
+ route: 'operator';
30
+ reason: OperatorRouteReason;
31
+ detail: string;
32
+ };
33
+ /** The facts the routing reads. */
34
+ export interface RoutingFacts {
35
+ disposition: string | null;
36
+ metadata: Record<string, unknown>;
37
+ /** The escalation's focus as this daemon runs it: null when it is not an active focus of a configured product. */
38
+ focus: {
39
+ armed: boolean;
40
+ } | null;
41
+ }
42
+ /** Pure: the human-only act a filing names, or null. */
43
+ export declare function humanActOf(metadata: Record<string, unknown>): {
44
+ kind: string;
45
+ act: string;
46
+ } | null;
47
+ /** Pure: route one pending team escalation. */
48
+ export declare function routeTeamEscalation(facts: RoutingFacts): TowerEscalationRoute;
49
+ //# sourceMappingURL=tower-escalation-routing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tower-escalation-routing.d.ts","sourceRoot":"","sources":["../../src/tower/tower-escalation-routing.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,iEAAiE;AACjE,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAA0D,CAAC;AAExG,uDAAuD;AACvD,MAAM,MAAM,mBAAmB,GAAG,WAAW,GAAG,eAAe,GAAG,SAAS,GAAG,cAAc,CAAC;AAE7F,yCAAyC;AACzC,MAAM,MAAM,oBAAoB,GAC5B;IAAE,KAAK,EAAE,YAAY,CAAA;CAAE,GACvB;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvE,mCAAmC;AACnC,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,kHAAkH;IAClH,KAAK,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;CAClC;AAED,wDAAwD;AACxD,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAMlG;AAED,+CAA+C;AAC/C,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,oBAAoB,CAe7E"}
@@ -0,0 +1,53 @@
1
+ // PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
2
+ // Pinned by: packages/daemon/src/tower/tower-escalation-prompt.test.ts
3
+ // PINNED-BY-END
4
+ /**
5
+ * THE ROUTING TABLE for a team escalation pending on the Tower supervisor: does
6
+ * the supervisor decide it, or does the daemon hand it straight to the
7
+ * operator? Pure; the one place the rule is written (product-api stamps the
8
+ * candidates -- a team filing on an armed focus -- and this decides each).
9
+ *
10
+ * -> the OPERATOR, with no supervisor session, when
11
+ * human_act the filing names a human-only act (metadata.human_act
12
+ * kind irreversible | outward | unreachable_capability):
13
+ * no agent can perform it, so no agent should hold it;
14
+ * external_wait the filing waits on a third party: not a judgement call;
15
+ * unarmed the focus is no longer armed (no assigned agent role):
16
+ * the supervisor decides within the scope an ARM authorised;
17
+ * focus_closed the focus is not active on a product this daemon runs.
18
+ * -> the SUPERVISOR otherwise. Whether it then answers (a path within the
19
+ * scope the team is solving for) or defers (a major new build, or it feels
20
+ * a human is needed) is its judgement, told in tower/tower-escalation-prompt.ts.
21
+ *
22
+ * @module tower/tower-escalation-routing
23
+ */
24
+ /** The human-only act kinds (mcp telora_agent humanAct.kind). */
25
+ export const HUMAN_ACT_KINDS = ['irreversible', 'outward', 'unreachable_capability'];
26
+ /** Pure: the human-only act a filing names, or null. */
27
+ export function humanActOf(metadata) {
28
+ const raw = metadata.human_act;
29
+ if (raw === null || typeof raw !== 'object' || Array.isArray(raw))
30
+ return null;
31
+ const { kind, act } = raw;
32
+ if (typeof kind !== 'string' || !HUMAN_ACT_KINDS.includes(kind))
33
+ return null;
34
+ return { kind, act: typeof act === 'string' ? act : '' };
35
+ }
36
+ /** Pure: route one pending team escalation. */
37
+ export function routeTeamEscalation(facts) {
38
+ const act = humanActOf(facts.metadata);
39
+ if (act) {
40
+ return { route: 'operator', reason: 'human_act', detail: `it names a human-only act (${act.kind}): ${act.act || '(unstated)'}` };
41
+ }
42
+ if (facts.disposition === 'external_wait') {
43
+ return { route: 'operator', reason: 'external_wait', detail: 'it waits on a third party, which no judgement answers' };
44
+ }
45
+ if (facts.focus === null) {
46
+ return { route: 'operator', reason: 'focus_closed', detail: 'its focus is not an active focus this daemon runs' };
47
+ }
48
+ if (!facts.focus.armed) {
49
+ return { route: 'operator', reason: 'unarmed', detail: 'its focus is no longer armed, so no arm bounds what the supervisor may decide' };
50
+ }
51
+ return { route: 'supervisor' };
52
+ }
53
+ //# sourceMappingURL=tower-escalation-routing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tower-escalation-routing.js","sourceRoot":"","sources":["../../src/tower/tower-escalation-routing.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,uEAAuE;AACvE,gBAAgB;AAEhB;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,iEAAiE;AACjE,MAAM,CAAC,MAAM,eAAe,GAAsB,CAAC,cAAc,EAAE,SAAS,EAAE,wBAAwB,CAAC,CAAC;AAkBxG,wDAAwD;AACxD,MAAM,UAAU,UAAU,CAAC,QAAiC;IAC1D,MAAM,GAAG,GAAG,QAAQ,CAAC,SAAS,CAAC;IAC/B,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/E,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,GAAwC,CAAC;IAC/D,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7E,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AAC3D,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,mBAAmB,CAAC,KAAmB;IACrD,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,GAAG,EAAE,CAAC;QACR,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,8BAA8B,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,GAAG,IAAI,YAAY,EAAE,EAAE,CAAC;IACnI,CAAC;IACD,IAAI,KAAK,CAAC,WAAW,KAAK,eAAe,EAAE,CAAC;QAC1C,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,uDAAuD,EAAE,CAAC;IACzH,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,mDAAmD,EAAE,CAAC;IACpH,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACvB,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,+EAA+E,EAAE,CAAC;IAC3I,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;AACjC,CAAC"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * THE TOWER SUPERVISOR FOR TEAM ESCALATIONS: a team's escalation is answered by
3
+ * the Tower supervisor, and reaches the operator only when the supervisor cannot
4
+ * answer it.
5
+ *
6
+ * WHO OWNS WHICH ESCALATION (the reconcile with the routing decider,
7
+ * supervision/agent-resolvable-promotion.ts). The routing decider keeps the
8
+ * DAEMON-filed observations (the machine lane). The supervisor takes the
9
+ * TEAM-filed escalations: product-api escalation_create stamps tower_state
10
+ * 'pending' on a team filing (agent_filed) on an armed focus, and both the coding
11
+ * spawn's ride-in and the decider's sweep skip a Tower-routed row
12
+ * (queries/escalations/escalation-consumption.ts isTowerRoutedRow). One owner
13
+ * per row, no second lane.
14
+ *
15
+ * ONE SWEEP (sweep(), registered in focus/focus-loop-registry.ts under the
16
+ * escalation-lane gate, not TELORA_FOCUS_LOOP: escalations are filed whether or
17
+ * not the differential loop runs) reads the org's pending rows of the products
18
+ * this daemon runs and, per row:
19
+ * - routes it (tower/tower-escalation-routing.ts): a human act, an
20
+ * external_wait, an un-armed or closed focus -> the daemon defers it to the
21
+ * operator with the reason (daemon_escalation_tower_defer records
22
+ * escalation_deferred), no session spent;
23
+ * - otherwise starts ONE one-shot supervisor session for it (the review-loop
24
+ * supervisor's process, spawn/routing-decider-spawn.ts
25
+ * spawnOneShotJudgementSession, opus, a governor slot, the scoped
26
+ * `tower_supervisor` MCP profile) in the background. The session answers it
27
+ * (telora_agent escalation_answer) or defers it (escalation_defer); each is
28
+ * one attributed edge act that records the decision on the focus.
29
+ *
30
+ * AFTER A SESSION the daemon reads the row:
31
+ * - answered -> the answer reaches the team: injected into its live session now
32
+ * (spawn/live-answer-delivery.ts), else read back at its next spawn through
33
+ * the answer re-arm signal the answer wrote; a decision record the edge
34
+ * failed to write is backstopped here (escalation_answered, by the daemon).
35
+ * - deferred -> it stands in the operator's inbox.
36
+ * - still pending: a session that CRASHED or timed out -> deferred at once
37
+ * ("crash -> the operator"); one that exited cleanly without deciding is an
38
+ * attempt, and after TOWER_ESCALATION_MAX_ATTEMPTS it is deferred. A session
39
+ * that never ran (no slot, the model unavailable, no scoped MCP) is not an
40
+ * attempt: the next sweep retries. Attempts are counted in memory.
41
+ *
42
+ * @module tower/tower-escalation-session
43
+ */
44
+ import type { ResourceGovernor } from '@telora/daemon-core';
45
+ import type { DaemonConfig } from '../types/index.js';
46
+ import type { TowerDecision, TowerDecisionInput } from '../queries/tower-decisions/tower-decisions.js';
47
+ import type { TowerDeferral, TowerEscalationState, TowerPendingEscalation } from '../queries/escalations/tower-escalations.js';
48
+ import { type TowerEscalationRoute } from './tower-escalation-routing.js';
49
+ import { type EscalationContext } from './tower-escalation-prompt.js';
50
+ import type { TowerSupervisorSpawnResult } from './tower-supervisor-session.js';
51
+ /** Sessions that ran cleanly without deciding, per escalation, before the daemon defers it. */
52
+ export declare const TOWER_ESCALATION_MAX_ATTEMPTS = 2;
53
+ /** Kill an escalation session that has not exited within this window. */
54
+ export declare const TOWER_ESCALATION_TIMEOUT_MS: number;
55
+ /** Governor engine for escalation sessions (bounded by the global session cap, as the loop supervisor's). */
56
+ export declare const TOWER_ESCALATION_GOVERNOR_ENGINE = "tower-supervisor";
57
+ /**
58
+ * Tools the escalation session is pre-approved for: reading the worktree, and
59
+ * the Telora reads plus the two acts it decides through (telora_agent
60
+ * escalation_answer / escalation_defer). Pre-approval only; the scoped MCP
61
+ * profile is the bound.
62
+ */
63
+ export declare const TOWER_ESCALATION_MCP_TOOLS: readonly string[];
64
+ /** A focus as the escalation supervisor reads it. */
65
+ export interface TowerEscalationFocus {
66
+ focusId: string;
67
+ focusName: string;
68
+ focusDescription: string | null;
69
+ productId: string;
70
+ armed: boolean;
71
+ /** The arm's baseline deliveries (product_focuses.armed_baseline_delivery_ids), or null when none is recorded. */
72
+ armedBaselineDeliveryIds: readonly string[] | null;
73
+ }
74
+ /** What one escalation session is spawned with. */
75
+ export interface TowerEscalationSpawnOptions {
76
+ config: DaemonConfig;
77
+ prompt: string;
78
+ cwd: string;
79
+ focusId: string;
80
+ escalationId: string;
81
+ model: string;
82
+ timeoutMs: number;
83
+ allowedTools: readonly string[];
84
+ }
85
+ /** The collaborators, all required, bound at the composition root. */
86
+ export interface TowerEscalationSupervisorDeps {
87
+ readConfig: () => DaemonConfig | null;
88
+ productConfig: (config: DaemonConfig, productId: string) => DaemonConfig | null;
89
+ readGovernor: () => Pick<ResourceGovernor, 'tryAcquireSlot' | 'releaseSlot'> | null;
90
+ listPending: () => Promise<TowerPendingEscalation[]>;
91
+ readEscalation: (escalationId: string) => Promise<TowerEscalationState>;
92
+ defer: (deferral: TowerDeferral) => Promise<{
93
+ towerDecisionId: string | null;
94
+ }>;
95
+ /** The active focuses of one product this daemon runs. */
96
+ listFocuses: (productId: string) => Promise<TowerEscalationFocus[]>;
97
+ focusWorktreePath: (focusId: string) => string | null;
98
+ gatherContext: (args: {
99
+ focus: TowerEscalationFocus;
100
+ config: DaemonConfig;
101
+ repoRoot: string;
102
+ }) => Promise<EscalationContext>;
103
+ spawn: (opts: TowerEscalationSpawnOptions) => Promise<TowerSupervisorSpawnResult>;
104
+ /** Inject the focus's unconsumed answers into its live team (spawn/live-answer-delivery.ts). */
105
+ deliverAnswer: (args: {
106
+ focusId: string;
107
+ rearmValues: readonly string[];
108
+ }) => Promise<{
109
+ delivered: boolean;
110
+ detail?: string;
111
+ }>;
112
+ listTowerDecisions: (focusId: string) => Promise<{
113
+ decisions: TowerDecision[];
114
+ openLoopDecisionIds: string[];
115
+ }>;
116
+ recordTowerDecision: (input: TowerDecisionInput) => Promise<{
117
+ decision: TowerDecision;
118
+ created: boolean;
119
+ }>;
120
+ newSessionId: () => string;
121
+ model: string;
122
+ }
123
+ /** What one sweep did. */
124
+ export interface TowerEscalationSweepCounts {
125
+ pending: number;
126
+ started: number;
127
+ inFlight: number;
128
+ deferred: number;
129
+ skipped: number;
130
+ unreadable: number;
131
+ }
132
+ /** Pure: whether a session that ran ended abnormally (crash or kill): straight to the operator. */
133
+ export declare function crashed(result: TowerSupervisorSpawnResult): boolean;
134
+ /** Pure: the deferral the daemon records for a route straight to the operator. */
135
+ export declare function operatorRouteDeferral(route: Extract<TowerEscalationRoute, {
136
+ route: 'operator';
137
+ }>): Pick<TowerDeferral, 'summary' | 'rationale' | 'evidence'>;
138
+ /** Pure: whether a pending row belongs to a product this daemon runs. */
139
+ export declare function ownedByThisDaemon(esc: Pick<TowerPendingEscalation, 'productId' | 'focusId'>, productIds: ReadonlySet<string>, focusIds: ReadonlySet<string>): boolean;
140
+ /** The escalation half of the Tower supervisor (one per process). */
141
+ export interface TowerEscalationSupervisor {
142
+ sweep(): Promise<TowerEscalationSweepCounts>;
143
+ }
144
+ /** Build it (the composition root binds one per process). */
145
+ export declare function createTowerEscalationSupervisor(deps: TowerEscalationSupervisorDeps): TowerEscalationSupervisor & {
146
+ /** Test seam: resolves once every session started so far has finished. */
147
+ settled(): Promise<void>;
148
+ };
149
+ //# sourceMappingURL=tower-escalation-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tower-escalation-session.d.ts","sourceRoot":"","sources":["../../src/tower/tower-escalation-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,238 @@
1
+ // PINNED-BY-BEGIN (generated by gen:pinned-by -- do not hand-edit; checked by lint:pinned-by)
2
+ // Pinned by: packages/daemon/src/tower/tower-escalation-session.test.ts
3
+ // PINNED-BY-END
4
+ import { createLogger } from '../log/daemon-log.js';
5
+ import { routeTeamEscalation } from './tower-escalation-routing.js';
6
+ import { buildTowerEscalationPrompt, parseTowerEscalationLine } from './tower-escalation-prompt.js';
7
+ const log = createLogger({ module: 'tower' });
8
+ /** Sessions that ran cleanly without deciding, per escalation, before the daemon defers it. */
9
+ export const TOWER_ESCALATION_MAX_ATTEMPTS = 2;
10
+ /** Kill an escalation session that has not exited within this window. */
11
+ export const TOWER_ESCALATION_TIMEOUT_MS = 20 * 60 * 1000;
12
+ /** Governor engine for escalation sessions (bounded by the global session cap, as the loop supervisor's). */
13
+ export const TOWER_ESCALATION_GOVERNOR_ENGINE = 'tower-supervisor';
14
+ /**
15
+ * Tools the escalation session is pre-approved for: reading the worktree, and
16
+ * the Telora reads plus the two acts it decides through (telora_agent
17
+ * escalation_answer / escalation_defer). Pre-approval only; the scoped MCP
18
+ * profile is the bound.
19
+ */
20
+ export const TOWER_ESCALATION_MCP_TOOLS = [
21
+ 'Read', 'Grep', 'Glob',
22
+ 'mcp__telora-products__telora_agent',
23
+ 'mcp__telora-products__telora_product_focus',
24
+ 'mcp__telora-products__telora_product_issue',
25
+ 'mcp__telora-products__telora_product_delivery',
26
+ 'mcp__telora-products__telora_product_tower',
27
+ 'mcp__telora-products__telora_reality_tree_traverse',
28
+ 'mcp__telora-products__telora_wiki_search',
29
+ ];
30
+ function emptyCounts() {
31
+ return { pending: 0, started: 0, inFlight: 0, deferred: 0, skipped: 0, unreadable: 0 };
32
+ }
33
+ /** Pure: whether a finished spawn ran at all (an unrun session is retried, uncounted). */
34
+ function ran(result) {
35
+ return result.started && result.modelUnavailable === undefined;
36
+ }
37
+ /** Pure: whether a session that ran ended abnormally (crash or kill): straight to the operator. */
38
+ export function crashed(result) {
39
+ return ran(result) && (result.timedOut || (result.exitCode !== null && result.exitCode !== 0));
40
+ }
41
+ function describeEnd(result) {
42
+ if (result.modelUnavailable)
43
+ return `model unavailable (${result.modelUnavailable.kind})`;
44
+ if (!result.started)
45
+ return result.errorMessage ?? 'did not start';
46
+ if (result.timedOut)
47
+ return 'timed out (killed)';
48
+ const said = parseTowerEscalationLine(result.stdout);
49
+ return `exited ${result.exitCode ?? 'null'}${said ? `; said "${said}"` : ''}`;
50
+ }
51
+ async function deferAs(st, esc, summary, rationale, evidence) {
52
+ const { towerDecisionId } = await st.deps.defer({ escalationId: esc.escalationId, summary, rationale, evidence });
53
+ st.attempts.delete(esc.escalationId);
54
+ log.info(`[tower-escalation] handed escalation ${esc.escalationId.slice(0, 8)} to the operator: ${summary} (decision ${towerDecisionId?.slice(0, 8) ?? 'unrecorded'}).`);
55
+ }
56
+ /** Pure: the deferral the daemon records for a route straight to the operator. */
57
+ export function operatorRouteDeferral(route) {
58
+ return {
59
+ summary: `Handed to the operator without a supervisor session: ${route.detail}.`,
60
+ rationale: 'The Tower supervisor answers what lies within the scope a team is solving for under an arm; this escalation ' +
61
+ `is outside what any agent can settle (${route.reason}), so it goes to the operator as filed.`,
62
+ evidence: { route: route.reason, detail: route.detail },
63
+ };
64
+ }
65
+ /** Answered: hand the answer to the live team, and backstop the decision record. */
66
+ async function onAnswered(st, esc, focusId, now, sessionId) {
67
+ const delivery = await st.deps.deliverAnswer({ focusId, rearmValues: now.answeredAt ? [now.answeredAt] : [] });
68
+ log.info(`[tower-escalation] the supervisor answered escalation ${esc.escalationId.slice(0, 8)}; ` +
69
+ (delivery.delivered ? 'injected into the live team.' : `no live team took it (${delivery.detail ?? 'none'}); it is read back at the next spawn.`));
70
+ const record = await st.deps.listTowerDecisions(focusId);
71
+ if (record.decisions.some((d) => d.kind === 'escalation_answered' && d.escalationId === esc.escalationId))
72
+ return;
73
+ await st.deps.recordTowerDecision({
74
+ focusId, kind: 'escalation_answered', decidedByKind: 'daemon', escalationId: esc.escalationId,
75
+ summary: 'The Tower supervisor answered this escalation; its own decision record did not land.',
76
+ rationale: 'Recorded by the daemon so the answer is on the focus record; the answer text is on the escalation.',
77
+ evidence: { supervisorSessionId: sessionId, answeredAt: now.answeredAt },
78
+ });
79
+ }
80
+ /** After a session exits: deliver an answer, leave a deferral, defer a crash, count an undecided run. */
81
+ async function settle(st, esc, focus, result, sessionId) {
82
+ const detail = describeEnd(result);
83
+ const now = await st.deps.readEscalation(esc.escalationId);
84
+ if (now.towerState === 'answered') {
85
+ st.attempts.delete(esc.escalationId);
86
+ await onAnswered(st, esc, focus.focusId, now, sessionId);
87
+ return;
88
+ }
89
+ if (now.towerState !== 'pending' || !['pending', 'in_review'].includes(now.status)) {
90
+ st.attempts.delete(esc.escalationId);
91
+ return;
92
+ }
93
+ if (!ran(result)) {
94
+ log.info(`[tower-escalation] supervisor for ${esc.escalationId.slice(0, 8)} did not run (${detail}); the next sweep retries.`);
95
+ return;
96
+ }
97
+ const evidence = { supervisorSessionId: sessionId, lastDetail: detail };
98
+ if (crashed(result)) {
99
+ await deferAs(st, esc, `The Tower supervisor session ended abnormally (${detail}); handed to the operator.`, 'A supervisor that crashed decided nothing; the escalation is left for the operator rather than retried blind.', evidence);
100
+ return;
101
+ }
102
+ const tried = (st.attempts.get(esc.escalationId) ?? 0) + 1;
103
+ st.attempts.set(esc.escalationId, tried);
104
+ log.warn(`[tower-escalation] supervisor for ${esc.escalationId.slice(0, 8)} ${detail} without deciding (attempt ${tried} of ${TOWER_ESCALATION_MAX_ATTEMPTS}).`);
105
+ if (tried >= TOWER_ESCALATION_MAX_ATTEMPTS) {
106
+ await deferAs(st, esc, `The Tower supervisor ran ${tried} time(s) without deciding; handed to the operator.`, 'No session answered or deferred it; the daemon stops spending sessions on it and the operator decides.', { ...evidence, attempts: tried });
107
+ }
108
+ }
109
+ /** One session inside a governor slot: gather, prompt, spawn, settle. */
110
+ async function runSession(st, esc, focus, config) {
111
+ const governor = st.deps.readGovernor();
112
+ let token = null;
113
+ if (governor) {
114
+ token = governor.tryAcquireSlot(TOWER_ESCALATION_GOVERNOR_ENGINE);
115
+ if (!token) {
116
+ log.info(`[tower-escalation] no governor slot free for ${esc.escalationId.slice(0, 8)}; the next sweep retries.`);
117
+ return;
118
+ }
119
+ }
120
+ try {
121
+ const repoRoot = st.deps.focusWorktreePath(focus.focusId) ?? config.repoPath;
122
+ const context = await st.deps.gatherContext({ focus, config, repoRoot });
123
+ const supervisorSessionId = st.deps.newSessionId();
124
+ const prompt = buildTowerEscalationPrompt({ focus, escalation: esc, supervisorSessionId, context });
125
+ log.info(`[tower-escalation] deciding escalation ${esc.escalationId.slice(0, 8)} of "${focus.focusName}" (session ${supervisorSessionId.slice(0, 8)}).`);
126
+ const result = await st.deps.spawn({
127
+ config, prompt, cwd: repoRoot, focusId: focus.focusId, escalationId: esc.escalationId,
128
+ model: st.deps.model, timeoutMs: TOWER_ESCALATION_TIMEOUT_MS, allowedTools: TOWER_ESCALATION_MCP_TOOLS,
129
+ });
130
+ await settle(st, esc, focus, result, supervisorSessionId);
131
+ }
132
+ finally {
133
+ if (token && governor)
134
+ governor.releaseSlot(token);
135
+ }
136
+ }
137
+ /** One step for one pending escalation. Never throws. */
138
+ async function step(st, esc, focuses, config) {
139
+ if (st.inFlight.has(esc.escalationId))
140
+ return 'in_flight';
141
+ try {
142
+ const focus = esc.focusId ? focuses.get(esc.focusId) ?? null : null;
143
+ const route = routeTeamEscalation({ disposition: esc.disposition, metadata: esc.metadata, focus });
144
+ if (route.route === 'operator') {
145
+ const d = operatorRouteDeferral(route);
146
+ await deferAs(st, esc, d.summary, d.rationale, d.evidence);
147
+ return 'deferred';
148
+ }
149
+ if (!focus)
150
+ return 'skipped';
151
+ const scoped = st.deps.productConfig(config, focus.productId);
152
+ if (!scoped)
153
+ return 'skipped';
154
+ if ((st.attempts.get(esc.escalationId) ?? 0) >= TOWER_ESCALATION_MAX_ATTEMPTS) {
155
+ await deferAs(st, esc, 'The Tower supervisor could not decide it; handed to the operator.', 'Its attempts ran out before a restart of this sweep could hand it on.', { attempts: st.attempts.get(esc.escalationId) });
156
+ return 'deferred';
157
+ }
158
+ const run = runSession(st, esc, focus, scoped)
159
+ .catch((err) => log.warn(`[tower-escalation] supervision of ${esc.escalationId.slice(0, 8)} failed: ${err.message}; the next sweep retries.`))
160
+ .finally(() => st.inFlight.delete(esc.escalationId));
161
+ st.inFlight.set(esc.escalationId, run);
162
+ return 'started';
163
+ }
164
+ catch (err) {
165
+ log.warn(`[tower-escalation] could not route escalation ${esc.escalationId.slice(0, 8)}: ${err.message}; the next sweep retries.`);
166
+ return 'unreadable';
167
+ }
168
+ }
169
+ /** Pure: whether a pending row belongs to a product this daemon runs. */
170
+ export function ownedByThisDaemon(esc, productIds, focusIds) {
171
+ if (esc.productId !== null)
172
+ return productIds.has(esc.productId);
173
+ return esc.focusId !== null && focusIds.has(esc.focusId);
174
+ }
175
+ async function readFocuses(st, config, counts) {
176
+ const focuses = new Map();
177
+ for (const product of config.products) {
178
+ try {
179
+ for (const f of await st.deps.listFocuses(product.id))
180
+ focuses.set(f.focusId, f);
181
+ }
182
+ catch (err) {
183
+ log.warn(`[tower-escalation] focus read failed for product ${product.id.slice(0, 8)}: ${err.message}`);
184
+ counts.unreadable += 1;
185
+ return null;
186
+ }
187
+ }
188
+ return focuses;
189
+ }
190
+ /** Sweep the pending team escalations of every configured product. */
191
+ async function sweepPending(st) {
192
+ const counts = emptyCounts();
193
+ const config = st.deps.readConfig();
194
+ if (!config)
195
+ return counts;
196
+ let pending;
197
+ try {
198
+ pending = await st.deps.listPending();
199
+ }
200
+ catch (err) {
201
+ log.warn(`[tower-escalation] pending read failed: ${err.message}`);
202
+ counts.unreadable += 1;
203
+ return counts;
204
+ }
205
+ if (pending.length === 0)
206
+ return counts;
207
+ // A focus read that fails routes nothing: an absent focus would read as closed and defer a live one.
208
+ const focuses = await readFocuses(st, config, counts);
209
+ if (!focuses)
210
+ return counts;
211
+ const productIds = new Set(config.products.map((p) => p.id));
212
+ for (const esc of pending) {
213
+ if (!ownedByThisDaemon(esc, productIds, new Set(focuses.keys())))
214
+ continue;
215
+ counts.pending += 1;
216
+ const outcome = await step(st, esc, focuses, config);
217
+ if (outcome === 'started')
218
+ counts.started += 1;
219
+ else if (outcome === 'in_flight')
220
+ counts.inFlight += 1;
221
+ else if (outcome === 'deferred')
222
+ counts.deferred += 1;
223
+ else if (outcome === 'unreadable')
224
+ counts.unreadable += 1;
225
+ else
226
+ counts.skipped += 1;
227
+ }
228
+ return counts;
229
+ }
230
+ /** Build it (the composition root binds one per process). */
231
+ export function createTowerEscalationSupervisor(deps) {
232
+ const st = { deps, inFlight: new Map(), attempts: new Map() };
233
+ return {
234
+ sweep: () => sweepPending(st),
235
+ settled: async () => { await Promise.all([...st.inFlight.values()]); },
236
+ };
237
+ }
238
+ //# sourceMappingURL=tower-escalation-session.js.map