@aitne/daemon 0.1.3 → 0.1.6

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 (421) hide show
  1. package/dist/adapters/notification-manager.d.ts +12 -0
  2. package/dist/adapters/notification-manager.d.ts.map +1 -1
  3. package/dist/adapters/notification-manager.js +39 -1
  4. package/dist/adapters/notification-manager.js.map +1 -1
  5. package/dist/adapters/whatsapp-adapter.d.ts.map +1 -1
  6. package/dist/adapters/whatsapp-adapter.js +0 -1
  7. package/dist/adapters/whatsapp-adapter.js.map +1 -1
  8. package/dist/api/integration-route-gate.d.ts +15 -11
  9. package/dist/api/integration-route-gate.d.ts.map +1 -1
  10. package/dist/api/integration-route-gate.js +60 -23
  11. package/dist/api/integration-route-gate.js.map +1 -1
  12. package/dist/api/json-body.d.ts +22 -7
  13. package/dist/api/json-body.d.ts.map +1 -1
  14. package/dist/api/json-body.js +27 -8
  15. package/dist/api/json-body.js.map +1 -1
  16. package/dist/api/routes/agent.d.ts.map +1 -1
  17. package/dist/api/routes/agent.js +25 -0
  18. package/dist/api/routes/agent.js.map +1 -1
  19. package/dist/api/routes/backends.d.ts.map +1 -1
  20. package/dist/api/routes/backends.js +96 -1
  21. package/dist/api/routes/backends.js.map +1 -1
  22. package/dist/api/routes/books.js +1 -1
  23. package/dist/api/routes/books.js.map +1 -1
  24. package/dist/api/routes/commands.d.ts.map +1 -1
  25. package/dist/api/routes/commands.js +16 -13
  26. package/dist/api/routes/commands.js.map +1 -1
  27. package/dist/api/routes/context.d.ts.map +1 -1
  28. package/dist/api/routes/context.js +26 -3
  29. package/dist/api/routes/context.js.map +1 -1
  30. package/dist/api/routes/dashboard.d.ts.map +1 -1
  31. package/dist/api/routes/dashboard.js +103 -5
  32. package/dist/api/routes/dashboard.js.map +1 -1
  33. package/dist/api/routes/fs.d.ts +23 -0
  34. package/dist/api/routes/fs.d.ts.map +1 -0
  35. package/dist/api/routes/fs.js +156 -0
  36. package/dist/api/routes/fs.js.map +1 -0
  37. package/dist/api/routes/fs.logic.d.ts +62 -0
  38. package/dist/api/routes/fs.logic.d.ts.map +1 -0
  39. package/dist/api/routes/fs.logic.js +137 -0
  40. package/dist/api/routes/fs.logic.js.map +1 -0
  41. package/dist/api/routes/github.d.ts.map +1 -1
  42. package/dist/api/routes/github.js +38 -5
  43. package/dist/api/routes/github.js.map +1 -1
  44. package/dist/api/routes/health.d.ts.map +1 -1
  45. package/dist/api/routes/health.js +4 -2
  46. package/dist/api/routes/health.js.map +1 -1
  47. package/dist/api/routes/integrations.d.ts +35 -6
  48. package/dist/api/routes/integrations.d.ts.map +1 -1
  49. package/dist/api/routes/integrations.js +192 -15
  50. package/dist/api/routes/integrations.js.map +1 -1
  51. package/dist/api/routes/mail.d.ts.map +1 -1
  52. package/dist/api/routes/mail.js +112 -46
  53. package/dist/api/routes/mail.js.map +1 -1
  54. package/dist/api/routes/metrics.d.ts +1 -0
  55. package/dist/api/routes/metrics.d.ts.map +1 -1
  56. package/dist/api/routes/metrics.js +24 -0
  57. package/dist/api/routes/metrics.js.map +1 -1
  58. package/dist/api/routes/observations.d.ts.map +1 -1
  59. package/dist/api/routes/observations.js +696 -30
  60. package/dist/api/routes/observations.js.map +1 -1
  61. package/dist/api/routes/setup-migrate.d.ts +9 -1
  62. package/dist/api/routes/setup-migrate.d.ts.map +1 -1
  63. package/dist/api/routes/setup-migrate.js +4 -2
  64. package/dist/api/routes/setup-migrate.js.map +1 -1
  65. package/dist/api/routes/skills.d.ts +9 -1
  66. package/dist/api/routes/skills.d.ts.map +1 -1
  67. package/dist/api/routes/skills.js +77 -17
  68. package/dist/api/routes/skills.js.map +1 -1
  69. package/dist/api/routes/voice.d.ts.map +1 -1
  70. package/dist/api/routes/voice.js +62 -4
  71. package/dist/api/routes/voice.js.map +1 -1
  72. package/dist/api/routes/wiki.d.ts +4 -0
  73. package/dist/api/routes/wiki.d.ts.map +1 -0
  74. package/dist/api/routes/wiki.js +1075 -0
  75. package/dist/api/routes/wiki.js.map +1 -0
  76. package/dist/api/server.d.ts +13 -0
  77. package/dist/api/server.d.ts.map +1 -1
  78. package/dist/api/server.js +27 -1
  79. package/dist/api/server.js.map +1 -1
  80. package/dist/bootstrap/adapters.d.ts +109 -0
  81. package/dist/bootstrap/adapters.d.ts.map +1 -0
  82. package/dist/bootstrap/adapters.js +237 -0
  83. package/dist/bootstrap/adapters.js.map +1 -0
  84. package/dist/bootstrap/catchup.d.ts +23 -0
  85. package/dist/bootstrap/catchup.d.ts.map +1 -0
  86. package/dist/bootstrap/catchup.js +124 -0
  87. package/dist/bootstrap/catchup.js.map +1 -0
  88. package/dist/bootstrap/schedule-helpers.d.ts +18 -0
  89. package/dist/bootstrap/schedule-helpers.d.ts.map +1 -0
  90. package/dist/bootstrap/schedule-helpers.js +96 -0
  91. package/dist/bootstrap/schedule-helpers.js.map +1 -0
  92. package/dist/bootstrap/services.d.ts +60 -0
  93. package/dist/bootstrap/services.d.ts.map +1 -0
  94. package/dist/bootstrap/services.js +209 -0
  95. package/dist/bootstrap/services.js.map +1 -0
  96. package/dist/config.d.ts.map +1 -1
  97. package/dist/config.js +26 -0
  98. package/dist/config.js.map +1 -1
  99. package/dist/core/agent-core.d.ts +25 -0
  100. package/dist/core/agent-core.d.ts.map +1 -1
  101. package/dist/core/agent-core.js.map +1 -1
  102. package/dist/core/backends/backend-router.d.ts +28 -1
  103. package/dist/core/backends/backend-router.d.ts.map +1 -1
  104. package/dist/core/backends/backend-router.js +58 -4
  105. package/dist/core/backends/backend-router.js.map +1 -1
  106. package/dist/core/backends/claude-auth.d.ts +70 -0
  107. package/dist/core/backends/claude-auth.d.ts.map +1 -0
  108. package/dist/core/backends/claude-auth.js +198 -0
  109. package/dist/core/backends/claude-auth.js.map +1 -0
  110. package/dist/core/backends/claude-code-core.d.ts +47 -119
  111. package/dist/core/backends/claude-code-core.d.ts.map +1 -1
  112. package/dist/core/backends/claude-code-core.js +166 -1561
  113. package/dist/core/backends/claude-code-core.js.map +1 -1
  114. package/dist/core/backends/claude-delegated.d.ts +86 -0
  115. package/dist/core/backends/claude-delegated.d.ts.map +1 -0
  116. package/dist/core/backends/claude-delegated.js +801 -0
  117. package/dist/core/backends/claude-delegated.js.map +1 -0
  118. package/dist/core/backends/claude-errors.d.ts +39 -0
  119. package/dist/core/backends/claude-errors.d.ts.map +1 -0
  120. package/dist/core/backends/claude-errors.js +71 -0
  121. package/dist/core/backends/claude-errors.js.map +1 -0
  122. package/dist/core/backends/claude-probe.d.ts +103 -0
  123. package/dist/core/backends/claude-probe.d.ts.map +1 -0
  124. package/dist/core/backends/claude-probe.js +336 -0
  125. package/dist/core/backends/claude-probe.js.map +1 -0
  126. package/dist/core/backends/claude-tool-collection.d.ts +135 -0
  127. package/dist/core/backends/claude-tool-collection.d.ts.map +1 -0
  128. package/dist/core/backends/claude-tool-collection.js +1093 -0
  129. package/dist/core/backends/claude-tool-collection.js.map +1 -0
  130. package/dist/core/backends/codex-core.d.ts.map +1 -1
  131. package/dist/core/backends/codex-core.js +36 -0
  132. package/dist/core/backends/codex-core.js.map +1 -1
  133. package/dist/core/backends/gemini-cli-core.d.ts +45 -5
  134. package/dist/core/backends/gemini-cli-core.d.ts.map +1 -1
  135. package/dist/core/backends/gemini-cli-core.js +146 -36
  136. package/dist/core/backends/gemini-cli-core.js.map +1 -1
  137. package/dist/core/backends/plan-presets.d.ts +3 -1
  138. package/dist/core/backends/plan-presets.d.ts.map +1 -1
  139. package/dist/core/backends/plan-presets.js +42 -2
  140. package/dist/core/backends/plan-presets.js.map +1 -1
  141. package/dist/core/backends/prompt-utils.d.ts +1 -0
  142. package/dist/core/backends/prompt-utils.d.ts.map +1 -1
  143. package/dist/core/backends/prompt-utils.js +60 -3
  144. package/dist/core/backends/prompt-utils.js.map +1 -1
  145. package/dist/core/bang-commands/commands-help.d.ts +5 -0
  146. package/dist/core/bang-commands/commands-help.d.ts.map +1 -0
  147. package/dist/core/bang-commands/commands-help.js +69 -0
  148. package/dist/core/bang-commands/commands-help.js.map +1 -0
  149. package/dist/core/bang-commands/commands-wiki.d.ts +75 -0
  150. package/dist/core/bang-commands/commands-wiki.d.ts.map +1 -0
  151. package/dist/core/bang-commands/commands-wiki.js +574 -0
  152. package/dist/core/bang-commands/commands-wiki.js.map +1 -0
  153. package/dist/core/bang-commands/index.d.ts +4 -2
  154. package/dist/core/bang-commands/index.d.ts.map +1 -1
  155. package/dist/core/bang-commands/index.js +15 -1
  156. package/dist/core/bang-commands/index.js.map +1 -1
  157. package/dist/core/bang-commands/registry.d.ts +47 -4
  158. package/dist/core/bang-commands/registry.d.ts.map +1 -1
  159. package/dist/core/bang-commands/registry.js +85 -15
  160. package/dist/core/bang-commands/registry.js.map +1 -1
  161. package/dist/core/context-builder.d.ts +53 -12
  162. package/dist/core/context-builder.d.ts.map +1 -1
  163. package/dist/core/context-builder.js +240 -92
  164. package/dist/core/context-builder.js.map +1 -1
  165. package/dist/core/daemon-api-cli.d.ts.map +1 -1
  166. package/dist/core/daemon-api-cli.js +50 -2
  167. package/dist/core/daemon-api-cli.js.map +1 -1
  168. package/dist/core/dispatcher-date-utils.d.ts +49 -0
  169. package/dist/core/dispatcher-date-utils.d.ts.map +1 -0
  170. package/dist/core/dispatcher-date-utils.js +132 -0
  171. package/dist/core/dispatcher-date-utils.js.map +1 -0
  172. package/dist/core/dispatcher-error-handling.d.ts +159 -0
  173. package/dist/core/dispatcher-error-handling.d.ts.map +1 -0
  174. package/dist/core/dispatcher-error-handling.js +393 -0
  175. package/dist/core/dispatcher-error-handling.js.map +1 -0
  176. package/dist/core/dispatcher-hourly-check.d.ts +150 -0
  177. package/dist/core/dispatcher-hourly-check.d.ts.map +1 -0
  178. package/dist/core/dispatcher-hourly-check.js +665 -0
  179. package/dist/core/dispatcher-hourly-check.js.map +1 -0
  180. package/dist/core/dispatcher-message-handler.d.ts +170 -0
  181. package/dist/core/dispatcher-message-handler.d.ts.map +1 -0
  182. package/dist/core/dispatcher-message-handler.js +1064 -0
  183. package/dist/core/dispatcher-message-handler.js.map +1 -0
  184. package/dist/core/dispatcher-morning-routine.d.ts +169 -0
  185. package/dist/core/dispatcher-morning-routine.d.ts.map +1 -0
  186. package/dist/core/dispatcher-morning-routine.js +449 -0
  187. package/dist/core/dispatcher-morning-routine.js.map +1 -0
  188. package/dist/core/dispatcher-prompt.d.ts +107 -0
  189. package/dist/core/dispatcher-prompt.d.ts.map +1 -0
  190. package/dist/core/dispatcher-prompt.js +227 -0
  191. package/dist/core/dispatcher-prompt.js.map +1 -0
  192. package/dist/core/dispatcher-repository-helpers.d.ts +39 -0
  193. package/dist/core/dispatcher-repository-helpers.d.ts.map +1 -0
  194. package/dist/core/dispatcher-repository-helpers.js +86 -0
  195. package/dist/core/dispatcher-repository-helpers.js.map +1 -0
  196. package/dist/core/dispatcher-result-processor.d.ts +168 -0
  197. package/dist/core/dispatcher-result-processor.d.ts.map +1 -0
  198. package/dist/core/dispatcher-result-processor.js +533 -0
  199. package/dist/core/dispatcher-result-processor.js.map +1 -0
  200. package/dist/core/dispatcher-scheduled-tasks.d.ts +406 -0
  201. package/dist/core/dispatcher-scheduled-tasks.d.ts.map +1 -0
  202. package/dist/core/dispatcher-scheduled-tasks.js +1032 -0
  203. package/dist/core/dispatcher-scheduled-tasks.js.map +1 -0
  204. package/dist/core/dispatcher-types.d.ts +411 -0
  205. package/dist/core/dispatcher-types.d.ts.map +1 -0
  206. package/dist/core/dispatcher-types.js +106 -0
  207. package/dist/core/dispatcher-types.js.map +1 -0
  208. package/dist/core/dispatcher.d.ts +122 -610
  209. package/dist/core/dispatcher.d.ts.map +1 -1
  210. package/dist/core/dispatcher.js +365 -3521
  211. package/dist/core/dispatcher.js.map +1 -1
  212. package/dist/core/integration-health.d.ts +18 -10
  213. package/dist/core/integration-health.d.ts.map +1 -1
  214. package/dist/core/integration-health.js +31 -1
  215. package/dist/core/integration-health.js.map +1 -1
  216. package/dist/core/integration-lifecycle.d.ts +65 -0
  217. package/dist/core/integration-lifecycle.d.ts.map +1 -1
  218. package/dist/core/integration-lifecycle.js +163 -14
  219. package/dist/core/integration-lifecycle.js.map +1 -1
  220. package/dist/core/integration-main-backend.d.ts +40 -0
  221. package/dist/core/integration-main-backend.d.ts.map +1 -1
  222. package/dist/core/integration-main-backend.js +89 -2
  223. package/dist/core/integration-main-backend.js.map +1 -1
  224. package/dist/core/management-md.d.ts +51 -17
  225. package/dist/core/management-md.d.ts.map +1 -1
  226. package/dist/core/management-md.js +233 -56
  227. package/dist/core/management-md.js.map +1 -1
  228. package/dist/core/metrics.d.ts +127 -0
  229. package/dist/core/metrics.d.ts.map +1 -1
  230. package/dist/core/metrics.js +256 -1
  231. package/dist/core/metrics.js.map +1 -1
  232. package/dist/core/output-language-policy.d.ts +74 -0
  233. package/dist/core/output-language-policy.d.ts.map +1 -0
  234. package/dist/core/output-language-policy.js +194 -0
  235. package/dist/core/output-language-policy.js.map +1 -0
  236. package/dist/core/prompts.d.ts +3 -1
  237. package/dist/core/prompts.d.ts.map +1 -1
  238. package/dist/core/prompts.js +161 -3
  239. package/dist/core/prompts.js.map +1 -1
  240. package/dist/core/repository-management-docs.d.ts +24 -0
  241. package/dist/core/repository-management-docs.d.ts.map +1 -1
  242. package/dist/core/repository-management-docs.js +210 -26
  243. package/dist/core/repository-management-docs.js.map +1 -1
  244. package/dist/core/roadmap-validate.js +13 -1
  245. package/dist/core/roadmap-validate.js.map +1 -1
  246. package/dist/core/routine-acquisition-plan.d.ts +182 -0
  247. package/dist/core/routine-acquisition-plan.d.ts.map +1 -0
  248. package/dist/core/routine-acquisition-plan.js +367 -0
  249. package/dist/core/routine-acquisition-plan.js.map +1 -0
  250. package/dist/core/routine-fetch-window-retry.d.ts +109 -0
  251. package/dist/core/routine-fetch-window-retry.d.ts.map +1 -0
  252. package/dist/core/routine-fetch-window-retry.js +210 -0
  253. package/dist/core/routine-fetch-window-retry.js.map +1 -0
  254. package/dist/core/routine-fetch-window-runner.d.ts +427 -0
  255. package/dist/core/routine-fetch-window-runner.d.ts.map +1 -0
  256. package/dist/core/routine-fetch-window-runner.js +1591 -0
  257. package/dist/core/routine-fetch-window-runner.js.map +1 -0
  258. package/dist/core/routine-windows.d.ts +171 -0
  259. package/dist/core/routine-windows.d.ts.map +1 -0
  260. package/dist/core/routine-windows.js +377 -0
  261. package/dist/core/routine-windows.js.map +1 -0
  262. package/dist/core/scheduler.d.ts +50 -2
  263. package/dist/core/scheduler.d.ts.map +1 -1
  264. package/dist/core/scheduler.js +88 -7
  265. package/dist/core/scheduler.js.map +1 -1
  266. package/dist/core/skill-curation/declarations.d.ts.map +1 -1
  267. package/dist/core/skill-curation/declarations.js +11 -12
  268. package/dist/core/skill-curation/declarations.js.map +1 -1
  269. package/dist/core/skill-source-paths.d.ts +14 -0
  270. package/dist/core/skill-source-paths.d.ts.map +1 -0
  271. package/dist/core/skill-source-paths.js +82 -0
  272. package/dist/core/skill-source-paths.js.map +1 -0
  273. package/dist/core/skills-compiler.d.ts +29 -0
  274. package/dist/core/skills-compiler.d.ts.map +1 -1
  275. package/dist/core/skills-compiler.js +166 -30
  276. package/dist/core/skills-compiler.js.map +1 -1
  277. package/dist/core/skills-manifest.d.ts.map +1 -1
  278. package/dist/core/skills-manifest.js +72 -0
  279. package/dist/core/skills-manifest.js.map +1 -1
  280. package/dist/core/system-reset.d.ts +25 -0
  281. package/dist/core/system-reset.d.ts.map +1 -1
  282. package/dist/core/system-reset.js +72 -2
  283. package/dist/core/system-reset.js.map +1 -1
  284. package/dist/core/wiki/approval-queue.d.ts +31 -0
  285. package/dist/core/wiki/approval-queue.d.ts.map +1 -0
  286. package/dist/core/wiki/approval-queue.js +44 -0
  287. package/dist/core/wiki/approval-queue.js.map +1 -0
  288. package/dist/core/wiki/bridge.d.ts +74 -0
  289. package/dist/core/wiki/bridge.d.ts.map +1 -0
  290. package/dist/core/wiki/bridge.js +405 -0
  291. package/dist/core/wiki/bridge.js.map +1 -0
  292. package/dist/core/wiki/compile-lock.d.ts +42 -0
  293. package/dist/core/wiki/compile-lock.d.ts.map +1 -0
  294. package/dist/core/wiki/compile-lock.js +55 -0
  295. package/dist/core/wiki/compile-lock.js.map +1 -0
  296. package/dist/core/wiki/compile-preview.d.ts +8 -0
  297. package/dist/core/wiki/compile-preview.d.ts.map +1 -0
  298. package/dist/core/wiki/compile-preview.js +200 -0
  299. package/dist/core/wiki/compile-preview.js.map +1 -0
  300. package/dist/core/wiki/cost-estimate.d.ts +30 -0
  301. package/dist/core/wiki/cost-estimate.d.ts.map +1 -0
  302. package/dist/core/wiki/cost-estimate.js +243 -0
  303. package/dist/core/wiki/cost-estimate.js.map +1 -0
  304. package/dist/core/wiki/dispatcher.d.ts +48 -0
  305. package/dist/core/wiki/dispatcher.d.ts.map +1 -0
  306. package/dist/core/wiki/dispatcher.js +92 -0
  307. package/dist/core/wiki/dispatcher.js.map +1 -0
  308. package/dist/core/wiki/git-precompile.d.ts +86 -0
  309. package/dist/core/wiki/git-precompile.d.ts.map +1 -0
  310. package/dist/core/wiki/git-precompile.js +96 -0
  311. package/dist/core/wiki/git-precompile.js.map +1 -0
  312. package/dist/core/wiki/import-migrate.d.ts +38 -0
  313. package/dist/core/wiki/import-migrate.d.ts.map +1 -0
  314. package/dist/core/wiki/import-migrate.js +310 -0
  315. package/dist/core/wiki/import-migrate.js.map +1 -0
  316. package/dist/core/wiki/import-probe.d.ts +76 -0
  317. package/dist/core/wiki/import-probe.d.ts.map +1 -0
  318. package/dist/core/wiki/import-probe.js +245 -0
  319. package/dist/core/wiki/import-probe.js.map +1 -0
  320. package/dist/core/wiki/index-cache.d.ts +39 -0
  321. package/dist/core/wiki/index-cache.d.ts.map +1 -0
  322. package/dist/core/wiki/index-cache.js +152 -0
  323. package/dist/core/wiki/index-cache.js.map +1 -0
  324. package/dist/core/wiki/multi-url-dispatch.d.ts +52 -0
  325. package/dist/core/wiki/multi-url-dispatch.d.ts.map +1 -0
  326. package/dist/core/wiki/multi-url-dispatch.js +72 -0
  327. package/dist/core/wiki/multi-url-dispatch.js.map +1 -0
  328. package/dist/core/wiki/wiki-fts.d.ts +75 -0
  329. package/dist/core/wiki/wiki-fts.d.ts.map +1 -0
  330. package/dist/core/wiki/wiki-fts.js +265 -0
  331. package/dist/core/wiki/wiki-fts.js.map +1 -0
  332. package/dist/core/wiki/workspaces.d.ts +101 -0
  333. package/dist/core/wiki/workspaces.d.ts.map +1 -0
  334. package/dist/core/wiki/workspaces.js +352 -0
  335. package/dist/core/wiki/workspaces.js.map +1 -0
  336. package/dist/core/wiki/write-strategy.d.ts +70 -0
  337. package/dist/core/wiki/write-strategy.d.ts.map +1 -0
  338. package/dist/core/wiki/write-strategy.js +112 -0
  339. package/dist/core/wiki/write-strategy.js.map +1 -0
  340. package/dist/core/workdir.d.ts +8 -1
  341. package/dist/core/workdir.d.ts.map +1 -1
  342. package/dist/core/workdir.js +4 -1
  343. package/dist/core/workdir.js.map +1 -1
  344. package/dist/db/observations.d.ts +45 -2
  345. package/dist/db/observations.d.ts.map +1 -1
  346. package/dist/db/observations.js +112 -14
  347. package/dist/db/observations.js.map +1 -1
  348. package/dist/db/schema.d.ts.map +1 -1
  349. package/dist/db/schema.js +135 -25
  350. package/dist/db/schema.js.map +1 -1
  351. package/dist/db/wiki-store.d.ts +3 -0
  352. package/dist/db/wiki-store.d.ts.map +1 -0
  353. package/dist/db/wiki-store.js +7 -0
  354. package/dist/db/wiki-store.js.map +1 -0
  355. package/dist/index.js +159 -610
  356. package/dist/index.js.map +1 -1
  357. package/dist/messaging/url-extract.d.ts +8 -0
  358. package/dist/messaging/url-extract.d.ts.map +1 -0
  359. package/dist/messaging/url-extract.js +41 -0
  360. package/dist/messaging/url-extract.js.map +1 -0
  361. package/dist/observers/delegated-sync-worker.d.ts +52 -1
  362. package/dist/observers/delegated-sync-worker.d.ts.map +1 -1
  363. package/dist/observers/delegated-sync-worker.js +75 -18
  364. package/dist/observers/delegated-sync-worker.js.map +1 -1
  365. package/dist/observers/imminent-event-scheduler.d.ts +20 -7
  366. package/dist/observers/imminent-event-scheduler.d.ts.map +1 -1
  367. package/dist/observers/imminent-event-scheduler.js +134 -29
  368. package/dist/observers/imminent-event-scheduler.js.map +1 -1
  369. package/dist/observers/mail-poller.d.ts +12 -5
  370. package/dist/observers/mail-poller.d.ts.map +1 -1
  371. package/dist/observers/mail-poller.js +36 -14
  372. package/dist/observers/mail-poller.js.map +1 -1
  373. package/dist/observers/manager.d.ts +37 -5
  374. package/dist/observers/manager.d.ts.map +1 -1
  375. package/dist/observers/manager.js +28 -10
  376. package/dist/observers/manager.js.map +1 -1
  377. package/dist/safety/always-disallowed.d.ts +65 -0
  378. package/dist/safety/always-disallowed.d.ts.map +1 -1
  379. package/dist/safety/always-disallowed.js +106 -10
  380. package/dist/safety/always-disallowed.js.map +1 -1
  381. package/dist/safety/audit.d.ts +46 -1
  382. package/dist/safety/audit.d.ts.map +1 -1
  383. package/dist/safety/audit.js +79 -16
  384. package/dist/safety/audit.js.map +1 -1
  385. package/dist/safety/risk-classifier.d.ts.map +1 -1
  386. package/dist/safety/risk-classifier.js +29 -0
  387. package/dist/safety/risk-classifier.js.map +1 -1
  388. package/dist/services/delegated-backend-invoker.d.ts +1 -51
  389. package/dist/services/delegated-backend-invoker.d.ts.map +1 -1
  390. package/dist/services/delegated-backend-invoker.js +41 -480
  391. package/dist/services/delegated-backend-invoker.js.map +1 -1
  392. package/dist/services/delegated-invoker-audit.d.ts +94 -0
  393. package/dist/services/delegated-invoker-audit.d.ts.map +1 -0
  394. package/dist/services/delegated-invoker-audit.js +238 -0
  395. package/dist/services/delegated-invoker-audit.js.map +1 -0
  396. package/dist/services/delegated-invoker-cache-hits.d.ts +34 -0
  397. package/dist/services/delegated-invoker-cache-hits.d.ts.map +1 -0
  398. package/dist/services/delegated-invoker-cache-hits.js +104 -0
  399. package/dist/services/delegated-invoker-cache-hits.js.map +1 -0
  400. package/dist/services/delegated-invoker-janitors.d.ts +28 -0
  401. package/dist/services/delegated-invoker-janitors.d.ts.map +1 -0
  402. package/dist/services/delegated-invoker-janitors.js +104 -0
  403. package/dist/services/delegated-invoker-janitors.js.map +1 -0
  404. package/dist/services/delegated-invoker-utils.d.ts +42 -0
  405. package/dist/services/delegated-invoker-utils.d.ts.map +1 -0
  406. package/dist/services/delegated-invoker-utils.js +100 -0
  407. package/dist/services/delegated-invoker-utils.js.map +1 -0
  408. package/dist/services/delegated-task-runtime.d.ts +1 -1
  409. package/dist/services/delegated-task-runtime.js +1 -1
  410. package/dist/services/integrations/snapshot-partitions.d.ts +5 -0
  411. package/dist/services/integrations/snapshot-partitions.d.ts.map +1 -1
  412. package/dist/services/integrations/snapshot-partitions.js +12 -0
  413. package/dist/services/integrations/snapshot-partitions.js.map +1 -1
  414. package/dist/services/voice/transcriber-impl.d.ts.map +1 -1
  415. package/dist/services/voice/transcriber-impl.js +7 -8
  416. package/dist/services/voice/transcriber-impl.js.map +1 -1
  417. package/dist/settings/runtime-settings.d.ts +12 -1
  418. package/dist/settings/runtime-settings.d.ts.map +1 -1
  419. package/dist/settings/runtime-settings.js +59 -1
  420. package/dist/settings/runtime-settings.js.map +1 -1
  421. package/package.json +2 -2
@@ -0,0 +1,665 @@
1
+ /**
2
+ * `HourlyCheckCoordinator` — owns the dispatcher's
3
+ * `triggerHourlyCheck` entry point and the cost-reduction-structural §B
4
+ * three-stage gate that fronts it. The coordinator decides whether a
5
+ * given hourly tick:
6
+ * - skips (autonomous gate / morning routine active / already running
7
+ * / below threshold);
8
+ * - silently consumes observations + records an Agent Log line
9
+ * (Stage 0 deterministic gate or Stage 2 lite-tier `log_only`);
10
+ * - escalates to the existing Stage 3 enqueue (Stage 2 `escalate`
11
+ * verdict or `failed` cautious-escalate path).
12
+ *
13
+ * Extracted from `core/dispatcher.ts` as part of phase D-2 of
14
+ * `docs/design/appendices/file-split-plan.md`. Pattern B (stateful
15
+ * coordinator): the coordinator owns the gate logic but borrows live
16
+ * accessors for state the dispatcher continues to own — the
17
+ * `hourlyCheckInProgress` flag (atomic check-and-set inside the
18
+ * trigger), the `morningRoutineInProgress` flag (read-only), and the
19
+ * lazily-injected delegated-sync refresh callback.
20
+ *
21
+ * Dispatcher entry points served:
22
+ * - `EventDispatcher.triggerHourlyCheck(source, options)` is now a
23
+ * thin one-liner that delegates to `trigger(source, options)`.
24
+ *
25
+ * Invariants preserved bit-for-bit from
26
+ * `docs/design/02-event-pipeline.md` §2:
27
+ * - skip-if-morning-routine-in-progress;
28
+ * - skip-if-hourly-already-running (atomic flag flip BEFORE any
29
+ * await boundary — the C1 race fix from before the split);
30
+ * - skip-if-pending-observations-below-threshold (legacy
31
+ * min-observations floor honoured only when the gate would have
32
+ * proceeded to Stage 3 anyway);
33
+ * - skip-if-setup-incomplete / vault-degraded / user-paused via
34
+ * `isAutonomousAllowed`.
35
+ *
36
+ * Shared-state references held:
37
+ * - `setHourlyCheckInProgress` / `isHourlyCheckInProgress` —
38
+ * getter/setter pair around the dispatcher's flag. The flag is
39
+ * left `true` when an enqueue actually happens (the EventBus
40
+ * consumer's `dispatchSafe` finally clears it on routine
41
+ * completion); it is reset inline when the coordinator owns the
42
+ * turn (silent gate paths) or when the trigger is skipping.
43
+ * - `isMorningRoutineActive` — read-only mirror of the dispatcher
44
+ * method so the gate stays single-sourced.
45
+ * - `isAutonomousAllowed` — same; returns the
46
+ * `TriggerHourlyCheckSkipReason` the gate should surface.
47
+ * - `getDelegatedSyncRefresh` — accessor; null when no delegated
48
+ * integration is wired, in which case the gate proceeds without
49
+ * a refresh, matching pre-injection behaviour.
50
+ */
51
+ import { EventPriority, createEvent, nativeIntegrationsContributingObservationsForProcessKey, } from "@aitne/shared";
52
+ import { readIntegrations } from "../db/integrations-store.js";
53
+ import { existsSync, readFileSync } from "node:fs";
54
+ import { join } from "node:path";
55
+ import { CONTEXT_RELATIVE_PATHS } from "./context-paths.js";
56
+ import { getContextDir } from "../config.js";
57
+ import { consumeObservations, getPendingCount, getPendingObservations, } from "../db/observations.js";
58
+ import { computeHourlyCheckSignals } from "../db/hourly-check-signals.js";
59
+ import { buildGateAuditDetail, decideStage, renderGateDecisionBlock, } from "../scheduler/hourly-check-gate.js";
60
+ import { appendAgentLogLine } from "./today-direct-writer.js";
61
+ import { parseStage2Verdict } from "./dispatcher-types.js";
62
+ import { createLogger } from "../logging.js";
63
+ const logger = createLogger("dispatcher-hourly-check");
64
+ export class HourlyCheckCoordinator {
65
+ db;
66
+ config;
67
+ eventBus;
68
+ contextBuilder;
69
+ agentRouter;
70
+ audit;
71
+ todayWriteLock;
72
+ prompt;
73
+ fetchWindowRunner;
74
+ getDelegatedSyncRefresh;
75
+ setHourlyCheckInProgress;
76
+ isHourlyCheckInProgress;
77
+ isMorningRoutineActive;
78
+ isAutonomousAllowed;
79
+ constructor(deps) {
80
+ this.db = deps.db;
81
+ this.config = deps.config;
82
+ this.eventBus = deps.eventBus;
83
+ this.contextBuilder = deps.contextBuilder;
84
+ this.agentRouter = deps.agentRouter;
85
+ this.audit = deps.audit;
86
+ this.todayWriteLock = deps.todayWriteLock;
87
+ this.prompt = deps.prompt;
88
+ this.fetchWindowRunner = deps.fetchWindowRunner;
89
+ this.getDelegatedSyncRefresh = deps.getDelegatedSyncRefresh;
90
+ this.setHourlyCheckInProgress = deps.setHourlyCheckInProgress;
91
+ this.isHourlyCheckInProgress = deps.isHourlyCheckInProgress;
92
+ this.isMorningRoutineActive = deps.isMorningRoutineActive;
93
+ this.isAutonomousAllowed = deps.isAutonomousAllowed;
94
+ }
95
+ async trigger(source, options = {}) {
96
+ const forced = options.force === true;
97
+ const minObservations = this.config.hourlyCheckMinObservations;
98
+ // C1 fix: atomic check-and-set on hourlyCheckInProgress BEFORE any await
99
+ // boundary. Previously `await this.isMorningRoutineActive()` yielded to
100
+ // the microtask queue, allowing cron + /api/agent/run-now arriving in
101
+ // the same tick to both observe `hourlyCheckInProgress === false` and
102
+ // both enqueue. Because Node is single-threaded and better-sqlite3 is
103
+ // synchronous, doing set-first + sync checks + rollback-on-skip is now
104
+ // race-free.
105
+ if (this.isHourlyCheckInProgress()) {
106
+ logger.info({ source }, "Hourly check skipped — previous hourly check is still running");
107
+ return {
108
+ status: "skipped",
109
+ reason: "hourly_check_in_progress",
110
+ minObservations,
111
+ forced,
112
+ };
113
+ }
114
+ this.setHourlyCheckInProgress(true);
115
+ // Rollback flag unless we actually enqueue the event or land on a
116
+ // silent path that owns its own reset.
117
+ let enqueued = false;
118
+ let silentPathOwnsReset = false;
119
+ try {
120
+ const setupBlock = this.isAutonomousAllowed();
121
+ if (setupBlock !== null) {
122
+ logger.info({ source, reason: setupBlock }, "Hourly check skipped — autonomous work paused for setup");
123
+ return {
124
+ status: "skipped",
125
+ reason: setupBlock,
126
+ minObservations,
127
+ forced,
128
+ };
129
+ }
130
+ if (this.isMorningRoutineActive()) {
131
+ logger.info({ source }, "Hourly check skipped — morning routine is active");
132
+ return {
133
+ status: "skipped",
134
+ reason: "morning_routine_active",
135
+ minObservations,
136
+ forced,
137
+ };
138
+ }
139
+ // Refresh delegated-sync snapshots for any cadence the operator
140
+ // left opted-OUT (the post-Phase-9 default). Without this, Gmail /
141
+ // Notion observations would dry up entirely in delegated mode and
142
+ // the routine.hourly_check.delegated.* task flow's Step 0a / 0c
143
+ // would have nothing to consume — Step 1's `/api/observations`
144
+ // call would return only Obsidian / Git rows. Calendar's Step 0b
145
+ // already fetches actively via `/reconcile`, so the gap is
146
+ // specific to gmail / notion. See `docs/design/appendices/
147
+ // delegated-sync-opt-in.md` and the worker's
148
+ // `runDisabledCadencesForHourlyCheck` doc-comment for the full
149
+ // reasoning. Failures are logged but do NOT block the check —
150
+ // a stuck cadence cannot starve the entire hourly loop.
151
+ const delegatedSyncRefresh = this.getDelegatedSyncRefresh();
152
+ if (delegatedSyncRefresh) {
153
+ try {
154
+ await delegatedSyncRefresh();
155
+ }
156
+ catch (err) {
157
+ logger.warn({ err, source }, "Pre-hourly-check delegated sync refresh failed; proceeding with stale snapshot");
158
+ }
159
+ }
160
+ const pendingCount = getPendingCount(this.db, { actorFilter: "user" });
161
+ // INTEGRATION_NATIVE_MODE_DESIGN.md §6.5.1 — threshold bypass when
162
+ // at least one native integration contributes observations during
163
+ // hourly_check execution. "Contributes observations" is the union
164
+ // of `taskFlowsTouched` (in-turn variant POSTs) and
165
+ // `taskFlowsReferenced` (partial-include POSTs from the
166
+ // `routine.fetch_window` pre-pass — RDAD §10 R3). Without the
167
+ // referenced arm, an Outlook-only-native deployment
168
+ // (taskFlowsTouched is `[]` for user-managed connectors) would
169
+ // never trip the bypass: pre-pass would never run, no observations
170
+ // would land, and the gate would lock the routine into permanent
171
+ // skip. When the bypass fires the legacy `below_threshold` floor
172
+ // is suppressed; the in-turn POSTs populate the table by end of
173
+ // turn.
174
+ const nativeHourlyCheckIntegrations = nativeIntegrationsContributingObservationsForProcessKey("routine.hourly_check", readIntegrations(this.db));
175
+ const hasNativeForHourlyCheck = nativeHourlyCheckIntegrations.length > 0;
176
+ if (hasNativeForHourlyCheck) {
177
+ logger.debug({
178
+ source,
179
+ pendingCount,
180
+ minObservations,
181
+ nativeIntegrations: nativeHourlyCheckIntegrations,
182
+ }, "Hourly check: native integrations active — pre-run threshold bypass per §6.5.1");
183
+ }
184
+ // cost-reduction-structural §B — three-stage gate.
185
+ // Mode `off` falls through to the legacy min-observations gate +
186
+ // straight enqueue (rollback path for the gate); `shadow`/`live`
187
+ // compute the gate verdict before any other branch fires.
188
+ const gateMode = (this.config.hourlyCheckGateMode
189
+ ?? "shadow");
190
+ if (gateMode === "off") {
191
+ if (!forced && !hasNativeForHourlyCheck && pendingCount < minObservations) {
192
+ logger.debug({ source, pendingCount, minObservations }, "Hourly check skipped — not enough pending observations");
193
+ return {
194
+ status: "skipped",
195
+ reason: "below_threshold",
196
+ pendingCount,
197
+ minObservations,
198
+ forced,
199
+ };
200
+ }
201
+ await this.eventBus.put({
202
+ ...createEvent({
203
+ type: "routine.hourly_check",
204
+ source,
205
+ priority: EventPriority.NORMAL,
206
+ }),
207
+ routine: "hourly_check",
208
+ data: { pendingCount, forced },
209
+ ...(options.requestedModel ? { requestedModel: options.requestedModel } : {}),
210
+ });
211
+ enqueued = true;
212
+ return {
213
+ status: "queued",
214
+ pendingCount,
215
+ minObservations,
216
+ forced,
217
+ gateMode: "off",
218
+ };
219
+ }
220
+ const decision = this.computeHourlyCheckGateDecision();
221
+ if (gateMode === "shadow") {
222
+ // Shadow mode: log the gate verdict, then proceed to Stage 3
223
+ // exactly as before so the existing pipeline is uncovered.
224
+ this.logGateAuditRow(decision, {
225
+ mode: "shadow",
226
+ appliedDecision: "stage3_shadow",
227
+ forced,
228
+ });
229
+ if (!forced && !hasNativeForHourlyCheck && pendingCount < minObservations) {
230
+ logger.debug({ source, pendingCount, minObservations, gateStage: decision.stage }, "Hourly check skipped (shadow) — not enough pending observations");
231
+ return {
232
+ status: "skipped",
233
+ reason: "below_threshold",
234
+ pendingCount,
235
+ minObservations,
236
+ forced,
237
+ gateMode: "shadow",
238
+ gateStage: decision.stage,
239
+ gateReason: decision.reason,
240
+ appliedStage: "stage3_shadow",
241
+ };
242
+ }
243
+ await this.enqueueStage3HourlyCheck(source, { ...decision }, { mode: "shadow", forced, pendingCount, requestedModel: options.requestedModel });
244
+ enqueued = true;
245
+ return {
246
+ status: "queued",
247
+ pendingCount,
248
+ minObservations,
249
+ forced,
250
+ gateMode: "shadow",
251
+ gateStage: decision.stage,
252
+ gateReason: decision.reason,
253
+ appliedStage: "stage3_shadow",
254
+ };
255
+ }
256
+ // gateMode === 'live'
257
+ // Honour the legacy min-observations floor only when the gate
258
+ // would have proceeded to Stage 3 anyway. The silent gate path
259
+ // already short-circuits the noisy "1 obs, no signal" case below
260
+ // it, so keeping the floor active there would just suppress the
261
+ // gate's telemetry.
262
+ if (!forced
263
+ && !hasNativeForHourlyCheck
264
+ && decision.stage === "stage3"
265
+ && pendingCount < minObservations) {
266
+ this.logGateAuditRow(decision, {
267
+ mode: "live",
268
+ appliedDecision: "stage3",
269
+ forced,
270
+ // Mark the row as a skip even though the gate wanted Stage 3 —
271
+ // the legacy min-observations floor short-circuited it. Without
272
+ // this, every `below_threshold` skip would persist as a phantom
273
+ // `result='success'` row in the audit feed.
274
+ resultOverride: "skipped",
275
+ extra: { skipped: "below_threshold" },
276
+ });
277
+ return {
278
+ status: "skipped",
279
+ reason: "below_threshold",
280
+ pendingCount,
281
+ minObservations,
282
+ forced,
283
+ gateMode: "live",
284
+ gateStage: decision.stage,
285
+ gateReason: decision.reason,
286
+ };
287
+ }
288
+ if (decision.stage === "stage0_silent") {
289
+ const silentResult = this.runSilentHourlyCheckPath(decision, "stage0_silent", {
290
+ source,
291
+ forced,
292
+ });
293
+ silentPathOwnsReset = true;
294
+ return {
295
+ ...silentResult,
296
+ minObservations,
297
+ gateMode: "live",
298
+ gateStage: decision.stage,
299
+ gateReason: decision.reason,
300
+ appliedStage: "stage0_silent",
301
+ };
302
+ }
303
+ if (decision.stage === "stage2") {
304
+ const verdict = await this.runStage2Triage(decision, source);
305
+ if (verdict === "log_only") {
306
+ const silentResult = this.runSilentHourlyCheckPath(decision, "stage2_log_only", { source, forced });
307
+ silentPathOwnsReset = true;
308
+ return {
309
+ ...silentResult,
310
+ minObservations,
311
+ gateMode: "live",
312
+ gateStage: decision.stage,
313
+ gateReason: decision.reason,
314
+ appliedStage: "stage2_log_only",
315
+ };
316
+ }
317
+ // verdict === 'escalate' OR 'failed' (failed → cautious escalate
318
+ // since a malformed JSON should not silently skip a hour's worth
319
+ // of signals; matches the prompt contract's stated default).
320
+ await this.enqueueStage3HourlyCheck(source, decision, {
321
+ mode: "live",
322
+ forced,
323
+ pendingCount,
324
+ requestedModel: options.requestedModel,
325
+ stage2Verdict: verdict,
326
+ });
327
+ enqueued = true;
328
+ return {
329
+ status: "queued",
330
+ pendingCount,
331
+ minObservations,
332
+ forced,
333
+ gateMode: "live",
334
+ gateStage: decision.stage,
335
+ gateReason: decision.reason,
336
+ appliedStage: "stage3",
337
+ };
338
+ }
339
+ // decision.stage === 'stage3'
340
+ await this.enqueueStage3HourlyCheck(source, decision, { mode: "live", forced, pendingCount, requestedModel: options.requestedModel });
341
+ enqueued = true;
342
+ return {
343
+ status: "queued",
344
+ pendingCount,
345
+ minObservations,
346
+ forced,
347
+ gateMode: "live",
348
+ gateStage: decision.stage,
349
+ gateReason: decision.reason,
350
+ appliedStage: "stage3",
351
+ };
352
+ }
353
+ finally {
354
+ // Flag is only left true when we successfully enqueued OR the
355
+ // silent path explicitly opted out of resetting (it resets at
356
+ // the end of its own helper). The event loop's dispatchSafe()
357
+ // finally block clears the flag when an enqueued routine event
358
+ // finishes processing.
359
+ if (!enqueued && !silentPathOwnsReset) {
360
+ this.setHourlyCheckInProgress(false);
361
+ }
362
+ }
363
+ }
364
+ /**
365
+ * cost-reduction-structural §B — pull a fresh signal snapshot and run
366
+ * the deterministic gate. Helper so the dispatcher's call site stays
367
+ * compact and tests can spy on the boundary.
368
+ */
369
+ computeHourlyCheckGateDecision() {
370
+ const todayMd = this.readTodayMdSafe();
371
+ const signals = computeHourlyCheckSignals(this.db, {
372
+ vipMailSenders: this.config.vipMailSenders ?? [],
373
+ todayMd,
374
+ // Pass the configured agent timezone so `agentPlanOverdueCount`
375
+ // compares HH:MM rows in the right zone. Falls back to the
376
+ // engine's local TZ inside `computeHourlyCheckSignals` when this
377
+ // config field is empty (the common single-user case).
378
+ ...(this.config.timezone
379
+ ? { agentTimezone: this.config.timezone }
380
+ : {}),
381
+ });
382
+ return decideStage(signals, {
383
+ heartbeatHours: this.config.hourlyCheckHeartbeatHours ?? 4,
384
+ stage2Enabled: this.config.hourlyCheckStage2Enabled ?? false,
385
+ pendingObsLowSignalCeiling: this.config.hourlyCheckLowSignalPendingCeiling ?? 0,
386
+ });
387
+ }
388
+ readTodayMdSafe() {
389
+ try {
390
+ const path = join(getContextDir(this.config, this.db), CONTEXT_RELATIVE_PATHS.today);
391
+ if (!existsSync(path))
392
+ return null;
393
+ return readFileSync(path, "utf-8");
394
+ }
395
+ catch (err) {
396
+ logger.warn({ err }, "Failed to read today.md for hourly_check signals");
397
+ return null;
398
+ }
399
+ }
400
+ /**
401
+ * cost-reduction-structural §B — daemon-direct silent path. Used by
402
+ * Stage 0 and Stage 2 log-only verdicts. Consumes pending user
403
+ * observations + appends a single Agent Log line + records the gate
404
+ * verdict to `agent_actions`. The flag is reset before return.
405
+ */
406
+ runSilentHourlyCheckPath(decision, appliedDecision, ctx) {
407
+ const reason = appliedDecision === "stage0_silent"
408
+ ? "gate_stage0_silent"
409
+ : "gate_stage2_log_only";
410
+ let pendingCount = 0;
411
+ try {
412
+ pendingCount = decision.signals.pendingObsCount;
413
+ // Append a single bullet to today.md ## Agent Log. Best-effort —
414
+ // when today.md is missing or the lock is held, we still consume
415
+ // the observations so the queue doesn't grow indefinitely.
416
+ const message = appliedDecision === "stage0_silent"
417
+ ? `[hourly_check] Quiet (${decision.reason}) — ${pendingCount} obs consumed silently`
418
+ : `[hourly_check] Stage 2 log-only (${decision.reason}) — ${pendingCount} obs consumed silently`;
419
+ if (this.todayWriteLock) {
420
+ appendAgentLogLine({
421
+ contextDir: getContextDir(this.config, this.db),
422
+ message,
423
+ todayWriteLock: this.todayWriteLock,
424
+ timezone: this.config.timezone || undefined,
425
+ });
426
+ }
427
+ // Consume the observations under the gate's correlation id so
428
+ // dashboards can attribute "consumed by gate" rows separately
429
+ // from agent-driven consumption.
430
+ try {
431
+ const pending = getPendingObservations(this.db, {
432
+ actorFilter: "user",
433
+ limit: 100,
434
+ });
435
+ if (pending.length > 0) {
436
+ consumeObservations(this.db, pending.map((row) => row.id), `hourly_check_gate:${appliedDecision}`);
437
+ }
438
+ }
439
+ catch (err) {
440
+ logger.warn({ err }, "Failed to consume observations on silent gate path");
441
+ }
442
+ this.logGateAuditRow(decision, {
443
+ mode: "live",
444
+ appliedDecision,
445
+ forced: ctx.forced,
446
+ });
447
+ logger.info({
448
+ source: ctx.source,
449
+ gateStage: decision.stage,
450
+ gateReason: decision.reason,
451
+ appliedDecision,
452
+ pendingCount,
453
+ }, "Hourly check silenced by Stage-1 gate");
454
+ }
455
+ finally {
456
+ this.setHourlyCheckInProgress(false);
457
+ }
458
+ return {
459
+ status: "skipped",
460
+ reason,
461
+ pendingCount,
462
+ forced: ctx.forced,
463
+ };
464
+ }
465
+ async enqueueStage3HourlyCheck(source, decision, extra) {
466
+ const gateBlock = renderGateDecisionBlock(decision, {
467
+ mode: extra.mode,
468
+ forced: extra.forced,
469
+ });
470
+ if (extra.mode === "live") {
471
+ this.logGateAuditRow(decision, {
472
+ mode: extra.mode,
473
+ appliedDecision: "stage3",
474
+ forced: extra.forced,
475
+ ...(extra.stage2Verdict ? { stage2Verdict: extra.stage2Verdict } : {}),
476
+ });
477
+ }
478
+ const stage3Event = {
479
+ ...createEvent({
480
+ type: "routine.hourly_check",
481
+ source,
482
+ priority: EventPriority.NORMAL,
483
+ }),
484
+ routine: "hourly_check",
485
+ data: {
486
+ pendingCount: extra.pendingCount,
487
+ forced: extra.forced,
488
+ gateDecision: {
489
+ mode: extra.mode,
490
+ stage: decision.stage,
491
+ reason: decision.reason,
492
+ forced: extra.forced,
493
+ ...(extra.stage2Verdict ? { stage2Verdict: extra.stage2Verdict } : {}),
494
+ block: gateBlock,
495
+ },
496
+ },
497
+ ...(extra.requestedModel ? { requestedModel: extra.requestedModel } : {}),
498
+ };
499
+ // ROUTINE_DATA_ACQUISITION_DESIGN.md Phase 4 / D3 — synchronous
500
+ // pre-pass between the gate's escalate verdict and the Stage 3
501
+ // enqueue. The block lives on `event.data.fetchReportBlock` so
502
+ // ContextBuilder folds it into the Stage 3 prompt when the EventBus
503
+ // consumer dispatches the routine. Pre-pass is skipped when the
504
+ // gate's escalate reason is `forced` (operator-pushed runs already
505
+ // know they want a fresh look) or `shadow` (shadow mode is
506
+ // explicitly running the existing pipeline unchanged, so the
507
+ // pre-pass would change the comparison fixture). Failures inside
508
+ // the runner surface as `<fetch_report status="failed">` and never
509
+ // throw — design §11 R5.
510
+ if (extra.mode === "live" && !extra.forced) {
511
+ const prepass = await this.fetchWindowRunner.run(stage3Event, "routine.hourly_check");
512
+ stage3Event.data = {
513
+ ...stage3Event.data,
514
+ fetchReportBlock: prepass.block,
515
+ };
516
+ }
517
+ await this.eventBus.put(stage3Event);
518
+ }
519
+ logGateAuditRow(decision, params) {
520
+ try {
521
+ // The gate-audit helper only knows about the canonical stages
522
+ // (gate output) plus the shadow-mode marker. Map the silent-path
523
+ // alias `stage2_log_only` onto its canonical sibling so the
524
+ // helper's typing stays narrow; the verdict is preserved verbatim
525
+ // alongside `stage_reached` in the merged detail.
526
+ const auditAppliedDecision = params.appliedDecision === "stage2_log_only"
527
+ ? "stage0_silent"
528
+ : params.appliedDecision;
529
+ const detail = {
530
+ ...buildGateAuditDetail(decision, {
531
+ mode: params.mode,
532
+ appliedDecision: auditAppliedDecision,
533
+ forced: params.forced,
534
+ ...(params.stage2Verdict ? { stage2Verdict: params.stage2Verdict } : {}),
535
+ }),
536
+ // Always reflect the *real* applied stage in the row regardless
537
+ // of the alias mapping above.
538
+ stage_reached: params.appliedDecision,
539
+ ...(params.extra ?? {}),
540
+ };
541
+ const isShadow = params.appliedDecision === "stage3_shadow";
542
+ const isSilentPath = params.appliedDecision === "stage0_silent"
543
+ || params.appliedDecision === "stage2_log_only";
544
+ const result = params.resultOverride
545
+ ?? (isShadow ? "success" : isSilentPath ? "skipped" : "success");
546
+ this.db
547
+ .prepare(`INSERT INTO agent_actions
548
+ (action_type, trigger, result, detail, started_at, completed_at)
549
+ VALUES ('hourly_check.gate', 'autonomous', ?, json(?), datetime('now'), datetime('now'))`)
550
+ .run(result, JSON.stringify(detail));
551
+ }
552
+ catch (err) {
553
+ logger.warn({ err }, "Failed to record hourly_check.gate audit row");
554
+ }
555
+ }
556
+ /**
557
+ * cost-reduction-structural §B Stage 2 — synchronous lite-tier triage.
558
+ * Builds a `routine.hourly_check.triage` RoutineEvent and runs it
559
+ * inline through the agent router (NOT the EventBus, so the result
560
+ * is available before we decide whether to silence or escalate).
561
+ *
562
+ * The agent contract is JSON-only output (`{ "action": "log_only" |
563
+ * "escalate", "reason": "..." }`); on parse failure we return
564
+ * `'failed'` and the caller treats that as cautious escalate.
565
+ *
566
+ * Tool/turn clamp (defense-in-depth):
567
+ * - `allowedToolsOverride: []` removes every tool from the SDK's
568
+ * allowlist for the spawn. Stage 2 has nothing to do but emit a
569
+ * JSON line; the design's "no write tools" rule is enforced here
570
+ * instead of relying on the prompt alone.
571
+ * - `maxTurns: 1` caps the spawn at a single assistant turn. Even
572
+ * if a future prompt change accidentally invites tool use, the
573
+ * spawn cannot loop. Codex/Gemini have no per-spawn `allowedTools`
574
+ * surface today (acknowledged gap in `agent-core.ts`); the
575
+ * `maxTurns` cap and process_backend_config envelope are the
576
+ * remaining safety floor on those backends.
577
+ */
578
+ async runStage2Triage(decision, source) {
579
+ const triageEvent = {
580
+ ...createEvent({
581
+ type: "routine.hourly_check.triage",
582
+ source,
583
+ priority: EventPriority.NORMAL,
584
+ }),
585
+ routine: "hourly_check.triage",
586
+ data: {
587
+ forced: false,
588
+ gateDecision: {
589
+ mode: "live",
590
+ stage: decision.stage,
591
+ reason: decision.reason,
592
+ forced: false,
593
+ block: renderGateDecisionBlock(decision, { mode: "live", forced: false }),
594
+ },
595
+ },
596
+ };
597
+ let context;
598
+ try {
599
+ context = await this.contextBuilder.build(triageEvent);
600
+ }
601
+ catch (err) {
602
+ logger.error({ err }, "Stage 2 triage context build failed");
603
+ return "failed";
604
+ }
605
+ const processKey = "routine.hourly_check.triage";
606
+ const reassemblePrompt = (bid) => this.prompt.assemble(triageEvent.type, processKey, bid);
607
+ let binding;
608
+ try {
609
+ binding = this.agentRouter.resolveBinding(triageEvent, { processKey });
610
+ }
611
+ catch (err) {
612
+ logger.error({ err }, "Stage 2 triage binding resolve failed");
613
+ return "failed";
614
+ }
615
+ const prompt = reassemblePrompt(binding.main.backendId);
616
+ let result;
617
+ try {
618
+ result = await this.agentRouter.execute({
619
+ prompt,
620
+ context,
621
+ event: triageEvent,
622
+ processKey,
623
+ preResolvedBinding: binding,
624
+ reassemblePrompt,
625
+ // Defense-in-depth: Stage 2 must not call any tool. Empty
626
+ // `allowedToolsOverride` REPLACES the default allowlist on
627
+ // Claude (Codex/Gemini have no per-spawn `allowedTools` surface
628
+ // — acknowledged gap in `agent-core.ts`). The `max_turns=1` cap
629
+ // for the spawn comes from the seeded `process_backend_config`
630
+ // row for `routine.hourly_check.triage` (see `db/schema.ts`),
631
+ // which the router reads via `binding.main.maxTurns`. Together
632
+ // these mean: zero tools on Claude, one assistant turn on every
633
+ // backend.
634
+ allowedToolsOverride: [],
635
+ });
636
+ }
637
+ catch (err) {
638
+ logger.error({ err }, "Stage 2 triage agent execution failed");
639
+ return "failed";
640
+ }
641
+ // Audit row for the lite-tier session itself, distinct from the gate
642
+ // audit row written by `logGateAuditRow`.
643
+ try {
644
+ this.audit.logAction({
645
+ event: triageEvent,
646
+ model: result.model,
647
+ costUsd: result.costUsd,
648
+ usage: result.usage,
649
+ modelUsage: result.modelUsage,
650
+ durationMs: result.durationMs,
651
+ numTurns: result.numTurns,
652
+ trigger: "autonomous",
653
+ backend: result.backendId,
654
+ costSource: result.costSource,
655
+ contextUpdated: result.contextUpdated,
656
+ advisorCallCount: result.advisorCallCount,
657
+ });
658
+ }
659
+ catch (err) {
660
+ logger.warn({ err }, "Failed to log Stage 2 triage agent_actions row");
661
+ }
662
+ return parseStage2Verdict(result.output);
663
+ }
664
+ }
665
+ //# sourceMappingURL=dispatcher-hourly-check.js.map