@telora/daemon 0.23.1 → 0.23.5

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 (298) hide show
  1. package/build-info.json +6 -3
  2. package/dist/completion/review-exit/review-exit-deps.d.ts +2 -1
  3. package/dist/completion/review-exit/review-exit-deps.d.ts.map +1 -1
  4. package/dist/completion/review-exit/review-exit-phase.d.ts.map +1 -1
  5. package/dist/completion/review-exit/review-exit-phase.js +5 -4
  6. package/dist/completion/review-exit/review-exit-phase.js.map +1 -1
  7. package/dist/completion/review-exit-holds/review-exit-verdict-gate.d.ts +2 -1
  8. package/dist/completion/review-exit-holds/review-exit-verdict-gate.d.ts.map +1 -1
  9. package/dist/completion/review-exit-holds/review-exit-verdict-gate.js +8 -5
  10. package/dist/completion/review-exit-holds/review-exit-verdict-gate.js.map +1 -1
  11. package/dist/completion/state-cascade/review-next-step.d.ts.map +1 -1
  12. package/dist/completion/state-cascade/review-next-step.js +15 -8
  13. package/dist/completion/state-cascade/review-next-step.js.map +1 -1
  14. package/dist/completion/team-exit/status-advance-phase.d.ts.map +1 -1
  15. package/dist/completion/team-exit/status-advance-phase.js +6 -6
  16. package/dist/completion/team-exit/status-advance-phase.js.map +1 -1
  17. package/dist/completion/team-liveness/supervision-firing-record.d.ts +6 -0
  18. package/dist/completion/team-liveness/supervision-firing-record.d.ts.map +1 -1
  19. package/dist/completion/team-liveness/supervision-firing-record.js +10 -1
  20. package/dist/completion/team-liveness/supervision-firing-record.js.map +1 -1
  21. package/dist/completion/team-outcome/decide-close-rows.d.ts +9 -0
  22. package/dist/completion/team-outcome/decide-close-rows.d.ts.map +1 -1
  23. package/dist/completion/team-outcome/decide-close-rows.js +18 -4
  24. package/dist/completion/team-outcome/decide-close-rows.js.map +1 -1
  25. package/dist/composition/completion-event-context.js +2 -2
  26. package/dist/composition/completion-event-context.js.map +1 -1
  27. package/dist/composition/daemon-contexts.d.ts.map +1 -1
  28. package/dist/composition/daemon-contexts.js +5 -1
  29. package/dist/composition/daemon-contexts.js.map +1 -1
  30. package/dist/composition/engine-start-context.d.ts +3 -0
  31. package/dist/composition/engine-start-context.d.ts.map +1 -0
  32. package/dist/composition/engine-start-context.js +24 -0
  33. package/dist/composition/engine-start-context.js.map +1 -0
  34. package/dist/composition/execution-spawn-context.d.ts.map +1 -1
  35. package/dist/composition/execution-spawn-context.js +13 -1
  36. package/dist/composition/execution-spawn-context.js.map +1 -1
  37. package/dist/composition/runtime-delivery-advance-context.js +3 -3
  38. package/dist/composition/runtime-delivery-advance-context.js.map +1 -1
  39. package/dist/composition/runtime-heartbeat-context.d.ts.map +1 -1
  40. package/dist/composition/runtime-heartbeat-context.js +3 -0
  41. package/dist/composition/runtime-heartbeat-context.js.map +1 -1
  42. package/dist/composition/runtime-poll-context.d.ts +29 -2
  43. package/dist/composition/runtime-poll-context.d.ts.map +1 -1
  44. package/dist/composition/runtime-poll-context.js +51 -4
  45. package/dist/composition/runtime-poll-context.js.map +1 -1
  46. package/dist/composition/runtime-prd-context.d.ts.map +1 -1
  47. package/dist/composition/runtime-prd-context.js +25 -1
  48. package/dist/composition/runtime-prd-context.js.map +1 -1
  49. package/dist/composition/runtime-spawn-pass-context.js +1 -1
  50. package/dist/composition/runtime-spawn-pass-context.js.map +1 -1
  51. package/dist/composition/spawn-pass-deps.d.ts +1 -1
  52. package/dist/composition/spawn-pass-deps.d.ts.map +1 -1
  53. package/dist/composition/spawn-pass-deps.js +3 -0
  54. package/dist/composition/spawn-pass-deps.js.map +1 -1
  55. package/dist/composition/standing-approval-context.d.ts.map +1 -1
  56. package/dist/composition/standing-approval-context.js +2 -1
  57. package/dist/composition/standing-approval-context.js.map +1 -1
  58. package/dist/composition/state-cascade-context.js +1 -1
  59. package/dist/composition/state-cascade-context.js.map +1 -1
  60. package/dist/composition/tower-pass-context.d.ts +9 -0
  61. package/dist/composition/tower-pass-context.d.ts.map +1 -0
  62. package/dist/composition/tower-pass-context.js +53 -0
  63. package/dist/composition/tower-pass-context.js.map +1 -0
  64. package/dist/composition/verify-rework-context.d.ts +26 -2
  65. package/dist/composition/verify-rework-context.d.ts.map +1 -1
  66. package/dist/composition/verify-rework-context.js +34 -10
  67. package/dist/composition/verify-rework-context.js.map +1 -1
  68. package/dist/config/live-daemon-config.d.ts.map +1 -1
  69. package/dist/config/live-daemon-config.js +1 -19
  70. package/dist/config/live-daemon-config.js.map +1 -1
  71. package/dist/daemon-state/awaiting-slot.d.ts.map +1 -1
  72. package/dist/daemon-state/awaiting-slot.js +2 -1
  73. package/dist/daemon-state/awaiting-slot.js.map +1 -1
  74. package/dist/daemon-state/focus-team-state.js +1 -1
  75. package/dist/daemon-state/intake-control.d.ts.map +1 -1
  76. package/dist/daemon-state/intake-control.js +2 -1
  77. package/dist/daemon-state/intake-control.js.map +1 -1
  78. package/dist/delivery/recorded-concerns.d.ts +19 -2
  79. package/dist/delivery/recorded-concerns.d.ts.map +1 -1
  80. package/dist/delivery/recorded-concerns.js +32 -6
  81. package/dist/delivery/recorded-concerns.js.map +1 -1
  82. package/dist/directive/directive-queue.js +1 -1
  83. package/dist/focus/closed-review-window.d.ts +12 -0
  84. package/dist/focus/closed-review-window.d.ts.map +1 -1
  85. package/dist/focus/closed-review-window.js +18 -0
  86. package/dist/focus/closed-review-window.js.map +1 -1
  87. package/dist/focus/control-state.d.ts +30 -26
  88. package/dist/focus/control-state.d.ts.map +1 -1
  89. package/dist/focus/control-state.js +60 -46
  90. package/dist/focus/control-state.js.map +1 -1
  91. package/dist/focus/daemon-contexts.d.ts +23 -0
  92. package/dist/focus/daemon-contexts.d.ts.map +1 -1
  93. package/dist/focus/daemon-contexts.js +1 -1
  94. package/dist/focus/daemon-contexts.js.map +1 -1
  95. package/dist/focus/engine-ready-pass.d.ts +11 -0
  96. package/dist/focus/engine-ready-pass.d.ts.map +1 -0
  97. package/dist/focus/engine-ready-pass.js +25 -0
  98. package/dist/focus/engine-ready-pass.js.map +1 -0
  99. package/dist/focus/failed-head-wedge.d.ts +95 -0
  100. package/dist/focus/failed-head-wedge.d.ts.map +1 -0
  101. package/dist/focus/failed-head-wedge.js +85 -0
  102. package/dist/focus/failed-head-wedge.js.map +1 -0
  103. package/dist/focus/focus-engine.d.ts.map +1 -1
  104. package/dist/focus/focus-engine.js +20 -20
  105. package/dist/focus/focus-engine.js.map +1 -1
  106. package/dist/focus/focus-loop-registry.d.ts.map +1 -1
  107. package/dist/focus/focus-loop-registry.js +2 -1
  108. package/dist/focus/focus-loop-registry.js.map +1 -1
  109. package/dist/focus/focus-poller-auto-advance.d.ts.map +1 -1
  110. package/dist/focus/focus-poller-auto-advance.js +4 -4
  111. package/dist/focus/focus-poller-auto-advance.js.map +1 -1
  112. package/dist/focus/focus-poller-spawn.d.ts +42 -49
  113. package/dist/focus/focus-poller-spawn.d.ts.map +1 -1
  114. package/dist/focus/focus-poller-spawn.js +129 -83
  115. package/dist/focus/focus-poller-spawn.js.map +1 -1
  116. package/dist/focus/focus-poller-state.d.ts.map +1 -1
  117. package/dist/focus/focus-poller-state.js +1 -19
  118. package/dist/focus/focus-poller-state.js.map +1 -1
  119. package/dist/focus/focus-poller.d.ts.map +1 -1
  120. package/dist/focus/focus-poller.js +2 -1
  121. package/dist/focus/focus-poller.js.map +1 -1
  122. package/dist/focus/focus-respawn-guard.d.ts +7 -0
  123. package/dist/focus/focus-respawn-guard.d.ts.map +1 -1
  124. package/dist/focus/focus-respawn-guard.js +20 -1
  125. package/dist/focus/focus-respawn-guard.js.map +1 -1
  126. package/dist/focus/focus-spawn-decision.d.ts +11 -3
  127. package/dist/focus/focus-spawn-decision.d.ts.map +1 -1
  128. package/dist/focus/focus-spawn-decision.js +3 -1
  129. package/dist/focus/focus-spawn-decision.js.map +1 -1
  130. package/dist/focus/heartbeat-metadata.d.ts +3 -0
  131. package/dist/focus/heartbeat-metadata.d.ts.map +1 -1
  132. package/dist/focus/heartbeat-metadata.js +6 -1
  133. package/dist/focus/heartbeat-metadata.js.map +1 -1
  134. package/dist/focus/heartbeat.d.ts.map +1 -1
  135. package/dist/focus/heartbeat.js +2 -0
  136. package/dist/focus/heartbeat.js.map +1 -1
  137. package/dist/focus/pending-directive-gates.d.ts +47 -0
  138. package/dist/focus/pending-directive-gates.d.ts.map +1 -0
  139. package/dist/focus/pending-directive-gates.js +76 -0
  140. package/dist/focus/pending-directive-gates.js.map +1 -0
  141. package/dist/focus/pending-review-approved-head.d.ts +2 -1
  142. package/dist/focus/pending-review-approved-head.d.ts.map +1 -1
  143. package/dist/focus/pending-review-approved-head.js +3 -4
  144. package/dist/focus/pending-review-approved-head.js.map +1 -1
  145. package/dist/focus/pending-spawn-pass-deps.d.ts +5 -0
  146. package/dist/focus/pending-spawn-pass-deps.d.ts.map +1 -1
  147. package/dist/focus/pending-spawn-pass-deps.js +4 -1
  148. package/dist/focus/pending-spawn-pass-deps.js.map +1 -1
  149. package/dist/focus/pending-spawn-verify-hold.d.ts +13 -0
  150. package/dist/focus/pending-spawn-verify-hold.d.ts.map +1 -0
  151. package/dist/focus/pending-spawn-verify-hold.js +30 -0
  152. package/dist/focus/pending-spawn-verify-hold.js.map +1 -0
  153. package/dist/focus/ready-focus-spawn-action.d.ts +15 -2
  154. package/dist/focus/ready-focus-spawn-action.d.ts.map +1 -1
  155. package/dist/focus/ready-focus-spawn-action.js +25 -8
  156. package/dist/focus/ready-focus-spawn-action.js.map +1 -1
  157. package/dist/focus/spawn-demand-probe.d.ts +45 -0
  158. package/dist/focus/spawn-demand-probe.d.ts.map +1 -0
  159. package/dist/focus/spawn-demand-probe.js +74 -0
  160. package/dist/focus/spawn-demand-probe.js.map +1 -0
  161. package/dist/focus/stranded-review-reroute.d.ts.map +1 -1
  162. package/dist/focus/stranded-review-reroute.js +5 -3
  163. package/dist/focus/stranded-review-reroute.js.map +1 -1
  164. package/dist/focus/verify-routing-passes.d.ts +8 -3
  165. package/dist/focus/verify-routing-passes.d.ts.map +1 -1
  166. package/dist/focus/verify-routing-passes.js +1 -0
  167. package/dist/focus/verify-routing-passes.js.map +1 -1
  168. package/dist/git/focus-branch-containment.d.ts +39 -0
  169. package/dist/git/focus-branch-containment.d.ts.map +1 -0
  170. package/dist/git/focus-branch-containment.js +47 -0
  171. package/dist/git/focus-branch-containment.js.map +1 -0
  172. package/dist/git/types.d.ts.map +1 -1
  173. package/dist/git/types.js +1 -0
  174. package/dist/git/types.js.map +1 -1
  175. package/dist/poll-trigger.js +1 -1
  176. package/dist/poll-trigger.js.map +1 -1
  177. package/dist/prd/arm-readiness.d.ts.map +1 -1
  178. package/dist/prd/arm-readiness.js +2 -1
  179. package/dist/prd/arm-readiness.js.map +1 -1
  180. package/dist/prd/controller-shared.d.ts +32 -8
  181. package/dist/prd/controller-shared.d.ts.map +1 -1
  182. package/dist/prd/controller-shared.js +34 -18
  183. package/dist/prd/controller-shared.js.map +1 -1
  184. package/dist/prd/controller.d.ts.map +1 -1
  185. package/dist/prd/controller.js +3 -8
  186. package/dist/prd/controller.js.map +1 -1
  187. package/dist/prd/done-sweep.d.ts.map +1 -1
  188. package/dist/prd/done-sweep.js +2 -7
  189. package/dist/prd/done-sweep.js.map +1 -1
  190. package/dist/prd/frontier-arming.d.ts +13 -1
  191. package/dist/prd/frontier-arming.d.ts.map +1 -1
  192. package/dist/prd/frontier-arming.js +50 -2
  193. package/dist/prd/frontier-arming.js.map +1 -1
  194. package/dist/prd/index.d.ts.map +1 -1
  195. package/dist/prd/index.js +2 -1
  196. package/dist/prd/index.js.map +1 -1
  197. package/dist/queries/api-client/shared.d.ts +1 -0
  198. package/dist/queries/api-client/shared.d.ts.map +1 -1
  199. package/dist/queries/api-client/shared.js +16 -1
  200. package/dist/queries/api-client/shared.js.map +1 -1
  201. package/dist/queries/deliveries/issues.d.ts.map +1 -1
  202. package/dist/queries/deliveries/issues.js +3 -0
  203. package/dist/queries/deliveries/issues.js.map +1 -1
  204. package/dist/queries/focuses/focus-discovery.d.ts +15 -0
  205. package/dist/queries/focuses/focus-discovery.d.ts.map +1 -1
  206. package/dist/queries/focuses/focus-discovery.js +10 -1
  207. package/dist/queries/focuses/focus-discovery.js.map +1 -1
  208. package/dist/queries/prd/prd.d.ts.map +1 -1
  209. package/dist/queries/prd/prd.js +2 -1
  210. package/dist/queries/prd/prd.js.map +1 -1
  211. package/dist/queries/tower/tower-state.d.ts +56 -0
  212. package/dist/queries/tower/tower-state.d.ts.map +1 -0
  213. package/dist/queries/tower/tower-state.js +76 -0
  214. package/dist/queries/tower/tower-state.js.map +1 -0
  215. package/dist/queries/wire-schemas/schemas.d.ts +12 -0
  216. package/dist/queries/wire-schemas/schemas.d.ts.map +1 -1
  217. package/dist/queries/wire-schemas/schemas.js +11 -0
  218. package/dist/queries/wire-schemas/schemas.js.map +1 -1
  219. package/dist/spawn/lead-continuation.d.ts +9 -1
  220. package/dist/spawn/lead-continuation.d.ts.map +1 -1
  221. package/dist/spawn/lead-continuation.js +37 -11
  222. package/dist/spawn/lead-continuation.js.map +1 -1
  223. package/dist/spawn/spawn-decision.d.ts.map +1 -1
  224. package/dist/spawn/spawn-decision.js +4 -1
  225. package/dist/spawn/spawn-decision.js.map +1 -1
  226. package/dist/supervision/spawn-cooldown.js +1 -1
  227. package/dist/supervision/stop-rows-team-session.d.ts.map +1 -1
  228. package/dist/supervision/stop-rows-team-session.js +11 -10
  229. package/dist/supervision/stop-rows-team-session.js.map +1 -1
  230. package/dist/supervision/team-work.d.ts.map +1 -1
  231. package/dist/supervision/team-work.js +3 -1
  232. package/dist/supervision/team-work.js.map +1 -1
  233. package/dist/testing/fixtures/api-client.js +1 -1
  234. package/dist/testing/fixtures/approved-head-inert-deps.js +1 -1
  235. package/dist/testing/fixtures/approved-head-inert-deps.js.map +1 -1
  236. package/dist/testing/fixtures/index.js +1 -1
  237. package/dist/testing/fixtures/pending-spawn-world.d.ts.map +1 -1
  238. package/dist/testing/fixtures/pending-spawn-world.js +3 -1
  239. package/dist/testing/fixtures/pending-spawn-world.js.map +1 -1
  240. package/dist/testing/fixtures/review-exit-deps.js +1 -1
  241. package/dist/testing/fixtures/review-exit-deps.js.map +1 -1
  242. package/dist/testing/fixtures/verification-feedback-deps.d.ts.map +1 -1
  243. package/dist/testing/fixtures/verification-feedback-deps.js +2 -0
  244. package/dist/testing/fixtures/verification-feedback-deps.js.map +1 -1
  245. package/dist/tower/focus-landed.d.ts +4 -0
  246. package/dist/tower/focus-landed.d.ts.map +1 -0
  247. package/dist/tower/focus-landed.js +45 -0
  248. package/dist/tower/focus-landed.js.map +1 -0
  249. package/dist/tower/tower-admission.d.ts +91 -0
  250. package/dist/tower/tower-admission.d.ts.map +1 -0
  251. package/dist/tower/tower-admission.js +137 -0
  252. package/dist/tower/tower-admission.js.map +1 -0
  253. package/dist/tower/tower-graph.d.ts +23 -0
  254. package/dist/tower/tower-graph.d.ts.map +1 -0
  255. package/dist/tower/tower-graph.js +53 -0
  256. package/dist/tower/tower-graph.js.map +1 -0
  257. package/dist/tower/tower-heartbeat-status.d.ts +28 -0
  258. package/dist/tower/tower-heartbeat-status.d.ts.map +1 -0
  259. package/dist/tower/tower-heartbeat-status.js +11 -0
  260. package/dist/tower/tower-heartbeat-status.js.map +1 -0
  261. package/dist/tower/tower-mode.d.ts +9 -0
  262. package/dist/tower/tower-mode.d.ts.map +1 -0
  263. package/dist/tower/tower-mode.js +16 -0
  264. package/dist/tower/tower-mode.js.map +1 -0
  265. package/dist/tower/tower-pass-standing.d.ts +8 -0
  266. package/dist/tower/tower-pass-standing.d.ts.map +1 -0
  267. package/dist/tower/tower-pass-standing.js +50 -0
  268. package/dist/tower/tower-pass-standing.js.map +1 -0
  269. package/dist/tower/tower-pass.d.ts +55 -0
  270. package/dist/tower/tower-pass.d.ts.map +1 -0
  271. package/dist/tower/tower-pass.js +59 -0
  272. package/dist/tower/tower-pass.js.map +1 -0
  273. package/dist/tower/tower-production-pass.d.ts +3 -0
  274. package/dist/tower/tower-production-pass.d.ts.map +1 -0
  275. package/dist/tower/tower-production-pass.js +24 -0
  276. package/dist/tower/tower-production-pass.js.map +1 -0
  277. package/dist/tower/tower-spawn-intent.d.ts +72 -0
  278. package/dist/tower/tower-spawn-intent.d.ts.map +1 -0
  279. package/dist/tower/tower-spawn-intent.js +138 -0
  280. package/dist/tower/tower-spawn-intent.js.map +1 -0
  281. package/dist/tower/tower-verdicts.d.ts +81 -0
  282. package/dist/tower/tower-verdicts.d.ts.map +1 -0
  283. package/dist/tower/tower-verdicts.js +139 -0
  284. package/dist/tower/tower-verdicts.js.map +1 -0
  285. package/dist/types/index.js +1 -1
  286. package/dist/types/issue-status.d.ts +14 -0
  287. package/dist/types/issue-status.d.ts.map +1 -1
  288. package/dist/types/issue-status.js +14 -0
  289. package/dist/types/issue-status.js.map +1 -1
  290. package/dist/verify/gate-verdicts/commit-verdict-record.js +1 -1
  291. package/dist/verify/outcome-routing/verification-rework-issue.d.ts +44 -5
  292. package/dist/verify/outcome-routing/verification-rework-issue.d.ts.map +1 -1
  293. package/dist/verify/outcome-routing/verification-rework-issue.js +85 -27
  294. package/dist/verify/outcome-routing/verification-rework-issue.js.map +1 -1
  295. package/dist/worktree/focus-worktree-state.d.ts.map +1 -1
  296. package/dist/worktree/focus-worktree-state.js +1 -0
  297. package/dist/worktree/focus-worktree-state.js.map +1 -1
  298. package/package.json +3 -3
@@ -0,0 +1,24 @@
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-production-pass.test.ts,
3
+ // packages/daemon/src/tower/tower-spawn-modes.test.ts
4
+ // PINNED-BY-END
5
+ /**
6
+ * The tower pass at the head of every production ready-focus pass
7
+ * (focus/focus-poller-spawn.ts runProductionReadyFocusPass), over the deps the
8
+ * composition root binds (composition/tower-pass-context.ts). Never throws into
9
+ * the spawn pass it heads: a failed tower costs no spawn.
10
+ */
11
+ import { createLogger } from '../log/daemon-log.js';
12
+ import { runTowerPass } from './tower-pass.js';
13
+ const log = createLogger({ module: 'tower' });
14
+ export async function runTowerPassSafely(source) {
15
+ try {
16
+ const deps = source();
17
+ if (deps)
18
+ await runTowerPass(deps);
19
+ }
20
+ catch (err) {
21
+ log.warn(`[tower] pass failed: ${err instanceof Error ? err.message : String(err)} -- admission fails open`);
22
+ }
23
+ }
24
+ //# sourceMappingURL=tower-production-pass.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tower-production-pass.js","sourceRoot":"","sources":["../../src/tower/tower-production-pass.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,sEAAsE;AACtE,wDAAwD;AACxD,gBAAgB;AAEhB;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,YAAY,EAA4B,MAAM,iBAAiB,CAAC;AAEzE,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,MAA2B;IAClE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC;QACtB,IAAI,IAAI;YAAE,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,wBAAwB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;IAC/G,CAAC;AACH,CAAC"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Which armed foci the spawn passes last found WANTING a team -- the tower's
3
+ * memory of demand, so a free slot goes to a focus that would use it.
4
+ *
5
+ * A spawn pass records a focus as wanting only when the focus reached the
6
+ * tower's admission and was stopped there by the tower or the host cap --
7
+ * demand still OPEN. A focus that spawned has had its demand met (its live team
8
+ * holds a slot by the slot rule, not by wanting), and a focus a pass stopped
9
+ * for any other reason (no team work, a verify hold, an escalation, an operator
10
+ * hold, the review-cycle cap, a cooldown) cannot run, so it does not want.
11
+ *
12
+ * Two rules keep the record CURRENT rather than a snapshot of an older pass:
13
+ * - Each spawn pass is a unit (beginSpawnIntentPass .. commitSpawnIntentPass):
14
+ * every focus the pass OFFERED and did not record as wanting is committed as
15
+ * not wanting, whichever earlier gate stopped it -- so a queued directive
16
+ * parked behind a verify hold or an escalation reserves no product slot.
17
+ * - Before the tower allocates slots, the ready pass reconciles the record
18
+ * against what could run NOW (reconcileSurfacedSpawnIntent, run by
19
+ * focus/focus-poller-spawn.ts runReadyFocusPassThroughTower ahead of the
20
+ * tower pass): every surfaced focus is probed through its spawn pass's gates
21
+ * bar the tower and the host cap (focus/spawn-demand-probe.ts), and wants a
22
+ * slot exactly when they are open -- the first time it surfaces, and the
23
+ * pass its gate clears. A focus no longer surfaced (not ready, no queued
24
+ * directive) wants nothing.
25
+ *
26
+ * Before any pass or reconcile has recorded anything the set is UNKNOWN (null)
27
+ * and the tower treats every focus as wanting -- the safe reading on daemon
28
+ * start.
29
+ *
30
+ * A leaf: in-process state only, imported by the spawn passes (focus/), the
31
+ * admission (tower-admission.ts) and the tower pass (tower-pass.ts).
32
+ */
33
+ /** A record older than this no longer counts (two missed 30s polls plus margin). */
34
+ export declare const SPAWN_INTENT_TTL_MS = 90000;
35
+ /** The spawn pass a record comes from (each runs as its own unit). */
36
+ export type SpawnIntentSource = 'ready' | 'pending';
37
+ /**
38
+ * Open a spawn pass over the foci it offers. Until it commits, what the pass
39
+ * records stays staged: the tower reads the last COMMITTED record, never a
40
+ * half-finished pass.
41
+ */
42
+ export declare function beginSpawnIntentPass(source: SpawnIntentSource, offeredFocusIds: Iterable<string>): void;
43
+ /** Record what a spawn pass found for one focus (staged while that pass is open). */
44
+ export declare function recordSpawnIntent(focusId: string, wants: boolean, nowMs?: number, source?: SpawnIntentSource): void;
45
+ /**
46
+ * Close a spawn pass: every focus it offered is committed -- wanting when the
47
+ * pass recorded it so, not wanting otherwise. No-op when no pass is open (a pass
48
+ * that returned before offering anything changes nothing).
49
+ */
50
+ export declare function commitSpawnIntentPass(source: SpawnIntentSource, nowMs?: number): void;
51
+ /** Drop an open pass uncommitted (the pass threw): the last committed record stands. */
52
+ export declare function abandonSpawnIntentPass(source: SpawnIntentSource): void;
53
+ /**
54
+ * Reconcile demand with what could run NOW. `demand` holds EVERY surfaced focus
55
+ * (ready, or holding a queued directive) with whether its spawn pass's gates,
56
+ * bar the tower and the host cap, are open on this pass
57
+ * (focus/spawn-demand-probe.ts), or null when its probe could not answer:
58
+ * - a focus not in `demand` is no longer surfaced: its record is dropped, so it
59
+ * reads as not wanting;
60
+ * - a probed focus's record becomes the probe's answer, whatever an earlier
61
+ * pass recorded -- a gate that has cleared since makes it want, a gate that
62
+ * holds it (even on the first pass that surfaces it) makes it not want;
63
+ * - a focus whose probe could not answer keeps a fresh record; with none (the
64
+ * first pass that surfaces it) or an expired one it WANTS: an unreadable gate
65
+ * fails open, so a read error never silently demotes a higher-ranked focus.
66
+ */
67
+ export declare function reconcileSurfacedSpawnIntent(demand: ReadonlyMap<string, boolean | null>, nowMs?: number): void;
68
+ /** The foci last found wanting a team, or null before any pass has recorded. */
69
+ export declare function wantingFocusIds(nowMs?: number): ReadonlySet<string> | null;
70
+ /** Test-only reset. */
71
+ export declare function resetSpawnIntent(): void;
72
+ //# sourceMappingURL=tower-spawn-intent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tower-spawn-intent.d.ts","sourceRoot":"","sources":["../../src/tower/tower-spawn-intent.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,oFAAoF;AACpF,eAAO,MAAM,mBAAmB,QAAS,CAAC;AAE1C,sEAAsE;AACtE,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,SAAS,CAAC;AAapD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,EAAE,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,CAEvG;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,GAAE,MAAmB,EAAE,MAAM,GAAE,iBAA2B,GAAG,IAAI,CASxI;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,EAAE,KAAK,GAAE,MAAmB,GAAG,IAAI,CAMjG;AAED,wFAAwF;AACxF,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAEtE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC,EAAE,KAAK,GAAE,MAAmB,GAAG,IAAI,CAe1H;AAED,gFAAgF;AAChF,wBAAgB,eAAe,CAAC,KAAK,GAAE,MAAmB,GAAG,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAWtF;AAED,uBAAuB;AACvB,wBAAgB,gBAAgB,IAAI,IAAI,CAIvC"}
@@ -0,0 +1,138 @@
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-entrypoints.test.ts,
3
+ // packages/daemon/src/tower/tower-prd-arm.test.ts,
4
+ // packages/daemon/src/tower/tower-ready-row-ingestion.test.ts,
5
+ // packages/daemon/src/tower/tower-spawn-modes.test.ts
6
+ // PINNED-BY-END
7
+ /**
8
+ * Which armed foci the spawn passes last found WANTING a team -- the tower's
9
+ * memory of demand, so a free slot goes to a focus that would use it.
10
+ *
11
+ * A spawn pass records a focus as wanting only when the focus reached the
12
+ * tower's admission and was stopped there by the tower or the host cap --
13
+ * demand still OPEN. A focus that spawned has had its demand met (its live team
14
+ * holds a slot by the slot rule, not by wanting), and a focus a pass stopped
15
+ * for any other reason (no team work, a verify hold, an escalation, an operator
16
+ * hold, the review-cycle cap, a cooldown) cannot run, so it does not want.
17
+ *
18
+ * Two rules keep the record CURRENT rather than a snapshot of an older pass:
19
+ * - Each spawn pass is a unit (beginSpawnIntentPass .. commitSpawnIntentPass):
20
+ * every focus the pass OFFERED and did not record as wanting is committed as
21
+ * not wanting, whichever earlier gate stopped it -- so a queued directive
22
+ * parked behind a verify hold or an escalation reserves no product slot.
23
+ * - Before the tower allocates slots, the ready pass reconciles the record
24
+ * against what could run NOW (reconcileSurfacedSpawnIntent, run by
25
+ * focus/focus-poller-spawn.ts runReadyFocusPassThroughTower ahead of the
26
+ * tower pass): every surfaced focus is probed through its spawn pass's gates
27
+ * bar the tower and the host cap (focus/spawn-demand-probe.ts), and wants a
28
+ * slot exactly when they are open -- the first time it surfaces, and the
29
+ * pass its gate clears. A focus no longer surfaced (not ready, no queued
30
+ * directive) wants nothing.
31
+ *
32
+ * Before any pass or reconcile has recorded anything the set is UNKNOWN (null)
33
+ * and the tower treats every focus as wanting -- the safe reading on daemon
34
+ * start.
35
+ *
36
+ * A leaf: in-process state only, imported by the spawn passes (focus/), the
37
+ * admission (tower-admission.ts) and the tower pass (tower-pass.ts).
38
+ */
39
+ /** A record older than this no longer counts (two missed 30s polls plus margin). */
40
+ export const SPAWN_INTENT_TTL_MS = 90_000;
41
+ const records = new Map();
42
+ let everRecorded = false;
43
+ /** A spawn pass in progress: the foci it offered and what it recorded for them so far. */
44
+ const openPasses = new Map();
45
+ /**
46
+ * Open a spawn pass over the foci it offers. Until it commits, what the pass
47
+ * records stays staged: the tower reads the last COMMITTED record, never a
48
+ * half-finished pass.
49
+ */
50
+ export function beginSpawnIntentPass(source, offeredFocusIds) {
51
+ openPasses.set(source, { offered: new Set(offeredFocusIds), wanting: new Set() });
52
+ }
53
+ /** Record what a spawn pass found for one focus (staged while that pass is open). */
54
+ export function recordSpawnIntent(focusId, wants, nowMs = Date.now(), source = 'ready') {
55
+ const open = openPasses.get(source);
56
+ if (open && open.offered.has(focusId)) {
57
+ if (wants)
58
+ open.wanting.add(focusId);
59
+ else
60
+ open.wanting.delete(focusId);
61
+ return;
62
+ }
63
+ records.set(focusId, { wants, atMs: nowMs });
64
+ everRecorded = true;
65
+ }
66
+ /**
67
+ * Close a spawn pass: every focus it offered is committed -- wanting when the
68
+ * pass recorded it so, not wanting otherwise. No-op when no pass is open (a pass
69
+ * that returned before offering anything changes nothing).
70
+ */
71
+ export function commitSpawnIntentPass(source, nowMs = Date.now()) {
72
+ const open = openPasses.get(source);
73
+ if (!open)
74
+ return;
75
+ openPasses.delete(source);
76
+ for (const focusId of open.offered)
77
+ records.set(focusId, { wants: open.wanting.has(focusId), atMs: nowMs });
78
+ if (open.offered.size > 0)
79
+ everRecorded = true;
80
+ }
81
+ /** Drop an open pass uncommitted (the pass threw): the last committed record stands. */
82
+ export function abandonSpawnIntentPass(source) {
83
+ openPasses.delete(source);
84
+ }
85
+ /**
86
+ * Reconcile demand with what could run NOW. `demand` holds EVERY surfaced focus
87
+ * (ready, or holding a queued directive) with whether its spawn pass's gates,
88
+ * bar the tower and the host cap, are open on this pass
89
+ * (focus/spawn-demand-probe.ts), or null when its probe could not answer:
90
+ * - a focus not in `demand` is no longer surfaced: its record is dropped, so it
91
+ * reads as not wanting;
92
+ * - a probed focus's record becomes the probe's answer, whatever an earlier
93
+ * pass recorded -- a gate that has cleared since makes it want, a gate that
94
+ * holds it (even on the first pass that surfaces it) makes it not want;
95
+ * - a focus whose probe could not answer keeps a fresh record; with none (the
96
+ * first pass that surfaces it) or an expired one it WANTS: an unreadable gate
97
+ * fails open, so a read error never silently demotes a higher-ranked focus.
98
+ */
99
+ export function reconcileSurfacedSpawnIntent(demand, nowMs = Date.now()) {
100
+ for (const focusId of [...records.keys()]) {
101
+ if (!demand.has(focusId))
102
+ records.delete(focusId);
103
+ }
104
+ for (const [focusId, wants] of demand) {
105
+ if (wants !== null) {
106
+ records.set(focusId, { wants, atMs: nowMs });
107
+ continue;
108
+ }
109
+ // Unknown: a fresh record stands; with none (first surface) or an expired one, fail OPEN --
110
+ // the focus is ranked with the waiters, never silently demoted behind them by a read error.
111
+ const r = records.get(focusId);
112
+ if (!r || nowMs - r.atMs > SPAWN_INTENT_TTL_MS)
113
+ records.set(focusId, { wants: true, atMs: nowMs });
114
+ }
115
+ everRecorded = true;
116
+ }
117
+ /** The foci last found wanting a team, or null before any pass has recorded. */
118
+ export function wantingFocusIds(nowMs = Date.now()) {
119
+ if (!everRecorded)
120
+ return null;
121
+ const out = new Set();
122
+ for (const [focusId, r] of records) {
123
+ if (nowMs - r.atMs > SPAWN_INTENT_TTL_MS) {
124
+ records.delete(focusId);
125
+ continue;
126
+ }
127
+ if (r.wants)
128
+ out.add(focusId);
129
+ }
130
+ return out;
131
+ }
132
+ /** Test-only reset. */
133
+ export function resetSpawnIntent() {
134
+ records.clear();
135
+ openPasses.clear();
136
+ everRecorded = false;
137
+ }
138
+ //# sourceMappingURL=tower-spawn-intent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tower-spawn-intent.js","sourceRoot":"","sources":["../../src/tower/tower-spawn-intent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * The tower's verdict computation for ONE product -- pure (inputs in, verdicts
3
+ * out), so the slot rule, the rank order and the reason precedence are tested
4
+ * directly. The pass that feeds it and writes the result is tower-pass.ts.
5
+ *
6
+ * THE SLOT RULE. A focus occupies one of the product's slots only while it has a
7
+ * live coding or review team. A live focus is always cleared: the tower never
8
+ * stops a running team. The free slots (limit minus live foci; unbounded when
9
+ * the product has no limit) are cleared to the other foci in RANK order (lowest
10
+ * priority_rank first), foci the spawn pass last found WANTING a team ahead of
11
+ * foci it found idle -- so a focus that is armed but has nothing to run (waiting
12
+ * on CI, a verify hold, an escalation) never takes the slot from one that does.
13
+ * Every focus beyond the free slots holds with `product_limit_reached`.
14
+ *
15
+ * THE REASONS, in the precedence daemon-core TOWER_HOLD_REASONS declares:
16
+ * waits_on -- a depends_on predecessor has not landed;
17
+ * excluded_by -- an excludes edge joins it to a focus that has a live
18
+ * team or was cleared ahead of it in this pass (so two
19
+ * excluded foci are never cleared together);
20
+ * product_limit_reached -- the free slots went to foci ahead of it.
21
+ * A focus held for a graph reason takes no slot.
22
+ *
23
+ * A focus whose inputs could not be judged (UNAVAILABLE) gets no verdict (null):
24
+ * the spawn pass fails open on it rather than holding it.
25
+ */
26
+ import { type TowerMode, type TowerVerdict } from '@telora/daemon-core';
27
+ /** One armed, active focus of the product. */
28
+ export interface TowerFocusInput {
29
+ focusId: string;
30
+ focusName: string;
31
+ priorityRank: number;
32
+ /** product_focuses.agent_assigned_at: the instant of the current arm. */
33
+ armedAt: string | null;
34
+ /** The stored product_focuses.tower_verdict (raw JSONB). */
35
+ previousVerdict: unknown;
36
+ }
37
+ /** An excludes edge seen from one side. */
38
+ export interface TowerExclusion {
39
+ otherFocusId: string;
40
+ otherFocusName: string;
41
+ evidence: string;
42
+ }
43
+ /** The first depends_on predecessor that has not landed. */
44
+ export interface TowerUnlandedPredecessor {
45
+ focusId: string;
46
+ focusName: string;
47
+ }
48
+ export interface TowerComputeInput {
49
+ foci: readonly TowerFocusInput[];
50
+ /** products.tower_concurrency_limit; null = no product limit. */
51
+ limit: number | null;
52
+ /** Foci holding a live coding or review team. */
53
+ liveTeamFocusIds: ReadonlySet<string>;
54
+ /** Foci the spawn pass last found wanting a team; null = not yet known (all want). */
55
+ wantingFocusIds: ReadonlySet<string> | null;
56
+ /** depends_on: focus -> its first unlanded predecessor. Absent = none. */
57
+ waitsOn?: ReadonlyMap<string, TowerUnlandedPredecessor>;
58
+ /** excludes: focus -> the foci an excludes edge joins it to. Absent = none. */
59
+ excludes?: ReadonlyMap<string, readonly TowerExclusion[]>;
60
+ /** Foci whose graph inputs could not be judged (e.g. a landed check failed). */
61
+ unavailableFocusIds?: ReadonlySet<string>;
62
+ mode: Exclude<TowerMode, 'off'>;
63
+ now: string;
64
+ }
65
+ /** focusId -> the verdict to hold, or null for "no verdict" (fail open). */
66
+ export type TowerComputed = Map<string, TowerVerdict | null>;
67
+ /** Compute every armed focus's verdict for one product. */
68
+ export declare function computeTowerVerdicts(input: TowerComputeInput): TowerComputed;
69
+ /** One verdict write: the verdict, or null to clear it. */
70
+ export interface TowerVerdictWrite {
71
+ focusId: string;
72
+ verdict: TowerVerdict | null;
73
+ }
74
+ /**
75
+ * Which computed verdicts need writing: a changed verdict, a cleared-to-null
76
+ * one, or an unchanged one whose last confirmation is past HALF the bounded age
77
+ * (so a running tower's verdicts never go stale under the spawn pass). Plus a
78
+ * clear for every un-armed focus still carrying a verdict.
79
+ */
80
+ export declare function planTowerWrites(foci: readonly TowerFocusInput[], computed: TowerComputed, unarmedWithVerdictFocusIds: readonly string[], nowMs: number, maxAgeMs?: number): TowerVerdictWrite[];
81
+ //# sourceMappingURL=tower-verdicts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tower-verdicts.d.ts","sourceRoot":"","sources":["../../src/tower/tower-verdicts.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAML,KAAK,SAAS,EACd,KAAK,YAAY,EAElB,MAAM,qBAAqB,CAAC;AAE7B,8CAA8C;AAC9C,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,4DAA4D;IAC5D,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,2CAA2C;AAC3C,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,4DAA4D;AAC5D,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,SAAS,eAAe,EAAE,CAAC;IACjC,iEAAiE;IACjE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,iDAAiD;IACjD,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC,sFAAsF;IACtF,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC5C,0EAA0E;IAC1E,OAAO,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;IACxD,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,CAAC,CAAC;IAC1D,gFAAgF;IAChF,mBAAmB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1C,IAAI,EAAE,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAChC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,4EAA4E;AAC5E,MAAM,MAAM,aAAa,GAAG,GAAG,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC,CAAC;AAyC7D,2DAA2D;AAC3D,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,iBAAiB,GAAG,aAAa,CAkD5E;AAED,2DAA2D;AAC3D,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;CAC9B;AAOD;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,SAAS,eAAe,EAAE,EAChC,QAAQ,EAAE,aAAa,EACvB,0BAA0B,EAAE,SAAS,MAAM,EAAE,EAC7C,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,MAAiC,GAC1C,iBAAiB,EAAE,CAgBrB"}
@@ -0,0 +1,139 @@
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-pass.test.ts, packages/daemon/src/tower/tower-verdicts.test.ts
3
+ // PINNED-BY-END
4
+ /**
5
+ * The tower's verdict computation for ONE product -- pure (inputs in, verdicts
6
+ * out), so the slot rule, the rank order and the reason precedence are tested
7
+ * directly. The pass that feeds it and writes the result is tower-pass.ts.
8
+ *
9
+ * THE SLOT RULE. A focus occupies one of the product's slots only while it has a
10
+ * live coding or review team. A live focus is always cleared: the tower never
11
+ * stops a running team. The free slots (limit minus live foci; unbounded when
12
+ * the product has no limit) are cleared to the other foci in RANK order (lowest
13
+ * priority_rank first), foci the spawn pass last found WANTING a team ahead of
14
+ * foci it found idle -- so a focus that is armed but has nothing to run (waiting
15
+ * on CI, a verify hold, an escalation) never takes the slot from one that does.
16
+ * Every focus beyond the free slots holds with `product_limit_reached`.
17
+ *
18
+ * THE REASONS, in the precedence daemon-core TOWER_HOLD_REASONS declares:
19
+ * waits_on -- a depends_on predecessor has not landed;
20
+ * excluded_by -- an excludes edge joins it to a focus that has a live
21
+ * team or was cleared ahead of it in this pass (so two
22
+ * excluded foci are never cleared together);
23
+ * product_limit_reached -- the free slots went to foci ahead of it.
24
+ * A focus held for a graph reason takes no slot.
25
+ *
26
+ * A focus whose inputs could not be judged (UNAVAILABLE) gets no verdict (null):
27
+ * the spawn pass fails open on it rather than holding it.
28
+ */
29
+ import { TOWER_HOLD_REASON, TOWER_VERDICT_MAX_AGE_MS, TOWER_VERDICT_STATE, parseTowerVerdict, } from '@telora/daemon-core';
30
+ function byRank(a, b) {
31
+ return a.priorityRank - b.priorityRank || (a.focusId < b.focusId ? -1 : a.focusId > b.focusId ? 1 : 0);
32
+ }
33
+ /** Keep `since` when the focus already held this exact state + reason (+ other focus) under this arm. */
34
+ function sinceFor(focus, state, reason, detail, now) {
35
+ const prev = parseTowerVerdict(focus.previousVerdict);
36
+ if (!prev)
37
+ return now;
38
+ const sameArm = prev.armedAt === focus.armedAt
39
+ || (prev.armedAt !== null && focus.armedAt !== null && Date.parse(prev.armedAt) === Date.parse(focus.armedAt));
40
+ if (!sameArm || prev.state !== state || prev.reason !== reason)
41
+ return now;
42
+ if ((prev.detail.focusId ?? null) !== (detail.focusId ?? null))
43
+ return now;
44
+ return prev.since;
45
+ }
46
+ function verdict(focus, input, reason, detail = {}) {
47
+ const state = reason === null ? TOWER_VERDICT_STATE.CLEARED : TOWER_VERDICT_STATE.HOLDING;
48
+ return {
49
+ state,
50
+ reason,
51
+ since: sinceFor(focus, state, reason, detail, input.now),
52
+ computedAt: input.now,
53
+ armedAt: focus.armedAt,
54
+ mode: input.mode,
55
+ detail,
56
+ };
57
+ }
58
+ /** Compute every armed focus's verdict for one product. */
59
+ export function computeTowerVerdicts(input) {
60
+ const out = new Map();
61
+ const ordered = [...input.foci].sort(byRank);
62
+ const live = ordered.filter((f) => input.liveTeamFocusIds.has(f.focusId));
63
+ const cleared = new Set();
64
+ for (const f of live) {
65
+ out.set(f.focusId, verdict(f, input, null));
66
+ cleared.add(f.focusId);
67
+ }
68
+ // Wanting foci first, then idle ones, each in rank order.
69
+ const waiting = ordered.filter((f) => !input.liveTeamFocusIds.has(f.focusId));
70
+ const wants = (f) => input.wantingFocusIds === null || input.wantingFocusIds.has(f.focusId);
71
+ const queue = [...waiting.filter(wants), ...waiting.filter((f) => !wants(f))];
72
+ let free = input.limit === null ? Number.POSITIVE_INFINITY : Math.max(0, input.limit - live.length);
73
+ for (const f of queue) {
74
+ if (input.unavailableFocusIds?.has(f.focusId)) {
75
+ out.set(f.focusId, null);
76
+ continue;
77
+ }
78
+ const predecessor = input.waitsOn?.get(f.focusId);
79
+ if (predecessor) {
80
+ out.set(f.focusId, verdict(f, input, TOWER_HOLD_REASON.WAITS_ON, {
81
+ focusId: predecessor.focusId,
82
+ focusName: predecessor.focusName,
83
+ }));
84
+ continue;
85
+ }
86
+ const blocker = input.excludes?.get(f.focusId)?.find((e) => cleared.has(e.otherFocusId));
87
+ if (blocker) {
88
+ out.set(f.focusId, verdict(f, input, TOWER_HOLD_REASON.EXCLUDED_BY, {
89
+ focusId: blocker.otherFocusId,
90
+ focusName: blocker.otherFocusName,
91
+ evidence: blocker.evidence,
92
+ }));
93
+ continue;
94
+ }
95
+ if (free <= 0) {
96
+ out.set(f.focusId, verdict(f, input, TOWER_HOLD_REASON.PRODUCT_LIMIT_REACHED, {
97
+ ...(input.limit !== null ? { limit: input.limit } : {}),
98
+ occupied: live.length,
99
+ }));
100
+ continue;
101
+ }
102
+ free -= 1;
103
+ cleared.add(f.focusId);
104
+ out.set(f.focusId, verdict(f, input, null));
105
+ }
106
+ return out;
107
+ }
108
+ /** The facts that make two verdicts the same verdict (computedAt aside). */
109
+ function verdictKey(v) {
110
+ return JSON.stringify([v.state, v.reason, v.since, v.armedAt, v.mode, v.detail]);
111
+ }
112
+ /**
113
+ * Which computed verdicts need writing: a changed verdict, a cleared-to-null
114
+ * one, or an unchanged one whose last confirmation is past HALF the bounded age
115
+ * (so a running tower's verdicts never go stale under the spawn pass). Plus a
116
+ * clear for every un-armed focus still carrying a verdict.
117
+ */
118
+ export function planTowerWrites(foci, computed, unarmedWithVerdictFocusIds, nowMs, maxAgeMs = TOWER_VERDICT_MAX_AGE_MS) {
119
+ const writes = [];
120
+ for (const f of foci) {
121
+ if (!computed.has(f.focusId))
122
+ continue;
123
+ const next = computed.get(f.focusId) ?? null;
124
+ const prev = parseTowerVerdict(f.previousVerdict);
125
+ if (next === null) {
126
+ if (f.previousVerdict !== null && f.previousVerdict !== undefined)
127
+ writes.push({ focusId: f.focusId, verdict: null });
128
+ continue;
129
+ }
130
+ const changed = !prev || verdictKey(prev) !== verdictKey(next);
131
+ const aging = prev !== null && nowMs - Date.parse(prev.computedAt) > maxAgeMs / 2;
132
+ if (changed || aging)
133
+ writes.push({ focusId: f.focusId, verdict: next });
134
+ }
135
+ for (const focusId of unarmedWithVerdictFocusIds)
136
+ writes.push({ focusId, verdict: null });
137
+ return writes;
138
+ }
139
+ //# sourceMappingURL=tower-verdicts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tower-verdicts.js","sourceRoot":"","sources":["../../src/tower/tower-verdicts.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: 254 tests -- run: npm run gen:pinned-by -- --list packages/daemon/src/types/index.ts
2
+ // Pinned by: 256 tests -- run: npm run gen:pinned-by -- --list packages/daemon/src/types/index.ts
3
3
  // PINNED-BY-END
4
4
  /**
5
5
  * Domain-specific type re-exports.
@@ -25,6 +25,20 @@ export declare const OPEN_ISSUE_STATUSES: Set<string>;
25
25
  export declare const TERMINAL_ISSUE_STATUSES: Set<string>;
26
26
  /** The issue type string for context groups (reference material, not actionable work). */
27
27
  export declare const CONTEXT_GROUP_TYPE: "Context Group";
28
+ /**
29
+ * Title prefix of the rework Bug the daemon files for a failed gate verdict
30
+ * (verify/outcome-routing/verification-rework-issue.ts); the failed commit follows it.
31
+ */
32
+ export declare const REWORK_ISSUE_TITLE_PREFIX = "Verify gate failed at";
33
+ /**
34
+ * Whether an issue is a daemon-filed gate rework Bug. Such a Bug is owed work by
35
+ * construction -- the failure it names is the gate's, not a review's -- so it is
36
+ * never a recorded review concern (delivery/recorded-concerns.ts), whatever
37
+ * session it was attributed to when filed.
38
+ */
39
+ export declare function isGateReworkIssue(issue: {
40
+ title: string;
41
+ }): boolean;
28
42
  /** Filter issues to only actionable work (tasks and bugs, not context groups). */
29
43
  export declare function filterWorkIssues<T extends {
30
44
  issueType: string;
@@ -1 +1 @@
1
- {"version":3,"file":"issue-status.d.ts","sourceRoot":"","sources":["../../src/types/issue-status.ts"],"names":[],"mappings":"AAOA;;;GAGG;AAEH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,aAA+C,CAAC;AAEhF;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,aAA6C,CAAC;AAElF,0FAA0F;AAC1F,eAAO,MAAM,kBAAkB,EAAG,eAAwB,CAAC;AAE3D,kFAAkF;AAClF,wBAAgB,gBAAgB,CAAC,CAAC,SAAS;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAElF;AAED,4CAA4C;AAC5C,wBAAgB,mBAAmB,CAAC,CAAC,SAAS;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAErF;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,EAChG,MAAM,EAAE,CAAC,EAAE,GACV,MAAM,EAAE,CAIV"}
1
+ {"version":3,"file":"issue-status.d.ts","sourceRoot":"","sources":["../../src/types/issue-status.ts"],"names":[],"mappings":"AAOA;;;GAGG;AAEH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,aAA+C,CAAC;AAEhF;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,aAA6C,CAAC;AAElF,0FAA0F;AAC1F,eAAO,MAAM,kBAAkB,EAAG,eAAwB,CAAC;AAE3D;;;GAGG;AACH,eAAO,MAAM,yBAAyB,0BAA0B,CAAC;AAEjE;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAEnE;AAED,kFAAkF;AAClF,wBAAgB,gBAAgB,CAAC,CAAC,SAAS;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAElF;AAED,4CAA4C;AAC5C,wBAAgB,mBAAmB,CAAC,CAAC,SAAS;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAErF;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,EAChG,MAAM,EAAE,CAAC,EAAE,GACV,MAAM,EAAE,CAIV"}
@@ -31,6 +31,20 @@ export const OPEN_ISSUE_STATUSES = new Set(['To Do', 'In Progress', 'Blocked']);
31
31
  export const TERMINAL_ISSUE_STATUSES = new Set(['Done', 'Verified', 'In Review']);
32
32
  /** The issue type string for context groups (reference material, not actionable work). */
33
33
  export const CONTEXT_GROUP_TYPE = 'Context Group';
34
+ /**
35
+ * Title prefix of the rework Bug the daemon files for a failed gate verdict
36
+ * (verify/outcome-routing/verification-rework-issue.ts); the failed commit follows it.
37
+ */
38
+ export const REWORK_ISSUE_TITLE_PREFIX = 'Verify gate failed at';
39
+ /**
40
+ * Whether an issue is a daemon-filed gate rework Bug. Such a Bug is owed work by
41
+ * construction -- the failure it names is the gate's, not a review's -- so it is
42
+ * never a recorded review concern (delivery/recorded-concerns.ts), whatever
43
+ * session it was attributed to when filed.
44
+ */
45
+ export function isGateReworkIssue(issue) {
46
+ return issue.title.startsWith(REWORK_ISSUE_TITLE_PREFIX);
47
+ }
34
48
  /** Filter issues to only actionable work (tasks and bugs, not context groups). */
35
49
  export function filterWorkIssues(issues) {
36
50
  return issues.filter(i => i.issueType !== CONTEXT_GROUP_TYPE);
@@ -1 +1 @@
1
- {"version":3,"file":"issue-status.js","sourceRoot":"","sources":["../../src/types/issue-status.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,iFAAiF;AACjF,uDAAuD;AACvD,0EAA0E;AAC1E,2DAA2D;AAC3D,gBAAgB;AAEhB;;;GAGG;AAEH;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC;AAEhF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;AAElF,0FAA0F;AAC1F,MAAM,CAAC,MAAM,kBAAkB,GAAG,eAAwB,CAAC;AAE3D,kFAAkF;AAClF,MAAM,UAAU,gBAAgB,CAAkC,MAAW;IAC3E,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,kBAAkB,CAAC,CAAC;AAChE,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,mBAAmB,CAAkC,MAAW;IAC9E,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,kBAAkB,CAAC,CAAC;AAChE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CACpC,MAAW;IAEX,OAAO,gBAAgB,CAAC,MAAM,CAAC;SAC5B,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC;SAChE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACpB,CAAC"}
1
+ {"version":3,"file":"issue-status.js","sourceRoot":"","sources":["../../src/types/issue-status.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,iFAAiF;AACjF,uDAAuD;AACvD,0EAA0E;AAC1E,2DAA2D;AAC3D,gBAAgB;AAEhB;;;GAGG;AAEH;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC;AAEhF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;AAElF,0FAA0F;AAC1F,MAAM,CAAC,MAAM,kBAAkB,GAAG,eAAwB,CAAC;AAE3D;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,uBAAuB,CAAC;AAEjE;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAwB;IACxD,OAAO,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,yBAAyB,CAAC,CAAC;AAC3D,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,gBAAgB,CAAkC,MAAW;IAC3E,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,kBAAkB,CAAC,CAAC;AAChE,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,mBAAmB,CAAkC,MAAW;IAC9E,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,kBAAkB,CAAC,CAAC;AAChE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CACpC,MAAW;IAEX,OAAO,gBAAgB,CAAC,MAAM,CAAC;SAC5B,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC;SAChE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACpB,CAAC"}
@@ -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/verify/gate-verdicts/commit-verdict-record.ts
2
+ // Pinned by: 29 tests -- run: npm run gen:pinned-by -- --list packages/daemon/src/verify/gate-verdicts/commit-verdict-record.ts
3
3
  // PINNED-BY-END
4
4
  /**
5
5
  * The deterministic gate verdict for a focus commit, recorded durably.