cloving 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (568) hide show
  1. package/README.md +584 -144
  2. package/assets/watch-fonts/fira-code-OFL.md +93 -0
  3. package/assets/watch-fonts/fira-code-latin-400-normal.woff2 +0 -0
  4. package/assets/watch-fonts/fira-code-latin-500-normal.woff2 +0 -0
  5. package/assets/watch-fonts/heebo-OFL.md +93 -0
  6. package/assets/watch-fonts/heebo-latin-500-normal.woff2 +0 -0
  7. package/assets/watch-fonts/heebo-latin-700-normal.woff2 +0 -0
  8. package/assets/watch-fonts/heebo-latin-800-normal.woff2 +0 -0
  9. package/assets/watch-fonts/manifest.json +112 -0
  10. package/assets/watch-fonts/space-grotesk-OFL.md +93 -0
  11. package/assets/watch-fonts/space-grotesk-latin-400-normal.woff2 +0 -0
  12. package/assets/watch-fonts/space-grotesk-latin-500-normal.woff2 +0 -0
  13. package/assets/watch-fonts/space-grotesk-latin-600-normal.woff2 +0 -0
  14. package/assets/watch-fonts/space-grotesk-latin-700-normal.woff2 +0 -0
  15. package/dist/src/agent-harness-shell.d.ts +12 -0
  16. package/dist/src/agent-harness-shell.js +90 -0
  17. package/dist/src/agent-harness-versions.d.ts +8 -0
  18. package/dist/src/agent-harness-versions.js +49 -0
  19. package/dist/src/agent-harnesses.d.ts +4 -0
  20. package/dist/src/agent-harnesses.js +13 -0
  21. package/dist/src/authority/commands.d.ts +2 -0
  22. package/dist/src/authority/commands.js +49 -8
  23. package/dist/src/authority/dispatch-decision.d.ts +1 -0
  24. package/dist/src/authority/dispatch-decision.js +7 -4
  25. package/dist/src/authority/events.js +2 -2
  26. package/dist/src/authority/gate-reduction.d.ts +1 -0
  27. package/dist/src/authority/gate-reduction.js +18 -3
  28. package/dist/src/authority/gates.d.ts +2 -1
  29. package/dist/src/authority/gates.js +5 -1
  30. package/dist/src/authority/handoff-chain.d.ts +24 -0
  31. package/dist/src/authority/handoff-chain.js +46 -0
  32. package/dist/src/authority/operations.js +1 -1
  33. package/dist/src/authority/reconciliation.d.ts +1 -0
  34. package/dist/src/authority/reconciliation.js +18 -11
  35. package/dist/src/authority/reduction.d.ts +1 -1
  36. package/dist/src/authority/reduction.js +6 -1
  37. package/dist/src/authority/status-input.d.ts +1 -1
  38. package/dist/src/authority/status.d.ts +1 -0
  39. package/dist/src/authority/status.js +27 -3
  40. package/dist/src/authority/transitions.d.ts +5 -5
  41. package/dist/src/authority/transitions.js +9 -0
  42. package/dist/src/broker/actor/authority-delivery.js +1 -0
  43. package/dist/src/broker/actor/authority-queries.d.ts +11 -1
  44. package/dist/src/broker/actor/authority-queries.js +67 -3
  45. package/dist/src/broker/actor/authority-receipts.js +11 -1
  46. package/dist/src/broker/actor/authority-session.js +2 -2
  47. package/dist/src/broker/actor/authority-settings.js +4 -0
  48. package/dist/src/broker/actor/delivery-intents.d.ts +3 -1
  49. package/dist/src/broker/actor/delivery-intents.js +4 -4
  50. package/dist/src/broker/actor/effect-delivery.js +13 -1
  51. package/dist/src/broker/actor/effect-queries.d.ts +1 -0
  52. package/dist/src/broker/actor/effect-queries.js +7 -0
  53. package/dist/src/broker/actor/pin-check.js +1 -1
  54. package/dist/src/broker/actor/stop-plan.js +1 -1
  55. package/dist/src/broker/actor/turn-state.js +1 -1
  56. package/dist/src/broker/authority-admission.js +26 -5
  57. package/dist/src/broker/authority-restore.js +1 -0
  58. package/dist/src/broker/decision-restore.js +4 -4
  59. package/dist/src/broker/socket-address.d.ts +3 -1
  60. package/dist/src/broker/socket-address.js +2 -2
  61. package/dist/src/cli/arguments.d.ts +11 -13
  62. package/dist/src/cli/arguments.js +37 -107
  63. package/dist/src/cli/command-effects.d.ts +7 -0
  64. package/dist/src/cli/command-effects.js +39 -0
  65. package/dist/src/cli/commands.js +11 -4
  66. package/dist/src/cli/config-arguments.d.ts +11 -0
  67. package/dist/src/cli/config-arguments.js +59 -0
  68. package/dist/src/cli/config-command.d.ts +2 -0
  69. package/dist/src/cli/config-command.js +105 -0
  70. package/dist/src/cli/config-file.d.ts +3 -0
  71. package/dist/src/cli/config-file.js +50 -0
  72. package/dist/src/cli/config-lock.d.ts +7 -0
  73. package/dist/src/cli/config-lock.js +61 -0
  74. package/dist/src/cli/config-notice.d.ts +5 -0
  75. package/dist/src/cli/config-notice.js +46 -0
  76. package/dist/src/cli/doctor-github.d.ts +9 -0
  77. package/dist/src/cli/doctor-github.js +138 -0
  78. package/dist/src/cli/doctor-harness.d.ts +13 -0
  79. package/dist/src/cli/doctor-harness.js +242 -0
  80. package/dist/src/cli/doctor-local.d.ts +18 -0
  81. package/dist/src/cli/doctor-local.js +77 -0
  82. package/dist/src/cli/doctor-runtime.d.ts +15 -0
  83. package/dist/src/cli/doctor-runtime.js +176 -0
  84. package/dist/src/cli/doctor-service.d.ts +1 -0
  85. package/dist/src/cli/doctor-service.js +11 -0
  86. package/dist/src/cli/doctor-workflows.d.ts +3 -0
  87. package/dist/src/cli/doctor-workflows.js +45 -0
  88. package/dist/src/cli/doctor.d.ts +15 -0
  89. package/dist/src/cli/doctor.js +190 -0
  90. package/dist/src/cli/github-ci-progress.d.ts +8 -0
  91. package/dist/src/cli/github-ci-progress.js +83 -0
  92. package/dist/src/cli/github-retry.d.ts +6 -0
  93. package/dist/src/cli/github-retry.js +47 -0
  94. package/dist/src/cli/harness-probes.d.ts +22 -0
  95. package/dist/src/cli/harness-probes.js +183 -0
  96. package/dist/src/cli/main.d.ts +7 -1
  97. package/dist/src/cli/main.js +39 -61
  98. package/dist/src/cli/phone-arguments.d.ts +14 -0
  99. package/dist/src/cli/phone-arguments.js +37 -0
  100. package/dist/src/cli/phone-client.d.ts +2 -0
  101. package/dist/src/cli/phone-client.js +32 -0
  102. package/dist/src/cli/phone-command.d.ts +13 -0
  103. package/dist/src/cli/phone-command.js +101 -0
  104. package/dist/src/cli/probe-command.d.ts +36 -0
  105. package/dist/src/cli/probe-command.js +59 -0
  106. package/dist/src/cli/project-settings.d.ts +4 -0
  107. package/dist/src/cli/project-settings.js +33 -0
  108. package/dist/src/cli/render.d.ts +3 -1
  109. package/dist/src/cli/render.js +102 -39
  110. package/dist/src/cli/report-github.d.ts +18 -0
  111. package/dist/src/cli/report-github.js +200 -0
  112. package/dist/src/cli/report.d.ts +17 -0
  113. package/dist/src/cli/report.js +192 -0
  114. package/dist/src/cli/repository-arguments.d.ts +5 -0
  115. package/dist/src/cli/repository-arguments.js +34 -0
  116. package/dist/src/cli/runtime-arguments.d.ts +4 -0
  117. package/dist/src/cli/runtime-arguments.js +15 -0
  118. package/dist/src/cli/runtime-directory.d.ts +6 -2
  119. package/dist/src/cli/runtime-directory.js +72 -14
  120. package/dist/src/cli/toolchain.d.ts +2 -0
  121. package/dist/src/cli/toolchain.js +22 -2
  122. package/dist/src/cli/usage-render.d.ts +5 -0
  123. package/dist/src/cli/usage-render.js +40 -1
  124. package/dist/src/cli/usage.d.ts +3 -3
  125. package/dist/src/cli/usage.js +74 -45
  126. package/dist/src/cli/watch-actions.d.ts +2 -0
  127. package/dist/src/cli/watch-actions.js +4 -4
  128. package/dist/src/cli/watch-board-view.d.ts +12 -1
  129. package/dist/src/cli/watch-board-view.js +64 -12
  130. package/dist/src/cli/watch-board.d.ts +7 -1
  131. package/dist/src/cli/watch-board.js +61 -16
  132. package/dist/src/cli/watch-card-forms.js +2 -2
  133. package/dist/src/cli/watch-client.d.ts +1 -1
  134. package/dist/src/cli/watch-client.js +12 -3
  135. package/dist/src/cli/watch-header-view.d.ts +27 -0
  136. package/dist/src/cli/watch-header-view.js +116 -0
  137. package/dist/src/cli/watch-model.d.ts +10 -4
  138. package/dist/src/cli/watch-model.js +49 -59
  139. package/dist/src/cli/watch-page.js +67 -14
  140. package/dist/src/cli/watch-phases.js +3 -3
  141. package/dist/src/cli/watch-phone-client.d.ts +1 -0
  142. package/dist/src/cli/watch-phone-client.js +84 -0
  143. package/dist/src/cli/watch-phone-view.d.ts +56 -0
  144. package/dist/src/cli/watch-phone-view.js +113 -0
  145. package/dist/src/cli/watch-phone.d.ts +5 -0
  146. package/dist/src/cli/watch-phone.js +53 -0
  147. package/dist/src/cli/watch-pr-command.d.ts +5 -2
  148. package/dist/src/cli/watch-pr-command.js +41 -4
  149. package/dist/src/cli/watch-pr-identity.d.ts +14 -2
  150. package/dist/src/cli/watch-pr-identity.js +25 -0
  151. package/dist/src/cli/watch-pr-observer.d.ts +1 -0
  152. package/dist/src/cli/watch-pr-observer.js +48 -6
  153. package/dist/src/cli/watch-pull-request.d.ts +12 -0
  154. package/dist/src/cli/watch-pull-request.js +134 -0
  155. package/dist/src/cli/watch-reads.d.ts +7 -1
  156. package/dist/src/cli/watch-reads.js +42 -20
  157. package/dist/src/cli/watch-render.d.ts +23 -2
  158. package/dist/src/cli/watch-render.js +2 -1
  159. package/dist/src/cli/watch-server.js +56 -7
  160. package/dist/src/cli/watch-turn.d.ts +4 -1
  161. package/dist/src/cli/watch-turn.js +38 -2
  162. package/dist/src/cli/watch-usage.js +5 -1
  163. package/dist/src/cli/watch-view.d.ts +10 -17
  164. package/dist/src/cli/watch-view.js +33 -77
  165. package/dist/src/cli.js +106 -23
  166. package/dist/src/command-settings.d.ts +16 -0
  167. package/dist/src/command-settings.js +42 -0
  168. package/dist/src/configuration-change.d.ts +11 -0
  169. package/dist/src/configuration-change.js +62 -0
  170. package/dist/src/configuration-display.d.ts +21 -0
  171. package/dist/src/configuration-display.js +69 -0
  172. package/dist/src/configuration-schema.d.ts +49 -0
  173. package/dist/src/configuration-schema.js +159 -0
  174. package/dist/src/daemon/claude-turn.d.ts +20 -5
  175. package/dist/src/daemon/claude-turn.js +116 -53
  176. package/dist/src/daemon/claude-worker.d.ts +3 -5
  177. package/dist/src/daemon/claude-worker.js +64 -80
  178. package/dist/src/daemon/command-journal.d.ts +5 -0
  179. package/dist/src/daemon/command-journal.js +50 -0
  180. package/dist/src/daemon/command-process.d.ts +28 -0
  181. package/dist/src/daemon/command-process.js +164 -0
  182. package/dist/src/daemon/command-worker.d.ts +19 -0
  183. package/dist/src/daemon/command-worker.js +182 -0
  184. package/dist/src/daemon/cursor-stream.d.ts +4 -0
  185. package/dist/src/daemon/cursor-stream.js +154 -0
  186. package/dist/src/daemon/daemon-adapters.d.ts +58 -0
  187. package/dist/src/daemon/daemon-adapters.js +102 -0
  188. package/dist/src/daemon/daemon-loops.d.ts +14 -0
  189. package/dist/src/daemon/daemon-loops.js +39 -0
  190. package/dist/src/daemon/daemon.d.ts +3 -30
  191. package/dist/src/daemon/daemon.js +132 -110
  192. package/dist/src/daemon/declared-input.d.ts +3 -0
  193. package/dist/src/daemon/declared-input.js +9 -0
  194. package/dist/src/daemon/delivery-router.js +7 -1
  195. package/dist/src/daemon/gemini-stream.d.ts +4 -0
  196. package/dist/src/daemon/gemini-stream.js +129 -0
  197. package/dist/src/daemon/github-calls.d.ts +4 -0
  198. package/dist/src/daemon/github-calls.js +16 -7
  199. package/dist/src/daemon/github-ci-rerun.d.ts +26 -0
  200. package/dist/src/daemon/github-ci-rerun.js +92 -0
  201. package/dist/src/daemon/github-ci.d.ts +6 -0
  202. package/dist/src/daemon/github-ci.js +251 -0
  203. package/dist/src/daemon/github-merge-call.d.ts +16 -0
  204. package/dist/src/daemon/github-merge-call.js +73 -0
  205. package/dist/src/daemon/github-merge.d.ts +3 -5
  206. package/dist/src/daemon/github-merge.js +59 -98
  207. package/dist/src/daemon/github-methods.d.ts +28 -0
  208. package/dist/src/daemon/github-methods.js +90 -16
  209. package/dist/src/daemon/github-operation.d.ts +3 -0
  210. package/dist/src/daemon/github-retry.d.ts +6 -0
  211. package/dist/src/daemon/github-retry.js +13 -0
  212. package/dist/src/daemon/github-ticket-status.js +27 -1
  213. package/dist/src/daemon/github-worker.js +2 -1
  214. package/dist/src/daemon/handoff-worker.d.ts +10 -0
  215. package/dist/src/daemon/handoff-worker.js +232 -0
  216. package/dist/src/daemon/issue-queue.d.ts +2 -0
  217. package/dist/src/daemon/issue-queue.js +92 -63
  218. package/dist/src/daemon/notify-journal.d.ts +18 -0
  219. package/dist/src/daemon/notify-journal.js +108 -0
  220. package/dist/src/daemon/notify-message.js +2 -1
  221. package/dist/src/daemon/notify.js +177 -37
  222. package/dist/src/daemon/opencode-stream.d.ts +5 -0
  223. package/dist/src/daemon/opencode-stream.js +87 -0
  224. package/dist/src/daemon/queue-status.d.ts +4 -0
  225. package/dist/src/daemon/queue-status.js +38 -0
  226. package/dist/src/daemon/retry-worktree.d.ts +18 -0
  227. package/dist/src/daemon/retry-worktree.js +139 -0
  228. package/dist/src/daemon/retrying-turn.d.ts +5 -0
  229. package/dist/src/daemon/retrying-turn.js +145 -21
  230. package/dist/src/daemon/schedule-journal.d.ts +19 -0
  231. package/dist/src/daemon/schedule-journal.js +57 -0
  232. package/dist/src/daemon/text-output.d.ts +18 -0
  233. package/dist/src/daemon/text-output.js +44 -0
  234. package/dist/src/daemon/ticket-dependency-waits.d.ts +18 -0
  235. package/dist/src/daemon/ticket-dependency-waits.js +60 -0
  236. package/dist/src/daemon/ticket-registration.d.ts +10 -8
  237. package/dist/src/daemon/ticket-registration.js +146 -47
  238. package/dist/src/daemon/ticket-source.d.ts +4 -1
  239. package/dist/src/daemon/ticket-source.js +8 -2
  240. package/dist/src/daemon/turn-command.d.ts +10 -0
  241. package/dist/src/daemon/turn-command.js +33 -0
  242. package/dist/src/daemon/turn-report.d.ts +18 -0
  243. package/dist/src/daemon/turn-report.js +79 -0
  244. package/dist/src/daemon/work-tree.d.ts +2 -1
  245. package/dist/src/daemon/work-tree.js +15 -12
  246. package/dist/src/daemon/workflow-generations.d.ts +32 -0
  247. package/dist/src/daemon/workflow-generations.js +57 -0
  248. package/dist/src/daemon/workflow-replay.d.ts +16 -0
  249. package/dist/src/daemon/workflow-replay.js +58 -0
  250. package/dist/src/daemon/workflow-schedules.d.ts +27 -0
  251. package/dist/src/daemon/workflow-schedules.js +185 -0
  252. package/dist/src/decision-visibility.d.ts +2 -0
  253. package/dist/src/decision-visibility.js +10 -0
  254. package/dist/src/decision-wait.d.ts +1 -0
  255. package/dist/src/decision-wait.js +3 -0
  256. package/dist/src/delivery-backoff.d.ts +1 -0
  257. package/dist/src/delivery-backoff.js +3 -0
  258. package/dist/src/doctor-report.d.ts +24 -0
  259. package/dist/src/doctor-report.js +70 -0
  260. package/dist/src/execution-pin.d.ts +9 -0
  261. package/dist/src/execution-pin.js +86 -2
  262. package/dist/src/grok-result.d.ts +12 -0
  263. package/dist/src/grok-result.js +61 -0
  264. package/dist/src/harness-defaults.d.ts +35 -0
  265. package/dist/src/harness-defaults.js +121 -0
  266. package/dist/src/host/decision-resume.d.ts +35 -0
  267. package/dist/src/host/decision-resume.js +86 -0
  268. package/dist/src/host/gate-bridge.d.ts +48 -0
  269. package/dist/src/host/gate-bridge.js +124 -0
  270. package/dist/src/host/run-wait.d.ts +26 -0
  271. package/dist/src/host/run-wait.js +37 -0
  272. package/dist/src/host/start-delivery.d.ts +3 -2
  273. package/dist/src/host/start-delivery.js +11 -4
  274. package/dist/src/host/step-bridge-host.d.ts +6 -19
  275. package/dist/src/host/step-bridge-host.js +57 -55
  276. package/dist/src/host/world-reconciliation.d.ts +1 -0
  277. package/dist/src/host/world-reconciliation.js +3 -0
  278. package/dist/src/host/world-runs.js +5 -0
  279. package/dist/src/issue-identity.d.ts +6 -0
  280. package/dist/src/issue-identity.js +23 -0
  281. package/dist/src/merge-request.d.ts +19 -0
  282. package/dist/src/merge-request.js +32 -0
  283. package/dist/src/phone/canonical-json.d.ts +1 -0
  284. package/dist/src/phone/canonical-json.js +16 -0
  285. package/dist/src/phone/phone-link.d.ts +7 -0
  286. package/dist/src/phone/phone-link.js +21 -0
  287. package/dist/src/phone/qr-data.d.ts +8 -0
  288. package/dist/src/phone/qr-data.js +133 -0
  289. package/dist/src/phone/qr-matrix.d.ts +6 -0
  290. package/dist/src/phone/qr-matrix.js +175 -0
  291. package/dist/src/phone/qr-penalty.d.ts +3 -0
  292. package/dist/src/phone/qr-penalty.js +67 -0
  293. package/dist/src/phone/qr-picture.d.ts +5 -0
  294. package/dist/src/phone/qr-picture.js +24 -0
  295. package/dist/src/private-config.schema.json +263 -0
  296. package/dist/src/project-config.schema.json +65 -0
  297. package/dist/src/project-settings.d.ts +19 -0
  298. package/dist/src/project-settings.js +131 -0
  299. package/dist/src/relay/answer-check.d.ts +24 -0
  300. package/dist/src/relay/answer-check.js +145 -0
  301. package/dist/src/relay/answer-inbox.d.ts +15 -0
  302. package/dist/src/relay/answer-inbox.js +173 -0
  303. package/dist/src/relay/daemon-keys.d.ts +16 -0
  304. package/dist/src/relay/daemon-keys.js +75 -0
  305. package/dist/src/relay/decision-check.d.ts +3 -0
  306. package/dist/src/relay/decision-check.js +77 -0
  307. package/dist/src/relay/decision-close.d.ts +6 -0
  308. package/dist/src/relay/decision-close.js +72 -0
  309. package/dist/src/relay/decision-envelopes.d.ts +29 -0
  310. package/dist/src/relay/decision-envelopes.js +93 -0
  311. package/dist/src/relay/decision-watch.d.ts +14 -0
  312. package/dist/src/relay/decision-watch.js +68 -0
  313. package/dist/src/relay/envelope-post.d.ts +8 -0
  314. package/dist/src/relay/envelope-post.js +71 -0
  315. package/dist/src/relay/envelope.d.ts +28 -0
  316. package/dist/src/relay/envelope.js +53 -0
  317. package/dist/src/relay/hpke.d.ts +25 -0
  318. package/dist/src/relay/hpke.js +108 -0
  319. package/dist/src/relay/pairing-checks.d.ts +42 -0
  320. package/dist/src/relay/pairing-checks.js +172 -0
  321. package/dist/src/relay/pairing-follow.d.ts +8 -0
  322. package/dist/src/relay/pairing-follow.js +95 -0
  323. package/dist/src/relay/pairing-session.d.ts +29 -0
  324. package/dist/src/relay/pairing-session.js +87 -0
  325. package/dist/src/relay/phone-delivery.d.ts +51 -0
  326. package/dist/src/relay/phone-delivery.js +139 -0
  327. package/dist/src/relay/phone-devices.d.ts +36 -0
  328. package/dist/src/relay/phone-devices.js +46 -0
  329. package/dist/src/relay/phone-inbox.d.ts +18 -0
  330. package/dist/src/relay/phone-inbox.js +17 -0
  331. package/dist/src/relay/phone-operations.d.ts +18 -0
  332. package/dist/src/relay/phone-operations.js +121 -0
  333. package/dist/src/relay/phone-outbox.d.ts +21 -0
  334. package/dist/src/relay/phone-outbox.js +25 -0
  335. package/dist/src/relay/phone-socket.d.ts +6 -0
  336. package/dist/src/relay/phone-socket.js +63 -0
  337. package/dist/src/relay/relay-control.d.ts +7 -0
  338. package/dist/src/relay/relay-control.js +24 -0
  339. package/dist/src/relay/relay-files.d.ts +2 -0
  340. package/dist/src/relay/relay-files.js +23 -0
  341. package/dist/src/relay/relay-heartbeat.d.ts +17 -0
  342. package/dist/src/relay/relay-heartbeat.js +81 -0
  343. package/dist/src/relay/relay-http.d.ts +14 -0
  344. package/dist/src/relay/relay-http.js +63 -0
  345. package/dist/src/relay/relay-registration.d.ts +15 -0
  346. package/dist/src/relay/relay-registration.js +63 -0
  347. package/dist/src/relay/relay-service.d.ts +25 -0
  348. package/dist/src/relay/relay-service.js +216 -0
  349. package/dist/src/relay/relay-store.d.ts +48 -0
  350. package/dist/src/relay/relay-store.js +131 -0
  351. package/dist/src/relay/sealed-post.d.ts +25 -0
  352. package/dist/src/relay/sealed-post.js +52 -0
  353. package/dist/src/relay.d.ts +1 -0
  354. package/dist/src/relay.js +8 -0
  355. package/dist/src/report-statistics.d.ts +50 -0
  356. package/dist/src/report-statistics.js +70 -0
  357. package/dist/src/report.d.ts +171 -0
  358. package/dist/src/report.js +119 -0
  359. package/dist/src/repository-identity.d.ts +4 -0
  360. package/dist/src/repository-identity.js +4 -0
  361. package/dist/src/review-subject.d.ts +41 -0
  362. package/dist/src/review-subject.js +91 -0
  363. package/dist/src/run-wait.d.ts +23 -0
  364. package/dist/src/run-wait.js +20 -0
  365. package/dist/src/service/active-tickets.d.ts +4 -0
  366. package/dist/src/service/active-tickets.js +49 -0
  367. package/dist/src/service/command-effects.d.ts +4 -0
  368. package/dist/src/service/command-effects.js +16 -0
  369. package/dist/src/service/decision-handler.d.ts +4 -0
  370. package/dist/src/service/decision-handler.js +39 -4
  371. package/dist/src/service/gateway.js +18 -3
  372. package/dist/src/service/queue-runs.d.ts +3 -0
  373. package/dist/src/service/queue-runs.js +39 -0
  374. package/dist/src/service/registry.d.ts +22 -3
  375. package/dist/src/service/registry.js +51 -8
  376. package/dist/src/service/replies.d.ts +10 -0
  377. package/dist/src/service/replies.js +12 -0
  378. package/dist/src/service/run-handlers.js +45 -54
  379. package/dist/src/service/run-metadata.d.ts +8 -0
  380. package/dist/src/service/run-metadata.js +53 -0
  381. package/dist/src/service/run-waits.d.ts +3 -0
  382. package/dist/src/service/run-waits.js +41 -0
  383. package/dist/src/service/service.d.ts +21 -2
  384. package/dist/src/service/service.js +23 -5
  385. package/dist/src/service/submission-handler.js +70 -19
  386. package/dist/src/service/worker-port.d.ts +1 -0
  387. package/dist/src/service/worker-totals.js +10 -1
  388. package/dist/src/step-bridge.d.ts +32 -0
  389. package/dist/src/steps/decision-gate.d.ts +2 -1
  390. package/dist/src/steps/decision-gate.js +7 -0
  391. package/dist/src/steps/handoff.d.ts +2 -0
  392. package/dist/src/steps/handoff.js +13 -0
  393. package/dist/src/steps/merge-by-person.d.ts +2 -0
  394. package/dist/src/steps/merge-by-person.js +18 -0
  395. package/dist/src/steps/merge-when-green.d.ts +2 -0
  396. package/dist/src/steps/merge-when-green.js +62 -0
  397. package/dist/src/steps/review-by-agent.d.ts +5 -0
  398. package/dist/src/steps/review-by-agent.js +124 -0
  399. package/dist/src/steps/review-by-person.d.ts +4 -0
  400. package/dist/src/steps/review-by-person.js +16 -0
  401. package/dist/src/steps/review-subject.d.ts +2 -0
  402. package/dist/src/steps/review-subject.js +11 -0
  403. package/dist/src/steps/run-command.d.ts +2 -0
  404. package/dist/src/steps/run-command.js +15 -0
  405. package/dist/src/steps/sleep.d.ts +3 -0
  406. package/dist/src/steps/sleep.js +19 -0
  407. package/dist/src/steps/wait-for-decision.d.ts +2 -0
  408. package/dist/src/steps/wait-for-decision.js +71 -0
  409. package/dist/src/steps/wait-for-run.d.ts +5 -0
  410. package/dist/src/steps/wait-for-run.js +9 -0
  411. package/dist/src/storage/decision-snapshots.d.ts +1 -0
  412. package/dist/src/storage/decision-snapshots.js +7 -1
  413. package/dist/src/submission.d.ts +4 -0
  414. package/dist/src/submission.js +6 -2
  415. package/dist/src/testing.d.ts +29 -0
  416. package/dist/src/testing.js +264 -0
  417. package/dist/src/ticket-dependencies.d.ts +1 -0
  418. package/dist/src/ticket-dependencies.js +15 -0
  419. package/dist/src/ticket-status-stream.d.ts +9 -0
  420. package/dist/src/ticket-status-stream.js +94 -0
  421. package/dist/src/ticket-status.js +7 -4
  422. package/dist/src/token-prices.d.ts +14 -4
  423. package/dist/src/token-prices.js +56 -11
  424. package/dist/src/turn-profile.d.ts +1 -0
  425. package/dist/src/turn-profile.js +8 -1
  426. package/dist/src/worker-usage.d.ts +25 -0
  427. package/dist/src/worker-usage.js +58 -1
  428. package/dist/src/workflow-admission.d.ts +6 -0
  429. package/dist/src/workflow-candidate.d.ts +7 -2
  430. package/dist/src/workflow-candidate.js +48 -5
  431. package/dist/src/workflow-contracts.d.ts +2 -0
  432. package/dist/src/workflow-contracts.js +8 -3
  433. package/dist/src/workflow-declaration.d.ts +31 -2
  434. package/dist/src/workflow-declaration.js +140 -16
  435. package/dist/src/workflow-discovery.d.ts +19 -0
  436. package/dist/src/workflow-discovery.js +36 -0
  437. package/dist/src/workflow-refusals.d.ts +6 -0
  438. package/dist/src/workflow-refusals.js +42 -0
  439. package/dist/src/workflow-schedule.d.ts +22 -0
  440. package/dist/src/workflow-schedule.js +53 -0
  441. package/dist/src/workflows.d.ts +12 -1
  442. package/dist/src/workflows.js +9 -0
  443. package/dist/tools/admit-workflow.d.ts +14 -0
  444. package/dist/tools/admit-workflow.js +107 -0
  445. package/dist/tools/doctor-adoption.d.ts +1 -0
  446. package/dist/tools/doctor-adoption.js +11 -0
  447. package/dist/tools/project-configuration.d.ts +4 -0
  448. package/dist/tools/project-configuration.js +47 -0
  449. package/dist/tools/self-host-processes.d.ts +1 -0
  450. package/dist/tools/self-host-processes.js +33 -22
  451. package/dist/tools/self-host-project.d.ts +21 -0
  452. package/dist/tools/self-host-project.js +224 -0
  453. package/dist/tools/self-host-runtime.d.ts +16 -0
  454. package/dist/tools/self-host-runtime.js +60 -0
  455. package/dist/tools/self-host-workflows.d.ts +1 -0
  456. package/dist/tools/self-host-workflows.js +36 -1
  457. package/dist/tools/self-host.js +106 -135
  458. package/dist/tools/workflow-bundle-dependencies.d.ts +5 -0
  459. package/dist/tools/workflow-bundle-dependencies.js +93 -0
  460. package/dist/tools/workflow-bundles.d.ts +20 -0
  461. package/dist/tools/workflow-bundles.js +173 -0
  462. package/dist/tools/workflow-candidate-counts.d.ts +12 -0
  463. package/dist/tools/workflow-candidate-counts.js +266 -0
  464. package/dist/tools/workflow-candidate-fields.d.ts +5 -0
  465. package/dist/tools/workflow-candidate-fields.js +24 -0
  466. package/dist/tools/workflow-candidate-helper-counts.d.ts +10 -0
  467. package/dist/tools/workflow-candidate-helper-counts.js +129 -0
  468. package/dist/tools/workflow-candidate-program.d.ts +13 -0
  469. package/dist/tools/workflow-candidate-program.js +106 -0
  470. package/dist/tools/workflow-candidate-source.d.ts +6 -0
  471. package/dist/tools/workflow-candidate-source.js +169 -0
  472. package/dist/tools/workflow-candidate-syntax.d.ts +21 -0
  473. package/dist/tools/workflow-candidate-syntax.js +263 -0
  474. package/dist/tools/workflow-command.d.ts +1 -0
  475. package/dist/tools/workflow-command.js +143 -0
  476. package/dist/tools/workflow-folder-capture.d.ts +18 -0
  477. package/dist/tools/workflow-folder-capture.js +261 -0
  478. package/dist/tools/workflow-folders.d.ts +49 -0
  479. package/dist/tools/workflow-folders.js +203 -0
  480. package/dist/tools/workflow-source-effects.d.ts +10 -0
  481. package/dist/tools/workflow-source-effects.js +213 -0
  482. package/dist/tools/workflow-test-hook.d.ts +7 -0
  483. package/dist/tools/workflow-test-hook.js +16 -0
  484. package/dist/tools/workflow-test-loader.d.ts +1 -0
  485. package/dist/tools/workflow-test-loader.js +10 -0
  486. package/dist/workflows/develop-prd.js +71 -3
  487. package/dist/workflows/develop-ticket.js +6 -1
  488. package/dist/workflows/ticket-prompts.js +17 -3
  489. package/package.json +66 -6
  490. package/templates/develop/README.md +78 -0
  491. package/templates/develop/develop/accept.ts +11 -0
  492. package/templates/develop/develop/flow-tests.ts +357 -0
  493. package/templates/develop/develop/local.ts +40 -0
  494. package/templates/develop/develop/option-tests.ts +174 -0
  495. package/templates/develop/develop/partial-choice.ts +29 -0
  496. package/templates/develop/develop/partial.ts +28 -0
  497. package/templates/develop/develop/pull.ts +152 -0
  498. package/templates/develop/develop/queue-partial.ts +39 -0
  499. package/templates/develop/develop/refusal-tests.ts +174 -0
  500. package/templates/develop/develop/report.ts +156 -0
  501. package/templates/develop/develop/round.ts +40 -0
  502. package/templates/develop/develop/scenarios.ts +87 -0
  503. package/templates/develop/develop/turn.ts +67 -0
  504. package/templates/develop/develop.declaration.json +24 -0
  505. package/templates/develop/develop.test.ts +287 -0
  506. package/templates/develop/develop.ts +30 -0
  507. package/templates/develop/template.json +153 -0
  508. package/dist/src/chats/analysis-batches.d.ts +0 -24
  509. package/dist/src/chats/analysis-batches.js +0 -83
  510. package/dist/src/chats/analysis-contract.d.ts +0 -80
  511. package/dist/src/chats/analysis-contract.js +0 -16
  512. package/dist/src/chats/analysis-data.d.ts +0 -3
  513. package/dist/src/chats/analysis-data.js +0 -85
  514. package/dist/src/chats/analysis-input.d.ts +0 -12
  515. package/dist/src/chats/analysis-input.js +0 -83
  516. package/dist/src/chats/analysis-links.d.ts +0 -2
  517. package/dist/src/chats/analysis-links.js +0 -25
  518. package/dist/src/chats/analysis-prompt.d.ts +0 -10
  519. package/dist/src/chats/analysis-prompt.js +0 -16
  520. package/dist/src/chats/analysis-proposal.d.ts +0 -2
  521. package/dist/src/chats/analysis-proposal.js +0 -32
  522. package/dist/src/chats/analysis-provenance.d.ts +0 -4
  523. package/dist/src/chats/analysis-provenance.js +0 -99
  524. package/dist/src/chats/analysis-shape.d.ts +0 -3
  525. package/dist/src/chats/analysis-shape.js +0 -228
  526. package/dist/src/chats/analysis.d.ts +0 -3
  527. package/dist/src/chats/analysis.js +0 -42
  528. package/dist/src/chats/corpus-input.d.ts +0 -5
  529. package/dist/src/chats/corpus-input.js +0 -288
  530. package/dist/src/chats/destination.d.ts +0 -4
  531. package/dist/src/chats/destination.js +0 -96
  532. package/dist/src/chats/import.d.ts +0 -15
  533. package/dist/src/chats/import.js +0 -243
  534. package/dist/src/chats/input-file.d.ts +0 -3
  535. package/dist/src/chats/input-file.js +0 -32
  536. package/dist/src/chats/normalize.d.ts +0 -29
  537. package/dist/src/chats/normalize.js +0 -155
  538. package/dist/src/chats/previous-import.d.ts +0 -5
  539. package/dist/src/chats/previous-import.js +0 -34
  540. package/dist/src/chats/reader.d.ts +0 -21
  541. package/dist/src/chats/reader.js +0 -118
  542. package/dist/src/chats/redact-import.d.ts +0 -14
  543. package/dist/src/chats/redact-import.js +0 -141
  544. package/dist/src/chats/redaction.d.ts +0 -41
  545. package/dist/src/chats/redaction.js +0 -161
  546. package/dist/src/chats/revision-input.d.ts +0 -3
  547. package/dist/src/chats/revision-input.js +0 -180
  548. package/dist/src/chats/revision.d.ts +0 -48
  549. package/dist/src/chats/revision.js +0 -94
  550. package/dist/src/chats/selection.d.ts +0 -25
  551. package/dist/src/chats/selection.js +0 -109
  552. package/dist/src/chats/source.d.ts +0 -23
  553. package/dist/src/chats/source.js +0 -135
  554. package/dist/src/chats/structure.d.ts +0 -57
  555. package/dist/src/chats/structure.js +0 -216
  556. package/dist/src/daemon/analysis-launch.d.ts +0 -5
  557. package/dist/src/daemon/analysis-launch.js +0 -81
  558. package/dist/src/daemon/analysis-token.d.ts +0 -6
  559. package/dist/src/daemon/analysis-token.js +0 -88
  560. package/dist/src/daemon/analysis-worker.d.ts +0 -22
  561. package/dist/src/daemon/analysis-worker.js +0 -219
  562. package/dist/src/daemon/chats-files.d.ts +0 -15
  563. package/dist/src/daemon/chats-files.js +0 -113
  564. package/dist/src/daemon/chats-worker.d.ts +0 -12
  565. package/dist/src/daemon/chats-worker.js +0 -200
  566. package/dist/workflows/analyze-chats.d.ts +0 -10
  567. package/dist/workflows/analyze-chats.declaration.json +0 -9
  568. package/dist/workflows/analyze-chats.js +0 -73
@@ -0,0 +1,173 @@
1
+ import { createHash } from "node:crypto";
2
+ import { constants } from "node:fs";
3
+ import { lstat, mkdir, mkdtemp, open, readdir, realpath, rename, rm, writeFile, } from "node:fs/promises";
4
+ import { dirname, join } from "node:path";
5
+ const unavailable = {
6
+ kind: "unavailable",
7
+ code: "pinned-workflow-unavailable",
8
+ };
9
+ export async function readRetainedWorkflowBundle(input) {
10
+ if (!/^[a-f0-9]{64}$/.test(input.id))
11
+ return unavailable;
12
+ try {
13
+ const directory = join(input.directory, input.id);
14
+ if (!(await lstat(directory)).isDirectory())
15
+ return unavailable;
16
+ const repository = await realpath(input.repository);
17
+ const contents = bundleContents(repository, await projectFiles(directory));
18
+ const stored = await regularFile(join(directory, "bundle.json"));
19
+ if (digest(contents) !== input.id || stored.toString("utf8") !== contents)
20
+ return unavailable;
21
+ return { kind: "available", directory };
22
+ }
23
+ catch {
24
+ return unavailable;
25
+ }
26
+ }
27
+ function digest(bytes) {
28
+ return createHash("sha256").update(bytes).digest("hex");
29
+ }
30
+ async function regularFile(path) {
31
+ const file = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
32
+ try {
33
+ if (!(await file.stat()).isFile())
34
+ throw new Error("invalid-bundle-file");
35
+ return await file.readFile();
36
+ }
37
+ finally {
38
+ await file.close();
39
+ }
40
+ }
41
+ async function treeFiles(root, name) {
42
+ const path = join(root, name);
43
+ const entry = await lstat(path);
44
+ if (entry.isFile())
45
+ return [{ name, bytes: await regularFile(path) }];
46
+ if (!entry.isDirectory())
47
+ throw new Error("invalid-bundle-file");
48
+ const files = [];
49
+ for (const child of (await readdir(path)).sort())
50
+ files.push(...(await treeFiles(root, `${name}/${child}`)));
51
+ return files;
52
+ }
53
+ async function projectFiles(project) {
54
+ const files = [];
55
+ const names = (await readdir(project)).filter((name) => name.endsWith(".json") && name !== "bundle.json");
56
+ for (const name of [...names, "artifacts", "workflows"].sort())
57
+ files.push(...(await treeFiles(project, name)));
58
+ const required = [
59
+ "package.json",
60
+ "declarations.json",
61
+ "dependencies.json",
62
+ ...[
63
+ "client.mjs",
64
+ "flow.mjs",
65
+ "steps.mjs",
66
+ "manifest.json",
67
+ "flow.mjs.__wf_tmp.js.debug.json",
68
+ "steps.mjs.debug.json",
69
+ ].map((name) => `artifacts/${name}`),
70
+ ];
71
+ if (required.some((name) => !files.some((file) => file.name === name)))
72
+ throw new Error("incomplete-workflow-bundle");
73
+ return files;
74
+ }
75
+ function bundleContents(repository, files) {
76
+ return JSON.stringify({
77
+ schemaVersion: 1,
78
+ repository,
79
+ files: Object.fromEntries(files.map(({ name, bytes }) => [name, digest(bytes)])),
80
+ });
81
+ }
82
+ async function validatedId(input) {
83
+ if ((await readRetainedWorkflowBundle(input)).kind !== "available")
84
+ throw new Error("pinned-workflow-unavailable");
85
+ return input.id;
86
+ }
87
+ async function existingEntry(path) {
88
+ return lstat(path).catch((error) => {
89
+ if (error instanceof Error && "code" in error && error.code === "ENOENT")
90
+ return undefined;
91
+ throw error;
92
+ });
93
+ }
94
+ async function retainedBefore(input, contents) {
95
+ try {
96
+ const history = join(input.directory, ".history");
97
+ await mkdir(history, { recursive: true, mode: 0o700 });
98
+ if (!(await lstat(history)).isDirectory())
99
+ throw new Error("pinned-workflow-unavailable");
100
+ const directory = join(history, input.id);
101
+ const entry = await existingEntry(directory);
102
+ if (entry === undefined)
103
+ return false;
104
+ if (!entry.isDirectory())
105
+ throw new Error("pinned-workflow-unavailable");
106
+ const receipt = await regularFile(join(directory, "bundle.json"));
107
+ if (receipt.toString("utf8") !== contents)
108
+ throw new Error("pinned-workflow-unavailable");
109
+ return true;
110
+ }
111
+ catch {
112
+ throw new Error("pinned-workflow-unavailable");
113
+ }
114
+ }
115
+ async function rememberBundle(input, contents) {
116
+ const history = join(input.directory, ".history");
117
+ const temporary = await mkdtemp(join(history, ".pending-"));
118
+ try {
119
+ await writeFile(join(temporary, "bundle.json"), contents, {
120
+ flag: "wx",
121
+ mode: 0o600,
122
+ });
123
+ await publishDirectory(temporary, join(history, input.id));
124
+ await retainedBefore(input, contents);
125
+ }
126
+ finally {
127
+ await rm(temporary, { recursive: true, force: true });
128
+ }
129
+ }
130
+ async function publishDirectory(from, to) {
131
+ await rename(from, to).catch((error) => {
132
+ if (error instanceof Error &&
133
+ "code" in error &&
134
+ ["ENOTEMPTY", "EEXIST"].includes(String(error.code)))
135
+ return;
136
+ throw error;
137
+ });
138
+ }
139
+ export async function retainWorkflowBundle(input) {
140
+ const repository = await realpath(input.repository);
141
+ const files = await projectFiles(input.project);
142
+ const contents = bundleContents(repository, files);
143
+ const id = digest(contents);
144
+ await mkdir(input.directory, { recursive: true, mode: 0o700 });
145
+ const destination = join(input.directory, id);
146
+ const lookup = { ...input, id };
147
+ if (await retainedBefore(lookup, contents))
148
+ return validatedId(lookup);
149
+ if (await existingEntry(destination)) {
150
+ await validatedId(lookup);
151
+ await rememberBundle(lookup, contents);
152
+ return id;
153
+ }
154
+ const temporary = await mkdtemp(join(input.directory, ".pending-"));
155
+ try {
156
+ for (const { name, bytes } of files) {
157
+ const path = join(temporary, name);
158
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 });
159
+ await writeFile(path, bytes, { flag: "wx", mode: 0o600 });
160
+ }
161
+ await writeFile(join(temporary, "bundle.json"), contents, {
162
+ flag: "wx",
163
+ mode: 0o600,
164
+ });
165
+ await publishDirectory(temporary, destination);
166
+ }
167
+ finally {
168
+ await rm(temporary, { recursive: true, force: true });
169
+ }
170
+ await validatedId(lookup);
171
+ await rememberBundle(lookup, contents);
172
+ return id;
173
+ }
@@ -0,0 +1,12 @@
1
+ import ts from "typescript";
2
+ import { type CandidateSymbols } from "./workflow-candidate-syntax.ts";
3
+ export interface Totals {
4
+ readonly knownCallCount: number;
5
+ readonly knownUnitTotal: number;
6
+ }
7
+ interface CountSymbols extends CandidateSymbols {
8
+ readonly localTotals?: (node: ts.Node) => Totals | undefined;
9
+ }
10
+ export declare function candidateEffectTotals(source: ts.Node, symbols: CountSymbols): Totals;
11
+ export declare function candidateLoopRepetitions(node: ts.IterationStatement, symbols: CandidateSymbols): number | undefined;
12
+ export {};
@@ -0,0 +1,266 @@
1
+ import ts from "typescript";
2
+ import { protectedCall, helperCall, } from "./workflow-candidate-syntax.js";
3
+ import { propertyName } from "./workflow-candidate-fields.js";
4
+ import { referenceSymbol } from "./workflow-source-effects.js";
5
+ const zero = { knownCallCount: 0, knownUnitTotal: 0 };
6
+ function add(first, second) {
7
+ return {
8
+ knownCallCount: Math.min(Number.MAX_SAFE_INTEGER, first.knownCallCount + second.knownCallCount),
9
+ knownUnitTotal: Math.min(Number.MAX_SAFE_INTEGER, first.knownUnitTotal + second.knownUnitTotal),
10
+ };
11
+ }
12
+ function maximum(first, second) {
13
+ return {
14
+ knownCallCount: Math.max(first.knownCallCount, second.knownCallCount),
15
+ knownUnitTotal: Math.max(first.knownUnitTotal, second.knownUnitTotal),
16
+ };
17
+ }
18
+ function multiply(total, repetitions) {
19
+ return {
20
+ knownCallCount: Math.min(Number.MAX_SAFE_INTEGER, total.knownCallCount * repetitions),
21
+ knownUnitTotal: Math.min(Number.MAX_SAFE_INTEGER, total.knownUnitTotal * repetitions),
22
+ };
23
+ }
24
+ function units(node, symbols) {
25
+ if (helperCall(node, symbols))
26
+ return 1;
27
+ const argument = node.arguments[0];
28
+ if (!argument || !ts.isObjectLiteralExpression(argument))
29
+ return 0;
30
+ const property = argument.properties.find((entry) => entry.name && propertyName(entry.name) === "units");
31
+ if (!property || !ts.isPropertyAssignment(property))
32
+ return 0;
33
+ const value = Number(constantNumber(property.initializer));
34
+ return Number.isSafeInteger(value) && value > 0 ? value : 0;
35
+ }
36
+ function loopIncrement(node, variable) {
37
+ if ((ts.isPostfixUnaryExpression(node) || ts.isPrefixUnaryExpression(node)) &&
38
+ ts.isIdentifier(node.operand) &&
39
+ node.operand.text === variable)
40
+ return unaryIncrement(node.operator);
41
+ return assignmentIncrement(node, variable);
42
+ }
43
+ function unaryIncrement(operator) {
44
+ if (operator === ts.SyntaxKind.PlusPlusToken)
45
+ return 1;
46
+ if (operator === ts.SyntaxKind.MinusMinusToken)
47
+ return -1;
48
+ return undefined;
49
+ }
50
+ function assignmentIncrement(node, variable) {
51
+ if (!ts.isBinaryExpression(node) ||
52
+ !ts.isIdentifier(node.left) ||
53
+ node.left.text !== variable)
54
+ return undefined;
55
+ const amount = constantNumber(node.right);
56
+ if (amount === undefined)
57
+ return undefined;
58
+ if (node.operatorToken.kind === ts.SyntaxKind.PlusEqualsToken)
59
+ return amount;
60
+ if (node.operatorToken.kind === ts.SyntaxKind.MinusEqualsToken)
61
+ return -amount;
62
+ return undefined;
63
+ }
64
+ function constantNumber(node) {
65
+ if (ts.isParenthesizedExpression(node))
66
+ return constantNumber(node.expression);
67
+ if (ts.isNumericLiteral(node)) {
68
+ const value = Number(node.text);
69
+ return Number.isFinite(value) ? value : undefined;
70
+ }
71
+ if (!ts.isPrefixUnaryExpression(node))
72
+ return undefined;
73
+ const value = constantNumber(node.operand);
74
+ if (value === undefined)
75
+ return undefined;
76
+ if (node.operator === ts.SyntaxKind.PlusToken)
77
+ return value;
78
+ if (node.operator === ts.SyntaxKind.MinusToken)
79
+ return -value;
80
+ return undefined;
81
+ }
82
+ function rangeIterations(input) {
83
+ const { start, end, increment, operator } = input;
84
+ if (![
85
+ ts.SyntaxKind.LessThanToken,
86
+ ts.SyntaxKind.LessThanEqualsToken,
87
+ ts.SyntaxKind.GreaterThanToken,
88
+ ts.SyntaxKind.GreaterThanEqualsToken,
89
+ ].includes(operator))
90
+ return undefined;
91
+ let iterations = 0;
92
+ let value = start;
93
+ while (iterations < 101 && loopContinues(value, { end, operator })) {
94
+ iterations += 1;
95
+ value += increment;
96
+ }
97
+ return iterations;
98
+ }
99
+ function loopContinues(value, condition) {
100
+ const { end, operator } = condition;
101
+ if (operator === ts.SyntaxKind.LessThanToken)
102
+ return value < end;
103
+ if (operator === ts.SyntaxKind.LessThanEqualsToken)
104
+ return value <= end;
105
+ if (operator === ts.SyntaxKind.GreaterThanToken)
106
+ return value > end;
107
+ return value >= end;
108
+ }
109
+ function referencesCounter(node, context) {
110
+ if (!context.counter)
111
+ return false;
112
+ if (ts.isIdentifier(node) &&
113
+ referenceSymbol(node, { parent: node.parent, checker: context.checker }) ===
114
+ context.counter)
115
+ return true;
116
+ return (ts.forEachChild(node, (child) => referencesCounter(child, context) ? true : undefined) ?? false);
117
+ }
118
+ function assignmentTarget(node) {
119
+ if (ts.isBinaryExpression(node) &&
120
+ node.operatorToken.kind >= ts.SyntaxKind.FirstAssignment &&
121
+ node.operatorToken.kind <= ts.SyntaxKind.LastAssignment)
122
+ return node.left;
123
+ if ((ts.isPrefixUnaryExpression(node) || ts.isPostfixUnaryExpression(node)) &&
124
+ unaryIncrement(node.operator) !== undefined)
125
+ return node.operand;
126
+ return undefined;
127
+ }
128
+ function writesCounter(node, context) {
129
+ if (ts.isVariableDeclaration(node) && node.initializer !== undefined)
130
+ return referencesCounter(node.name, context);
131
+ if (ts.isForOfStatement(node) || ts.isForInStatement(node))
132
+ return referencesCounter(node.initializer, context);
133
+ const target = assignmentTarget(node);
134
+ return target !== undefined && referencesCounter(target, context);
135
+ }
136
+ function uncertainLoopBody(node, context) {
137
+ if (ts.isBreakStatement(node) ||
138
+ ts.isContinueStatement(node) ||
139
+ ts.isReturnStatement(node) ||
140
+ ts.isThrowStatement(node) ||
141
+ writesCounter(node, context))
142
+ return true;
143
+ return (ts.forEachChild(node, (child) => uncertainLoopBody(child, context) ? true : undefined) ?? false);
144
+ }
145
+ function loopIterations(node, symbols) {
146
+ const { initializer, condition, incrementor } = node;
147
+ const declaration = loopStart(initializer);
148
+ if (!declaration)
149
+ return undefined;
150
+ if (!condition || !ts.isBinaryExpression(condition))
151
+ return undefined;
152
+ if (!ts.isIdentifier(condition.left) ||
153
+ condition.left.text !== declaration.variable.text)
154
+ return undefined;
155
+ if (!incrementor)
156
+ return undefined;
157
+ const end = constantNumber(condition.right);
158
+ if (end === undefined)
159
+ return undefined;
160
+ const increment = loopIncrement(incrementor, declaration.variable.text);
161
+ if (increment === undefined)
162
+ return undefined;
163
+ if (uncertainLoopBody(node.statement, {
164
+ checker: symbols.checker,
165
+ counter: symbols.checker.getSymbolAtLocation(declaration.variable),
166
+ }))
167
+ return undefined;
168
+ return rangeIterations({
169
+ start: declaration.start,
170
+ end,
171
+ increment,
172
+ operator: condition.operatorToken.kind,
173
+ });
174
+ }
175
+ function loopStart(initializer) {
176
+ if (!initializer ||
177
+ !ts.isVariableDeclarationList(initializer) ||
178
+ initializer.declarations.length !== 1)
179
+ return undefined;
180
+ const declaration = initializer.declarations[0];
181
+ if (!declaration ||
182
+ !ts.isIdentifier(declaration.name) ||
183
+ !declaration.initializer)
184
+ return undefined;
185
+ const start = constantNumber(declaration.initializer);
186
+ if (start === undefined)
187
+ return undefined;
188
+ return {
189
+ variable: declaration.name,
190
+ start,
191
+ };
192
+ }
193
+ export function candidateEffectTotals(source, symbols) {
194
+ function count(node) {
195
+ if (!node)
196
+ return zero;
197
+ if (ts.isIfStatement(node))
198
+ return add(count(node.expression), maximum(count(node.thenStatement), count(node.elseStatement)));
199
+ if (ts.isConditionalExpression(node))
200
+ return add(count(node.condition), maximum(count(node.whenTrue), count(node.whenFalse)));
201
+ if (ts.isForStatement(node)) {
202
+ const iterations = loopIterations(node, symbols) ?? 1;
203
+ const body = count(node.statement);
204
+ const headers = add(count(node.initializer), add(count(node.condition), count(node.incrementor)));
205
+ return add(headers, multiply(body, iterations));
206
+ }
207
+ if (ts.isForOfStatement(node) &&
208
+ ts.isArrayLiteralExpression(node.expression))
209
+ return add(count(node.expression), multiply(add(count(node.initializer), count(node.statement)), arrayIterations(node, symbols)));
210
+ if (ts.isSwitchStatement(node))
211
+ return add(count(node.expression), switchTotals(node.caseBlock, count));
212
+ return nodeTotals(node, { symbols, count });
213
+ }
214
+ return count(source);
215
+ }
216
+ function nodeTotals(node, input) {
217
+ const local = input.symbols.localTotals?.(node);
218
+ if (local && ts.isFunctionLike(node))
219
+ return local;
220
+ let total = local ??
221
+ (protectedCall(node, input.symbols)
222
+ ? { knownCallCount: 1, knownUnitTotal: units(node, input.symbols) }
223
+ : zero);
224
+ ts.forEachChild(node, (child) => {
225
+ total = add(total, input.count(child));
226
+ });
227
+ return total;
228
+ }
229
+ export function candidateLoopRepetitions(node, symbols) {
230
+ if (ts.isForStatement(node))
231
+ return loopIterations(node, symbols);
232
+ if (ts.isForOfStatement(node) &&
233
+ ts.isArrayLiteralExpression(node.expression) &&
234
+ !uncertainLoopBody(node.statement, {
235
+ checker: symbols.checker,
236
+ counter: undefined,
237
+ }))
238
+ return node.expression.elements.length;
239
+ return undefined;
240
+ }
241
+ function arrayIterations(node, symbols) {
242
+ if (!ts.isArrayLiteralExpression(node.expression))
243
+ return 1;
244
+ return uncertainLoopBody(node.statement, {
245
+ checker: symbols.checker,
246
+ counter: undefined,
247
+ })
248
+ ? 1
249
+ : node.expression.elements.length;
250
+ }
251
+ function switchTotals(block, count) {
252
+ let suffix = zero;
253
+ let largest = zero;
254
+ let conditions = zero;
255
+ for (const clause of [...block.clauses].reverse()) {
256
+ if (ts.isCaseClause(clause))
257
+ conditions = add(conditions, count(clause.expression));
258
+ const ends = clause.statements.some((node) => ts.isBreakStatement(node) ||
259
+ ts.isReturnStatement(node) ||
260
+ ts.isThrowStatement(node));
261
+ const statements = clause.statements.reduce((total, statement) => add(total, count(statement)), zero);
262
+ suffix = add(statements, ends ? zero : suffix);
263
+ largest = maximum(largest, suffix);
264
+ }
265
+ return add(conditions, largest);
266
+ }
@@ -0,0 +1,5 @@
1
+ import ts from "typescript";
2
+ export declare function propertyName(name: ts.PropertyName): string | undefined;
3
+ export declare function propertyInitializer(node: ts.Node | undefined, field: string): ts.Expression | undefined;
4
+ export declare function literalField(node: ts.Node | undefined, field: string): string | null;
5
+ export declare function invalidFields(object: ts.ObjectLiteralExpression): boolean;
@@ -0,0 +1,24 @@
1
+ import ts from "typescript";
2
+ export function propertyName(name) {
3
+ if (ts.isIdentifier(name) || ts.isStringLiteral(name))
4
+ return name.text;
5
+ return undefined;
6
+ }
7
+ export function propertyInitializer(node, field) {
8
+ if (!node || !ts.isObjectLiteralExpression(node))
9
+ return undefined;
10
+ const property = node.properties.find((entry) => entry.name && propertyName(entry.name) === field);
11
+ return property && ts.isPropertyAssignment(property)
12
+ ? property.initializer
13
+ : undefined;
14
+ }
15
+ export function literalField(node, field) {
16
+ const value = propertyInitializer(node, field);
17
+ return value && ts.isStringLiteral(value) ? value.text : null;
18
+ }
19
+ export function invalidFields(object) {
20
+ const names = object.properties.map((entry) => entry.name && propertyName(entry.name));
21
+ return (names.includes(undefined) ||
22
+ new Set(names).size !== names.length ||
23
+ object.properties.some((entry) => !ts.isPropertyAssignment(entry)));
24
+ }
@@ -0,0 +1,10 @@
1
+ import ts from "typescript";
2
+ import { type Totals } from "./workflow-candidate-counts.ts";
3
+ import { type CandidateSymbols } from "./workflow-candidate-syntax.ts";
4
+ export declare function helperEffectTotals(input: {
5
+ readonly symbols: CandidateSymbols;
6
+ readonly sources: readonly ts.SourceFile[];
7
+ }): {
8
+ readonly totals?: Totals;
9
+ readonly unsupportedForms: readonly string[];
10
+ };
@@ -0,0 +1,129 @@
1
+ import ts from "typescript";
2
+ import { candidateEffectTotals, candidateLoopRepetitions, } from "./workflow-candidate-counts.js";
3
+ import { protectedCall, } from "./workflow-candidate-syntax.js";
4
+ import { resolvedSymbol } from "./workflow-candidate-program.js";
5
+ import { referenceSymbol, typeOnlyEffectNode, } from "./workflow-source-effects.js";
6
+ const zero = { knownCallCount: 0, knownUnitTotal: 0 };
7
+ export function helperEffectTotals(input) {
8
+ const { symbols, sources } = input;
9
+ const unsupportedForms = [];
10
+ if (sources.length === 1)
11
+ return { unsupportedForms };
12
+ const active = new Set();
13
+ const totals = new Map();
14
+ const functions = localFunctions(sources);
15
+ const functionAt = (node) => localFunctionAt(node, { checker: symbols.checker, functions });
16
+ function count(declaration) {
17
+ const cached = totals.get(declaration);
18
+ if (cached)
19
+ return cached;
20
+ if (active.has(declaration)) {
21
+ unsupportedForms.push("recursive-helper-effects");
22
+ return zero;
23
+ }
24
+ active.add(declaration);
25
+ const result = candidateEffectTotals(declaration, {
26
+ ...symbols,
27
+ localTotals: (node) => {
28
+ if (ts.isFunctionLike(node) && node !== declaration)
29
+ return zero;
30
+ if (!ts.isCallExpression(node) || !ts.isIdentifier(node.expression))
31
+ return undefined;
32
+ const called = functionAt(node.expression);
33
+ return called && effectful.has(called) ? count(called) : undefined;
34
+ },
35
+ });
36
+ active.delete(declaration);
37
+ totals.set(declaration, result);
38
+ return result;
39
+ }
40
+ const effectful = effectfulFunctions({ functions, functionAt, symbols });
41
+ if ([...effectful].every((entry) => entry.getSourceFile() === symbols.source))
42
+ return { unsupportedForms };
43
+ for (const source of sources)
44
+ inspectHelperReferences(source, {
45
+ functionAt,
46
+ effectful,
47
+ symbols,
48
+ unsupportedForms,
49
+ });
50
+ for (const declaration of effectful)
51
+ count(declaration);
52
+ const workflow = [...functions].find((entry) => entry.getSourceFile() === symbols.source &&
53
+ (ts.getCombinedModifierFlags(entry) & ts.ModifierFlags.Export) !== 0);
54
+ return { totals: workflow ? count(workflow) : zero, unsupportedForms };
55
+ }
56
+ function localFunctions(sources) {
57
+ return new Set(sources.flatMap((source) => source.statements.filter((node) => ts.isFunctionDeclaration(node) && node.body !== undefined)));
58
+ }
59
+ function localFunctionAt(node, input) {
60
+ const symbol = resolvedSymbol(input.checker, referenceSymbol(node, {
61
+ parent: node.parent,
62
+ checker: input.checker,
63
+ }));
64
+ return symbol?.declarations?.find((entry) => ts.isFunctionDeclaration(entry) && input.functions.has(entry));
65
+ }
66
+ function effectfulFunctions(input) {
67
+ const effectful = new Set();
68
+ const calls = (node) => {
69
+ if (typeOnlyEffectNode(node))
70
+ return false;
71
+ if (protectedCall(node, input.symbols))
72
+ return true;
73
+ const called = ts.isIdentifier(node) ? input.functionAt(node) : undefined;
74
+ if (called && effectful.has(called))
75
+ return true;
76
+ return ts.forEachChild(node, (child) => calls(child) || undefined) ?? false;
77
+ };
78
+ let previous = -1;
79
+ while (previous !== effectful.size) {
80
+ previous = effectful.size;
81
+ for (const declaration of input.functions)
82
+ if (calls(declaration))
83
+ effectful.add(declaration);
84
+ }
85
+ return effectful;
86
+ }
87
+ function inspectHelperReferences(source, input) {
88
+ function visit(node) {
89
+ if (typeOnlyEffectNode(node))
90
+ return;
91
+ if (source !== input.symbols.source &&
92
+ protectedCall(node, input.symbols) &&
93
+ !checkedHelperContext(node, input.symbols))
94
+ input.unsupportedForms.push("uncheckable-helper-effects");
95
+ const declaration = ts.isIdentifier(node)
96
+ ? input.functionAt(node)
97
+ : undefined;
98
+ if (declaration &&
99
+ input.effectful.has(declaration) &&
100
+ ts.isIdentifier(node) &&
101
+ !checkedHelperReference(node, input.symbols))
102
+ input.unsupportedForms.push("uncheckable-helper-effects");
103
+ ts.forEachChild(node, visit);
104
+ }
105
+ visit(source);
106
+ }
107
+ function checkedHelperReference(node, symbols) {
108
+ if (ts.isFunctionDeclaration(node.parent) && node.parent.name === node)
109
+ return true;
110
+ if (ts.isImportSpecifier(node.parent))
111
+ return true;
112
+ if (!ts.isCallExpression(node.parent) ||
113
+ node.parent.expression !== node ||
114
+ node.parent.questionDotToken !== undefined)
115
+ return false;
116
+ return checkedHelperContext(node.parent, symbols);
117
+ }
118
+ function checkedHelperContext(node, symbols) {
119
+ let parent = node;
120
+ while (!ts.isFunctionLike(parent)) {
121
+ if (ts.isSourceFile(parent))
122
+ return false;
123
+ if (ts.isIterationStatement(parent, false) &&
124
+ candidateLoopRepetitions(parent, symbols) === undefined)
125
+ return false;
126
+ parent = parent.parent;
127
+ }
128
+ return ts.isFunctionDeclaration(parent) && ts.isSourceFile(parent.parent);
129
+ }
@@ -0,0 +1,13 @@
1
+ import ts from "typescript";
2
+ export declare const candidatePackageRoot: string;
3
+ export interface CandidatePackageOptions {
4
+ readonly packageRoot?: string;
5
+ readonly helpers?: Readonly<Record<string, string>>;
6
+ }
7
+ export declare function resolvedSymbol(checker: ts.TypeChecker, symbol: ts.Symbol | undefined): ts.Symbol | undefined;
8
+ export declare function candidateProgram(text: string, installed?: CandidatePackageOptions): {
9
+ readonly program: ts.Program;
10
+ readonly source: ts.SourceFile;
11
+ readonly sources: readonly ts.SourceFile[];
12
+ readonly modules: ReadonlyMap<string, ts.SourceFile>;
13
+ };