@aitne/daemon 0.1.9 → 0.1.11

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 (333) hide show
  1. package/dist/adapters/adapter-watchdog.d.ts +70 -0
  2. package/dist/adapters/adapter-watchdog.js +115 -0
  3. package/dist/adapters/discord.d.ts +17 -1
  4. package/dist/adapters/discord.js +33 -0
  5. package/dist/adapters/notification-manager.d.ts +27 -1
  6. package/dist/adapters/notification-manager.js +54 -39
  7. package/dist/adapters/slack-adapter.d.ts +26 -1
  8. package/dist/adapters/slack-adapter.js +41 -0
  9. package/dist/adapters/telegram-adapter.d.ts +18 -1
  10. package/dist/adapters/telegram-adapter.js +41 -2
  11. package/dist/adapters/types.d.ts +20 -0
  12. package/dist/adapters/whatsapp-adapter.d.ts +26 -7
  13. package/dist/adapters/whatsapp-adapter.js +74 -21
  14. package/dist/api/env-writer.d.ts +1 -0
  15. package/dist/api/env-writer.js +17 -7
  16. package/dist/api/helpers/agent-errors-registry.d.ts +5 -5
  17. package/dist/api/helpers/agent-errors-registry.js +5 -5
  18. package/dist/api/routes/agent-schedule.js +5 -1
  19. package/dist/api/routes/agent.js +33 -12
  20. package/dist/api/routes/agents/index.js +75 -16
  21. package/dist/api/routes/agents/views.d.ts +37 -2
  22. package/dist/api/routes/agents/views.js +64 -2
  23. package/dist/api/routes/apple-calendar.js +4 -1
  24. package/dist/api/routes/background-task.d.ts +22 -0
  25. package/dist/api/routes/background-task.js +338 -0
  26. package/dist/api/routes/browser-history.js +9 -1
  27. package/dist/api/routes/calendar.js +12 -2
  28. package/dist/api/routes/context/path-resolve.js +6 -1
  29. package/dist/api/routes/context/permissions.js +12 -2
  30. package/dist/api/routes/context/snapshots.js +0 -3
  31. package/dist/api/routes/context/write.js +3 -17
  32. package/dist/api/routes/dashboard/config.js +58 -12
  33. package/dist/api/routes/dashboard/cost-approvals.js +66 -0
  34. package/dist/api/routes/dashboard/notifications.js +9 -9
  35. package/dist/api/routes/dashboard/oauth-google.js +5 -3
  36. package/dist/api/routes/feedback.d.ts +3 -0
  37. package/dist/api/routes/feedback.js +349 -0
  38. package/dist/api/routes/git.js +10 -3
  39. package/dist/api/routes/github.js +5 -1
  40. package/dist/api/routes/integrations/crud-patch.js +5 -1
  41. package/dist/api/routes/integrations-reconcile.js +2 -2
  42. package/dist/api/routes/mcp.js +65 -13
  43. package/dist/api/routes/notion.d.ts +1 -1
  44. package/dist/api/routes/observations.js +7 -7
  45. package/dist/api/routes/obsidian.d.ts +1 -1
  46. package/dist/api/routes/receipts.js +5 -1
  47. package/dist/api/routes/setup-migrate.js +1 -1
  48. package/dist/api/routes/setup.js +1 -1
  49. package/dist/api/routes/task-flows.d.ts +1 -1
  50. package/dist/api/routes/task-flows.js +1 -1
  51. package/dist/api/routes/tuning.d.ts +29 -0
  52. package/dist/api/routes/tuning.js +304 -0
  53. package/dist/api/server.d.ts +44 -16
  54. package/dist/api/server.js +12 -0
  55. package/dist/bootstrap/adapters.d.ts +19 -0
  56. package/dist/bootstrap/adapters.js +61 -0
  57. package/dist/bootstrap/api.d.ts +5 -3
  58. package/dist/bootstrap/api.js +45 -13
  59. package/dist/bootstrap/catchup.d.ts +1 -1
  60. package/dist/bootstrap/catchup.js +11 -11
  61. package/dist/bootstrap/event-pipeline.d.ts +11 -0
  62. package/dist/bootstrap/event-pipeline.js +246 -8
  63. package/dist/bootstrap/observers.js +9 -6
  64. package/dist/bootstrap/schedule-helpers.d.ts +104 -6
  65. package/dist/bootstrap/schedule-helpers.js +172 -19
  66. package/dist/config.js +32 -12
  67. package/dist/core/agent-core.d.ts +33 -1
  68. package/dist/core/agent-core.js +36 -1
  69. package/dist/core/agents/activity-scan-cadence.d.ts +103 -0
  70. package/dist/core/agents/activity-scan-cadence.js +127 -0
  71. package/dist/core/agents/agent-route-override.d.ts +53 -0
  72. package/dist/core/agents/agent-route-override.js +69 -0
  73. package/dist/core/agents/builtin-registry.d.ts +51 -14
  74. package/dist/core/agents/builtin-registry.js +92 -15
  75. package/dist/core/agents/config-gate-reconcile.d.ts +38 -0
  76. package/dist/core/agents/config-gate-reconcile.js +51 -0
  77. package/dist/core/agents/cron-substitute.d.ts +1 -1
  78. package/dist/core/agents/cron-substitute.js +1 -1
  79. package/dist/core/agents/custom-routine-migration.d.ts +60 -0
  80. package/dist/core/agents/custom-routine-migration.js +149 -0
  81. package/dist/core/agents/firing-blocked.d.ts +1 -1
  82. package/dist/core/agents/hourly-cadence.d.ts +102 -0
  83. package/dist/core/agents/hourly-cadence.js +126 -0
  84. package/dist/core/agents/loader-boot.js +23 -0
  85. package/dist/core/agents/loader.d.ts +19 -0
  86. package/dist/core/agents/loader.js +34 -2
  87. package/dist/core/agents/override-merge.d.ts +1 -1
  88. package/dist/core/agents/override-merge.js +9 -1
  89. package/dist/core/agents/recurrence-convert.d.ts +1 -1
  90. package/dist/core/agents/recurrence-convert.js +1 -1
  91. package/dist/core/agents/recurring-schedule-adapter.js +8 -0
  92. package/dist/core/alerts.js +6 -6
  93. package/dist/core/backends/auth-health-monitor.d.ts +2 -2
  94. package/dist/core/backends/auth-health-monitor.js +1 -1
  95. package/dist/core/backends/backend-router.d.ts +27 -1
  96. package/dist/core/backends/backend-router.js +165 -1
  97. package/dist/core/backends/claude-code-core.d.ts +71 -31
  98. package/dist/core/backends/claude-code-core.js +282 -54
  99. package/dist/core/backends/cli-quota-guards.d.ts +29 -1
  100. package/dist/core/backends/cli-quota-guards.js +40 -5
  101. package/dist/core/backends/codex-core.d.ts +6 -0
  102. package/dist/core/backends/codex-core.js +22 -6
  103. package/dist/core/backends/failure-spend.d.ts +58 -0
  104. package/dist/core/backends/failure-spend.js +137 -0
  105. package/dist/core/backends/gemini-cli-core.d.ts +6 -0
  106. package/dist/core/backends/gemini-cli-core.js +38 -6
  107. package/dist/core/backends/model-registry.d.ts +1 -1
  108. package/dist/core/backends/model-registry.js +4 -4
  109. package/dist/core/backends/opencode-core.d.ts +1 -1
  110. package/dist/core/backends/opencode-core.js +5 -5
  111. package/dist/core/backends/plan-presets.js +47 -18
  112. package/dist/core/bang-commands/commands-cost.js +3 -1
  113. package/dist/core/bang-commands/commands-report.js +4 -3
  114. package/dist/core/bang-commands/commands-research.js +4 -1
  115. package/dist/core/bang-commands/commands-revert-tuning.d.ts +18 -0
  116. package/dist/core/bang-commands/commands-revert-tuning.js +63 -0
  117. package/dist/core/bang-commands/commands-stop-start.js +3 -3
  118. package/dist/core/bang-commands/commands-task-control.d.ts +19 -0
  119. package/dist/core/bang-commands/commands-task-control.js +147 -0
  120. package/dist/core/bang-commands/commands-wiki.js +5 -5
  121. package/dist/core/bang-commands/index.d.ts +2 -0
  122. package/dist/core/bang-commands/index.js +12 -0
  123. package/dist/core/bang-commands/registry.d.ts +12 -0
  124. package/dist/core/browser-history/research-cluster-fanout.d.ts +28 -14
  125. package/dist/core/browser-history/research-cluster-fanout.js +39 -16
  126. package/dist/core/channel-timeline.d.ts +5 -1
  127. package/dist/core/channel-timeline.js +13 -0
  128. package/dist/core/context/index-reconciler.js +5 -2
  129. package/dist/core/context/policy-index-reconciler.d.ts +6 -4
  130. package/dist/core/context/policy-index-runner.js +25 -6
  131. package/dist/core/context-builder-calendar.js +10 -2
  132. package/dist/core/context-builder-conversation.d.ts +8 -1
  133. package/dist/core/context-builder-conversation.js +41 -7
  134. package/dist/core/context-builder-yesterday.js +4 -3
  135. package/dist/core/context-builder.d.ts +7 -2
  136. package/dist/core/context-builder.js +193 -5
  137. package/dist/core/context-file-serializer.d.ts +1 -1
  138. package/dist/core/context-file-serializer.js +1 -1
  139. package/dist/core/context-health.js +2 -2
  140. package/dist/core/context-paths.d.ts +11 -1
  141. package/dist/core/context-paths.js +17 -1
  142. package/dist/core/context-validation/prepare-write.js +1 -1
  143. package/dist/core/context-validation/routine-rulebook.d.ts +1 -1
  144. package/dist/core/context-vault-aliases.d.ts +0 -13
  145. package/dist/core/context-vault-aliases.js +37 -0
  146. package/dist/core/custom-routines.d.ts +99 -0
  147. package/dist/core/custom-routines.js +187 -0
  148. package/dist/core/daemon-api-cli.js +50 -1
  149. package/dist/core/day-boundary.d.ts +46 -0
  150. package/dist/core/day-boundary.js +40 -0
  151. package/dist/core/dispatcher-activity-scan.d.ts +221 -0
  152. package/dist/core/dispatcher-activity-scan.js +775 -0
  153. package/dist/core/dispatcher-error-handling.d.ts +6 -11
  154. package/dist/core/dispatcher-error-handling.js +38 -62
  155. package/dist/core/dispatcher-hourly-check.js +6 -1
  156. package/dist/core/dispatcher-message-handler.d.ts +10 -0
  157. package/dist/core/dispatcher-message-handler.js +24 -0
  158. package/dist/core/dispatcher-morning-routine.d.ts +6 -6
  159. package/dist/core/dispatcher-morning-routine.js +13 -13
  160. package/dist/core/dispatcher-result-processor.d.ts +33 -0
  161. package/dist/core/dispatcher-result-processor.js +167 -11
  162. package/dist/core/dispatcher-scheduled-background-task.d.ts +42 -0
  163. package/dist/core/dispatcher-scheduled-background-task.js +89 -0
  164. package/dist/core/dispatcher-scheduled-tasks.d.ts +104 -1
  165. package/dist/core/dispatcher-scheduled-tasks.js +480 -8
  166. package/dist/core/dispatcher-task-delivery.d.ts +105 -0
  167. package/dist/core/dispatcher-task-delivery.js +555 -0
  168. package/dist/core/dispatcher-types.d.ts +48 -9
  169. package/dist/core/dispatcher-types.js +3 -3
  170. package/dist/core/dispatcher.d.ts +112 -31
  171. package/dist/core/dispatcher.js +297 -60
  172. package/dist/core/dm-freshness-metrics.d.ts +1 -1
  173. package/dist/core/drift-effects.js +2 -2
  174. package/dist/core/feedback/consolidation-prep.d.ts +94 -0
  175. package/dist/core/feedback/consolidation-prep.js +254 -0
  176. package/dist/core/feedback/eviction-scorer.d.ts +81 -0
  177. package/dist/core/feedback/eviction-scorer.js +136 -0
  178. package/dist/core/feedback/lesson-format.d.ts +79 -0
  179. package/dist/core/feedback/lesson-format.js +199 -0
  180. package/dist/core/feedback/lesson-injection.d.ts +98 -0
  181. package/dist/core/feedback/lesson-injection.js +174 -0
  182. package/dist/core/feedback/lesson-merge.d.ts +51 -0
  183. package/dist/core/feedback/lesson-merge.js +88 -0
  184. package/dist/core/feedback/lesson-store-overview.d.ts +46 -0
  185. package/dist/core/feedback/lesson-store-overview.js +42 -0
  186. package/dist/core/feedback/promotion-gate.d.ts +69 -0
  187. package/dist/core/feedback/promotion-gate.js +117 -0
  188. package/dist/core/feedback/regeneralization-prep.d.ts +87 -0
  189. package/dist/core/feedback/regeneralization-prep.js +152 -0
  190. package/dist/core/feedback/scope-parser.d.ts +86 -0
  191. package/dist/core/feedback/scope-parser.js +141 -0
  192. package/dist/core/feedback/self-performance-prep.d.ts +186 -0
  193. package/dist/core/feedback/self-performance-prep.js +541 -0
  194. package/dist/core/feedback/tuning-actuator.d.ts +198 -0
  195. package/dist/core/feedback/tuning-actuator.js +432 -0
  196. package/dist/core/feedback/tuning-recommender.d.ts +247 -0
  197. package/dist/core/feedback/tuning-recommender.js +580 -0
  198. package/dist/core/feedback/tuning-revert-monitor.d.ts +90 -0
  199. package/dist/core/feedback/tuning-revert-monitor.js +213 -0
  200. package/dist/core/health-monitor.d.ts +6 -0
  201. package/dist/core/health-monitor.js +1 -1
  202. package/dist/core/injection-policy.d.ts +83 -1
  203. package/dist/core/injection-policy.js +61 -3
  204. package/dist/core/integration-main-backend.js +4 -0
  205. package/dist/core/management-md.d.ts +2 -2
  206. package/dist/core/management-md.js +51 -13
  207. package/dist/core/morning/orchestrator.d.ts +2 -2
  208. package/dist/core/morning/orchestrator.js +2 -2
  209. package/dist/core/notification-gate.d.ts +64 -0
  210. package/dist/core/notification-gate.js +51 -0
  211. package/dist/core/notification-rate-limit.d.ts +40 -0
  212. package/dist/core/notification-rate-limit.js +50 -0
  213. package/dist/core/policy-files.d.ts +1 -1
  214. package/dist/core/policy-files.js +2 -2
  215. package/dist/core/pre-pass-freshness.d.ts +4 -4
  216. package/dist/core/retention.d.ts +5 -0
  217. package/dist/core/retention.js +20 -4
  218. package/dist/core/review-context.d.ts +1 -1
  219. package/dist/core/review-context.js +10 -5
  220. package/dist/core/roadmap-write-lock.d.ts +2 -1
  221. package/dist/core/roadmap-write-lock.js +15 -10
  222. package/dist/core/routine-acquisition-plan.d.ts +47 -1
  223. package/dist/core/routine-acquisition-plan.js +78 -20
  224. package/dist/core/routine-fetch-window-retry.js +7 -4
  225. package/dist/core/routine-fetch-window-runner.d.ts +39 -3
  226. package/dist/core/routine-fetch-window-runner.js +264 -13
  227. package/dist/core/routine-windows.d.ts +2 -2
  228. package/dist/core/routine-windows.js +8 -5
  229. package/dist/core/scheduler.d.ts +175 -16
  230. package/dist/core/scheduler.js +559 -102
  231. package/dist/core/signal-detector.d.ts +51 -1
  232. package/dist/core/signal-detector.js +321 -24
  233. package/dist/core/skills-compiler-denied-tools.js +2 -2
  234. package/dist/core/skills-compiler-skill-index.d.ts +2 -2
  235. package/dist/core/skills-compiler-skill-index.js +2 -2
  236. package/dist/core/skills-compiler-variants.d.ts +1 -1
  237. package/dist/core/skills-compiler-variants.js +8 -0
  238. package/dist/core/skills-compiler.d.ts +29 -26
  239. package/dist/core/skills-compiler.js +117 -81
  240. package/dist/core/skills-manifest.d.ts +37 -0
  241. package/dist/core/skills-manifest.js +73 -2
  242. package/dist/core/sleep-inhibitor.d.ts +79 -0
  243. package/dist/core/sleep-inhibitor.js +132 -0
  244. package/dist/core/slim-system-prompt-loader.d.ts +77 -0
  245. package/dist/core/slim-system-prompt-loader.js +141 -0
  246. package/dist/core/spawn-gates.d.ts +126 -0
  247. package/dist/core/spawn-gates.js +180 -0
  248. package/dist/core/today-direct-writer.d.ts +60 -14
  249. package/dist/core/today-direct-writer.js +90 -13
  250. package/dist/core/today-write-lock.d.ts +4 -2
  251. package/dist/core/today-write-lock.js +30 -20
  252. package/dist/core/wake-detector.d.ts +55 -0
  253. package/dist/core/wake-detector.js +80 -0
  254. package/dist/core/wiki/compile-lock.d.ts +1 -1
  255. package/dist/core/wiki/compile-lock.js +1 -1
  256. package/dist/core/wiki/wiki-fts.js +13 -6
  257. package/dist/core/workdir.js +15 -6
  258. package/dist/db/activity-scan-signals.d.ts +77 -0
  259. package/dist/db/activity-scan-signals.js +378 -0
  260. package/dist/db/agents-store.d.ts +28 -0
  261. package/dist/db/agents-store.js +62 -0
  262. package/dist/db/background-task-clarifications-store.d.ts +81 -0
  263. package/dist/db/background-task-clarifications-store.js +152 -0
  264. package/dist/db/background-task-store.d.ts +207 -0
  265. package/dist/db/background-task-store.js +380 -0
  266. package/dist/db/browser-history-store.d.ts +39 -6
  267. package/dist/db/browser-history-store.js +51 -7
  268. package/dist/db/browser-task-clarifications-store.d.ts +12 -0
  269. package/dist/db/browser-task-clarifications-store.js +35 -5
  270. package/dist/db/browser-task-store.d.ts +3 -0
  271. package/dist/db/browser-task-store.js +29 -4
  272. package/dist/db/deferred-dm.d.ts +86 -0
  273. package/dist/db/deferred-dm.js +199 -0
  274. package/dist/db/feedback-signals-store.d.ts +77 -0
  275. package/dist/db/feedback-signals-store.js +144 -0
  276. package/dist/db/migrations.js +380 -0
  277. package/dist/db/observations.d.ts +2 -2
  278. package/dist/db/observations.js +3 -3
  279. package/dist/db/schema.js +260 -22
  280. package/dist/db/voice-transcripts-store.d.ts +1 -1
  281. package/dist/index.js +86 -29
  282. package/dist/messaging/browser-task-mcp-notifier.d.ts +12 -70
  283. package/dist/messaging/browser-task-mcp-notifier.js +30 -151
  284. package/dist/messaging/browser-task-screenshot-attachment.d.ts +15 -0
  285. package/dist/messaging/browser-task-screenshot-attachment.js +63 -0
  286. package/dist/observers/delegated-sync-worker.d.ts +6 -6
  287. package/dist/observers/delegated-sync-worker.js +10 -10
  288. package/dist/observers/git-delegated-cron.d.ts +1 -1
  289. package/dist/observers/git-delegated-cron.js +2 -2
  290. package/dist/observers/github-poller-classifier.d.ts +3 -3
  291. package/dist/observers/github-poller-classifier.js +3 -3
  292. package/dist/observers/imminent-event-scheduler.d.ts +1 -1
  293. package/dist/observers/imminent-event-scheduler.js +1 -1
  294. package/dist/observers/mail-poller.d.ts +1 -0
  295. package/dist/observers/mail-poller.js +42 -3
  296. package/dist/observers/observation-summarizer/summarizer-client.d.ts +2 -2
  297. package/dist/observers/observation-summarizer/summarizer-client.js +2 -2
  298. package/dist/observers/observation-summarizer/worker.d.ts +2 -2
  299. package/dist/observers/observation-summarizer/worker.js +4 -4
  300. package/dist/observers/obsidian-watcher.d.ts +1 -1
  301. package/dist/observers/obsidian-watcher.js +1 -1
  302. package/dist/safety/agent-write-tracker.d.ts +4 -4
  303. package/dist/safety/agent-write-tracker.js +4 -4
  304. package/dist/safety/always-disallowed.d.ts +1 -1
  305. package/dist/safety/always-disallowed.js +39 -0
  306. package/dist/safety/audit.d.ts +43 -5
  307. package/dist/safety/audit.js +86 -18
  308. package/dist/safety/risk-classifier.d.ts +6 -0
  309. package/dist/safety/risk-classifier.js +97 -18
  310. package/dist/scheduler/activity-scan-gate.d.ts +86 -0
  311. package/dist/scheduler/activity-scan-gate.js +132 -0
  312. package/dist/services/background-task/background-task-budget.d.ts +80 -0
  313. package/dist/services/background-task/background-task-budget.js +91 -0
  314. package/dist/services/background-task/background-task-driver.d.ts +105 -0
  315. package/dist/services/background-task/background-task-driver.js +416 -0
  316. package/dist/services/background-task/background-task-runner.d.ts +96 -0
  317. package/dist/services/background-task/background-task-runner.js +673 -0
  318. package/dist/services/background-task/background-task-tools.d.ts +84 -0
  319. package/dist/services/background-task/background-task-tools.js +247 -0
  320. package/dist/services/background-task/background-task-transition-events.d.ts +43 -0
  321. package/dist/services/background-task/background-task-transition-events.js +54 -0
  322. package/dist/services/browser-history/automation/egress-denylist.d.ts +1 -1
  323. package/dist/services/browser-history/automation/egress-denylist.js +34 -8
  324. package/dist/services/browser-history/lifecycle/platform.js +44 -2
  325. package/dist/services/browser-history/managed-chromium/sandbox-launcher.js +0 -1
  326. package/dist/services/browser-task/browser-task-runner.js +53 -8
  327. package/dist/services/mcp/probe.js +30 -8
  328. package/dist/services/observations-batch.d.ts +1 -1
  329. package/dist/services/observations-batch.js +2 -2
  330. package/dist/settings/runtime-settings.d.ts +45 -12
  331. package/dist/settings/runtime-settings.js +215 -40
  332. package/dist/settings/settings-store.js +11 -3
  333. package/package.json +4 -4
@@ -4,7 +4,7 @@ import type { AgentConfig } from "../config.js";
4
4
  import { EventBroadcaster } from "./routes/sse.js";
5
5
  import type { AttachmentStore } from "../services/attachments/store.js";
6
6
  import type { EventBus } from "../core/event-bus.js";
7
- import type { InFlightExecutionInfo, TriggerHourlyCheckOptions, TriggerHourlyCheckResult } from "../core/dispatcher.js";
7
+ import type { InFlightExecutionInfo, TriggerActivityScanOptions, TriggerActivityScanResult } from "../core/dispatcher.js";
8
8
  import type { PromptContextChangedCallback } from "../core/context-staleness.js";
9
9
  import type { IAgentCore } from "../core/agent-core.js";
10
10
  import type { AuthHealthMonitor } from "../core/backends/auth-health-monitor.js";
@@ -58,6 +58,31 @@ export interface MessagingHealthStatus {
58
58
  lastInboundAt: string | null;
59
59
  error: string | null;
60
60
  }
61
+ /**
62
+ * Outcome of the API-deps `sendNotification` chokepoint
63
+ * (QUIET_HOURS_HARDENING_PLAN.md Phase 1). Inside quiet hours a
64
+ * non-critical message is deferred to a durable `task_type='dm'`
65
+ * schedule row at the quiet-hours edge (never silently dropped);
66
+ * outside quiet hours the proactive hourly/daily rate limits apply and
67
+ * a limited message is NOT sent — the live session can adapt.
68
+ */
69
+ export type SendNotificationResult = {
70
+ status: "sent";
71
+ dispatchId: string;
72
+ deliveries: {
73
+ platform: string;
74
+ channel: string;
75
+ messageId?: string;
76
+ }[];
77
+ } | {
78
+ status: "deferred_quiet_hours";
79
+ scheduleId: string;
80
+ /** SQLite-format UTC datetime the deferred DM fires at. */
81
+ deliverAfter: string;
82
+ } | {
83
+ status: "rate_limited";
84
+ retryAfter: string | null;
85
+ };
61
86
  export interface ApiDependencies {
62
87
  db: Database.Database;
63
88
  config: AgentConfig;
@@ -88,6 +113,7 @@ export interface ApiDependencies {
88
113
  isStartupComplete?: () => boolean;
89
114
  eventBus?: EventBus;
90
115
  getHealthData: () => {
116
+ /** Seconds since daemon start (see HealthStatus.daemonUptime). */
91
117
  uptime: number;
92
118
  eventBusSize: number;
93
119
  activeSessions: number;
@@ -132,14 +158,13 @@ export interface ApiDependencies {
132
158
  priority?: string;
133
159
  notificationType?: string;
134
160
  originSessionId?: number;
135
- }) => Promise<{
136
- dispatchId: string;
137
- deliveries: {
138
- platform: string;
139
- channel: string;
140
- messageId?: string;
141
- }[];
142
- }>;
161
+ /**
162
+ * Event correlation id of the calling agent session, when known —
163
+ * lets the quiet-hours gate resolve the owning user-Agent slug so
164
+ * deferred DMs coalesce per Agent (QUIET_HOURS_HARDENING_PLAN Phase 1).
165
+ */
166
+ correlationId?: string;
167
+ }) => Promise<SendNotificationResult>;
143
168
  /**
144
169
  * Notify-dedup hook — called by the `/api/notify` route when the request
145
170
  * carries an `X-Pa-Event-Correlation-Id` header (auto-injected by
@@ -176,6 +201,14 @@ export interface ApiDependencies {
176
201
  */
177
202
  browserTaskRunner?: import("../services/browser-task/browser-task-runner.js").BrowserTaskRunner;
178
203
  browserTaskSlotStateRef?: import("../services/browser-task/browser-task-runner.js").SlotStateRef;
204
+ /**
205
+ * BACKGROUND_TASK_RUNNER_DESIGN.md §4 — generic background-task runner
206
+ * + shared slot state, wired together at boot in `index.ts`. Optional
207
+ * in tests; when absent the POST /api/background-task route writes a
208
+ * synthetic terminal transition so the row doesn't hang in pending.
209
+ */
210
+ backgroundTaskRunner?: import("../services/background-task/background-task-runner.js").BackgroundTaskRunner;
211
+ backgroundTaskSlotStateRef?: import("../services/background-task/background-task-runner.js").BackgroundTaskSlotStateRef;
179
212
  /**
180
213
  * BROWSER_TASK_REDESIGN_PLAN.md §5 / §14.11 — lite-final-confirm
181
214
  * token handler. The runner calls into it from the final-confirm
@@ -199,11 +232,6 @@ export interface ApiDependencies {
199
232
  * without waiting for its own chokidar debounce window.
200
233
  */
201
234
  onIndexableContextChange?: (path: string) => void;
202
- /**
203
- * B-007 §5.8 — called after any write/delete under `policies/routines/custom/`
204
- * so the CustomRoutineScheduler re-enumerates and re-registers jobs.
205
- */
206
- onCustomRoutinesChanged?: () => void;
207
235
  /**
208
236
  * Called after a mutation to the effective mail scope — enabled providers,
209
237
  * account add/remove, active toggle, or app-password refresh. Implementations
@@ -212,8 +240,8 @@ export interface ApiDependencies {
212
240
  * tearing down the SDK session.
213
241
  */
214
242
  onMailScopeChanged?: (reason: string) => void;
215
- /** Manual trigger for the polling-based hourly check */
216
- triggerHourlyCheck?: (source: string, options?: TriggerHourlyCheckOptions) => Promise<TriggerHourlyCheckResult>;
243
+ /** Manual trigger for the polling-based activity scan */
244
+ triggerActivityScan?: (source: string, options?: TriggerActivityScanOptions) => Promise<TriggerActivityScanResult>;
217
245
  /**
218
246
  * Evening-review slimdown §2.2 — synchronous manual fire of
219
247
  * `runRoadmapMechanicalMaintenance` (substeps 2a / 2b / 2d). Used
@@ -30,6 +30,8 @@ import { createSystemRoutes } from "./routes/system.js";
30
30
  import { createBackendRoutes } from "./routes/backends.js";
31
31
  import { createSkillsRoutes } from "./routes/skills.js";
32
32
  import { createObservationRoutes } from "./routes/observations.js";
33
+ import { createFeedbackRoutes } from "./routes/feedback.js";
34
+ import { createTuningRoutes } from "./routes/tuning.js";
33
35
  import { createSkillCurationRoutes } from "./routes/skill-curation.js";
34
36
  import { createProfileQuestionsRoutes } from "./routes/profile-questions.js";
35
37
  import { createRecurringScheduleRoutes } from "./routes/recurring-schedules.js";
@@ -54,6 +56,7 @@ import { createBrowserHistoryManagedRoutes } from "./routes/browser-history-mana
54
56
  import { createBrowserAutomationSitesRoutes } from "./routes/browser-automation-sites.js";
55
57
  import { createBrowserAutomationPurchaseRoutes } from "./routes/browser-automation-purchase.js";
56
58
  import { createBrowserTaskRoutes } from "./routes/browser-task.js";
59
+ import { createBackgroundTaskRoutes } from "./routes/background-task.js";
57
60
  import { buildManagedTasksRoutesDepsFromApi, createManagedTasksRoutes, } from "./routes/managed-tasks.js";
58
61
  import { buildSotBindingsRoutesDepsFromApi, createSotBindingsRoutes, } from "./routes/sot-bindings.js";
59
62
  import { buildEntitiesRoutesDepsFromApi, createEntitiesRoutes, } from "./routes/entities.js";
@@ -326,6 +329,8 @@ export function createApp(deps) {
326
329
  const backendRoutes = createBackendRoutes(deps);
327
330
  const skillsRoutes = createSkillsRoutes({ config: deps.config });
328
331
  const observationRoutes = createObservationRoutes(deps);
332
+ const feedbackRoutes = createFeedbackRoutes(deps);
333
+ const tuningRoutes = createTuningRoutes(deps);
329
334
  const skillCurationRoutes = createSkillCurationRoutes(deps);
330
335
  const profileQuestionsRoutes = createProfileQuestionsRoutes(deps);
331
336
  const recurringScheduleRoutes = createRecurringScheduleRoutes(deps);
@@ -368,6 +373,10 @@ export function createApp(deps) {
368
373
  // wired (tests / lite installs). The route handlers degrade
369
374
  // gracefully on absent runner / slot ref.
370
375
  const browserTaskRoutes = createBrowserTaskRoutes(deps);
376
+ // BACKGROUND_TASK_RUNNER_DESIGN.md §7 — generic background-task surface.
377
+ // Mounted unconditionally; the handlers degrade gracefully when the
378
+ // runner / slot ref are absent (tests / lite installs).
379
+ const backgroundTaskRoutes = createBackgroundTaskRoutes(deps);
371
380
  // Management Registry & Entities (docs/design/21-management-registry-
372
381
  // and-entities.md). The managed-tasks and sot-bindings routes MUST
373
382
  // share one lock manager — separate instances would let back-to-back
@@ -395,6 +404,8 @@ export function createApp(deps) {
395
404
  app.route("/api", backendRoutes);
396
405
  app.route("/api", skillsRoutes);
397
406
  app.route("/api", observationRoutes);
407
+ app.route("/api", feedbackRoutes);
408
+ app.route("/api", tuningRoutes);
398
409
  app.route("/api", skillCurationRoutes);
399
410
  app.route("/api", profileQuestionsRoutes);
400
411
  app.route("/api", recurringScheduleRoutes);
@@ -423,6 +434,7 @@ export function createApp(deps) {
423
434
  app.route("/api", browserAutomationSitesRoutes);
424
435
  app.route("/api", browserAutomationPurchaseRoutes);
425
436
  app.route("/api", browserTaskRoutes);
437
+ app.route("/api", backgroundTaskRoutes);
426
438
  // ── Chat file attachments (Phase 1) ──
427
439
  if (deps.attachmentStore) {
428
440
  const attachmentRoutes = createAttachmentRoutes({
@@ -37,6 +37,7 @@ import { SlackAdapter } from "../adapters/slack-adapter.js";
37
37
  import { TelegramAdapter } from "../adapters/telegram-adapter.js";
38
38
  import { WhatsAppAdapter, type WhatsAppQrSnapshot } from "../adapters/whatsapp-adapter.js";
39
39
  import type { WhatsAppQrResponse } from "../api/server.js";
40
+ import { AdapterWatchdog } from "../adapters/adapter-watchdog.js";
40
41
  /**
41
42
  * Mutable holder for the live adapter instances. The bootstrap factory
42
43
  * updates these fields in place; `index.ts` and the dashboard-controls
@@ -98,6 +99,24 @@ export interface AdapterReloaders {
98
99
  enableWhatsAppAdapter(): Promise<void>;
99
100
  }
100
101
  export declare function createAdapterReloaders(deps: BootstrapAdapterDeps): AdapterReloaders;
102
+ /**
103
+ * Build the connection watchdog for the library-managed adapters
104
+ * (Slack socket-mode, Discord gateway, Telegram long-poll).
105
+ *
106
+ * Each entry reads the live instance out of the mutable `AdapterState`
107
+ * slot — a reload that swaps the instance is picked up on the next probe
108
+ * automatically — and restarts through the bootstrap reloader so the
109
+ * stop→register→start lifecycle (and its MessageHub status transitions)
110
+ * stays in one place. WhatsApp is deliberately NOT watched: the Baileys
111
+ * adapter owns a sustained reconnect watch with ban-risk-aware pacing
112
+ * that a blunt stop→start cycle would fight against.
113
+ *
114
+ * On a down/recovery transition the hub status flips to error/ok so
115
+ * `/health` and notification-eligibility reflect the live socket state
116
+ * instead of the boot-time snapshot (pre-watchdog, a dead socket kept
117
+ * reporting "ok" forever).
118
+ */
119
+ export declare function createAdapterWatchdog(deps: Pick<BootstrapAdapterDeps, "messageHub" | "state">, reloaders: Pick<AdapterReloaders, "reloadDiscordAdapter" | "reloadSlackAdapter" | "reloadTelegramAdapter">): AdapterWatchdog;
101
120
  /**
102
121
  * Pure projection of the WhatsApp adapter (+ optional snapshot
103
122
  * override) into the `WhatsAppQrResponse` wire shape. Lives outside
@@ -32,6 +32,7 @@ import { DiscordAdapter } from "../adapters/discord.js";
32
32
  import { SlackAdapter } from "../adapters/slack-adapter.js";
33
33
  import { TelegramAdapter } from "../adapters/telegram-adapter.js";
34
34
  import { WhatsAppAdapter, } from "../adapters/whatsapp-adapter.js";
35
+ import { AdapterWatchdog } from "../adapters/adapter-watchdog.js";
35
36
  import { createLogger, toSafeErrorMessage } from "../logging.js";
36
37
  const logger = createLogger("daemon-bootstrap-adapters");
37
38
  export function createAdapterReloaders(deps) {
@@ -207,6 +208,66 @@ export function createAdapterReloaders(deps) {
207
208
  enableWhatsAppAdapter,
208
209
  };
209
210
  }
211
+ /**
212
+ * Build the connection watchdog for the library-managed adapters
213
+ * (Slack socket-mode, Discord gateway, Telegram long-poll).
214
+ *
215
+ * Each entry reads the live instance out of the mutable `AdapterState`
216
+ * slot — a reload that swaps the instance is picked up on the next probe
217
+ * automatically — and restarts through the bootstrap reloader so the
218
+ * stop→register→start lifecycle (and its MessageHub status transitions)
219
+ * stays in one place. WhatsApp is deliberately NOT watched: the Baileys
220
+ * adapter owns a sustained reconnect watch with ban-risk-aware pacing
221
+ * that a blunt stop→start cycle would fight against.
222
+ *
223
+ * On a down/recovery transition the hub status flips to error/ok so
224
+ * `/health` and notification-eligibility reflect the live socket state
225
+ * instead of the boot-time snapshot (pre-watchdog, a dead socket kept
226
+ * reporting "ok" forever).
227
+ */
228
+ export function createAdapterWatchdog(deps, reloaders) {
229
+ const { messageHub, state } = deps;
230
+ const watchdog = new AdapterWatchdog();
231
+ const entries = [
232
+ {
233
+ platform: "discord",
234
+ getConnectionState: () => state.discord?.getConnectionState() ?? "unknown",
235
+ restart: () => reloaders.reloadDiscordAdapter(true),
236
+ },
237
+ {
238
+ platform: "slack",
239
+ getConnectionState: () => state.slack?.getConnectionState() ?? "unknown",
240
+ restart: () => reloaders.reloadSlackAdapter(true),
241
+ },
242
+ {
243
+ platform: "telegram",
244
+ getConnectionState: () => state.telegram?.getConnectionState() ?? "unknown",
245
+ restart: () => reloaders.reloadTelegramAdapter(true),
246
+ },
247
+ ];
248
+ for (const entry of entries) {
249
+ watchdog.register({
250
+ platform: entry.platform,
251
+ getConnectionState: entry.getConnectionState,
252
+ restart: entry.restart,
253
+ onStateChange: (connectionState) => {
254
+ if (connectionState === "down") {
255
+ messageHub.setPlatformRuntimeStatus(entry.platform, {
256
+ runtimeState: "error",
257
+ error: "Connection lost — watchdog will restart the adapter if it does not self-recover",
258
+ });
259
+ }
260
+ else if (connectionState === "ok") {
261
+ messageHub.setPlatformRuntimeStatus(entry.platform, {
262
+ runtimeState: "ok",
263
+ error: null,
264
+ });
265
+ }
266
+ },
267
+ });
268
+ }
269
+ return watchdog;
270
+ }
210
271
  /**
211
272
  * Pure projection of the WhatsApp adapter (+ optional snapshot
212
273
  * override) into the `WhatsAppQrResponse` wire shape. Lives outside
@@ -10,7 +10,7 @@
10
10
  * 1. Assemble the `ApiDependencies` record from typed inputs — translate
11
11
  * subsystem instances (dispatcher, scheduler, messageHub, …) into the
12
12
  * small closures the API surface consumes (`getHealthData`,
13
- * `sendNotification`, `triggerHourlyCheck`, etc.).
13
+ * `sendNotification`, `triggerActivityScan`, etc.).
14
14
  * 2. Construct WhatsApp / messaging-platform controls (Pattern-C; takes
15
15
  * the adapter state holder + reload closures as deps).
16
16
  * 3. Invoke `createApp(apiDeps)` to mount every route module and the
@@ -52,7 +52,6 @@ import type { AuthRecovery } from "../core/backends/auth-recovery.js";
52
52
  import type { AuthTelemetry } from "../core/backends/auth-telemetry.js";
53
53
  import type { EventBus } from "../core/event-bus.js";
54
54
  import type { AgentScheduler } from "../core/scheduler.js";
55
- import type { CustomRoutineScheduler } from "../core/custom-routine-scheduler.js";
56
55
  import type { HealthMonitor } from "../core/health-monitor.js";
57
56
  import type { Heartbeat } from "../core/heartbeat.js";
58
57
  import type { MessageHub } from "../adapters/message-hub.js";
@@ -128,7 +127,6 @@ export interface BootstrapApiDeps {
128
127
  * it on an `enabled` change. Optional so partial test harnesses can omit it.
129
128
  */
130
129
  readonly agentEnabledCache?: import("../core/agents/loader.js").AgentEnabledCache;
131
- readonly customRoutineScheduler: CustomRoutineScheduler;
132
130
  readonly healthMonitor: HealthMonitor;
133
131
  readonly heartbeat: Heartbeat;
134
132
  readonly messageHub: MessageHub;
@@ -145,6 +143,10 @@ export interface BootstrapApiDeps {
145
143
  * wired so the runner returns `failed (not_implemented)`; Phase 2
146
144
  * passes the Playwright + Claude SDK driver into the same factory. */
147
145
  readonly browserTaskRunner: import("../services/browser-task/browser-task-runner.js").BrowserTaskRunner;
146
+ /** BACKGROUND_TASK_RUNNER_DESIGN.md §4 — generic background-task runner
147
+ * + shared slot state, constructed in `event-pipeline.ts`. */
148
+ readonly backgroundTaskSlotStateRef: import("../services/background-task/background-task-runner.js").BackgroundTaskSlotStateRef;
149
+ readonly backgroundTaskRunner: import("../services/background-task/background-task-runner.js").BackgroundTaskRunner;
148
150
  readonly writeTracker: AgentWriteTracker;
149
151
  readonly auditLogger: AuditLogger;
150
152
  readonly attachmentStore: AttachmentStore;
@@ -10,7 +10,7 @@
10
10
  * 1. Assemble the `ApiDependencies` record from typed inputs — translate
11
11
  * subsystem instances (dispatcher, scheduler, messageHub, …) into the
12
12
  * small closures the API surface consumes (`getHealthData`,
13
- * `sendNotification`, `triggerHourlyCheck`, etc.).
13
+ * `sendNotification`, `triggerActivityScan`, etc.).
14
14
  * 2. Construct WhatsApp / messaging-platform controls (Pattern-C; takes
15
15
  * the adapter state holder + reload closures as deps).
16
16
  * 3. Invoke `createApp(apiDeps)` to mount every route module and the
@@ -49,6 +49,7 @@ import { applyIntegrationModeChange, } from "../core/integration-lifecycle.js";
49
49
  import { continueDashboardSession as continueDashboardSessionFromHistory, endDashboardSession as endDashboardSessionFromChannel, } from "../core/dashboard-session-controls.js";
50
50
  import { sendSetupWelcomeDm } from "../messaging/setup-welcome-dm.js";
51
51
  import { recordProactiveForwardDeliveries } from "../core/channel-timeline.js";
52
+ import { gateOutboundNotification } from "../core/notification-gate.js";
52
53
  import { createApp, } from "../api/server.js";
53
54
  import { createDocsRoutes } from "../api/routes/docs.js";
54
55
  import { whatsappQrResponseFromAdapter, } from "./adapters.js";
@@ -125,14 +126,51 @@ export function startApiServer(deps) {
125
126
  * call site reads as one factory call.
126
127
  */
127
128
  function composeApiDependencies(deps) {
128
- const { db, config, secretBroker, services, blobStore, agentBackends, authHealthMonitor, authRecovery, authTelemetry, eventBus, readTokenManager, morningRoutineLock, roadmapWriteLock, migrationLock, contextWriteGate, managementMdWriteLockManager, dispatcher, scheduler, agentEnabledCache, customRoutineScheduler, healthMonitor, heartbeat, messageHub, observerManager, contextIndexReconciler, primaryVaultWatcher, delegatedBackendInvoker, gitAccountRegistry, writeTracker, auditLogger, attachmentStore, dashboardAdapter, eventBroadcaster, getIntegrationStatus, getMessagingStatus, isStartupComplete, getDelegatedSyncWorker, handleSecretChange, handlePromptContextChanged, onGoogleServicesReady, rematerializeActiveDmWorkdirs, fireRoadmapMaintenance, buildCalendarPoller, buildNotionPoller, buildGitWatcher, buildGithubPoller, buildDelegatedSyncWorker, buildGitDelegatedCronObserver, clearGitWatcher, queueGitProjectInitsForCurrentConfig, } = deps;
129
+ const { db, config, secretBroker, services, blobStore, agentBackends, authHealthMonitor, authRecovery, authTelemetry, eventBus, readTokenManager, morningRoutineLock, roadmapWriteLock, migrationLock, contextWriteGate, managementMdWriteLockManager, dispatcher, scheduler, agentEnabledCache, healthMonitor, heartbeat, messageHub, observerManager, contextIndexReconciler, primaryVaultWatcher, delegatedBackendInvoker, gitAccountRegistry, writeTracker, auditLogger, attachmentStore, dashboardAdapter, eventBroadcaster, getIntegrationStatus, getMessagingStatus, isStartupComplete, getDelegatedSyncWorker, handleSecretChange, handlePromptContextChanged, onGoogleServicesReady, rematerializeActiveDmWorkdirs, fireRoadmapMaintenance, buildCalendarPoller, buildNotionPoller, buildGitWatcher, buildGithubPoller, buildDelegatedSyncWorker, buildGitDelegatedCronObserver, clearGitWatcher, queueGitProjectInitsForCurrentConfig, } = deps;
129
130
  const whatsappControls = buildWhatsAppControls(deps);
130
131
  const messagingControls = {
131
132
  telegram: deps.buildTelegramControls(),
132
133
  slack: deps.buildSlackControls(),
133
134
  discord: deps.buildDiscordControls(),
134
135
  };
135
- const sendNotification = async ({ message, platforms, priority, notificationType, originSessionId }) => {
136
+ const sendNotification = async ({ message, platforms, priority, notificationType, originSessionId, correlationId }) => {
137
+ // QUIET_HOURS_HARDENING_PLAN.md Phase 1 — this chokepoint used to
138
+ // wire straight into `messageHub.sendToUser`, letting any
139
+ // autonomous session DM the owner at 03:00 (finding F1). Gate
140
+ // order: safety/critical bypass → quiet-hours deferral (durable
141
+ // `task_type='dm'` row at the quiet-hours edge, coalesced per
142
+ // origin) → proactive rate limits on the immediate path.
143
+ const gateVerdict = gateOutboundNotification(db, config, {
144
+ message,
145
+ platforms,
146
+ priority,
147
+ notificationType,
148
+ originSessionId,
149
+ agentId: correlationId !== undefined
150
+ ? dispatcher.agentIdForCorrelation(correlationId)
151
+ : null,
152
+ deferredFrom: "api.notify",
153
+ });
154
+ if (gateVerdict.action === "defer") {
155
+ logger.info({
156
+ scheduleId: gateVerdict.scheduleId,
157
+ deliverAfter: gateVerdict.deliverAfter,
158
+ coalesced: gateVerdict.coalesced,
159
+ notificationType: notificationType ?? "agent",
160
+ }, "Outbound notification deferred to quiet-hours end");
161
+ return {
162
+ status: "deferred_quiet_hours",
163
+ scheduleId: gateVerdict.scheduleId,
164
+ deliverAfter: gateVerdict.deliverAfter,
165
+ };
166
+ }
167
+ if (gateVerdict.action === "rate_limit") {
168
+ logger.warn({
169
+ retryAfter: gateVerdict.retryAfter,
170
+ notificationType: notificationType ?? "agent",
171
+ }, "Outbound notification rate-limited — not sent");
172
+ return { status: "rate_limited", retryAfter: gateVerdict.retryAfter };
173
+ }
136
174
  const dispatchId = randomBytes(16).toString("hex");
137
175
  const deliveries = await messageHub.sendToUser(message, platforms, {
138
176
  dispatchId,
@@ -167,7 +205,7 @@ function composeApiDependencies(deps) {
167
205
  notificationType: "proactive_forward",
168
206
  });
169
207
  }
170
- return { dispatchId, deliveries };
208
+ return { status: "sent", dispatchId, deliveries };
171
209
  };
172
210
  const onIntegrationModeChange = async (key, prev, next) => {
173
211
  const buildObserver = (observerName) => {
@@ -369,6 +407,8 @@ function composeApiDependencies(deps) {
369
407
  // race on the same value.
370
408
  browserTaskRunner: deps.browserTaskRunner,
371
409
  browserTaskSlotStateRef: deps.browserTaskSlotStateRef,
410
+ backgroundTaskRunner: deps.backgroundTaskRunner,
411
+ backgroundTaskSlotStateRef: deps.backgroundTaskSlotStateRef,
372
412
  onIntegrationModeChange,
373
413
  onMainBackendChange,
374
414
  onSetupStart: (mode) => {
@@ -391,15 +431,7 @@ function composeApiDependencies(deps) {
391
431
  // non-indexed paths is harmless.
392
432
  contextIndexReconciler.requestReconcile("manual");
393
433
  },
394
- onCustomRoutinesChanged: () => {
395
- try {
396
- customRoutineScheduler.reload();
397
- }
398
- catch (err) {
399
- logger.error({ err }, "Custom routine reload failed");
400
- }
401
- },
402
- triggerHourlyCheck: (source, options) => dispatcher.triggerHourlyCheck(source, options),
434
+ triggerActivityScan: (source, options) => dispatcher.triggerActivityScan(source, options),
403
435
  triggerRoadmapRefresh: (source, options) => dispatcher.emitRoadmapRefresh(source, options),
404
436
  triggerRoadmapMaintenance: () => fireRoadmapMaintenance(),
405
437
  endDashboardSession: (channelId) => endDashboardSessionFromChannel({
@@ -15,7 +15,7 @@ import type { EventDispatcher } from "../core/dispatcher.js";
15
15
  export interface StartupCatchupResult {
16
16
  postMessagingRoadmapRefresh: boolean;
17
17
  postMessagingRoutines: string[];
18
- postMessagingHourlyCheck: boolean;
18
+ postMessagingActivityScan: boolean;
19
19
  }
20
20
  export declare function runCatchup(db: Database.Database, dispatcher: EventDispatcher, config: AgentConfig): Promise<StartupCatchupResult>;
21
21
  export declare function runPostMessagingCatchup(dispatcher: EventDispatcher, catchup: StartupCatchupResult): Promise<void>;
@@ -14,7 +14,7 @@ import { createEvent, EventPriority, getAgentDayBoundsUtc, } from "@aitne/shared
14
14
  import { getContextDir, isRoadmapStale } from "../config.js";
15
15
  import { discardStalePendingSchedules, recoverOrphanedRunningSchedules, } from "../core/schedule-maintenance.js";
16
16
  import { createLogger } from "../logging.js";
17
- import { getDueCatchupRoutines, hasFreshAgentDayTodayMd, shouldCatchUpHourlyCheck, } from "./schedule-helpers.js";
17
+ import { getDueCatchupRoutines, hasFreshAgentDayTodayMd, shouldCatchUpActivityScan, } from "./schedule-helpers.js";
18
18
  const logger = createLogger("daemon-bootstrap-catchup");
19
19
  export async function runCatchup(db, dispatcher, config) {
20
20
  // Setup gate — on first boot (before rules/management.md exists) we must
@@ -29,7 +29,7 @@ export async function runCatchup(db, dispatcher, config) {
29
29
  return {
30
30
  postMessagingRoadmapRefresh: false,
31
31
  postMessagingRoutines: [],
32
- postMessagingHourlyCheck: false,
32
+ postMessagingActivityScan: false,
33
33
  };
34
34
  }
35
35
  const now = new Date();
@@ -49,7 +49,7 @@ export async function runCatchup(db, dispatcher, config) {
49
49
  // clock across the catchup's pre / post freshness probes.
50
50
  const needsMorning = !hasFreshAgentDayTodayMd(todayMdPath, tz, config.dayBoundaryHour, now);
51
51
  const dueCatchupRoutines = getDueCatchupRoutines(db, config, agentDayStartUtc, agentDayEndUtc, now);
52
- const needsHourlyCheckCatchup = shouldCatchUpHourlyCheck(db, config, now);
52
+ const needsActivityScanCatchup = shouldCatchUpActivityScan(db, config, now);
53
53
  let ranMorningCatchup = false;
54
54
  if (needsMorning) {
55
55
  try {
@@ -66,7 +66,7 @@ export async function runCatchup(db, dispatcher, config) {
66
66
  priority: EventPriority.HIGH,
67
67
  data: {
68
68
  postCatchupRoutines: dueCatchupRoutines,
69
- postCatchupHourlyCheck: needsHourlyCheckCatchup,
69
+ postCatchupActivityScan: needsActivityScanCatchup,
70
70
  deferPostMorningCatchupsUntilStartupReady: true,
71
71
  },
72
72
  }),
@@ -78,13 +78,13 @@ export async function runCatchup(db, dispatcher, config) {
78
78
  return {
79
79
  postMessagingRoadmapRefresh: false,
80
80
  postMessagingRoutines: [],
81
- postMessagingHourlyCheck: false,
81
+ postMessagingActivityScan: false,
82
82
  };
83
83
  }
84
84
  return {
85
85
  postMessagingRoadmapRefresh: isRoadmapStale(contextDir),
86
86
  postMessagingRoutines: dueCatchupRoutines,
87
- postMessagingHourlyCheck: needsHourlyCheckCatchup,
87
+ postMessagingActivityScan: needsActivityScanCatchup,
88
88
  };
89
89
  }
90
90
  if (!ranMorningCatchup && isRoadmapStale(contextDir)) {
@@ -94,7 +94,7 @@ export async function runCatchup(db, dispatcher, config) {
94
94
  return {
95
95
  postMessagingRoadmapRefresh: false,
96
96
  postMessagingRoutines: dueCatchupRoutines,
97
- postMessagingHourlyCheck: needsHourlyCheckCatchup,
97
+ postMessagingActivityScan: needsActivityScanCatchup,
98
98
  };
99
99
  }
100
100
  export async function runPostMessagingCatchup(dispatcher, catchup) {
@@ -106,9 +106,9 @@ export async function runPostMessagingCatchup(dispatcher, catchup) {
106
106
  logger.info({ routine }, "Running same-day routine catchup after messaging startup");
107
107
  await processRoutineCatchup(dispatcher, routine);
108
108
  }
109
- if (catchup.postMessagingHourlyCheck) {
110
- logger.info("Triggering hourly_check catchup after messaging startup");
111
- await dispatcher.triggerHourlyCheck("catchup_startup", { force: false });
109
+ if (catchup.postMessagingActivityScan) {
110
+ logger.info("Triggering activity_scan catchup after messaging startup");
111
+ await dispatcher.triggerActivityScan("catchup_startup", { force: false });
112
112
  }
113
113
  }
114
114
  export async function processRoutineCatchup(dispatcher, routine) {
@@ -116,7 +116,7 @@ export async function processRoutineCatchup(dispatcher, routine) {
116
116
  ...createEvent({
117
117
  type: `routine.${routine}`,
118
118
  source: "catchup",
119
- priority: routine === "hourly_check" ? EventPriority.NORMAL : EventPriority.HIGH,
119
+ priority: routine === "activity_scan" ? EventPriority.NORMAL : EventPriority.HIGH,
120
120
  }),
121
121
  routine,
122
122
  });
@@ -226,6 +226,17 @@ export interface BootstrapEventPipelineResult {
226
226
  * driver into the same factory call.
227
227
  */
228
228
  readonly browserTaskRunner: import("../services/browser-task/browser-task-runner.js").BrowserTaskRunner;
229
+ /**
230
+ * BACKGROUND_TASK_RUNNER_DESIGN.md §4 — generic background-task runner +
231
+ * shared slot state. The runner + route layer hold THIS instance so a
232
+ * cancel-while-pending and a runner-side promote race on one value.
233
+ */
234
+ readonly backgroundTaskSlotStateRef: import("../services/background-task/background-task-runner.js").BackgroundTaskSlotStateRef;
235
+ readonly backgroundTaskRunner: import("../services/background-task/background-task-runner.js").BackgroundTaskRunner;
236
+ /** 30 s housekeeping tick — clarification-deadline + pending-queue
237
+ * timeout + delivery recovery sweep for background tasks. Cleared on
238
+ * graceful shutdown. */
239
+ readonly backgroundTaskHousekeepingTimer: NodeJS.Timeout;
229
240
  }
230
241
  /**
231
242
  * Construct the event-processing pipeline (§10). See the file-level