@mclawnet/swarm 0.1.13 → 0.1.15

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 (320) hide show
  1. package/dist/__tests__/always-on-activity-reader.test.d.ts +2 -0
  2. package/dist/__tests__/always-on-activity-reader.test.d.ts.map +1 -0
  3. package/dist/__tests__/always-on-activity-reader.test.js +193 -0
  4. package/dist/__tests__/always-on-activity-reader.test.js.map +1 -0
  5. package/dist/__tests__/always-on-config.test.d.ts +2 -0
  6. package/dist/__tests__/always-on-config.test.d.ts.map +1 -0
  7. package/dist/__tests__/always-on-config.test.js +285 -0
  8. package/dist/__tests__/always-on-config.test.js.map +1 -0
  9. package/dist/__tests__/always-on-manager.test.d.ts +2 -0
  10. package/dist/__tests__/always-on-manager.test.d.ts.map +1 -0
  11. package/dist/__tests__/always-on-manager.test.js +797 -0
  12. package/dist/__tests__/always-on-manager.test.js.map +1 -0
  13. package/dist/__tests__/always-on-parity.test.d.ts +2 -0
  14. package/dist/__tests__/always-on-parity.test.d.ts.map +1 -0
  15. package/dist/__tests__/always-on-parity.test.js +20 -0
  16. package/dist/__tests__/always-on-parity.test.js.map +1 -0
  17. package/dist/__tests__/cascade-picker.test.d.ts +2 -0
  18. package/dist/__tests__/cascade-picker.test.d.ts.map +1 -0
  19. package/dist/__tests__/cascade-picker.test.js +122 -0
  20. package/dist/__tests__/cascade-picker.test.js.map +1 -0
  21. package/dist/__tests__/coordinator-shipment.test.d.ts +2 -0
  22. package/dist/__tests__/coordinator-shipment.test.d.ts.map +1 -0
  23. package/dist/__tests__/coordinator-shipment.test.js +280 -0
  24. package/dist/__tests__/coordinator-shipment.test.js.map +1 -0
  25. package/dist/__tests__/coordinator-workspace-recover.test.d.ts +2 -0
  26. package/dist/__tests__/coordinator-workspace-recover.test.d.ts.map +1 -0
  27. package/dist/__tests__/coordinator-workspace-recover.test.js +140 -0
  28. package/dist/__tests__/coordinator-workspace-recover.test.js.map +1 -0
  29. package/dist/__tests__/coordinator-workspace.test.d.ts +2 -0
  30. package/dist/__tests__/coordinator-workspace.test.d.ts.map +1 -0
  31. package/dist/__tests__/coordinator-workspace.test.js +135 -0
  32. package/dist/__tests__/coordinator-workspace.test.js.map +1 -0
  33. package/dist/__tests__/default-runner-epipe.test.d.ts +2 -0
  34. package/dist/__tests__/default-runner-epipe.test.d.ts.map +1 -0
  35. package/dist/__tests__/default-runner-epipe.test.js +43 -0
  36. package/dist/__tests__/default-runner-epipe.test.js.map +1 -0
  37. package/dist/__tests__/discovery-scheduler.test.d.ts +2 -0
  38. package/dist/__tests__/discovery-scheduler.test.d.ts.map +1 -0
  39. package/dist/__tests__/discovery-scheduler.test.js +367 -0
  40. package/dist/__tests__/discovery-scheduler.test.js.map +1 -0
  41. package/dist/__tests__/env-forward-e2e.test.d.ts +2 -0
  42. package/dist/__tests__/env-forward-e2e.test.d.ts.map +1 -0
  43. package/dist/__tests__/env-forward-e2e.test.js +57 -0
  44. package/dist/__tests__/env-forward-e2e.test.js.map +1 -0
  45. package/dist/__tests__/gh-pr-creator.test.d.ts +2 -0
  46. package/dist/__tests__/gh-pr-creator.test.d.ts.map +1 -0
  47. package/dist/__tests__/gh-pr-creator.test.js +107 -0
  48. package/dist/__tests__/gh-pr-creator.test.js.map +1 -0
  49. package/dist/__tests__/git-worktree-provider.test.d.ts +2 -0
  50. package/dist/__tests__/git-worktree-provider.test.d.ts.map +1 -0
  51. package/dist/__tests__/git-worktree-provider.test.js +98 -0
  52. package/dist/__tests__/git-worktree-provider.test.js.map +1 -0
  53. package/dist/__tests__/gitignore-check.test.d.ts +2 -0
  54. package/dist/__tests__/gitignore-check.test.d.ts.map +1 -0
  55. package/dist/__tests__/gitignore-check.test.js +39 -0
  56. package/dist/__tests__/gitignore-check.test.js.map +1 -0
  57. package/dist/__tests__/idea-research-source.test.d.ts +2 -0
  58. package/dist/__tests__/idea-research-source.test.d.ts.map +1 -0
  59. package/dist/__tests__/idea-research-source.test.js +425 -0
  60. package/dist/__tests__/idea-research-source.test.js.map +1 -0
  61. package/dist/__tests__/idea-todo-source.test.d.ts +2 -0
  62. package/dist/__tests__/idea-todo-source.test.d.ts.map +1 -0
  63. package/dist/__tests__/idea-todo-source.test.js +258 -0
  64. package/dist/__tests__/idea-todo-source.test.js.map +1 -0
  65. package/dist/__tests__/introspection-dedupe.test.d.ts +2 -0
  66. package/dist/__tests__/introspection-dedupe.test.d.ts.map +1 -0
  67. package/dist/__tests__/introspection-dedupe.test.js +484 -0
  68. package/dist/__tests__/introspection-dedupe.test.js.map +1 -0
  69. package/dist/__tests__/introspection-source.test.d.ts +2 -0
  70. package/dist/__tests__/introspection-source.test.d.ts.map +1 -0
  71. package/dist/__tests__/introspection-source.test.js +1051 -0
  72. package/dist/__tests__/introspection-source.test.js.map +1 -0
  73. package/dist/__tests__/migration-roles.test.js +1 -22
  74. package/dist/__tests__/migration-roles.test.js.map +1 -1
  75. package/dist/__tests__/reconcile-researching.test.d.ts +2 -0
  76. package/dist/__tests__/reconcile-researching.test.d.ts.map +1 -0
  77. package/dist/__tests__/reconcile-researching.test.js +224 -0
  78. package/dist/__tests__/reconcile-researching.test.js.map +1 -0
  79. package/dist/__tests__/role-loader-preamble-all.test.js +3 -1
  80. package/dist/__tests__/role-loader-preamble-all.test.js.map +1 -1
  81. package/dist/__tests__/role-loader.test.js +95 -0
  82. package/dist/__tests__/role-loader.test.js.map +1 -1
  83. package/dist/__tests__/role-prompt-no-legacy-protocol.test.js +3 -1
  84. package/dist/__tests__/role-prompt-no-legacy-protocol.test.js.map +1 -1
  85. package/dist/__tests__/secret-scrub.test.d.ts +2 -0
  86. package/dist/__tests__/secret-scrub.test.d.ts.map +1 -0
  87. package/dist/__tests__/secret-scrub.test.js +55 -0
  88. package/dist/__tests__/secret-scrub.test.js.map +1 -0
  89. package/dist/__tests__/shipment-actions.test.d.ts +2 -0
  90. package/dist/__tests__/shipment-actions.test.d.ts.map +1 -0
  91. package/dist/__tests__/shipment-actions.test.js +378 -0
  92. package/dist/__tests__/shipment-actions.test.js.map +1 -0
  93. package/dist/__tests__/shipment-persistence.test.d.ts +2 -0
  94. package/dist/__tests__/shipment-persistence.test.d.ts.map +1 -0
  95. package/dist/__tests__/shipment-persistence.test.js +120 -0
  96. package/dist/__tests__/shipment-persistence.test.js.map +1 -0
  97. package/dist/__tests__/shipment-pipeline.test.d.ts +2 -0
  98. package/dist/__tests__/shipment-pipeline.test.d.ts.map +1 -0
  99. package/dist/__tests__/shipment-pipeline.test.js +392 -0
  100. package/dist/__tests__/shipment-pipeline.test.js.map +1 -0
  101. package/dist/__tests__/shipment-report.test.d.ts +2 -0
  102. package/dist/__tests__/shipment-report.test.d.ts.map +1 -0
  103. package/dist/__tests__/shipment-report.test.js +78 -0
  104. package/dist/__tests__/shipment-report.test.js.map +1 -0
  105. package/dist/__tests__/shipment-stdin-integration.test.d.ts +2 -0
  106. package/dist/__tests__/shipment-stdin-integration.test.d.ts.map +1 -0
  107. package/dist/__tests__/shipment-stdin-integration.test.js +49 -0
  108. package/dist/__tests__/shipment-stdin-integration.test.js.map +1 -0
  109. package/dist/__tests__/shipment-type-parity.test.d.ts +2 -0
  110. package/dist/__tests__/shipment-type-parity.test.d.ts.map +1 -0
  111. package/dist/__tests__/shipment-type-parity.test.js +10 -0
  112. package/dist/__tests__/shipment-type-parity.test.js.map +1 -0
  113. package/dist/__tests__/snapshot-copy-provider.test.d.ts +2 -0
  114. package/dist/__tests__/snapshot-copy-provider.test.d.ts.map +1 -0
  115. package/dist/__tests__/snapshot-copy-provider.test.js +88 -0
  116. package/dist/__tests__/snapshot-copy-provider.test.js.map +1 -0
  117. package/dist/__tests__/swarm-coordinator-backend.test.js +153 -0
  118. package/dist/__tests__/swarm-coordinator-backend.test.js.map +1 -1
  119. package/dist/__tests__/swarm-coordinator-complete-intercept.test.d.ts +2 -0
  120. package/dist/__tests__/swarm-coordinator-complete-intercept.test.d.ts.map +1 -0
  121. package/dist/__tests__/swarm-coordinator-complete-intercept.test.js +111 -0
  122. package/dist/__tests__/swarm-coordinator-complete-intercept.test.js.map +1 -0
  123. package/dist/__tests__/task-store-source.test.d.ts +2 -0
  124. package/dist/__tests__/task-store-source.test.d.ts.map +1 -0
  125. package/dist/__tests__/task-store-source.test.js +56 -0
  126. package/dist/__tests__/task-store-source.test.js.map +1 -0
  127. package/dist/__tests__/transport-detect.test.d.ts +2 -0
  128. package/dist/__tests__/transport-detect.test.d.ts.map +1 -0
  129. package/dist/__tests__/transport-detect.test.js +92 -0
  130. package/dist/__tests__/transport-detect.test.js.map +1 -0
  131. package/dist/__tests__/workcycle-runner-cascade.test.d.ts +2 -0
  132. package/dist/__tests__/workcycle-runner-cascade.test.d.ts.map +1 -0
  133. package/dist/__tests__/workcycle-runner-cascade.test.js +203 -0
  134. package/dist/__tests__/workcycle-runner-cascade.test.js.map +1 -0
  135. package/dist/__tests__/workcycle-runner.test.d.ts +2 -0
  136. package/dist/__tests__/workcycle-runner.test.d.ts.map +1 -0
  137. package/dist/__tests__/workcycle-runner.test.js +369 -0
  138. package/dist/__tests__/workcycle-runner.test.js.map +1 -0
  139. package/dist/__tests__/workspace-diff.test.d.ts +2 -0
  140. package/dist/__tests__/workspace-diff.test.d.ts.map +1 -0
  141. package/dist/__tests__/workspace-diff.test.js +62 -0
  142. package/dist/__tests__/workspace-diff.test.js.map +1 -0
  143. package/dist/__tests__/workspace-manager.test.d.ts +2 -0
  144. package/dist/__tests__/workspace-manager.test.d.ts.map +1 -0
  145. package/dist/__tests__/workspace-manager.test.js +120 -0
  146. package/dist/__tests__/workspace-manager.test.js.map +1 -0
  147. package/dist/__tests__/workspace-types.test.d.ts +2 -0
  148. package/dist/__tests__/workspace-types.test.d.ts.map +1 -0
  149. package/dist/__tests__/workspace-types.test.js +37 -0
  150. package/dist/__tests__/workspace-types.test.js.map +1 -0
  151. package/dist/__tests__/worktree-gc.test.d.ts +2 -0
  152. package/dist/__tests__/worktree-gc.test.d.ts.map +1 -0
  153. package/dist/__tests__/worktree-gc.test.js +183 -0
  154. package/dist/__tests__/worktree-gc.test.js.map +1 -0
  155. package/dist/always-on/activity-reader.d.ts +27 -0
  156. package/dist/always-on/activity-reader.d.ts.map +1 -0
  157. package/dist/always-on/activity-reader.js +95 -0
  158. package/dist/always-on/activity-reader.js.map +1 -0
  159. package/dist/always-on/always-on-manager.d.ts +170 -0
  160. package/dist/always-on/always-on-manager.d.ts.map +1 -0
  161. package/dist/always-on/always-on-manager.js +538 -0
  162. package/dist/always-on/always-on-manager.js.map +1 -0
  163. package/dist/always-on/config.d.ts +141 -0
  164. package/dist/always-on/config.d.ts.map +1 -0
  165. package/dist/always-on/config.js +324 -0
  166. package/dist/always-on/config.js.map +1 -0
  167. package/dist/always-on/discovery-scheduler.d.ts +60 -0
  168. package/dist/always-on/discovery-scheduler.d.ts.map +1 -0
  169. package/dist/always-on/discovery-scheduler.js +287 -0
  170. package/dist/always-on/discovery-scheduler.js.map +1 -0
  171. package/dist/always-on/ideas-client.d.ts +23 -0
  172. package/dist/always-on/ideas-client.d.ts.map +1 -0
  173. package/dist/always-on/ideas-client.js +13 -0
  174. package/dist/always-on/ideas-client.js.map +1 -0
  175. package/dist/always-on/reconcile-researching.d.ts +42 -0
  176. package/dist/always-on/reconcile-researching.d.ts.map +1 -0
  177. package/dist/always-on/reconcile-researching.js +133 -0
  178. package/dist/always-on/reconcile-researching.js.map +1 -0
  179. package/dist/always-on/task-sources/cascade-picker.d.ts +42 -0
  180. package/dist/always-on/task-sources/cascade-picker.d.ts.map +1 -0
  181. package/dist/always-on/task-sources/cascade-picker.js +65 -0
  182. package/dist/always-on/task-sources/cascade-picker.js.map +1 -0
  183. package/dist/always-on/task-sources/idea-dedupe.d.ts +62 -0
  184. package/dist/always-on/task-sources/idea-dedupe.d.ts.map +1 -0
  185. package/dist/always-on/task-sources/idea-dedupe.js +130 -0
  186. package/dist/always-on/task-sources/idea-dedupe.js.map +1 -0
  187. package/dist/always-on/task-sources/idea-research-source.d.ts +46 -0
  188. package/dist/always-on/task-sources/idea-research-source.d.ts.map +1 -0
  189. package/dist/always-on/task-sources/idea-research-source.js +308 -0
  190. package/dist/always-on/task-sources/idea-research-source.js.map +1 -0
  191. package/dist/always-on/task-sources/idea-sort.d.ts +3 -0
  192. package/dist/always-on/task-sources/idea-sort.d.ts.map +1 -0
  193. package/dist/always-on/task-sources/idea-sort.js +25 -0
  194. package/dist/always-on/task-sources/idea-sort.js.map +1 -0
  195. package/dist/always-on/task-sources/idea-todo-source.d.ts +48 -0
  196. package/dist/always-on/task-sources/idea-todo-source.d.ts.map +1 -0
  197. package/dist/always-on/task-sources/idea-todo-source.js +226 -0
  198. package/dist/always-on/task-sources/idea-todo-source.js.map +1 -0
  199. package/dist/always-on/task-sources/introspection-source.d.ts +101 -0
  200. package/dist/always-on/task-sources/introspection-source.d.ts.map +1 -0
  201. package/dist/always-on/task-sources/introspection-source.js +695 -0
  202. package/dist/always-on/task-sources/introspection-source.js.map +1 -0
  203. package/dist/always-on/task-sources/task-store-source.d.ts +15 -0
  204. package/dist/always-on/task-sources/task-store-source.d.ts.map +1 -0
  205. package/dist/always-on/task-sources/task-store-source.js +59 -0
  206. package/dist/always-on/task-sources/task-store-source.js.map +1 -0
  207. package/dist/always-on/task-sources/types.d.ts +108 -0
  208. package/dist/always-on/task-sources/types.d.ts.map +1 -0
  209. package/dist/always-on/task-sources/types.js +13 -0
  210. package/dist/always-on/task-sources/types.js.map +1 -0
  211. package/dist/always-on/types.d.ts +76 -0
  212. package/dist/always-on/types.d.ts.map +1 -0
  213. package/dist/always-on/types.js +17 -0
  214. package/dist/always-on/types.js.map +1 -0
  215. package/dist/always-on/workcycle-runner.d.ts +115 -0
  216. package/dist/always-on/workcycle-runner.d.ts.map +1 -0
  217. package/dist/always-on/workcycle-runner.js +285 -0
  218. package/dist/always-on/workcycle-runner.js.map +1 -0
  219. package/dist/always-on/worktree-gc.d.ts +41 -0
  220. package/dist/always-on/worktree-gc.d.ts.map +1 -0
  221. package/dist/always-on/worktree-gc.js +167 -0
  222. package/dist/always-on/worktree-gc.js.map +1 -0
  223. package/dist/index.d.ts +26 -2
  224. package/dist/index.d.ts.map +1 -1
  225. package/dist/index.js +24 -1
  226. package/dist/index.js.map +1 -1
  227. package/dist/persistence.d.ts +37 -1
  228. package/dist/persistence.d.ts.map +1 -1
  229. package/dist/persistence.js +48 -0
  230. package/dist/persistence.js.map +1 -1
  231. package/dist/retrospective.d.ts.map +1 -1
  232. package/dist/retrospective.js +6 -0
  233. package/dist/retrospective.js.map +1 -1
  234. package/dist/roles/role-loader.d.ts +1 -1
  235. package/dist/roles/role-loader.d.ts.map +1 -1
  236. package/dist/roles/role-loader.js +18 -0
  237. package/dist/roles/role-loader.js.map +1 -1
  238. package/dist/roles/types.d.ts +12 -0
  239. package/dist/roles/types.d.ts.map +1 -1
  240. package/dist/shipment/gh-pr-creator.d.ts +28 -0
  241. package/dist/shipment/gh-pr-creator.d.ts.map +1 -0
  242. package/dist/shipment/gh-pr-creator.js +80 -0
  243. package/dist/shipment/gh-pr-creator.js.map +1 -0
  244. package/dist/shipment/report.d.ts +27 -0
  245. package/dist/shipment/report.d.ts.map +1 -0
  246. package/dist/shipment/report.js +41 -0
  247. package/dist/shipment/report.js.map +1 -0
  248. package/dist/shipment/secret-scrub.d.ts +12 -0
  249. package/dist/shipment/secret-scrub.d.ts.map +1 -0
  250. package/dist/shipment/secret-scrub.js +30 -0
  251. package/dist/shipment/secret-scrub.js.map +1 -0
  252. package/dist/shipment/shipment-actions.d.ts +85 -0
  253. package/dist/shipment/shipment-actions.d.ts.map +1 -0
  254. package/dist/shipment/shipment-actions.js +190 -0
  255. package/dist/shipment/shipment-actions.js.map +1 -0
  256. package/dist/shipment/shipment-pipeline.d.ts +48 -0
  257. package/dist/shipment/shipment-pipeline.d.ts.map +1 -0
  258. package/dist/shipment/shipment-pipeline.js +256 -0
  259. package/dist/shipment/shipment-pipeline.js.map +1 -0
  260. package/dist/shipment/transport-detect.d.ts +16 -0
  261. package/dist/shipment/transport-detect.d.ts.map +1 -0
  262. package/dist/shipment/transport-detect.js +54 -0
  263. package/dist/shipment/transport-detect.js.map +1 -0
  264. package/dist/shipment/workspace-diff.d.ts +39 -0
  265. package/dist/shipment/workspace-diff.d.ts.map +1 -0
  266. package/dist/shipment/workspace-diff.js +64 -0
  267. package/dist/shipment/workspace-diff.js.map +1 -0
  268. package/dist/swarm-coordinator.d.ts +20 -1
  269. package/dist/swarm-coordinator.d.ts.map +1 -1
  270. package/dist/swarm-coordinator.js +193 -10
  271. package/dist/swarm-coordinator.js.map +1 -1
  272. package/dist/types.d.ts +62 -0
  273. package/dist/types.d.ts.map +1 -1
  274. package/dist/workspace/git-worktree-provider.d.ts +11 -0
  275. package/dist/workspace/git-worktree-provider.d.ts.map +1 -0
  276. package/dist/workspace/git-worktree-provider.js +123 -0
  277. package/dist/workspace/git-worktree-provider.js.map +1 -0
  278. package/dist/workspace/gitignore-check.d.ts +10 -0
  279. package/dist/workspace/gitignore-check.d.ts.map +1 -0
  280. package/dist/workspace/gitignore-check.js +25 -0
  281. package/dist/workspace/gitignore-check.js.map +1 -0
  282. package/dist/workspace/index.d.ts +5 -0
  283. package/dist/workspace/index.d.ts.map +1 -0
  284. package/dist/workspace/index.js +5 -0
  285. package/dist/workspace/index.js.map +1 -0
  286. package/dist/workspace/snapshot-copy-provider.d.ts +11 -0
  287. package/dist/workspace/snapshot-copy-provider.d.ts.map +1 -0
  288. package/dist/workspace/snapshot-copy-provider.js +66 -0
  289. package/dist/workspace/snapshot-copy-provider.js.map +1 -0
  290. package/dist/workspace/types.d.ts +36 -0
  291. package/dist/workspace/types.d.ts.map +1 -0
  292. package/dist/workspace/types.js +2 -0
  293. package/dist/workspace/types.js.map +1 -0
  294. package/dist/workspace/workspace-manager.d.ts +30 -0
  295. package/dist/workspace/workspace-manager.d.ts.map +1 -0
  296. package/dist/workspace/workspace-manager.js +104 -0
  297. package/dist/workspace/workspace-manager.js.map +1 -0
  298. package/package.json +4 -4
  299. package/roles/queen.md +1 -0
  300. package/templates/introspection.md +64 -0
  301. package/templates/research-only.md +58 -0
  302. package/roles/preset-analyst-simons.md +0 -39
  303. package/roles/preset-architect-knuth.md +0 -39
  304. package/roles/preset-designer-norman.md +0 -39
  305. package/roles/preset-designer.md +0 -39
  306. package/roles/preset-dev-carmack.md +0 -39
  307. package/roles/preset-dev-gosling.md +0 -39
  308. package/roles/preset-developer.md +0 -52
  309. package/roles/preset-manager-grove.md +0 -39
  310. package/roles/preset-manager-musk.md +0 -39
  311. package/roles/preset-pm.md +0 -78
  312. package/roles/preset-researcher-feynman.md +0 -39
  313. package/roles/preset-reviewer.md +0 -46
  314. package/roles/preset-strategist-buffett.md +0 -39
  315. package/roles/preset-strategist-munger.md +0 -39
  316. package/roles/preset-strategist-sunzi.md +0 -39
  317. package/roles/preset-tester-beck.md +0 -40
  318. package/roles/preset-tester.md +0 -47
  319. package/roles/preset-writer-orwell.md +0 -39
  320. package/roles/preset-writer.md +0 -39
@@ -0,0 +1,141 @@
1
+ export interface AlwaysOnTaskSourcesConfig {
2
+ /** L1 — TaskStore (sprint backlog). Default true. */
3
+ taskStore?: boolean;
4
+ /** L2a — Ideas with status=todo. Default true. */
5
+ ideaTodo?: boolean;
6
+ /** L2b — Ideas with status=idea (research cycle). Default true. */
7
+ ideaResearch?: boolean;
8
+ /** L3 — Queen self-introspection (opt-in). Default false. */
9
+ introspection?: boolean;
10
+ }
11
+ export interface AlwaysOnConfig {
12
+ mode: "off" | "quiet" | "active" | "aggressive";
13
+ /** 1..20 cycles/day, integer. */
14
+ dailyBudget: number;
15
+ /**
16
+ * ISO timestamp; when set and in the future, the scheduler should treat
17
+ * every tick as gated regardless of mode. Cleared by setting back to
18
+ * undefined / null. M7.3 enforces via the manager's `pausedUntil` gate.
19
+ */
20
+ pausedUntil?: string;
21
+ /**
22
+ * Template (a.k.a. team) name used when AlwaysOnManager spawns a synthetic
23
+ * cycle swarm. Forward-compatible: the UI doesn't expose this yet (lands
24
+ * later), so callers and the persisted config use the DEFAULT below when
25
+ * absent. Validated against an allowlist on read/write — bad values fall
26
+ * back to the default so an unknown template can never bring the scheduler
27
+ * down (C1 hotfix).
28
+ */
29
+ templateName?: string;
30
+ /**
31
+ * M8.2 — per-source opt-in toggles. Omitted fields fall back to defaults
32
+ * (taskStore / ideaTodo / ideaResearch on; introspection off). Surfaced
33
+ * via JSON edit until M8.3 ships the UI toggles.
34
+ */
35
+ taskSources?: AlwaysOnTaskSourcesConfig;
36
+ /**
37
+ * M8.2 — cooldown (in hours) between consecutive introspection cycles.
38
+ * Independent of dailyBudget. Default 24. Validated to a sane range on
39
+ * load/save; out-of-range values fall back to the default.
40
+ */
41
+ introspectionCooldownHours?: number;
42
+ /**
43
+ * M8.2 — runtime state: ISO timestamp of the most recent introspection
44
+ * cycle that fired. Persisted so cooldown gates survive a restart.
45
+ */
46
+ lastIntrospectionAt?: string;
47
+ /**
48
+ * M8.2 — runtime state: when true, every idea produced by the previous
49
+ * introspection cycle ended up archived. IntrospectionSource self-skips
50
+ * the next cycle while this flag is set; clears as soon as one prior
51
+ * idea survives (status != archived) on the next pre-check.
52
+ */
53
+ lastIntrospectionRejected?: boolean;
54
+ /**
55
+ * M8 hotfix I1/I2 — fire-and-forget breadcrumb: the swarmId of an
56
+ * introspection cycle that was *spawned* on a prior tick but whose output
57
+ * has not yet been ingested. Set when IntrospectionSource queues the
58
+ * background swarm; cleared once the next pick observes the swarm has
59
+ * reached a terminal state and POSTs (or skips) the ideas. Persisted so
60
+ * an agent restart mid-cycle still picks up the in-flight result. Absent
61
+ * = no pending swarm to reconcile.
62
+ */
63
+ pendingIntrospectionSwarmId?: string;
64
+ /**
65
+ * PR-B follow-up — workspace.cwd of the pending introspection swarm,
66
+ * captured at spawn time. After `swarm_complete` deletes the swarm from
67
+ * the coordinator registry, `swarmCoordinator.getSwarm()` returns
68
+ * undefined and the spawner can no longer resolve where the queen wrote
69
+ * her candidates. Persisting the cwd alongside the swarm id lets
70
+ * `processPendingSwarm` find the output file in the worktree even when
71
+ * the live workspace handle is gone. Cleared in lockstep with
72
+ * `pendingIntrospectionSwarmId`.
73
+ */
74
+ pendingIntrospectionWorkspaceCwd?: string;
75
+ }
76
+ /**
77
+ * Runtime counters persisted alongside AlwaysOnConfig on disk so the daily
78
+ * budget survives an agent restart (M7.3). Kept structurally separate from
79
+ * AlwaysOnConfig so the wire-side `AlwaysOnConfig` in @mclawnet/shared can
80
+ * stay a clean user-facing surface — see always-on-parity.test.ts.
81
+ */
82
+ export interface AlwaysOnRuntimeState {
83
+ /**
84
+ * Current day's fired count (mirrors DiscoveryScheduler.ticksToday). Persists
85
+ * across agent restart so a quick crash + relaunch doesn't reset the budget
86
+ * to 0 and double-spend the cap. Reset to 0 on load when ticksTodayDate is
87
+ * older than today.
88
+ */
89
+ ticksToday?: number;
90
+ /** YYYY-MM-DD (local) the persisted `ticksToday` belongs to. */
91
+ ticksTodayDate?: string;
92
+ /** ISO timestamp of the most recent fired tick; absent when never. */
93
+ lastFireAt?: string;
94
+ }
95
+ export type AlwaysOnPersistedConfig = AlwaysOnConfig & AlwaysOnRuntimeState;
96
+ export declare const DEFAULT_ALWAYS_ON_CONFIG: AlwaysOnConfig;
97
+ /**
98
+ * M8.2 — default opt-in matrix. taskSources field omitted on disk falls back
99
+ * to this; UI/JSON edits override per-key (omitted keys still resolve to the
100
+ * default). Introspection stays off so the agent never wakes the user with
101
+ * auto-discovered ideas unless they've explicitly opted in.
102
+ */
103
+ export declare const DEFAULT_ALWAYS_ON_TASK_SOURCES: Required<AlwaysOnTaskSourcesConfig>;
104
+ /** M8.2 — default cooldown between introspection cycles, in hours. */
105
+ export declare const DEFAULT_INTROSPECTION_COOLDOWN_HOURS = 24;
106
+ /**
107
+ * Template used when no override is persisted. "minimal" ships in
108
+ * `packages/@clawnet/swarm/templates/` and is the safest single-role default —
109
+ * picked over the legacy `"default"` literal which never had a backing file
110
+ * and crashed every always-on cycle pre-hotfix (C1).
111
+ */
112
+ export declare const DEFAULT_ALWAYS_ON_TEMPLATE = "minimal";
113
+ /** Local YYYY-MM-DD (NOT UTC) so the daily-budget midnight matches user time. */
114
+ export declare function localYMD(d: Date): string;
115
+ /** Public so the agent boot scanner can distinguish "no config" from "corrupt config" (I4). */
116
+ export declare function alwaysOnConfigPath(workDir: string, home: string): string;
117
+ /**
118
+ * Merge a (possibly partial) taskSources object over the defaults, returning
119
+ * a fully-resolved record with every field present. The runtime always-on
120
+ * cascade reads this — undefined would force every caller to remember the
121
+ * defaults.
122
+ */
123
+ export declare function resolveTaskSources(v: AlwaysOnTaskSourcesConfig | undefined): Required<AlwaysOnTaskSourcesConfig>;
124
+ export declare function loadAlwaysOnConfig(workDir: string, home: string): AlwaysOnPersistedConfig;
125
+ export declare function saveAlwaysOnConfig(workDir: string, home: string, config: AlwaysOnPersistedConfig): void;
126
+ /**
127
+ * Merge a partial config update over the persisted baseline. Used by the
128
+ * agent handler so the UI can PATCH only `{mode}` or `{pausedUntil}` without
129
+ * having to reconstruct dailyBudget client-side.
130
+ *
131
+ * `pausedUntil: null` (or empty string) clears the pause; omitting it leaves
132
+ * the existing value alone.
133
+ */
134
+ export declare function mergeAlwaysOnConfig(current: AlwaysOnPersistedConfig, patch: Omit<Partial<AlwaysOnConfig>, "pausedUntil" | "lastIntrospectionAt" | "lastIntrospectionRejected" | "pendingIntrospectionSwarmId" | "pendingIntrospectionWorkspaceCwd"> & {
135
+ pausedUntil?: string | null;
136
+ lastIntrospectionAt?: string | null;
137
+ lastIntrospectionRejected?: boolean | null;
138
+ pendingIntrospectionSwarmId?: string | null;
139
+ pendingIntrospectionWorkspaceCwd?: string | null;
140
+ }): AlwaysOnPersistedConfig;
141
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/always-on/config.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,yBAAyB;IACxC,qDAAqD;IACrD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mEAAmE;IACnE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,6DAA6D;IAC7D,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,YAAY,CAAC;IAChD,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,WAAW,CAAC,EAAE,yBAAyB,CAAC;IACxC;;;;OAIG;IACH,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;OAKG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC;;;;;;;;OAQG;IACH,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC;;;;;;;;;OASG;IACH,gCAAgC,CAAC,EAAE,MAAM,CAAC;CAC3C;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,uBAAuB,GAAG,cAAc,GAAG,oBAAoB,CAAC;AAE5E,eAAO,MAAM,wBAAwB,EAAE,cAGtC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,EAAE,QAAQ,CAAC,yBAAyB,CAK9E,CAAC;AAEF,sEAAsE;AACtE,eAAO,MAAM,oCAAoC,KAAK,CAAC;AAEvD;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,YAAY,CAAC;AAIpD,iFAAiF;AACjF,wBAAgB,QAAQ,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,CAKxC;AAMD,+FAA+F;AAC/F,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAExE;AA+BD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,CAAC,EAAE,yBAAyB,GAAG,SAAS,GACvC,QAAQ,CAAC,yBAAyB,CAAC,CAErC;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,uBAAuB,CAgEzF;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,uBAAuB,GAC9B,IAAI,CAqFN;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,uBAAuB,EAChC,KAAK,EAAE,IAAI,CACT,OAAO,CAAC,cAAc,CAAC,EACvB,aAAa,GAAG,qBAAqB,GAAG,2BAA2B,GAAG,6BAA6B,GAAG,kCAAkC,CACzI,GAAG;IACF,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,yBAAyB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3C,2BAA2B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,gCAAgC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClD,GACA,uBAAuB,CAkEzB"}
@@ -0,0 +1,324 @@
1
+ // Per-project always-on configuration persistence (M7.2).
2
+ //
3
+ // Stores the user's mode/dailyBudget/pause choice under
4
+ // `<projectRoot>/always-on.json` so M7.3's wired scheduler can rehydrate
5
+ // from disk after an agent restart.
6
+ //
7
+ // Deliberately small + dependency-free: just file I/O + validation.
8
+ // The runtime live state (ticksToday / recentTicks / nextTickAt) belongs
9
+ // to DiscoveryScheduler.snapshot() and is NOT persisted here.
10
+ import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
11
+ import { dirname, join } from "node:path";
12
+ import { projectRoot as projRoot } from "@mclawnet/task";
13
+ export const DEFAULT_ALWAYS_ON_CONFIG = {
14
+ mode: "off",
15
+ dailyBudget: 3,
16
+ };
17
+ /**
18
+ * M8.2 — default opt-in matrix. taskSources field omitted on disk falls back
19
+ * to this; UI/JSON edits override per-key (omitted keys still resolve to the
20
+ * default). Introspection stays off so the agent never wakes the user with
21
+ * auto-discovered ideas unless they've explicitly opted in.
22
+ */
23
+ export const DEFAULT_ALWAYS_ON_TASK_SOURCES = {
24
+ taskStore: true,
25
+ ideaTodo: true,
26
+ ideaResearch: true,
27
+ introspection: false,
28
+ };
29
+ /** M8.2 — default cooldown between introspection cycles, in hours. */
30
+ export const DEFAULT_INTROSPECTION_COOLDOWN_HOURS = 24;
31
+ /**
32
+ * Template used when no override is persisted. "minimal" ships in
33
+ * `packages/@clawnet/swarm/templates/` and is the safest single-role default —
34
+ * picked over the legacy `"default"` literal which never had a backing file
35
+ * and crashed every always-on cycle pre-hotfix (C1).
36
+ */
37
+ export const DEFAULT_ALWAYS_ON_TEMPLATE = "minimal";
38
+ const CONFIG_FILENAME = "always-on.json";
39
+ /** Local YYYY-MM-DD (NOT UTC) so the daily-budget midnight matches user time. */
40
+ export function localYMD(d) {
41
+ const y = d.getFullYear();
42
+ const m = String(d.getMonth() + 1).padStart(2, "0");
43
+ const day = String(d.getDate()).padStart(2, "0");
44
+ return `${y}-${m}-${day}`;
45
+ }
46
+ function configPath(workDir, home) {
47
+ return join(projRoot(workDir, home), CONFIG_FILENAME);
48
+ }
49
+ /** Public so the agent boot scanner can distinguish "no config" from "corrupt config" (I4). */
50
+ export function alwaysOnConfigPath(workDir, home) {
51
+ return configPath(workDir, home);
52
+ }
53
+ function validMode(m) {
54
+ return m === "off" || m === "quiet" || m === "active" || m === "aggressive";
55
+ }
56
+ function validBudget(n) {
57
+ return typeof n === "number" && Number.isInteger(n) && n >= 1 && n <= 20;
58
+ }
59
+ function validCooldownHours(n) {
60
+ return typeof n === "number" && Number.isFinite(n) && n >= 0 && n <= 24 * 30;
61
+ }
62
+ /**
63
+ * Coerce an opaque value into a clean AlwaysOnTaskSourcesConfig. Unknown keys
64
+ * are dropped; non-boolean values are dropped (NOT coerced) so a typo doesn't
65
+ * silently flip a source on/off. Returns undefined when the input has no
66
+ * recognisable keys — caller stores nothing on disk in that case.
67
+ */
68
+ function sanitiseTaskSources(v) {
69
+ if (!v || typeof v !== "object" || Array.isArray(v))
70
+ return undefined;
71
+ const src = v;
72
+ const out = {};
73
+ if (typeof src.taskStore === "boolean")
74
+ out.taskStore = src.taskStore;
75
+ if (typeof src.ideaTodo === "boolean")
76
+ out.ideaTodo = src.ideaTodo;
77
+ if (typeof src.ideaResearch === "boolean")
78
+ out.ideaResearch = src.ideaResearch;
79
+ if (typeof src.introspection === "boolean")
80
+ out.introspection = src.introspection;
81
+ return Object.keys(out).length === 0 ? undefined : out;
82
+ }
83
+ /**
84
+ * Merge a (possibly partial) taskSources object over the defaults, returning
85
+ * a fully-resolved record with every field present. The runtime always-on
86
+ * cascade reads this — undefined would force every caller to remember the
87
+ * defaults.
88
+ */
89
+ export function resolveTaskSources(v) {
90
+ return { ...DEFAULT_ALWAYS_ON_TASK_SOURCES, ...(v ?? {}) };
91
+ }
92
+ export function loadAlwaysOnConfig(workDir, home) {
93
+ const path = configPath(workDir, home);
94
+ if (!existsSync(path))
95
+ return { ...DEFAULT_ALWAYS_ON_CONFIG };
96
+ try {
97
+ const data = JSON.parse(readFileSync(path, "utf-8"));
98
+ const cfg = {
99
+ mode: validMode(data.mode) ? data.mode : DEFAULT_ALWAYS_ON_CONFIG.mode,
100
+ dailyBudget: validBudget(data.dailyBudget)
101
+ ? data.dailyBudget
102
+ : DEFAULT_ALWAYS_ON_CONFIG.dailyBudget,
103
+ ...(typeof data.pausedUntil === "string" ? { pausedUntil: data.pausedUntil } : {}),
104
+ ...(typeof data.templateName === "string" && data.templateName.length > 0
105
+ ? { templateName: data.templateName }
106
+ : {}),
107
+ };
108
+ // M8.2 — task source toggles + introspection cooldown / runtime state.
109
+ const ts = sanitiseTaskSources(data.taskSources);
110
+ if (ts)
111
+ cfg.taskSources = ts;
112
+ if (validCooldownHours(data.introspectionCooldownHours)) {
113
+ cfg.introspectionCooldownHours = data.introspectionCooldownHours;
114
+ }
115
+ if (typeof data.lastIntrospectionAt === "string") {
116
+ cfg.lastIntrospectionAt = data.lastIntrospectionAt;
117
+ }
118
+ if (typeof data.lastIntrospectionRejected === "boolean") {
119
+ cfg.lastIntrospectionRejected = data.lastIntrospectionRejected;
120
+ }
121
+ if (typeof data.pendingIntrospectionSwarmId === "string" && data.pendingIntrospectionSwarmId.length > 0) {
122
+ cfg.pendingIntrospectionSwarmId = data.pendingIntrospectionSwarmId;
123
+ }
124
+ if (typeof data.pendingIntrospectionWorkspaceCwd === "string" && data.pendingIntrospectionWorkspaceCwd.length > 0) {
125
+ cfg.pendingIntrospectionWorkspaceCwd = data.pendingIntrospectionWorkspaceCwd;
126
+ }
127
+ // M7.3 runtime counters — best-effort restoration; bad shape drops silently.
128
+ if (typeof data.ticksToday === "number" &&
129
+ Number.isInteger(data.ticksToday) &&
130
+ data.ticksToday >= 0) {
131
+ cfg.ticksToday = data.ticksToday;
132
+ }
133
+ if (typeof data.ticksTodayDate === "string" &&
134
+ /^\d{4}-\d{2}-\d{2}$/.test(data.ticksTodayDate)) {
135
+ cfg.ticksTodayDate = data.ticksTodayDate;
136
+ }
137
+ if (typeof data.lastFireAt === "string") {
138
+ cfg.lastFireAt = data.lastFireAt;
139
+ }
140
+ return cfg;
141
+ }
142
+ catch (err) {
143
+ // Corrupt JSON / unreadable file → fall back to defaults so the user
144
+ // can still toggle the UI; their bad file gets replaced on next save.
145
+ // Hotfix I4: surface the failure so an unrecoverable file doesn't silently
146
+ // disable always-on across an agent restart.
147
+ // eslint-disable-next-line no-console
148
+ console.warn(`[always-on] config corrupt at ${path}; falling back to defaults: ${err instanceof Error ? err.message : String(err)}`);
149
+ return { ...DEFAULT_ALWAYS_ON_CONFIG };
150
+ }
151
+ }
152
+ export function saveAlwaysOnConfig(workDir, home, config) {
153
+ const path = configPath(workDir, home);
154
+ mkdirSync(dirname(path), { recursive: true });
155
+ // Validate before writing; bad values get coerced to defaults rather than
156
+ // silently persisted.
157
+ const safe = {
158
+ mode: validMode(config.mode) ? config.mode : DEFAULT_ALWAYS_ON_CONFIG.mode,
159
+ dailyBudget: validBudget(config.dailyBudget)
160
+ ? config.dailyBudget
161
+ : DEFAULT_ALWAYS_ON_CONFIG.dailyBudget,
162
+ ...(typeof config.pausedUntil === "string"
163
+ ? { pausedUntil: config.pausedUntil }
164
+ : {}),
165
+ ...(typeof config.templateName === "string" && config.templateName.length > 0
166
+ ? { templateName: config.templateName }
167
+ : {}),
168
+ ...(typeof config.ticksToday === "number" &&
169
+ Number.isInteger(config.ticksToday) &&
170
+ config.ticksToday >= 0
171
+ ? { ticksToday: config.ticksToday }
172
+ : {}),
173
+ ...(typeof config.ticksTodayDate === "string" &&
174
+ /^\d{4}-\d{2}-\d{2}$/.test(config.ticksTodayDate)
175
+ ? { ticksTodayDate: config.ticksTodayDate }
176
+ : {}),
177
+ ...(typeof config.lastFireAt === "string" ? { lastFireAt: config.lastFireAt } : {}),
178
+ };
179
+ // M8.2 — round-trip task sources + introspection state. Sanitise on the
180
+ // way out too so a hand-edited config that smuggled a non-boolean doesn't
181
+ // get re-persisted.
182
+ const ts = sanitiseTaskSources(config.taskSources);
183
+ if (ts)
184
+ safe.taskSources = ts;
185
+ if (validCooldownHours(config.introspectionCooldownHours)) {
186
+ safe.introspectionCooldownHours = config.introspectionCooldownHours;
187
+ }
188
+ if (typeof config.lastIntrospectionAt === "string") {
189
+ safe.lastIntrospectionAt = config.lastIntrospectionAt;
190
+ }
191
+ if (typeof config.lastIntrospectionRejected === "boolean") {
192
+ safe.lastIntrospectionRejected = config.lastIntrospectionRejected;
193
+ }
194
+ if (typeof config.pendingIntrospectionSwarmId === "string" && config.pendingIntrospectionSwarmId.length > 0) {
195
+ safe.pendingIntrospectionSwarmId = config.pendingIntrospectionSwarmId;
196
+ }
197
+ if (typeof config.pendingIntrospectionWorkspaceCwd === "string" && config.pendingIntrospectionWorkspaceCwd.length > 0) {
198
+ safe.pendingIntrospectionWorkspaceCwd = config.pendingIntrospectionWorkspaceCwd;
199
+ }
200
+ // R3 I-F: atomic write. `writeFileSync` is `open(O_TRUNC) + write` — a
201
+ // concurrent reader (per-pick filter reads always-on.json on every tick)
202
+ // landing in the truncate-then-write window sees an empty/truncated file
203
+ // and loadAlwaysOnConfig silently falls back to DEFAULT_ALWAYS_ON_CONFIG,
204
+ // temporarily forcing mode=off + budget=3 + introspection=off until the
205
+ // write completes. Worse: a crash in the window loses ticksToday +
206
+ // pendingIntrospectionSwarmId. Fix: write to <path>.tmp then rename —
207
+ // atomic on POSIX. Mirrors the .1 backup rename used by always-on.log
208
+ // rotation. On stringify failure we clean up the .tmp so a partial file
209
+ // doesn't accumulate.
210
+ const tmpPath = `${path}.tmp`;
211
+ let serialised;
212
+ try {
213
+ serialised = JSON.stringify(safe, null, 2);
214
+ }
215
+ catch (err) {
216
+ // Defensive: shouldn't happen for our flat config shape, but a circular
217
+ // ref or BigInt would throw. Surface it so callers see the failure.
218
+ try {
219
+ unlinkSync(tmpPath);
220
+ }
221
+ catch {
222
+ /* nothing to clean if it doesn't exist */
223
+ }
224
+ throw err;
225
+ }
226
+ try {
227
+ writeFileSync(tmpPath, serialised, "utf-8");
228
+ renameSync(tmpPath, path);
229
+ }
230
+ catch (err) {
231
+ // Best-effort .tmp cleanup so a failed write doesn't leave behind a
232
+ // half-written sidecar. Swallow the cleanup error (the original error
233
+ // is what callers care about).
234
+ try {
235
+ unlinkSync(tmpPath);
236
+ }
237
+ catch {
238
+ /* may not exist if writeFileSync failed before open */
239
+ }
240
+ throw err;
241
+ }
242
+ }
243
+ /**
244
+ * Merge a partial config update over the persisted baseline. Used by the
245
+ * agent handler so the UI can PATCH only `{mode}` or `{pausedUntil}` without
246
+ * having to reconstruct dailyBudget client-side.
247
+ *
248
+ * `pausedUntil: null` (or empty string) clears the pause; omitting it leaves
249
+ * the existing value alone.
250
+ */
251
+ export function mergeAlwaysOnConfig(current, patch) {
252
+ const next = { ...current };
253
+ if (patch.mode !== undefined && validMode(patch.mode))
254
+ next.mode = patch.mode;
255
+ if (patch.dailyBudget !== undefined && validBudget(patch.dailyBudget)) {
256
+ next.dailyBudget = patch.dailyBudget;
257
+ }
258
+ if (patch.templateName !== undefined) {
259
+ if (typeof patch.templateName === "string" && patch.templateName.length > 0) {
260
+ next.templateName = patch.templateName;
261
+ }
262
+ }
263
+ if ("pausedUntil" in patch) {
264
+ const v = patch.pausedUntil;
265
+ if (v === null || v === "" || v === undefined) {
266
+ delete next.pausedUntil;
267
+ }
268
+ else if (typeof v === "string") {
269
+ next.pausedUntil = v;
270
+ }
271
+ }
272
+ // M8.2 — taskSources: shallow merge over the existing record (not the
273
+ // defaults) so a patch with only { introspection: true } leaves the other
274
+ // toggles at whatever the user last set.
275
+ if (patch.taskSources !== undefined) {
276
+ const sanitised = sanitiseTaskSources(patch.taskSources);
277
+ if (sanitised) {
278
+ next.taskSources = { ...(next.taskSources ?? {}), ...sanitised };
279
+ }
280
+ }
281
+ if (patch.introspectionCooldownHours !== undefined) {
282
+ if (validCooldownHours(patch.introspectionCooldownHours)) {
283
+ next.introspectionCooldownHours = patch.introspectionCooldownHours;
284
+ }
285
+ }
286
+ if ("lastIntrospectionAt" in patch) {
287
+ const v = patch.lastIntrospectionAt;
288
+ if (v === null || v === "") {
289
+ delete next.lastIntrospectionAt;
290
+ }
291
+ else if (typeof v === "string") {
292
+ next.lastIntrospectionAt = v;
293
+ }
294
+ }
295
+ if ("lastIntrospectionRejected" in patch) {
296
+ const v = patch.lastIntrospectionRejected;
297
+ if (v === null) {
298
+ delete next.lastIntrospectionRejected;
299
+ }
300
+ else if (typeof v === "boolean") {
301
+ next.lastIntrospectionRejected = v;
302
+ }
303
+ }
304
+ if ("pendingIntrospectionSwarmId" in patch) {
305
+ const v = patch.pendingIntrospectionSwarmId;
306
+ if (v === null || v === "") {
307
+ delete next.pendingIntrospectionSwarmId;
308
+ }
309
+ else if (typeof v === "string") {
310
+ next.pendingIntrospectionSwarmId = v;
311
+ }
312
+ }
313
+ if ("pendingIntrospectionWorkspaceCwd" in patch) {
314
+ const v = patch.pendingIntrospectionWorkspaceCwd;
315
+ if (v === null || v === "") {
316
+ delete next.pendingIntrospectionWorkspaceCwd;
317
+ }
318
+ else if (typeof v === "string") {
319
+ next.pendingIntrospectionWorkspaceCwd = v;
320
+ }
321
+ }
322
+ return next;
323
+ }
324
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/always-on/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import { AlwaysOnMode, DiscoverySchedulerOptions, DiscoverySchedulerSnapshot, TickRecord } from "./types.js";
2
+ export declare class DiscoveryScheduler {
3
+ private mode;
4
+ private tickIntervalOverride;
5
+ private dailyBudget;
6
+ private userGates;
7
+ private onFire;
8
+ private onTick;
9
+ private now;
10
+ private timer;
11
+ private running;
12
+ private halted;
13
+ private inFlight;
14
+ private ticksToday;
15
+ private lastFireAt;
16
+ private recentTicks;
17
+ private nextTickAt;
18
+ constructor(opts: DiscoverySchedulerOptions);
19
+ /** Start the tick loop. No-op when mode === "off" or scheduler is halted. */
20
+ start(): void;
21
+ /** Stop the tick loop. Idempotent. */
22
+ stop(): void;
23
+ /**
24
+ * Manually trigger a tick. Bypasses the interval but still runs gates and
25
+ * still respects the in-flight guard: concurrent tickNow() calls reject the
26
+ * second caller with an Error so callers see deterministic semantics rather
27
+ * than silent overlap. Use `await` to serialise explicitly.
28
+ */
29
+ tickNow(): Promise<TickRecord>;
30
+ /** Change mode at runtime. Cancels current timer and reschedules. */
31
+ setMode(mode: AlwaysOnMode): void;
32
+ /**
33
+ * Change daily budget at runtime (M7.3). `null` removes the cap entirely.
34
+ * Does not retro-affect counters; if the new budget is lower than
35
+ * `ticksToday`, the next gate evaluation will simply skip.
36
+ */
37
+ setDailyBudget(budget: number | null): void;
38
+ /**
39
+ * Restore counters from persisted state (M7.3 AlwaysOnManager). Must be
40
+ * called BEFORE start() — restoring into a running scheduler is undefined
41
+ * behaviour. `lastFireAt` may be null when no prior fire exists.
42
+ */
43
+ restoreState(state: {
44
+ ticksToday: number;
45
+ lastFireAt: Date | null;
46
+ }): void;
47
+ snapshot(): DiscoverySchedulerSnapshot;
48
+ private currentInterval;
49
+ /**
50
+ * Arm the next-tick timer. No-op when not running, halted, or mode=off.
51
+ * Always clears any existing timer first — both setMode() and a manual
52
+ * tickNow() can race with the previously armed interval.
53
+ */
54
+ private schedule;
55
+ private runTick;
56
+ /** Built-ins (in order) then user gates. */
57
+ private buildGateChain;
58
+ private pushRecent;
59
+ }
60
+ //# sourceMappingURL=discovery-scheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery-scheduler.d.ts","sourceRoot":"","sources":["../../src/always-on/discovery-scheduler.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,YAAY,EAGZ,yBAAyB,EACzB,0BAA0B,EAK1B,UAAU,EACX,MAAM,YAAY,CAAC;AAIpB,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,IAAI,CAAe;IAC3B,OAAO,CAAC,oBAAoB,CAAqB;IACjD,OAAO,CAAC,WAAW,CAAgB;IACnC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAoD;IAClE,OAAO,CAAC,MAAM,CAA6C;IAC3D,OAAO,CAAC,GAAG,CAAa;IAExB,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAS;IAEzB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,UAAU,CAAqB;gBAE3B,IAAI,EAAE,yBAAyB;IAU3C,6EAA6E;IAC7E,KAAK,IAAI,IAAI;IAUb,sCAAsC;IACtC,IAAI,IAAI,IAAI;IASZ;;;;;OAKG;IACG,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC;IAOpC,qEAAqE;IACrE,OAAO,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IASjC;;;;OAIG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAI3C;;;;OAIG;IACH,YAAY,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,IAAI,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI;IAW1E,QAAQ,IAAI,0BAA0B;IAYtC,OAAO,CAAC,eAAe;IAMvB;;;;OAIG;IACH,OAAO,CAAC,QAAQ;YAoCF,OAAO;IA8FrB,4CAA4C;IAC5C,OAAO,CAAC,cAAc;IAyBtB,OAAO,CAAC,UAAU;CAMnB"}