@aitne/daemon 0.1.10 → 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 (305) 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.js +8 -5
  15. package/dist/api/helpers/agent-errors-registry.d.ts +5 -5
  16. package/dist/api/helpers/agent-errors-registry.js +5 -5
  17. package/dist/api/routes/agent.js +33 -12
  18. package/dist/api/routes/agents/index.js +75 -16
  19. package/dist/api/routes/agents/views.d.ts +37 -2
  20. package/dist/api/routes/agents/views.js +64 -2
  21. package/dist/api/routes/background-task.d.ts +22 -0
  22. package/dist/api/routes/background-task.js +338 -0
  23. package/dist/api/routes/browser-history.js +9 -1
  24. package/dist/api/routes/context/permissions.js +3 -2
  25. package/dist/api/routes/context/snapshots.js +0 -3
  26. package/dist/api/routes/context/write.js +3 -17
  27. package/dist/api/routes/dashboard/config.js +48 -12
  28. package/dist/api/routes/dashboard/cost-approvals.js +66 -0
  29. package/dist/api/routes/dashboard/notifications.js +9 -9
  30. package/dist/api/routes/integrations/crud-patch.js +5 -1
  31. package/dist/api/routes/integrations-reconcile.js +2 -2
  32. package/dist/api/routes/notion.d.ts +1 -1
  33. package/dist/api/routes/observations.js +7 -7
  34. package/dist/api/routes/obsidian.d.ts +1 -1
  35. package/dist/api/routes/receipts.js +5 -1
  36. package/dist/api/routes/setup-migrate.js +1 -1
  37. package/dist/api/routes/setup.js +1 -1
  38. package/dist/api/routes/task-flows.d.ts +1 -1
  39. package/dist/api/routes/task-flows.js +1 -1
  40. package/dist/api/routes/tuning.d.ts +29 -0
  41. package/dist/api/routes/tuning.js +304 -0
  42. package/dist/api/server.d.ts +44 -16
  43. package/dist/api/server.js +9 -0
  44. package/dist/bootstrap/adapters.d.ts +19 -0
  45. package/dist/bootstrap/adapters.js +61 -0
  46. package/dist/bootstrap/api.d.ts +5 -3
  47. package/dist/bootstrap/api.js +45 -13
  48. package/dist/bootstrap/catchup.d.ts +1 -1
  49. package/dist/bootstrap/catchup.js +11 -11
  50. package/dist/bootstrap/event-pipeline.d.ts +11 -0
  51. package/dist/bootstrap/event-pipeline.js +245 -7
  52. package/dist/bootstrap/observers.js +9 -6
  53. package/dist/bootstrap/schedule-helpers.d.ts +104 -6
  54. package/dist/bootstrap/schedule-helpers.js +172 -19
  55. package/dist/config.js +26 -12
  56. package/dist/core/agent-core.d.ts +33 -1
  57. package/dist/core/agent-core.js +36 -1
  58. package/dist/core/agents/activity-scan-cadence.d.ts +103 -0
  59. package/dist/core/agents/activity-scan-cadence.js +127 -0
  60. package/dist/core/agents/agent-route-override.d.ts +53 -0
  61. package/dist/core/agents/agent-route-override.js +69 -0
  62. package/dist/core/agents/builtin-registry.d.ts +51 -14
  63. package/dist/core/agents/builtin-registry.js +92 -15
  64. package/dist/core/agents/config-gate-reconcile.d.ts +38 -0
  65. package/dist/core/agents/config-gate-reconcile.js +51 -0
  66. package/dist/core/agents/cron-substitute.d.ts +1 -1
  67. package/dist/core/agents/cron-substitute.js +1 -1
  68. package/dist/core/agents/custom-routine-migration.d.ts +60 -0
  69. package/dist/core/agents/custom-routine-migration.js +149 -0
  70. package/dist/core/agents/firing-blocked.d.ts +1 -1
  71. package/dist/core/agents/hourly-cadence.d.ts +102 -0
  72. package/dist/core/agents/hourly-cadence.js +126 -0
  73. package/dist/core/agents/loader-boot.js +23 -0
  74. package/dist/core/agents/loader.d.ts +19 -0
  75. package/dist/core/agents/loader.js +34 -2
  76. package/dist/core/agents/override-merge.d.ts +1 -1
  77. package/dist/core/agents/override-merge.js +9 -1
  78. package/dist/core/agents/recurrence-convert.d.ts +1 -1
  79. package/dist/core/agents/recurrence-convert.js +1 -1
  80. package/dist/core/agents/recurring-schedule-adapter.js +8 -0
  81. package/dist/core/alerts.js +6 -6
  82. package/dist/core/backends/auth-health-monitor.d.ts +2 -2
  83. package/dist/core/backends/auth-health-monitor.js +1 -1
  84. package/dist/core/backends/backend-router.d.ts +27 -1
  85. package/dist/core/backends/backend-router.js +165 -1
  86. package/dist/core/backends/claude-code-core.d.ts +71 -31
  87. package/dist/core/backends/claude-code-core.js +282 -54
  88. package/dist/core/backends/cli-quota-guards.d.ts +29 -1
  89. package/dist/core/backends/cli-quota-guards.js +40 -5
  90. package/dist/core/backends/codex-core.d.ts +6 -0
  91. package/dist/core/backends/codex-core.js +22 -6
  92. package/dist/core/backends/failure-spend.d.ts +58 -0
  93. package/dist/core/backends/failure-spend.js +137 -0
  94. package/dist/core/backends/gemini-cli-core.d.ts +6 -0
  95. package/dist/core/backends/gemini-cli-core.js +25 -6
  96. package/dist/core/backends/model-registry.d.ts +1 -1
  97. package/dist/core/backends/model-registry.js +4 -4
  98. package/dist/core/backends/opencode-core.d.ts +1 -1
  99. package/dist/core/backends/opencode-core.js +5 -5
  100. package/dist/core/backends/plan-presets.js +39 -15
  101. package/dist/core/bang-commands/commands-cost.js +3 -1
  102. package/dist/core/bang-commands/commands-report.js +4 -3
  103. package/dist/core/bang-commands/commands-research.js +4 -1
  104. package/dist/core/bang-commands/commands-revert-tuning.d.ts +18 -0
  105. package/dist/core/bang-commands/commands-revert-tuning.js +63 -0
  106. package/dist/core/bang-commands/commands-stop-start.js +3 -3
  107. package/dist/core/bang-commands/commands-task-control.d.ts +19 -0
  108. package/dist/core/bang-commands/commands-task-control.js +147 -0
  109. package/dist/core/bang-commands/commands-wiki.js +5 -5
  110. package/dist/core/bang-commands/index.d.ts +2 -0
  111. package/dist/core/bang-commands/index.js +12 -0
  112. package/dist/core/bang-commands/registry.d.ts +12 -0
  113. package/dist/core/browser-history/research-cluster-fanout.d.ts +28 -14
  114. package/dist/core/browser-history/research-cluster-fanout.js +39 -16
  115. package/dist/core/channel-timeline.d.ts +5 -1
  116. package/dist/core/channel-timeline.js +13 -0
  117. package/dist/core/context/index-reconciler.js +5 -2
  118. package/dist/core/context/policy-index-reconciler.d.ts +6 -4
  119. package/dist/core/context/policy-index-runner.js +25 -6
  120. package/dist/core/context-builder-calendar.js +10 -2
  121. package/dist/core/context-builder-conversation.d.ts +8 -1
  122. package/dist/core/context-builder-conversation.js +41 -7
  123. package/dist/core/context-builder-yesterday.js +4 -3
  124. package/dist/core/context-builder.d.ts +7 -2
  125. package/dist/core/context-builder.js +62 -20
  126. package/dist/core/context-file-serializer.d.ts +1 -1
  127. package/dist/core/context-file-serializer.js +1 -1
  128. package/dist/core/context-health.js +2 -2
  129. package/dist/core/context-paths.d.ts +1 -1
  130. package/dist/core/context-paths.js +1 -1
  131. package/dist/core/context-validation/prepare-write.js +1 -1
  132. package/dist/core/context-validation/routine-rulebook.d.ts +1 -1
  133. package/dist/core/context-vault-aliases.d.ts +0 -13
  134. package/dist/core/context-vault-aliases.js +37 -0
  135. package/dist/core/custom-routines.d.ts +99 -0
  136. package/dist/core/custom-routines.js +187 -0
  137. package/dist/core/daemon-api-cli.js +49 -0
  138. package/dist/core/day-boundary.d.ts +46 -0
  139. package/dist/core/day-boundary.js +40 -0
  140. package/dist/core/dispatcher-activity-scan.d.ts +221 -0
  141. package/dist/core/dispatcher-activity-scan.js +775 -0
  142. package/dist/core/dispatcher-error-handling.d.ts +6 -11
  143. package/dist/core/dispatcher-error-handling.js +38 -62
  144. package/dist/core/dispatcher-hourly-check.js +6 -1
  145. package/dist/core/dispatcher-message-handler.d.ts +10 -0
  146. package/dist/core/dispatcher-message-handler.js +17 -0
  147. package/dist/core/dispatcher-morning-routine.d.ts +6 -6
  148. package/dist/core/dispatcher-morning-routine.js +13 -13
  149. package/dist/core/dispatcher-result-processor.d.ts +33 -0
  150. package/dist/core/dispatcher-result-processor.js +167 -11
  151. package/dist/core/dispatcher-scheduled-background-task.d.ts +42 -0
  152. package/dist/core/dispatcher-scheduled-background-task.js +89 -0
  153. package/dist/core/dispatcher-scheduled-tasks.d.ts +63 -1
  154. package/dist/core/dispatcher-scheduled-tasks.js +213 -6
  155. package/dist/core/dispatcher-task-delivery.d.ts +105 -0
  156. package/dist/core/dispatcher-task-delivery.js +555 -0
  157. package/dist/core/dispatcher-types.d.ts +48 -9
  158. package/dist/core/dispatcher-types.js +3 -3
  159. package/dist/core/dispatcher.d.ts +112 -31
  160. package/dist/core/dispatcher.js +284 -59
  161. package/dist/core/dm-freshness-metrics.d.ts +1 -1
  162. package/dist/core/drift-effects.js +2 -2
  163. package/dist/core/feedback/consolidation-prep.js +17 -5
  164. package/dist/core/feedback/eviction-scorer.js +6 -2
  165. package/dist/core/feedback/lesson-format.js +9 -4
  166. package/dist/core/feedback/lesson-injection.d.ts +1 -1
  167. package/dist/core/feedback/lesson-injection.js +17 -2
  168. package/dist/core/feedback/lesson-store-overview.d.ts +8 -4
  169. package/dist/core/feedback/lesson-store-overview.js +8 -4
  170. package/dist/core/feedback/regeneralization-prep.js +29 -16
  171. package/dist/core/feedback/self-performance-prep.d.ts +186 -0
  172. package/dist/core/feedback/self-performance-prep.js +541 -0
  173. package/dist/core/feedback/tuning-actuator.d.ts +198 -0
  174. package/dist/core/feedback/tuning-actuator.js +432 -0
  175. package/dist/core/feedback/tuning-recommender.d.ts +247 -0
  176. package/dist/core/feedback/tuning-recommender.js +580 -0
  177. package/dist/core/feedback/tuning-revert-monitor.d.ts +90 -0
  178. package/dist/core/feedback/tuning-revert-monitor.js +213 -0
  179. package/dist/core/health-monitor.d.ts +6 -0
  180. package/dist/core/health-monitor.js +1 -1
  181. package/dist/core/injection-policy.d.ts +4 -4
  182. package/dist/core/injection-policy.js +4 -4
  183. package/dist/core/integration-main-backend.js +4 -0
  184. package/dist/core/management-md.d.ts +2 -2
  185. package/dist/core/management-md.js +51 -13
  186. package/dist/core/morning/orchestrator.d.ts +2 -2
  187. package/dist/core/morning/orchestrator.js +2 -2
  188. package/dist/core/notification-gate.d.ts +64 -0
  189. package/dist/core/notification-gate.js +51 -0
  190. package/dist/core/notification-rate-limit.d.ts +40 -0
  191. package/dist/core/notification-rate-limit.js +50 -0
  192. package/dist/core/policy-files.d.ts +1 -1
  193. package/dist/core/policy-files.js +2 -2
  194. package/dist/core/pre-pass-freshness.d.ts +4 -4
  195. package/dist/core/retention.d.ts +5 -0
  196. package/dist/core/retention.js +20 -4
  197. package/dist/core/review-context.d.ts +1 -1
  198. package/dist/core/review-context.js +10 -5
  199. package/dist/core/roadmap-write-lock.d.ts +2 -1
  200. package/dist/core/roadmap-write-lock.js +15 -10
  201. package/dist/core/routine-acquisition-plan.d.ts +47 -1
  202. package/dist/core/routine-acquisition-plan.js +78 -20
  203. package/dist/core/routine-fetch-window-retry.js +7 -4
  204. package/dist/core/routine-fetch-window-runner.d.ts +39 -3
  205. package/dist/core/routine-fetch-window-runner.js +264 -13
  206. package/dist/core/routine-windows.d.ts +2 -2
  207. package/dist/core/routine-windows.js +8 -5
  208. package/dist/core/scheduler.d.ts +175 -16
  209. package/dist/core/scheduler.js +559 -102
  210. package/dist/core/signal-detector.d.ts +12 -0
  211. package/dist/core/signal-detector.js +53 -9
  212. package/dist/core/skills-compiler-denied-tools.js +2 -2
  213. package/dist/core/skills-compiler-skill-index.d.ts +2 -2
  214. package/dist/core/skills-compiler-skill-index.js +2 -2
  215. package/dist/core/skills-compiler-variants.d.ts +1 -1
  216. package/dist/core/skills-compiler-variants.js +8 -0
  217. package/dist/core/skills-compiler.d.ts +29 -26
  218. package/dist/core/skills-compiler.js +117 -81
  219. package/dist/core/skills-manifest.d.ts +37 -0
  220. package/dist/core/skills-manifest.js +73 -2
  221. package/dist/core/sleep-inhibitor.d.ts +79 -0
  222. package/dist/core/sleep-inhibitor.js +132 -0
  223. package/dist/core/slim-system-prompt-loader.d.ts +77 -0
  224. package/dist/core/slim-system-prompt-loader.js +141 -0
  225. package/dist/core/spawn-gates.d.ts +126 -0
  226. package/dist/core/spawn-gates.js +180 -0
  227. package/dist/core/today-direct-writer.d.ts +2 -2
  228. package/dist/core/today-direct-writer.js +1 -1
  229. package/dist/core/today-write-lock.d.ts +4 -2
  230. package/dist/core/today-write-lock.js +30 -20
  231. package/dist/core/wake-detector.d.ts +55 -0
  232. package/dist/core/wake-detector.js +80 -0
  233. package/dist/core/wiki/compile-lock.d.ts +1 -1
  234. package/dist/core/wiki/compile-lock.js +1 -1
  235. package/dist/core/workdir.js +15 -6
  236. package/dist/db/activity-scan-signals.d.ts +77 -0
  237. package/dist/db/activity-scan-signals.js +378 -0
  238. package/dist/db/agents-store.d.ts +28 -0
  239. package/dist/db/agents-store.js +62 -0
  240. package/dist/db/background-task-clarifications-store.d.ts +81 -0
  241. package/dist/db/background-task-clarifications-store.js +152 -0
  242. package/dist/db/background-task-store.d.ts +207 -0
  243. package/dist/db/background-task-store.js +380 -0
  244. package/dist/db/browser-history-store.d.ts +39 -6
  245. package/dist/db/browser-history-store.js +51 -7
  246. package/dist/db/browser-task-clarifications-store.d.ts +12 -0
  247. package/dist/db/browser-task-clarifications-store.js +35 -5
  248. package/dist/db/browser-task-store.d.ts +3 -0
  249. package/dist/db/browser-task-store.js +29 -4
  250. package/dist/db/deferred-dm.d.ts +86 -0
  251. package/dist/db/deferred-dm.js +199 -0
  252. package/dist/db/migrations.js +330 -0
  253. package/dist/db/observations.d.ts +2 -2
  254. package/dist/db/observations.js +3 -3
  255. package/dist/db/schema.js +217 -16
  256. package/dist/db/voice-transcripts-store.d.ts +1 -1
  257. package/dist/index.js +86 -29
  258. package/dist/messaging/browser-task-mcp-notifier.d.ts +12 -70
  259. package/dist/messaging/browser-task-mcp-notifier.js +30 -151
  260. package/dist/messaging/browser-task-screenshot-attachment.d.ts +15 -0
  261. package/dist/messaging/browser-task-screenshot-attachment.js +63 -0
  262. package/dist/observers/delegated-sync-worker.d.ts +6 -6
  263. package/dist/observers/delegated-sync-worker.js +10 -10
  264. package/dist/observers/git-delegated-cron.d.ts +1 -1
  265. package/dist/observers/git-delegated-cron.js +2 -2
  266. package/dist/observers/github-poller-classifier.d.ts +3 -3
  267. package/dist/observers/github-poller-classifier.js +3 -3
  268. package/dist/observers/imminent-event-scheduler.d.ts +1 -1
  269. package/dist/observers/imminent-event-scheduler.js +1 -1
  270. package/dist/observers/mail-poller.d.ts +1 -0
  271. package/dist/observers/mail-poller.js +42 -3
  272. package/dist/observers/observation-summarizer/summarizer-client.d.ts +2 -2
  273. package/dist/observers/observation-summarizer/summarizer-client.js +2 -2
  274. package/dist/observers/observation-summarizer/worker.d.ts +2 -2
  275. package/dist/observers/observation-summarizer/worker.js +4 -4
  276. package/dist/observers/obsidian-watcher.d.ts +1 -1
  277. package/dist/observers/obsidian-watcher.js +1 -1
  278. package/dist/safety/agent-write-tracker.d.ts +4 -4
  279. package/dist/safety/agent-write-tracker.js +4 -4
  280. package/dist/safety/audit.d.ts +43 -5
  281. package/dist/safety/audit.js +86 -18
  282. package/dist/safety/risk-classifier.d.ts +6 -0
  283. package/dist/safety/risk-classifier.js +75 -11
  284. package/dist/scheduler/activity-scan-gate.d.ts +86 -0
  285. package/dist/scheduler/activity-scan-gate.js +132 -0
  286. package/dist/services/background-task/background-task-budget.d.ts +80 -0
  287. package/dist/services/background-task/background-task-budget.js +91 -0
  288. package/dist/services/background-task/background-task-driver.d.ts +105 -0
  289. package/dist/services/background-task/background-task-driver.js +416 -0
  290. package/dist/services/background-task/background-task-runner.d.ts +96 -0
  291. package/dist/services/background-task/background-task-runner.js +673 -0
  292. package/dist/services/background-task/background-task-tools.d.ts +84 -0
  293. package/dist/services/background-task/background-task-tools.js +247 -0
  294. package/dist/services/background-task/background-task-transition-events.d.ts +43 -0
  295. package/dist/services/background-task/background-task-transition-events.js +54 -0
  296. package/dist/services/browser-history/automation/egress-denylist.d.ts +1 -1
  297. package/dist/services/browser-history/automation/egress-denylist.js +16 -6
  298. package/dist/services/browser-history/managed-chromium/sandbox-launcher.js +0 -1
  299. package/dist/services/browser-task/browser-task-runner.js +53 -8
  300. package/dist/services/observations-batch.d.ts +1 -1
  301. package/dist/services/observations-batch.js +2 -2
  302. package/dist/settings/runtime-settings.d.ts +38 -11
  303. package/dist/settings/runtime-settings.js +203 -40
  304. package/dist/settings/settings-store.js +11 -3
  305. package/package.json +4 -4
@@ -1,77 +1,19 @@
1
1
  /**
2
- * Browser-task MCP-side DM dispatcherBROWSER_TASK_REDESIGN_PLAN.md §5.
2
+ * Browser-task MCP-side delivery bridgeBACKGROUND_TASK_RUNNER_DESIGN.md
3
+ * Phase 1.
3
4
  *
4
- * The browser-task sub-agent's `ask_user` and `finish` tools call out to
5
- * this surface to DM the originating channel:
6
- *
7
- * - `notifyAskUser` → "❓ Browser task <id> needs your input." with
8
- * the question + the screenshot attached inline.
9
- * - `notifyFinish` → the agent's markdown report + the ordered list
10
- * of screenshots (attached inline) the user should
11
- * review.
12
- *
13
- * Distinct from the runner-side `BrowserTaskNotifier` (queued / terminal
14
- * structural DMs):
15
- *
16
- * - The runner-side notifier covers events the sub-agent never sees
17
- * (the slot manager queued the task, the SDK loop crashed before any
18
- * tool fired, etc.). Plain templated bodies.
19
- * - This MCP-side notifier carries agent-authored prose — the
20
- * `question` / `report` strings come from the sub-agent.
21
- *
22
- * The two cannot collapse into one because:
23
- * - The SDK tool body needs synchronous access to a notifier (it's
24
- * invoked inside `mcp__aitne-browser__ask_user`'s handler); the
25
- * runner-side notifier is invoked from the runner's lifecycle hooks.
26
- * - The agent-authored vs. structural split keeps the redaction-
27
- * coverage guard happy: structural bodies are templated text that
28
- * the guard knows is safe; agent bodies pass the same redaction
29
- * pipeline already applied to other LLM-authored outbound text.
30
- *
31
- * Best-effort delivery: DM failures log + continue. The DB row for the
32
- * task / clarification has already been written by the tool handler, so
33
- * a DM hiccup does NOT block the parent task — the dashboard surfaces
34
- * the row regardless. (See §5 ask_user "Resume — Deadline enforcement"
35
- * for the deadline-driven fallback when the user never sees the DM.)
36
- *
37
- * No capability-symbol gate here. The structural anti-spoofing surface
38
- * (B-4 purchase confirms + lite-final-confirm tokens) protects DM bodies
39
- * that the agent could otherwise mint to itself; `ask_user` / `finish`
40
- * bodies are intentionally agent-authored — the user is reading the
41
- * agent's question / report. The only header marker we attach is for the
42
- * user's benefit, not for adapter-side trust gating.
5
+ * The browser-task sub-agent still writes clarifications/reports through
6
+ * its `ask_user` and `finish` tools, but this bridge no longer sends a
7
+ * templated DM directly. It enqueues a `task.delivery` event instead; the
8
+ * dispatcher acquires the owner-DM gates, chooses active vs idle delivery,
9
+ * records the sent assistant message into conversation history, and marks
10
+ * the row delivered for recovery.
43
11
  */
44
- import { type MessageHub } from "../adapters/message-hub.js";
45
- import { type IngestOutboundImage } from "./browser-task-screenshot-attachment.js";
12
+ import type { EventBus } from "../core/event-bus.js";
13
+ import type Database from "better-sqlite3";
46
14
  import type { BrowserTaskMcpNotifier } from "../services/browser-history/automation/browser-task-tools/server.js";
47
- /** Header line for ask_user DMs. Chosen so it does NOT collide with the
48
- * B-4 / lite-final-confirm markers (which carry the literal substring
49
- * "confirmation") nor with the runner's `🕒` / `🟦` queue / terminal
50
- * emojis. */
51
- export declare const ASK_USER_HEADER = "Browser task \u2014 needs your input";
52
- /** Header line for finish DMs. */
53
- export declare const FINISH_HEADER = "Browser task \u2014 report";
54
15
  export interface CreateBrowserTaskMcpNotifierDeps {
55
- messageHub: MessageHub;
56
- /** Daemon data directory (`PA_DATA_DIR`). Required to resolve a
57
- * screenshotKey (`/api/browser-task/<id>/screenshots/<file>`) back to
58
- * its on-disk location under
59
- * `<paDataDir>/automation-traces/<id>/<file>` so the bytes can be
60
- * uploaded through the messaging adapter / ingested for the dashboard.
61
- * When omitted, every screenshot resolves to an "unavailable" note. */
62
- paDataDir?: string;
63
- /** Ingest a resolved trace-store screenshot into the chat
64
- * `AttachmentStore` and return a store-backed `OutboundAttachmentRef`
65
- * (or null on failure). Used for the `dashboard` platform ONLY: the
66
- * dashboard fetches attachments by id through the authenticated
67
- * same-origin `/api/chat/attachments/:id` proxy, so a loopback trace
68
- * URL embedded as markdown would 401 (the bearer token is never
69
- * attached to a raw `<img>` request). Minting a real store id lets the
70
- * dashboard render the bytes inline like any other agent attachment —
71
- * never a URL. Messaging adapters take the trace file directly via
72
- * their native upload API, so they do NOT go through this. Optional:
73
- * when omitted, dashboard screenshots resolve to an "unavailable"
74
- * note. */
75
- ingestOutboundImage?: IngestOutboundImage;
16
+ eventBus: EventBus;
17
+ db: Database.Database;
76
18
  }
77
19
  export declare function createBrowserTaskMcpNotifier(deps: CreateBrowserTaskMcpNotifierDeps): BrowserTaskMcpNotifier;
@@ -1,164 +1,43 @@
1
1
  /**
2
- * Browser-task MCP-side DM dispatcherBROWSER_TASK_REDESIGN_PLAN.md §5.
2
+ * Browser-task MCP-side delivery bridgeBACKGROUND_TASK_RUNNER_DESIGN.md
3
+ * Phase 1.
3
4
  *
4
- * The browser-task sub-agent's `ask_user` and `finish` tools call out to
5
- * this surface to DM the originating channel:
6
- *
7
- * - `notifyAskUser` → "❓ Browser task <id> needs your input." with
8
- * the question + the screenshot attached inline.
9
- * - `notifyFinish` → the agent's markdown report + the ordered list
10
- * of screenshots (attached inline) the user should
11
- * review.
12
- *
13
- * Distinct from the runner-side `BrowserTaskNotifier` (queued / terminal
14
- * structural DMs):
15
- *
16
- * - The runner-side notifier covers events the sub-agent never sees
17
- * (the slot manager queued the task, the SDK loop crashed before any
18
- * tool fired, etc.). Plain templated bodies.
19
- * - This MCP-side notifier carries agent-authored prose — the
20
- * `question` / `report` strings come from the sub-agent.
21
- *
22
- * The two cannot collapse into one because:
23
- * - The SDK tool body needs synchronous access to a notifier (it's
24
- * invoked inside `mcp__aitne-browser__ask_user`'s handler); the
25
- * runner-side notifier is invoked from the runner's lifecycle hooks.
26
- * - The agent-authored vs. structural split keeps the redaction-
27
- * coverage guard happy: structural bodies are templated text that
28
- * the guard knows is safe; agent bodies pass the same redaction
29
- * pipeline already applied to other LLM-authored outbound text.
30
- *
31
- * Best-effort delivery: DM failures log + continue. The DB row for the
32
- * task / clarification has already been written by the tool handler, so
33
- * a DM hiccup does NOT block the parent task — the dashboard surfaces
34
- * the row regardless. (See §5 ask_user "Resume — Deadline enforcement"
35
- * for the deadline-driven fallback when the user never sees the DM.)
36
- *
37
- * No capability-symbol gate here. The structural anti-spoofing surface
38
- * (B-4 purchase confirms + lite-final-confirm tokens) protects DM bodies
39
- * that the agent could otherwise mint to itself; `ask_user` / `finish`
40
- * bodies are intentionally agent-authored — the user is reading the
41
- * agent's question / report. The only header marker we attach is for the
42
- * user's benefit, not for adapter-side trust gating.
5
+ * The browser-task sub-agent still writes clarifications/reports through
6
+ * its `ask_user` and `finish` tools, but this bridge no longer sends a
7
+ * templated DM directly. It enqueues a `task.delivery` event instead; the
8
+ * dispatcher acquires the owner-DM gates, chooses active vs idle delivery,
9
+ * records the sent assistant message into conversation history, and marks
10
+ * the row delivered for recovery.
43
11
  */
12
+ import { createBrowserTaskClarificationDeliveryEvent, createBrowserTaskResultDeliveryEvent, } from "../core/dispatcher-task-delivery.js";
13
+ import { getBrowserTask } from "../db/browser-task-store.js";
44
14
  import { createLogger } from "../logging.js";
45
- import { MessageDeliveryError, } from "../adapters/message-hub.js";
46
- import { parseChannelRef } from "../db/browser-automation-purchase-primary-channels-store.js";
47
- import { resolveScreenshotAttachment, } from "./browser-task-screenshot-attachment.js";
48
15
  const logger = createLogger("browser-task-mcp-notifier");
49
- /** Header line for ask_user DMs. Chosen so it does NOT collide with the
50
- * B-4 / lite-final-confirm markers (which carry the literal substring
51
- * "confirmation") nor with the runner's `🕒` / `🟦` queue / terminal
52
- * emojis. */
53
- export const ASK_USER_HEADER = "Browser task — needs your input";
54
- /** Header line for finish DMs. */
55
- export const FINISH_HEADER = "Browser task — report";
56
- /** Soft cap on the `finish` report body inside the DM. The agent's tool
57
- * schema already caps `report` at 8 KB; some adapters (Telegram) cap
58
- * individual messages at ~4 KB. We truncate at 3 800 chars to leave
59
- * comfortable room for headers + screenshot links and append a "[…]"
60
- * marker so the user can tell the report was cropped.
61
- * The Aitne dashboard's per-task detail page renders the full report
62
- * via `GET /api/browser-task/:id`, so truncation is purely a DM-side
63
- * ergonomic. */
64
- const FINISH_REPORT_DM_BODY_CAP = 3_800;
65
- /** Max screenshots attached to a single finish DM. The full ordered list
66
- * is preserved in the row's `report` field; this cap just keeps the DM
67
- * from ballooning with attachments. */
68
- const FINISH_DM_SCREENSHOT_LINK_CAP = 8;
69
16
  export function createBrowserTaskMcpNotifier(deps) {
70
- const paDataDir = deps.paDataDir ?? null;
71
- /** Per-channel delivery. Both surfaces receive the screenshot as actual
72
- * image bytes — never a URL:
73
- *
74
- * - `dashboard`: each key is ingested into the chat `AttachmentStore`
75
- * and delivered as an `OutboundAttachmentRef`; the dashboard renders
76
- * it inline by fetching `/api/chat/attachments/:id` through its
77
- * authenticated same-origin proxy.
78
- * - messaging adapters (WhatsApp / Telegram / Slack / Discord): each
79
- * key is handed to the adapter as a trace-file `OutboundAttachmentRef`
80
- * so the adapter uploads the bytes via its native API.
81
- *
82
- * Any key that cannot be resolved (file dropped by §14.7 retention,
83
- * ingest unavailable, unknown extension) is replaced by a single
84
- * "unavailable" note rather than an unreachable link. The dashboard's
85
- * `/browser-tasks/<id>` page remains the canonical full-trace view. */
86
- async function dispatch(ref, head, tail, screenshotKeys) {
87
- const parsed = parseChannelRef(ref);
88
- if (!parsed) {
89
- logger.warn({ ref }, "browser-task MCP notifier: unparseable channel ref — DM skipped");
90
- return;
91
- }
92
- const headLines = head.filter((s) => s !== null);
93
- const tailLines = tail.filter((s) => s !== null);
94
- const resolved = (await Promise.all(screenshotKeys.map((key) => resolveScreenshotAttachment({
95
- platform: parsed.platform,
96
- key,
97
- paDataDir,
98
- ingestOutboundImage: deps.ingestOutboundImage,
99
- })))).filter((a) => a !== null);
100
- const unresolved = screenshotKeys.length - resolved.length;
101
- const noteBlock = unresolved > 0
102
- ? [
103
- "",
104
- `(${unresolved} screenshot${unresolved === 1 ? "" : "s"} could not be attached — open the browser-task detail page)`,
105
- ]
106
- : [];
107
- const body = [...headLines, ...noteBlock, ...tailLines].join("\n");
108
- const attachments = resolved.length > 0 ? resolved : undefined;
109
- try {
110
- await deps.messageHub.sendToPlatform(parsed.platform, parsed.channelId, body, undefined, attachments);
111
- }
112
- catch (err) {
113
- const reason = err instanceof MessageDeliveryError
114
- ? err.message
115
- : err instanceof Error
116
- ? err.message
117
- : String(err);
118
- logger.warn({ ref, reason }, "browser-task MCP notifier: DM dispatch failed (continuing)");
119
- }
17
+ function titleFor(taskId) {
18
+ return getBrowserTask(deps.db, taskId)?.description ?? `Browser task ${taskId}`;
120
19
  }
121
20
  async function notifyAskUser(input) {
122
- if (!input.originatingChannel) {
123
- logger.warn({
124
- taskId: input.taskId,
125
- clarificationId: input.clarificationId,
126
- }, "ask_user: no originating channel persisted — DM skipped (clarification row still written)");
127
- return;
128
- }
129
- const screenshotKeys = input.screenshotKey ? [input.screenshotKey] : [];
130
- const head = [
131
- `❓ ${ASK_USER_HEADER}`,
132
- `Task: ${input.taskId}`,
133
- `Question: ${input.question}`,
134
- `Context: ${input.contextSummary}`,
135
- ];
136
- const tail = [
137
- ``,
138
- `Reply in this DM to answer (clarification id: ${input.clarificationId}).`,
139
- ];
140
- await dispatch(input.originatingChannel, head, tail, screenshotKeys);
21
+ await deps.eventBus.put(createBrowserTaskClarificationDeliveryEvent({
22
+ taskId: input.taskId,
23
+ originatingChannel: input.originatingChannel,
24
+ title: titleFor(input.taskId),
25
+ clarificationId: input.clarificationId,
26
+ question: input.question,
27
+ contextSummary: input.contextSummary,
28
+ screenshotKey: input.screenshotKey,
29
+ }));
30
+ logger.debug({ taskId: input.taskId, clarificationId: input.clarificationId }, "browser-task clarification queued for task.delivery");
141
31
  }
142
32
  async function notifyFinish(input) {
143
- if (!input.originatingChannel) {
144
- logger.warn({ taskId: input.taskId }, "finish: no originating channel persisted — DM skipped (report still stored on the row)");
145
- return;
146
- }
147
- const reportBody = input.report.length > FINISH_REPORT_DM_BODY_CAP
148
- ? `${input.report.slice(0, FINISH_REPORT_DM_BODY_CAP)}\n\n[… truncated; open the dashboard for the full report]`
149
- : input.report;
150
- const keyBudget = input.screenshotKeys.slice(0, FINISH_DM_SCREENSHOT_LINK_CAP);
151
- const overflowCount = Math.max(0, input.screenshotKeys.length - keyBudget.length);
152
- const head = [
153
- `✅ ${FINISH_HEADER}`,
154
- `Task: ${input.taskId}`,
155
- ``,
156
- reportBody,
157
- ];
158
- const tail = overflowCount > 0
159
- ? [``, `(+${overflowCount} more — see dashboard)`]
160
- : [];
161
- await dispatch(input.originatingChannel, head, tail, keyBudget);
33
+ await deps.eventBus.put(createBrowserTaskResultDeliveryEvent({
34
+ taskId: input.taskId,
35
+ originatingChannel: input.originatingChannel,
36
+ title: titleFor(input.taskId),
37
+ report: input.report,
38
+ screenshotKeys: input.screenshotKeys,
39
+ }));
40
+ logger.debug({ taskId: input.taskId }, "browser-task report queued for task.delivery");
162
41
  }
163
42
  return { notifyAskUser, notifyFinish };
164
43
  }
@@ -60,3 +60,18 @@ export declare function resolveScreenshotAttachment(params: {
60
60
  paDataDir: string | null;
61
61
  ingestOutboundImage?: IngestOutboundImage;
62
62
  }): Promise<OutboundAttachmentRef | null>;
63
+ /**
64
+ * Resolve a worker-produced output FILE (absolute path) to a
65
+ * platform-appropriate outbound attachment — the generic-asset sibling of
66
+ * `resolveScreenshotAttachment` (BACKGROUND_TASK_RUNNER_DESIGN.md Phase 1 —
67
+ * delivery assets). Messaging adapters take the file path directly; the
68
+ * dashboard ingests it into the `AttachmentStore` so it renders inline.
69
+ * Returns null when the file is missing on disk or the dashboard ingest
70
+ * hook is unavailable — the caller omits it rather than sending a dead link.
71
+ */
72
+ export declare function buildPathAttachment(params: {
73
+ platform: string;
74
+ absPath: string;
75
+ filename: string;
76
+ ingestOutboundImage?: IngestOutboundImage;
77
+ }): Promise<OutboundAttachmentRef | null>;
@@ -113,3 +113,66 @@ export async function resolveScreenshotAttachment(params) {
113
113
  ? buildStoreAttachment(params.paDataDir, params.ingestOutboundImage, params.key)
114
114
  : buildTraceAttachment(params.paDataDir, params.key);
115
115
  }
116
+ /** MIME by extension for generic worker-produced deliverables (PDF / slides
117
+ * / docs / images). Superset of the screenshot image map. Unknown
118
+ * extensions fall back to `application/octet-stream` so the adapter still
119
+ * uploads the bytes. */
120
+ const DELIVERABLE_MIME_BY_EXT = {
121
+ ...IMAGE_MIME_BY_EXT,
122
+ gif: "image/gif",
123
+ pdf: "application/pdf",
124
+ pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
125
+ ppt: "application/vnd.ms-powerpoint",
126
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
127
+ doc: "application/msword",
128
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
129
+ csv: "text/csv",
130
+ txt: "text/plain",
131
+ md: "text/markdown",
132
+ };
133
+ function mimeForFilename(filename) {
134
+ const ext = filename.slice(filename.lastIndexOf(".") + 1).toLowerCase();
135
+ return DELIVERABLE_MIME_BY_EXT[ext] ?? "application/octet-stream";
136
+ }
137
+ /**
138
+ * Resolve a worker-produced output FILE (absolute path) to a
139
+ * platform-appropriate outbound attachment — the generic-asset sibling of
140
+ * `resolveScreenshotAttachment` (BACKGROUND_TASK_RUNNER_DESIGN.md Phase 1 —
141
+ * delivery assets). Messaging adapters take the file path directly; the
142
+ * dashboard ingests it into the `AttachmentStore` so it renders inline.
143
+ * Returns null when the file is missing on disk or the dashboard ingest
144
+ * hook is unavailable — the caller omits it rather than sending a dead link.
145
+ */
146
+ export async function buildPathAttachment(params) {
147
+ const mimeType = mimeForFilename(params.filename);
148
+ if (params.platform === "dashboard") {
149
+ if (!params.ingestOutboundImage)
150
+ return null;
151
+ try {
152
+ return await params.ingestOutboundImage({
153
+ absPath: params.absPath,
154
+ mimeType,
155
+ originalFilename: params.filename,
156
+ });
157
+ }
158
+ catch (err) {
159
+ logger.warn({ absPath: params.absPath, err: toErrMsg(err) }, "deliverable asset: dashboard ingest failed");
160
+ return null;
161
+ }
162
+ }
163
+ let sizeBytes;
164
+ try {
165
+ sizeBytes = (await stat(params.absPath)).size;
166
+ }
167
+ catch (err) {
168
+ logger.warn({ absPath: params.absPath, err: toErrMsg(err) }, "deliverable asset: file missing — omitted");
169
+ return null;
170
+ }
171
+ return {
172
+ id: params.absPath,
173
+ path: params.absPath,
174
+ originalFilename: params.filename,
175
+ mimeType,
176
+ sizeBytes,
177
+ };
178
+ }
@@ -43,7 +43,7 @@ interface DelegatedSyncRuntimeConfig {
43
43
  /**
44
44
  * Shared active-hours window applied to every cadence. Local-time hours
45
45
  * in the daemon's `timezone`; `[startHour, endHour)`. When unset, defaults
46
- * to `[4, 24)` to mirror the Hourly Check window.
46
+ * to `[4, 24)` to mirror the Activity Scan window.
47
47
  */
48
48
  activeStartHour?: number;
49
49
  activeEndHour?: number;
@@ -287,11 +287,11 @@ export declare class DelegatedSyncWorker implements Observer {
287
287
  * Native rows are skipped by `backendForCadence` returning null — their
288
288
  * observations come from the in-turn `routine.fetch_window` pre-pass
289
289
  * instead, see `docs/design/appendices/native-integration-mode.md`
290
- * §"Polling, observers, and the hourly-check threshold".
290
+ * §"Polling, observers, and the activity-scan threshold".
291
291
  *
292
292
  * Why this exists: when every cadence is disabled (the post-Phase-9
293
293
  * default), Gmail / Notion observations would otherwise dry up entirely
294
- * — the delegated `routine.hourly_check` task flow's Step 0a / 0c rely
294
+ * — the delegated `routine.activity_scan` task flow's Step 0a / 0c rely
295
295
  * on `mail:lifecycle` / `notion:<db>` rows the worker writes server-
296
296
  * side, and the agent prompt is explicitly told NOT to call the
297
297
  * gmail / notion `/reconcile` route directly (would poison the worker's
@@ -300,7 +300,7 @@ export declare class DelegatedSyncWorker implements Observer {
300
300
  * opted into a per-cadence schedule.
301
301
  *
302
302
  * Active-hours are NOT consulted: this method runs only because the
303
- * hourly check itself fired, which already passed `hourlyCheckActive*`
303
+ * activity scan itself fired, which already passed `activityScanActive*`
304
304
  * gating. The cadence-side `activeStartHour` / `activeEndHour` window
305
305
  * applies only to the worker's own 60 s tick.
306
306
  *
@@ -313,7 +313,7 @@ export declare class DelegatedSyncWorker implements Observer {
313
313
  * circuit-breaker) and surfaced through the next `getStatus()` snapshot;
314
314
  * this method does not throw.
315
315
  */
316
- runDisabledCadencesForHourlyCheck(): Promise<void>;
316
+ runDisabledCadencesForActivityScan(): Promise<void>;
317
317
  /**
318
318
  * Run a single cadence on demand (dashboard "Run Now" button). Bypasses
319
319
  * `cadenceEnabled`, `cadenceDue`, and active-hours gating — the user
@@ -410,7 +410,7 @@ export declare function resolveActiveHours(runtimeConfig: DelegatedSyncRuntimeCo
410
410
  /**
411
411
  * `true` when `now` falls inside `[startHour, endHour)` in the daemon's
412
412
  * configured timezone. `endHour=24` is exclusive — i.e. covers up to
413
- * 23:59:59. Mirrors the semantics of Hourly Check's window so an operator
413
+ * 23:59:59. Mirrors the semantics of Activity Scan's window so an operator
414
414
  * who already understands one understands the other.
415
415
  */
416
416
  export declare function isWithinActiveHours(now: Date, timezone: string | undefined, activeHours: DelegatedSyncActiveHours): boolean;
@@ -15,7 +15,7 @@ const CIRCUIT_FAILURE_THRESHOLD = 5;
15
15
  const CIRCUIT_BACKOFF_MULTIPLIER = 4;
16
16
  /**
17
17
  * Default active-hours window for delegated-sync cadences. Mirrors Hourly
18
- * Check defaults (`hourlyCheckActiveStartHour=4`, `hourlyCheckActiveEndHour=24`)
18
+ * Check defaults (`activityScanActiveStartHour=4`, `activityScanActiveEndHour=24`)
19
19
  * so the two schedules align unless an operator overrides one or the other.
20
20
  * See `docs/design/appendices/delegated-sync-opt-in.md`.
21
21
  *
@@ -126,7 +126,7 @@ const CALENDAR_24H_CADENCE = {
126
126
  * - Window is the last 7 days. Reconcile keys by `(integration,
127
127
  * window_key)` so the partition is wide enough that a recent thread
128
128
  * with a fresh reply doesn't drop out and falsely emit `deleted`. The
129
- * LLM hourly check still post-filters to "last hour" inside its own
129
+ * LLM activity scan still post-filters to "last hour" inside its own
130
130
  * decision flow; this cadence's job is structural diff, not selection.
131
131
  * - `query="newer_than:7d"` Gmail search operator. `pageSize` /
132
132
  * `max_results` / `maxResults` differs by backend (Claude / Codex /
@@ -136,7 +136,7 @@ const GMAIL_INBOX_7D_CADENCE = {
136
136
  integration: "gmail",
137
137
  windowKey: "inbox:7d",
138
138
  displayName: "Gmail — inbox (last 7 days)",
139
- description: "Polls thread-level changes in the last 7 days of inbox. Surfaces new threads and replies for the hourly check.",
139
+ description: "Polls thread-level changes in the last 7 days of inbox. Surfaces new threads and replies for the activity scan.",
140
140
  defaultIntervalSeconds: 30 * 60,
141
141
  softFloorSeconds: 15 * 60,
142
142
  maxResults: 25,
@@ -159,7 +159,7 @@ const GMAIL_INBOX_7D_CADENCE = {
159
159
  * and lets reconcile + the per-page `lastEditedTime` payload + the
160
160
  * Notion normalizer's `inWindow` predicate sort out true churn.
161
161
  * - The window's `created_date_range.start_date` arg is per the same
162
- * date format the hourly_check prompt uses (`YYYY-MM-DD`), to mirror
162
+ * date format the activity_scan prompt uses (`YYYY-MM-DD`), to mirror
163
163
  * what the LLM-driven path was already producing — connectors uniformly
164
164
  * accept that.
165
165
  */
@@ -387,11 +387,11 @@ export class DelegatedSyncWorker {
387
387
  * Native rows are skipped by `backendForCadence` returning null — their
388
388
  * observations come from the in-turn `routine.fetch_window` pre-pass
389
389
  * instead, see `docs/design/appendices/native-integration-mode.md`
390
- * §"Polling, observers, and the hourly-check threshold".
390
+ * §"Polling, observers, and the activity-scan threshold".
391
391
  *
392
392
  * Why this exists: when every cadence is disabled (the post-Phase-9
393
393
  * default), Gmail / Notion observations would otherwise dry up entirely
394
- * — the delegated `routine.hourly_check` task flow's Step 0a / 0c rely
394
+ * — the delegated `routine.activity_scan` task flow's Step 0a / 0c rely
395
395
  * on `mail:lifecycle` / `notion:<db>` rows the worker writes server-
396
396
  * side, and the agent prompt is explicitly told NOT to call the
397
397
  * gmail / notion `/reconcile` route directly (would poison the worker's
@@ -400,7 +400,7 @@ export class DelegatedSyncWorker {
400
400
  * opted into a per-cadence schedule.
401
401
  *
402
402
  * Active-hours are NOT consulted: this method runs only because the
403
- * hourly check itself fired, which already passed `hourlyCheckActive*`
403
+ * activity scan itself fired, which already passed `activityScanActive*`
404
404
  * gating. The cadence-side `activeStartHour` / `activeEndHour` window
405
405
  * applies only to the worker's own 60 s tick.
406
406
  *
@@ -413,9 +413,9 @@ export class DelegatedSyncWorker {
413
413
  * circuit-breaker) and surfaced through the next `getStatus()` snapshot;
414
414
  * this method does not throw.
415
415
  */
416
- async runDisabledCadencesForHourlyCheck() {
416
+ async runDisabledCadencesForActivityScan() {
417
417
  if (this.tickRunning) {
418
- logger.debug("Skipping hourly-check delegated refresh — worker tick already in flight");
418
+ logger.debug("Skipping activity-scan delegated refresh — worker tick already in flight");
419
419
  return;
420
420
  }
421
421
  this.tickRunning = true;
@@ -923,7 +923,7 @@ export function resolveActiveHours(runtimeConfig) {
923
923
  /**
924
924
  * `true` when `now` falls inside `[startHour, endHour)` in the daemon's
925
925
  * configured timezone. `endHour=24` is exclusive — i.e. covers up to
926
- * 23:59:59. Mirrors the semantics of Hourly Check's window so an operator
926
+ * 23:59:59. Mirrors the semantics of Activity Scan's window so an operator
927
927
  * who already understands one understands the other.
928
928
  */
929
929
  export function isWithinActiveHours(now, timezone, activeHours) {
@@ -11,7 +11,7 @@ interface GitDelegatedCronOptions {
11
11
  githubRepos: readonly string[];
12
12
  cadenceSeconds: number;
13
13
  pushOverdueMinutes: number;
14
- hourlyCheckEnabled?: boolean;
14
+ activityScanEnabled?: boolean;
15
15
  now?: () => Date;
16
16
  }
17
17
  export declare function hasActiveDelegatedGitLifecycleIntegration(db: Database.Database, override?: {
@@ -81,10 +81,10 @@ export class GitDelegatedCronObserver {
81
81
  this.timer.unref?.();
82
82
  }
83
83
  initialDelaySeconds() {
84
- // Keep 1h delegated Git checks away from routine.hourly_check. This is
84
+ // Keep 1h delegated Git checks away from routine.activity_scan. This is
85
85
  // the collision-avoidance rule from the Git lifecycle design: no session
86
86
  // reuse, just a 30-minute offset to avoid light-tier concurrency spikes.
87
- if (this.options.hourlyCheckEnabled && this.cadenceSeconds === 3600) {
87
+ if (this.options.activityScanEnabled && this.cadenceSeconds === 3600) {
88
88
  return 30 * 60;
89
89
  }
90
90
  return this.cadenceSeconds;
@@ -48,7 +48,7 @@ export type Classification = {
48
48
  /**
49
49
  * When `true`, the orchestrator emits to EventBus in addition to
50
50
  * recording the observation. Reserved for HIGH-priority signals that
51
- * should DM the user without waiting for the hourly check.
51
+ * should DM the user without waiting for the activity scan.
52
52
  */
53
53
  emitEvent: boolean;
54
54
  };
@@ -57,8 +57,8 @@ export type Classification = {
57
57
  * emit-to-EventBus) per the agent's "patterns not events" philosophy.
58
58
  *
59
59
  * - `review_requested` / `assign` / `security_alert` are HIGH and bypass
60
- * hourly_check via direct DM.
61
- * - `mention` / `team_mention` are NORMAL — coalesced in hourly_check.
60
+ * activity_scan via direct DM.
61
+ * - `mention` / `team_mention` are NORMAL — coalesced in activity_scan.
62
62
  * - `subscribed` / `manual` / `comment` / `state_change` etc. are LOW
63
63
  * noise; recorded as observations only so the agent can surface them
64
64
  * if a pattern emerges.
@@ -4,8 +4,8 @@ import { EventPriority } from "@aitne/shared";
4
4
  * emit-to-EventBus) per the agent's "patterns not events" philosophy.
5
5
  *
6
6
  * - `review_requested` / `assign` / `security_alert` are HIGH and bypass
7
- * hourly_check via direct DM.
8
- * - `mention` / `team_mention` are NORMAL — coalesced in hourly_check.
7
+ * activity_scan via direct DM.
8
+ * - `mention` / `team_mention` are NORMAL — coalesced in activity_scan.
9
9
  * - `subscribed` / `manual` / `comment` / `state_change` etc. are LOW
10
10
  * noise; recorded as observations only so the agent can surface them
11
11
  * if a pattern emerges.
@@ -145,7 +145,7 @@ export function classifyWorkflowRun(run, defaultBranch, repoFullName) {
145
145
  ref,
146
146
  payload,
147
147
  // Only DM-grade for default-branch failures. Feature-branch failures
148
- // are noise during normal development and only surface via hourly_check.
148
+ // are noise during normal development and only surface via activity_scan.
149
149
  emitEvent: onDefaultBranch,
150
150
  };
151
151
  }
@@ -17,7 +17,7 @@ import type { Observer } from "./manager.js";
17
17
  * by design (`INTEGRATION_SNAPSHOT_PARTITIONS_BY_MODE[google_calendar].native = []`);
18
18
  * without this second source, native-mode users would silently lose
19
19
  * every 15-minute reminder. Cadence note: native observations refresh
20
- * on the hourly_check tick (60-min cadence) so events scheduled with
20
+ * on the activity_scan tick (60-min cadence) so events scheduled with
21
21
  * less than ~60 min lead-time may miss their reminder. The 5-min
22
22
  * direct-mode polling cadence does not have this limit.
23
23
  *
@@ -38,7 +38,7 @@ function extractCalendarPayload(parsed) {
38
38
  * by design (`INTEGRATION_SNAPSHOT_PARTITIONS_BY_MODE[google_calendar].native = []`);
39
39
  * without this second source, native-mode users would silently lose
40
40
  * every 15-minute reminder. Cadence note: native observations refresh
41
- * on the hourly_check tick (60-min cadence) so events scheduled with
41
+ * on the activity_scan tick (60-min cadence) so events scheduled with
42
42
  * less than ~60 min lead-time may miss their reminder. The 5-min
43
43
  * direct-mode polling cadence does not have this limit.
44
44
  *
@@ -98,6 +98,7 @@ export declare class MailPoller implements Observer {
98
98
  private isAccountManagedExternally;
99
99
  private stopIdleForInactiveAccounts;
100
100
  private ensureIdle;
101
+ private startIdleForAccount;
101
102
  private softDeleteByProviderMsgId;
102
103
  /**
103
104
  * Upsert poller-observed messages into `mail_messages_index`.