@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
@@ -62,6 +62,9 @@ import { runRepositoryManagementInit, runRepositoryManagementScan, } from "./rep
62
62
  import { routineWindowKeyFromEvent } from "./routine-fetch-window-runner.js";
63
63
  import { routineHasWindows } from "./routine-windows.js";
64
64
  import { buildFeedbackWorksheet, gatherFeedbackWorksheetScopes, lessonCapsForScope, GLOBAL_LESSON_ENTRY_CAP, PER_AGENT_LESSON_ENTRY_CAP, } from "./feedback/consolidation-prep.js";
65
+ import { buildSelfPerformanceBlock, gatherSelfPerformanceData, summarizeLessonStoreUtilization, } from "./feedback/self-performance-prep.js";
66
+ import { TUNING_PENDING_CYCLE_STATE_KEY, buildTuningRecommendations, createPendingTuningCycle, gatherFailingRecurringSchedules, renderTuningRecommendationsBlock, } from "./feedback/tuning-recommender.js";
67
+ import { readRuntimeState, writeRuntimeState } from "../db/runtime-state.js";
65
68
  import { buildRegeneralizationWorksheet, } from "./feedback/regeneralization-prep.js";
66
69
  import { isSafeAgentSlug, scopeStoreFile, } from "./feedback/scope-parser.js";
67
70
  import { feedbackRetentionCutoff, sweepConsumedFeedbackSignals, } from "../db/feedback-signals-store.js";
@@ -203,6 +206,33 @@ export const REFRESH_ARCHITECTURE_ALLOWED_TOOLS = [
203
206
  "Bash(curl http://localhost:8321/api/repositories/*/architecture-section*)",
204
207
  "Bash(jq *)",
205
208
  ];
209
+ /**
210
+ * BACKGROUND_TASK_RUNNER_DESIGN.md §4.5 / §4.5-bis / Phase 4 — the active
211
+ * delivery turn is a NO-TOOL DM turn. Its sole job is to weave the
212
+ * already-injected artifact (`taskContext.task_delivery.report` carries the
213
+ * full verbatim result) into the live conversation; the agent's reply text
214
+ * IS the DM (recorded by the result processor) and any deliverable files
215
+ * are attached by the daemon, not by the agent. So the turn needs no tools
216
+ * at all — and an EMPTY override structurally prevents it from taking
217
+ * "further action" (spawning another task, writing memory, sending mail)
218
+ * during what should be a pure phrasing turn. Follow-up turns ("what did it
219
+ * find?") are ordinary DM turns and keep the full envelope, including the
220
+ * `GET /api/background-task/:id` read affordance.
221
+ */
222
+ export const TASK_DELIVERY_TURN_ALLOWED_TOOLS = [];
223
+ /**
224
+ * True when `taskCtx` is a synthetic `scheduled.dm` event minted by the
225
+ * task-delivery handler (`createScheduledDmDeliveryEvent`) — the only place
226
+ * that sets the `task_delivery` block. Used to pin the no-tool clamp above.
227
+ * Keying off this structural marker (not `event.source`) is fail-safe: the
228
+ * clamp only ever NARROWS the envelope, so a false positive degrades a turn
229
+ * to no-tool rather than widening anything.
230
+ */
231
+ export function isTaskDeliveryTurn(taskCtx) {
232
+ return (!!taskCtx
233
+ && typeof taskCtx === "object"
234
+ && "task_delivery" in taskCtx);
235
+ }
206
236
  /**
207
237
  * Backends that honor the per-execute `allowedToolsOverride` clamp end-to-
208
238
  * end. Claude consumes the list verbatim through the SDK's `dontAsk` +
@@ -214,6 +244,14 @@ export const REFRESH_ARCHITECTURE_ALLOWED_TOOLS = [
214
244
  * envelope; the operator sees an `agent_actions` row of action_type
215
245
  * `scheduled_task_clamp_unsupported` and a clear log line.
216
246
  *
247
+ * Exception — the Phase-4 task-delivery turn (`isTaskDeliveryTurn`)
248
+ * consumes this same set but DEGRADES rather than refuses: when the
249
+ * resolved backend can't enforce `[]` it still runs the delivery turn
250
+ * with the default envelope (logged), because failing to deliver the
251
+ * owner's result is worse than running the phrasing turn untooled. The
252
+ * clamp is keyed off `binding.main.backendId`, so — as with the refuse
253
+ * path — a runtime fallback to a non-claude backend is not re-evaluated.
254
+ *
217
255
  * Add a backend here only after verifying its core threads
218
256
  * `allowedToolsOverride` through to its concrete deny enforcement layer
219
257
  * — NOT just into the CLI flag set.
@@ -461,6 +499,23 @@ export class ScheduledTaskRunner {
461
499
  this.markScheduledTaskCompleted(event);
462
500
  return;
463
501
  }
502
+ // BACKGROUND_TASK_RUNNER_DESIGN.md §4.5 / Phase 4 — pin the no-tool
503
+ // clamp on the active delivery turn. Mutually exclusive with the
504
+ // refresh-architecture clamp (a delivery turn is never that process
505
+ // key). Unlike the safety-critical refresh/curation clamps, this is a
506
+ // HARDENING: when the resolved backend can't enforce a per-execute
507
+ // clamp we DEGRADE (deliver with the default envelope) rather than
508
+ // refuse — failing to deliver the owner's result would be the worse
509
+ // outcome. The degrade is logged per the "no silent drops" posture.
510
+ const taskDeliveryToolClamp = isTaskDeliveryTurn(taskCtx)
511
+ ? TOOL_CLAMP_SUPPORTING_BACKENDS.has(binding.main.backendId)
512
+ ? TASK_DELIVERY_TURN_ALLOWED_TOOLS
513
+ : undefined
514
+ : undefined;
515
+ if (isTaskDeliveryTurn(taskCtx) && taskDeliveryToolClamp === undefined) {
516
+ logger.info({ backendId: binding.main.backendId, correlationId: event.correlationId }, "task.delivery active turn: resolved backend does not honor the per-execute tool clamp; delivering with the default DM envelope (degraded, not refused)");
517
+ }
518
+ const effectiveAllowedToolsOverride = refreshArchitectureOverride ?? taskDeliveryToolClamp;
464
519
  // AGENT_DEFINITIONS_DESIGN.md §4.2 — fold the firing Agent's
465
520
  // `tools.skills` onto the process-key skill bundle. `undefined` for every
466
521
  // non-Agent firing (managed task, git project doc, automation trigger) and
@@ -474,8 +529,8 @@ export class ScheduledTaskRunner {
474
529
  requestedTier,
475
530
  preResolvedBinding: binding,
476
531
  reassemblePrompt,
477
- ...(refreshArchitectureOverride
478
- ? { allowedToolsOverride: refreshArchitectureOverride }
532
+ ...(effectiveAllowedToolsOverride
533
+ ? { allowedToolsOverride: effectiveAllowedToolsOverride }
479
534
  : {}),
480
535
  ...(agentSkillOverride
481
536
  ? {
@@ -808,7 +863,7 @@ export class ScheduledTaskRunner {
808
863
  // row insert (today.md is fresh, audit row is missing);
809
864
  // - the user manually edits today.md to the current date (CLAUDE.md
810
865
  // calls this out as a documented edit path).
811
- // In both, the hourly_check pre-routine gate (`morningRoutineRanToday`)
866
+ // In both, the activity_scan pre-routine gate (`morningRoutineRanToday`)
812
867
  // would keep refusing to run because the audit row is absent, the
813
868
  // pre-routine gate kept enqueuing wake rows, and each wake row was
814
869
  // fast-path completed here — never producing the audit row that would
@@ -844,6 +899,15 @@ export class ScheduledTaskRunner {
844
899
  // carries the previous attempt so executeMorningRoutine → scheduleMorningRetry
845
900
  // can increment properly. correlationId tracks back to the original
846
901
  // cron morning_routine for log correlation.
902
+ //
903
+ // `agentId` is carried over from the wake event (stamped there by
904
+ // `Dispatcher.beginAgentExecution` via `task_context.agent_id` /
905
+ // `task_context.routine`): the cron path's RoutineEvent gets the stamp
906
+ // directly, so dropping it here would make run-now / retry firings
907
+ // ignore the morning-routine Agent's overrides + lesson injection while
908
+ // cron firings honour them — the same manual-vs-cron divergence class
909
+ // AGENT_DEFINITIONS_KNOWN_LIMITATIONS §1 fixed for user Agents.
910
+ const wakeAgentId = event.data?.agentId;
847
911
  const synthEvent = {
848
912
  ...createEvent({
849
913
  type: "routine.morning_routine",
@@ -855,12 +919,15 @@ export class ScheduledTaskRunner {
855
919
  priority: retryCount > 0 ? EventPriority.NORMAL : EventPriority.HIGH,
856
920
  correlationId: taskCtx.originalCorrelationId ?? event.correlationId,
857
921
  data: {
922
+ ...(typeof wakeAgentId === "string" && wakeAgentId.length > 0
923
+ ? { agentId: wakeAgentId }
924
+ : {}),
858
925
  ...(retryCount > 0 ? { retryCount, isRetry: true } : {}),
859
926
  ...(Array.isArray(taskCtx.postCatchupRoutines)
860
927
  ? { postCatchupRoutines: taskCtx.postCatchupRoutines }
861
928
  : {}),
862
- ...(taskCtx.postCatchupHourlyCheck === true
863
- ? { postCatchupHourlyCheck: true }
929
+ ...(taskCtx.postCatchupActivityScan === true
930
+ ? { postCatchupActivityScan: true }
864
931
  : {}),
865
932
  ...(typeof taskCtx.source === "string"
866
933
  ? { queuedSource: taskCtx.source }
@@ -1068,7 +1135,7 @@ export class ScheduledTaskRunner {
1068
1135
  try {
1069
1136
  // docs/design/appendices/routine-data-acquisition.md Phase 4 / D4 — pre-pass for
1070
1137
  // routine events whose ProcessKey appears in `ROUTINE_WINDOWS`
1071
- // (today_refresh, evening_review, weekly_review). The hourly_check
1138
+ // (today_refresh, evening_review, weekly_review). The activity_scan
1072
1139
  // and morning_routine dispatch paths attach their own
1073
1140
  // `fetchReportBlock` upstream (D2 / D3); we honour an existing
1074
1141
  // attachment to avoid double-spawning the fetcher. `monthly_review`
@@ -1179,6 +1246,36 @@ export class ScheduledTaskRunner {
1179
1246
  if (isRoutineEvent(effectiveEvent)
1180
1247
  && effectiveEvent.routine === "weekly_review") {
1181
1248
  this.runWeeklyInterestsReflectionPreHook(effectiveEvent);
1249
+ // SELF_TUNING_REVIEW_CYCLE_DESIGN.md §3.1 + §3.2 / Phases 1–2 —
1250
+ // deterministic Measure + Recommend pre-steps for
1251
+ // `routine.weekly_review`. Run synchronously BEFORE
1252
+ // `contextBuilder.build` so the `<self_performance>` block (7-day
1253
+ // per-routine run/cost/duration aggregates + fetch_window empty-run
1254
+ // rates + hourly-gate stage distribution + notification reaction
1255
+ // breakdown + self-tuning ledger) and the `<tuning_recommendations>`
1256
+ // block (Phase 2 rule-table output for the Phase 3c verdict step)
1257
+ // land in the weekly session's context. Both share one gather pass;
1258
+ // each is independently failure-isolated inside
1259
+ // `prepareSelfTuningBlocks` — a throw is swallowed and the review
1260
+ // still ships. Either block is omitted entirely when empty (no
1261
+ // empty XML in the prompt).
1262
+ const selfTuning = this.prepareSelfTuningBlocks();
1263
+ if (selfTuning.selfPerformanceBlock || selfTuning.tuningRecommendationsBlock) {
1264
+ effectiveEvent = {
1265
+ ...effectiveEvent,
1266
+ data: {
1267
+ ...effectiveEvent.data,
1268
+ ...(selfTuning.selfPerformanceBlock
1269
+ ? { selfPerformanceBlock: selfTuning.selfPerformanceBlock }
1270
+ : {}),
1271
+ ...(selfTuning.tuningRecommendationsBlock
1272
+ ? {
1273
+ tuningRecommendationsBlock: selfTuning.tuningRecommendationsBlock,
1274
+ }
1275
+ : {}),
1276
+ },
1277
+ };
1278
+ }
1182
1279
  }
1183
1280
  const context = await this.contextBuilder.build(effectiveEvent);
1184
1281
  const processKey = resolveProcessKey(effectiveEvent);
@@ -1453,6 +1550,116 @@ export class ScheduledTaskRunner {
1453
1550
  return null;
1454
1551
  }
1455
1552
  }
1553
+ /**
1554
+ * SELF_TUNING_REVIEW_CYCLE_DESIGN.md §3.1 + §3.2 / Phases 1–2 — the
1555
+ * deterministic Measure + Recommend pre-steps. Computes the 7-day window +
1556
+ * 7-day-prior baseline SQL aggregates over `agent_actions` /
1557
+ * `notification_log` / the `runtime_state.self_tuning:*` ledger, reads each
1558
+ * lesson store's byte pressure (§3.5), and composes the
1559
+ * `<self_performance>` block via the pure
1560
+ * `core/feedback/self-performance-prep.ts` module. The same gathered data
1561
+ * then feeds the Phase 2 rule table (`core/feedback/tuning-recommender.ts`):
1562
+ * the resulting pending cycle is persisted to
1563
+ * `runtime_state.self_tuning.pending_cycle` — overwriting (and thereby
1564
+ * expiring, §3.4 single-use ids) the previous cycle even when this week
1565
+ * produced zero recommendations — and rendered as the
1566
+ * `<tuning_recommendations>` block for the Phase 3c verdict step.
1567
+ *
1568
+ * Either field is `null` when there is nothing to inject or its step threw —
1569
+ * the caller simply skips stamping and the weekly review proceeds
1570
+ * unchanged. The Recommend step is failure-isolated from the Measure step:
1571
+ * a recommender throw never drops the `<self_performance>` block.
1572
+ *
1573
+ * The DB handle + lesson-file FS reads live here (the dispatcher is
1574
+ * coverage-excluded); the byte-deterministic aggregation, rule table, and
1575
+ * rendering live in the pure modules, which are 100% unit-tested. Unlike
1576
+ * the consolidation/re-generalization pre-steps this is NOT gated on
1577
+ * `feedbackLearningEnabled` — it measures core daemon telemetry, not the
1578
+ * lesson loop; nor on `selfTuningEnabled` — that flag gates Phase 3
1579
+ * *actuation* only, while recommendation generation + verdict recording IS
1580
+ * the Phase 2 shadow period (§7). An unreadable lesson store only drops the
1581
+ * `<lesson_stores>` rows / the R5 input, never the whole block.
1582
+ */
1583
+ prepareSelfTuningBlocks() {
1584
+ try {
1585
+ const now = new Date();
1586
+ const data = gatherSelfPerformanceData(this.db, { now });
1587
+ const lessonStores = [];
1588
+ const contextDir = getContextDir(this.config, this.db);
1589
+ const readStoreFile = (rel) => {
1590
+ const full = join(contextDir, rel);
1591
+ if (!existsSync(full))
1592
+ return null;
1593
+ try {
1594
+ return readFileSync(full, "utf-8");
1595
+ }
1596
+ catch (err) {
1597
+ logger.warn({ err, path: rel }, "Skipping lesson store in self-performance block — file present but unreadable");
1598
+ return null;
1599
+ }
1600
+ };
1601
+ const globalMd = readStoreFile(CONTEXT_RELATIVE_PATHS.agentLessons);
1602
+ if (globalMd !== null) {
1603
+ lessonStores.push(summarizeLessonStoreUtilization("agent", globalMd, this.config.feedbackLessonMaxBytesGlobal));
1604
+ }
1605
+ const agentsDir = join(contextDir, "policies", "agents");
1606
+ if (existsSync(agentsDir)) {
1607
+ for (const entry of readdirSync(agentsDir, { withFileTypes: true })) {
1608
+ if (!entry.isDirectory() || !isSafeAgentSlug(entry.name))
1609
+ continue;
1610
+ const md = readStoreFile(agentLessonsPath(entry.name));
1611
+ if (md === null)
1612
+ continue;
1613
+ lessonStores.push(summarizeLessonStoreUtilization(`agent:${entry.name}`, md, this.config.feedbackLessonMaxBytesPerAgent));
1614
+ }
1615
+ }
1616
+ const selfPerformanceBlock = buildSelfPerformanceBlock(data, {
1617
+ generatedAt: now.toISOString(),
1618
+ lessonStores,
1619
+ });
1620
+ // Phase 2 Recommend step — isolated so a recommender failure cannot
1621
+ // cost the weekly session its Measure block.
1622
+ let tuningRecommendationsBlock = null;
1623
+ try {
1624
+ const recommendations = buildTuningRecommendations({
1625
+ data,
1626
+ knobs: {
1627
+ activityScanPrePassFreshnessMinutes: this.config.activityScanPrePassFreshnessMinutes,
1628
+ activityScanLowSignalPendingCeiling: this.config.activityScanLowSignalPendingCeiling,
1629
+ feedbackLessonMaxBytesGlobal: this.config.feedbackLessonMaxBytesGlobal,
1630
+ },
1631
+ lessonStores,
1632
+ failingSchedules: gatherFailingRecurringSchedules(this.db),
1633
+ now,
1634
+ });
1635
+ // Read the outgoing blob before overwriting: a SAME-day re-run
1636
+ // (manual `!run` / crash retry) regenerates the same cycle id and
1637
+ // ids, and verdicts already recorded against them must survive —
1638
+ // otherwise the re-run session re-verdicts judged ids and
1639
+ // double-posts rejection self_critique signals. A prior-day blob
1640
+ // is ignored inside createPendingTuningCycle (§3.4 expiry).
1641
+ const previousCycle = readRuntimeState(this.db, TUNING_PENDING_CYCLE_STATE_KEY);
1642
+ const cycle = createPendingTuningCycle(recommendations, now.toISOString(), previousCycle);
1643
+ // Always persist — an empty cycle still expires last week's
1644
+ // single-use verdict ids (§3.4).
1645
+ writeRuntimeState(this.db, TUNING_PENDING_CYCLE_STATE_KEY, cycle);
1646
+ // Phase 3 — the block's `mode` attribute tells the weekly session
1647
+ // whether apply verdicts actuate (`live`) or are recorded only
1648
+ // (`shadow`), so the task-flow never has to guess the flag state.
1649
+ tuningRecommendationsBlock = renderTuningRecommendationsBlock(cycle, {
1650
+ mode: this.config.selfTuningEnabled === true ? "live" : "shadow",
1651
+ });
1652
+ }
1653
+ catch (err) {
1654
+ logger.warn({ err }, "Failed to prepare tuning recommendations");
1655
+ }
1656
+ return { selfPerformanceBlock, tuningRecommendationsBlock };
1657
+ }
1658
+ catch (err) {
1659
+ logger.warn({ err }, "Failed to prepare self-performance block");
1660
+ return { selfPerformanceBlock: null, tuningRecommendationsBlock: null };
1661
+ }
1662
+ }
1456
1663
  /**
1457
1664
  * FEEDBACK_LEARNING_LOOP_DESIGN.md §4 "Monthly re-generalization" / Phase 5 —
1458
1665
  * the deterministic monthly pre-step. Enumerates the consolidated lesson
@@ -0,0 +1,105 @@
1
+ import type Database from "better-sqlite3";
2
+ import type { AgentTaskEvent, TaskDeliveryAsset, TaskDeliveryEvent } from "@aitne/shared";
3
+ import type { AgentConfig } from "../config.js";
4
+ import type { OutboundAttachmentRef } from "../adapters/types.js";
5
+ import type { INotificationManager } from "./dispatcher-types.js";
6
+ export declare const TASK_DELIVERY_GATE_KEYS: readonly ["owner_dm:owner", "dashboard_chat:dashboard"];
7
+ export interface BrowserTaskDeliveryEventInput {
8
+ taskId: string;
9
+ originatingChannel: string | null;
10
+ title: string;
11
+ }
12
+ export declare function createBrowserTaskResultDeliveryEvent(input: BrowserTaskDeliveryEventInput & {
13
+ report: string;
14
+ screenshotKeys?: readonly string[];
15
+ }): TaskDeliveryEvent;
16
+ export declare function createBrowserTaskClarificationDeliveryEvent(input: BrowserTaskDeliveryEventInput & {
17
+ clarificationId: string;
18
+ question: string;
19
+ contextSummary: string | null;
20
+ screenshotKey: string | null;
21
+ }): TaskDeliveryEvent;
22
+ export interface BackgroundTaskResultDeliveryInput {
23
+ taskId: string;
24
+ originatingChannel: string | null;
25
+ title: string;
26
+ /** Worker-authored summary — the idle-send body / active-turn grounding. */
27
+ draft: string;
28
+ /** Verbatim result — injected into the active delivery turn so the DM
29
+ * agent can weave full detail without a tool round-trip. */
30
+ report: string;
31
+ /** Worker-produced deliverable files (PDF / PPTX / PNG / docs) to attach
32
+ * to the result DM. Omit / empty when the task produced no files. */
33
+ assets?: readonly TaskDeliveryAsset[];
34
+ }
35
+ export declare function createBackgroundTaskResultDeliveryEvent(input: BackgroundTaskResultDeliveryInput): TaskDeliveryEvent;
36
+ export declare function createBackgroundTaskClarificationDeliveryEvent(input: {
37
+ taskId: string;
38
+ originatingChannel: string | null;
39
+ title: string;
40
+ clarificationId: string;
41
+ question: string;
42
+ contextSummary: string | null;
43
+ }): TaskDeliveryEvent;
44
+ /**
45
+ * BACKGROUND_TASK_RUNNER_DESIGN.md §2.3 / §13 Decision 4 (Phase 4, opt-in)
46
+ * — wrap a routine autonomous forward as a `task.delivery` event so it
47
+ * flows through the same gate + activity-branch machinery: an active owner
48
+ * gets a woven delivery turn, an idle owner the verbatim send + record.
49
+ * Carries no DB row (synthetic id, no `delivered_at` recovery — autonomous
50
+ * forwards are fire-and-forget, exactly as the verbatim path is today).
51
+ */
52
+ export declare function createAutonomousForwardDeliveryEvent(input: {
53
+ content: string;
54
+ originatingChannel: string | null;
55
+ title?: string;
56
+ correlationId?: string | null;
57
+ }): TaskDeliveryEvent;
58
+ export interface TaskDeliveryHandlerDeps {
59
+ db: Database.Database;
60
+ config: AgentConfig;
61
+ notificationMgr: INotificationManager;
62
+ executeScheduledTask(event: AgentTaskEvent): Promise<void>;
63
+ /**
64
+ * Resolve a task's deliverable assets (browser-task trace screenshots
65
+ * and/or worker-written files: PDF / PPTX / PNG / docs) to outbound
66
+ * attachments for the platform the DM lands on. Used by BOTH the idle
67
+ * direct-send and the active delivery turn so the owner receives the
68
+ * actual files inline (BACKGROUND_TASK_RUNNER_DESIGN.md Phase 1 — delivery
69
+ * assets). Injected from bootstrap (closure over `paDataDir` + the
70
+ * dashboard ingest hook); absent in unit tests, where assets are simply
71
+ * omitted. Best-effort — must resolve to `[]` rather than throw.
72
+ */
73
+ resolveAssets?(platform: string, assets: readonly TaskDeliveryAsset[]): Promise<readonly OutboundAttachmentRef[]>;
74
+ nowFn?: () => number;
75
+ }
76
+ /** The asset key the dispatch arm puts resolved refs under on the
77
+ * synthetic `scheduled.dm` event so the result processor can attach them
78
+ * to the woven reply. */
79
+ export declare const TASK_DELIVERY_ATTACHMENTS_KEY = "task_delivery_attachments";
80
+ export declare function handleTaskDeliveryInsideGate(deps: TaskDeliveryHandlerDeps, event: TaskDeliveryEvent): Promise<void>;
81
+ export declare function enqueueUndeliveredBrowserTaskDeliveries(params: {
82
+ db: Database.Database;
83
+ eventBus: {
84
+ put(event: TaskDeliveryEvent): Promise<void>;
85
+ };
86
+ nowMs?: number;
87
+ limit?: number;
88
+ }): Promise<number>;
89
+ /**
90
+ * BACKGROUND_TASK_RUNNER_DESIGN.md §10.2 — delivery recovery sweep for
91
+ * background tasks. Re-enqueues `task.delivery` events for completed
92
+ * notify=true artifacts whose DM was never sent/recorded
93
+ * (`delivered_at IS NULL`) plus undelivered open clarifications. Run on
94
+ * the housekeeping tick (boot + periodic). Idempotent against the
95
+ * in-gate message-existence dedup — a re-enqueue after a successful send
96
+ * only back-fills `delivered_at`, never double-sends (§4.4).
97
+ */
98
+ export declare function enqueueUndeliveredBackgroundTaskDeliveries(params: {
99
+ db: Database.Database;
100
+ eventBus: {
101
+ put(event: TaskDeliveryEvent): Promise<void>;
102
+ };
103
+ nowMs?: number;
104
+ limit?: number;
105
+ }): Promise<number>;