@aitne/daemon 0.1.7 → 0.1.8

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 (959) hide show
  1. package/dist/adapters/dashboard-adapter.d.ts +18 -2
  2. package/dist/adapters/dashboard-adapter.d.ts.map +1 -1
  3. package/dist/adapters/dashboard-adapter.js +101 -51
  4. package/dist/adapters/dashboard-adapter.js.map +1 -1
  5. package/dist/adapters/discord.d.ts +8 -0
  6. package/dist/adapters/discord.d.ts.map +1 -1
  7. package/dist/adapters/discord.js +100 -21
  8. package/dist/adapters/discord.js.map +1 -1
  9. package/dist/adapters/message-hub.d.ts.map +1 -1
  10. package/dist/adapters/message-hub.js +7 -1
  11. package/dist/adapters/message-hub.js.map +1 -1
  12. package/dist/adapters/notification-manager.d.ts +102 -2
  13. package/dist/adapters/notification-manager.d.ts.map +1 -1
  14. package/dist/adapters/notification-manager.js +228 -8
  15. package/dist/adapters/notification-manager.js.map +1 -1
  16. package/dist/adapters/outbound-text.d.ts +16 -0
  17. package/dist/adapters/outbound-text.d.ts.map +1 -1
  18. package/dist/adapters/outbound-text.js +118 -1
  19. package/dist/adapters/outbound-text.js.map +1 -1
  20. package/dist/adapters/primary-platform-resolver.d.ts +69 -0
  21. package/dist/adapters/primary-platform-resolver.d.ts.map +1 -0
  22. package/dist/adapters/primary-platform-resolver.js +55 -0
  23. package/dist/adapters/primary-platform-resolver.js.map +1 -0
  24. package/dist/adapters/slack-adapter.d.ts +28 -0
  25. package/dist/adapters/slack-adapter.d.ts.map +1 -1
  26. package/dist/adapters/slack-adapter.js +134 -35
  27. package/dist/adapters/slack-adapter.js.map +1 -1
  28. package/dist/adapters/telegram-adapter.d.ts +7 -1
  29. package/dist/adapters/telegram-adapter.d.ts.map +1 -1
  30. package/dist/adapters/telegram-adapter.js +49 -18
  31. package/dist/adapters/telegram-adapter.js.map +1 -1
  32. package/dist/adapters/whatsapp-adapter.d.ts +33 -0
  33. package/dist/adapters/whatsapp-adapter.d.ts.map +1 -1
  34. package/dist/adapters/whatsapp-adapter.js +84 -0
  35. package/dist/adapters/whatsapp-adapter.js.map +1 -1
  36. package/dist/api/directory-picker.d.ts.map +1 -1
  37. package/dist/api/directory-picker.js +14 -0
  38. package/dist/api/directory-picker.js.map +1 -1
  39. package/dist/api/env-writer.d.ts.map +1 -1
  40. package/dist/api/env-writer.js +6 -1
  41. package/dist/api/env-writer.js.map +1 -1
  42. package/dist/api/helpers/agent-errors.d.ts +2600 -0
  43. package/dist/api/helpers/agent-errors.d.ts.map +1 -0
  44. package/dist/api/helpers/agent-errors.js +2506 -0
  45. package/dist/api/helpers/agent-errors.js.map +1 -0
  46. package/dist/api/integration-route-gate.d.ts.map +1 -1
  47. package/dist/api/integration-route-gate.js +10 -3
  48. package/dist/api/integration-route-gate.js.map +1 -1
  49. package/dist/api/routes/agent-schedule-plan-match.d.ts +5 -0
  50. package/dist/api/routes/agent-schedule-plan-match.d.ts.map +1 -0
  51. package/dist/api/routes/agent-schedule-plan-match.js +101 -0
  52. package/dist/api/routes/agent-schedule-plan-match.js.map +1 -0
  53. package/dist/api/routes/agent-schedule.d.ts +4 -0
  54. package/dist/api/routes/agent-schedule.d.ts.map +1 -0
  55. package/dist/api/routes/agent-schedule.js +750 -0
  56. package/dist/api/routes/agent-schedule.js.map +1 -0
  57. package/dist/api/routes/agent.d.ts.map +1 -1
  58. package/dist/api/routes/agent.js +209 -366
  59. package/dist/api/routes/agent.js.map +1 -1
  60. package/dist/api/routes/apple-calendar.d.ts.map +1 -1
  61. package/dist/api/routes/apple-calendar.js +109 -27
  62. package/dist/api/routes/apple-calendar.js.map +1 -1
  63. package/dist/api/routes/attachments.d.ts.map +1 -1
  64. package/dist/api/routes/attachments.js +113 -21
  65. package/dist/api/routes/attachments.js.map +1 -1
  66. package/dist/api/routes/backends.d.ts.map +1 -1
  67. package/dist/api/routes/backends.js +100 -4
  68. package/dist/api/routes/backends.js.map +1 -1
  69. package/dist/api/routes/books.d.ts.map +1 -1
  70. package/dist/api/routes/books.js +58 -18
  71. package/dist/api/routes/books.js.map +1 -1
  72. package/dist/api/routes/calendar.d.ts +3 -2
  73. package/dist/api/routes/calendar.d.ts.map +1 -1
  74. package/dist/api/routes/calendar.js +330 -55
  75. package/dist/api/routes/calendar.js.map +1 -1
  76. package/dist/api/routes/commands.d.ts.map +1 -1
  77. package/dist/api/routes/commands.js +20 -1
  78. package/dist/api/routes/commands.js.map +1 -1
  79. package/dist/api/routes/context/index.d.ts +33 -0
  80. package/dist/api/routes/context/index.d.ts.map +1 -0
  81. package/dist/api/routes/context/index.js +193 -0
  82. package/dist/api/routes/context/index.js.map +1 -0
  83. package/dist/api/routes/context/locks.d.ts +4 -0
  84. package/dist/api/routes/context/locks.d.ts.map +1 -0
  85. package/dist/api/routes/context/locks.js +136 -0
  86. package/dist/api/routes/context/locks.js.map +1 -0
  87. package/dist/api/routes/context/path-resolve.d.ts +15 -0
  88. package/dist/api/routes/context/path-resolve.d.ts.map +1 -0
  89. package/dist/api/routes/context/path-resolve.js +109 -0
  90. package/dist/api/routes/context/path-resolve.js.map +1 -0
  91. package/dist/api/routes/context/permissions.d.ts +35 -0
  92. package/dist/api/routes/context/permissions.d.ts.map +1 -0
  93. package/dist/api/routes/context/permissions.js +192 -0
  94. package/dist/api/routes/context/permissions.js.map +1 -0
  95. package/dist/api/routes/context/read.d.ts +4 -0
  96. package/dist/api/routes/context/read.d.ts.map +1 -0
  97. package/dist/api/routes/context/read.js +295 -0
  98. package/dist/api/routes/context/read.js.map +1 -0
  99. package/dist/api/routes/context/repair.d.ts +4 -0
  100. package/dist/api/routes/context/repair.d.ts.map +1 -0
  101. package/dist/api/routes/context/repair.js +114 -0
  102. package/dist/api/routes/context/repair.js.map +1 -0
  103. package/dist/api/routes/context/snapshots.d.ts +4 -0
  104. package/dist/api/routes/context/snapshots.d.ts.map +1 -0
  105. package/dist/api/routes/context/snapshots.js +177 -0
  106. package/dist/api/routes/context/snapshots.js.map +1 -0
  107. package/dist/api/routes/context/write.d.ts +4 -0
  108. package/dist/api/routes/context/write.d.ts.map +1 -0
  109. package/dist/api/routes/context/write.js +570 -0
  110. package/dist/api/routes/context/write.js.map +1 -0
  111. package/dist/api/routes/context.d.ts +2 -43
  112. package/dist/api/routes/context.d.ts.map +1 -1
  113. package/dist/api/routes/context.js +415 -558
  114. package/dist/api/routes/context.js.map +1 -1
  115. package/dist/api/routes/dashboard/config.d.ts +4 -0
  116. package/dist/api/routes/dashboard/config.d.ts.map +1 -0
  117. package/dist/api/routes/dashboard/config.js +499 -0
  118. package/dist/api/routes/dashboard/config.js.map +1 -0
  119. package/dist/api/routes/dashboard/conversations.d.ts +4 -0
  120. package/dist/api/routes/dashboard/conversations.d.ts.map +1 -0
  121. package/dist/api/routes/dashboard/conversations.js +309 -0
  122. package/dist/api/routes/dashboard/conversations.js.map +1 -0
  123. package/dist/api/routes/dashboard/cost-approvals.d.ts +29 -0
  124. package/dist/api/routes/dashboard/cost-approvals.d.ts.map +1 -0
  125. package/dist/api/routes/dashboard/cost-approvals.js +259 -0
  126. package/dist/api/routes/dashboard/cost-approvals.js.map +1 -0
  127. package/dist/api/routes/dashboard/index.d.ts +27 -0
  128. package/dist/api/routes/dashboard/index.d.ts.map +1 -0
  129. package/dist/api/routes/dashboard/index.js +47 -0
  130. package/dist/api/routes/dashboard/index.js.map +1 -0
  131. package/dist/api/routes/dashboard/messaging.d.ts +4 -0
  132. package/dist/api/routes/dashboard/messaging.d.ts.map +1 -0
  133. package/dist/api/routes/dashboard/messaging.js +351 -0
  134. package/dist/api/routes/dashboard/messaging.js.map +1 -0
  135. package/dist/api/routes/dashboard/notifications.d.ts +4 -0
  136. package/dist/api/routes/dashboard/notifications.d.ts.map +1 -0
  137. package/dist/api/routes/dashboard/notifications.js +109 -0
  138. package/dist/api/routes/dashboard/notifications.js.map +1 -0
  139. package/dist/api/routes/dashboard/oauth-google.d.ts +4 -0
  140. package/dist/api/routes/dashboard/oauth-google.d.ts.map +1 -0
  141. package/dist/api/routes/dashboard/oauth-google.js +293 -0
  142. package/dist/api/routes/dashboard/oauth-google.js.map +1 -0
  143. package/dist/api/routes/dashboard/schedule-readonly.d.ts +4 -0
  144. package/dist/api/routes/dashboard/schedule-readonly.d.ts.map +1 -0
  145. package/dist/api/routes/dashboard/schedule-readonly.js +46 -0
  146. package/dist/api/routes/dashboard/schedule-readonly.js.map +1 -0
  147. package/dist/api/routes/dashboard/secrets.d.ts +24 -0
  148. package/dist/api/routes/dashboard/secrets.d.ts.map +1 -0
  149. package/dist/api/routes/dashboard/secrets.js +307 -0
  150. package/dist/api/routes/dashboard/secrets.js.map +1 -0
  151. package/dist/api/routes/dashboard/snapshots.d.ts +4 -0
  152. package/dist/api/routes/dashboard/snapshots.d.ts.map +1 -0
  153. package/dist/api/routes/dashboard/snapshots.js +33 -0
  154. package/dist/api/routes/dashboard/snapshots.js.map +1 -0
  155. package/dist/api/routes/dashboard.d.ts.map +1 -1
  156. package/dist/api/routes/dashboard.js +20 -12
  157. package/dist/api/routes/dashboard.js.map +1 -1
  158. package/dist/api/routes/delegated.d.ts +5 -4
  159. package/dist/api/routes/delegated.d.ts.map +1 -1
  160. package/dist/api/routes/delegated.js +6 -5
  161. package/dist/api/routes/delegated.js.map +1 -1
  162. package/dist/api/routes/docs.d.ts.map +1 -1
  163. package/dist/api/routes/docs.js +72 -9
  164. package/dist/api/routes/docs.js.map +1 -1
  165. package/dist/api/routes/entities.d.ts.map +1 -1
  166. package/dist/api/routes/entities.js +112 -43
  167. package/dist/api/routes/entities.js.map +1 -1
  168. package/dist/api/routes/fs.d.ts.map +1 -1
  169. package/dist/api/routes/fs.js +27 -12
  170. package/dist/api/routes/fs.js.map +1 -1
  171. package/dist/api/routes/git-templates.d.ts.map +1 -1
  172. package/dist/api/routes/git-templates.js +107 -27
  173. package/dist/api/routes/git-templates.js.map +1 -1
  174. package/dist/api/routes/git.d.ts.map +1 -1
  175. package/dist/api/routes/git.js +55 -11
  176. package/dist/api/routes/git.js.map +1 -1
  177. package/dist/api/routes/github.d.ts.map +1 -1
  178. package/dist/api/routes/github.js +110 -17
  179. package/dist/api/routes/github.js.map +1 -1
  180. package/dist/api/routes/integrations/crud-patch.d.ts +17 -0
  181. package/dist/api/routes/integrations/crud-patch.d.ts.map +1 -0
  182. package/dist/api/routes/integrations/crud-patch.js +600 -0
  183. package/dist/api/routes/integrations/crud-patch.js.map +1 -0
  184. package/dist/api/routes/integrations/crud.d.ts +16 -0
  185. package/dist/api/routes/integrations/crud.d.ts.map +1 -0
  186. package/dist/api/routes/integrations/crud.js +158 -0
  187. package/dist/api/routes/integrations/crud.js.map +1 -0
  188. package/dist/api/routes/integrations/exec.d.ts +23 -0
  189. package/dist/api/routes/integrations/exec.d.ts.map +1 -0
  190. package/dist/api/routes/integrations/exec.js +356 -0
  191. package/dist/api/routes/integrations/exec.js.map +1 -0
  192. package/dist/api/routes/integrations/index.d.ts +62 -0
  193. package/dist/api/routes/integrations/index.d.ts.map +1 -0
  194. package/dist/api/routes/integrations/index.js +70 -0
  195. package/dist/api/routes/integrations/index.js.map +1 -0
  196. package/dist/api/routes/integrations/integrations/crud.d.ts +16 -0
  197. package/dist/api/routes/integrations/integrations/crud.d.ts.map +1 -0
  198. package/dist/api/routes/integrations/integrations/crud.js +158 -0
  199. package/dist/api/routes/integrations/integrations/crud.js.map +1 -0
  200. package/dist/api/routes/integrations/integrations/index.d.ts +55 -0
  201. package/dist/api/routes/integrations/integrations/index.d.ts.map +1 -0
  202. package/dist/api/routes/integrations/integrations/index.js +65 -0
  203. package/dist/api/routes/integrations/integrations/index.js.map +1 -0
  204. package/dist/api/routes/integrations/integrations/invoke.d.ts +38 -0
  205. package/dist/api/routes/integrations/integrations/invoke.d.ts.map +1 -0
  206. package/dist/api/routes/integrations/integrations/invoke.js +320 -0
  207. package/dist/api/routes/integrations/integrations/invoke.js.map +1 -0
  208. package/dist/api/routes/integrations/integrations/probe.d.ts +21 -0
  209. package/dist/api/routes/integrations/integrations/probe.d.ts.map +1 -0
  210. package/dist/api/routes/integrations/integrations/probe.js +247 -0
  211. package/dist/api/routes/integrations/integrations/probe.js.map +1 -0
  212. package/dist/api/routes/integrations/invoke.d.ts +38 -0
  213. package/dist/api/routes/integrations/invoke.d.ts.map +1 -0
  214. package/dist/api/routes/integrations/invoke.js +320 -0
  215. package/dist/api/routes/integrations/invoke.js.map +1 -0
  216. package/dist/api/routes/integrations/probe.d.ts +21 -0
  217. package/dist/api/routes/integrations/probe.d.ts.map +1 -0
  218. package/dist/api/routes/integrations/probe.js +247 -0
  219. package/dist/api/routes/integrations/probe.js.map +1 -0
  220. package/dist/api/routes/integrations.d.ts.map +1 -1
  221. package/dist/api/routes/integrations.js +65 -13
  222. package/dist/api/routes/integrations.js.map +1 -1
  223. package/dist/api/routes/knowledge.d.ts.map +1 -1
  224. package/dist/api/routes/knowledge.js +13 -2
  225. package/dist/api/routes/knowledge.js.map +1 -1
  226. package/dist/api/routes/mail/_pa_wip_mail/app-password.d.ts +4 -0
  227. package/dist/api/routes/mail/_pa_wip_mail/app-password.d.ts.map +1 -0
  228. package/dist/api/routes/mail/_pa_wip_mail/app-password.js +192 -0
  229. package/dist/api/routes/mail/_pa_wip_mail/app-password.js.map +1 -0
  230. package/dist/api/routes/mail/_pa_wip_mail/body-helpers.d.ts +55 -0
  231. package/dist/api/routes/mail/_pa_wip_mail/body-helpers.d.ts.map +1 -0
  232. package/dist/api/routes/mail/_pa_wip_mail/body-helpers.js +91 -0
  233. package/dist/api/routes/mail/_pa_wip_mail/body-helpers.js.map +1 -0
  234. package/dist/api/routes/mail/_pa_wip_mail/dependencies.d.ts +36 -0
  235. package/dist/api/routes/mail/_pa_wip_mail/dependencies.d.ts.map +1 -0
  236. package/dist/api/routes/mail/_pa_wip_mail/dependencies.js +2 -0
  237. package/dist/api/routes/mail/_pa_wip_mail/dependencies.js.map +1 -0
  238. package/dist/api/routes/mail/_pa_wip_mail/gating.d.ts +45 -0
  239. package/dist/api/routes/mail/_pa_wip_mail/gating.d.ts.map +1 -0
  240. package/dist/api/routes/mail/_pa_wip_mail/gating.js +98 -0
  241. package/dist/api/routes/mail/_pa_wip_mail/gating.js.map +1 -0
  242. package/dist/api/routes/mail/_pa_wip_mail/mail/accounts.d.ts +4 -0
  243. package/dist/api/routes/mail/_pa_wip_mail/mail/accounts.d.ts.map +1 -0
  244. package/dist/api/routes/mail/_pa_wip_mail/mail/accounts.js +289 -0
  245. package/dist/api/routes/mail/_pa_wip_mail/mail/accounts.js.map +1 -0
  246. package/dist/api/routes/mail/_pa_wip_mail/mail/app-password.d.ts +4 -0
  247. package/dist/api/routes/mail/_pa_wip_mail/mail/app-password.d.ts.map +1 -0
  248. package/dist/api/routes/mail/_pa_wip_mail/mail/app-password.js +192 -0
  249. package/dist/api/routes/mail/_pa_wip_mail/mail/app-password.js.map +1 -0
  250. package/dist/api/routes/mail/_pa_wip_mail/mail/body-helpers.d.ts +55 -0
  251. package/dist/api/routes/mail/_pa_wip_mail/mail/body-helpers.d.ts.map +1 -0
  252. package/dist/api/routes/mail/_pa_wip_mail/mail/body-helpers.js +91 -0
  253. package/dist/api/routes/mail/_pa_wip_mail/mail/body-helpers.js.map +1 -0
  254. package/dist/api/routes/mail/_pa_wip_mail/mail/dependencies.d.ts +36 -0
  255. package/dist/api/routes/mail/_pa_wip_mail/mail/dependencies.d.ts.map +1 -0
  256. package/dist/api/routes/mail/_pa_wip_mail/mail/dependencies.js +2 -0
  257. package/dist/api/routes/mail/_pa_wip_mail/mail/dependencies.js.map +1 -0
  258. package/dist/api/routes/mail/_pa_wip_mail/mail/drafts.d.ts +5 -0
  259. package/dist/api/routes/mail/_pa_wip_mail/mail/drafts.d.ts.map +1 -0
  260. package/dist/api/routes/mail/_pa_wip_mail/mail/drafts.js +139 -0
  261. package/dist/api/routes/mail/_pa_wip_mail/mail/drafts.js.map +1 -0
  262. package/dist/api/routes/mail/_pa_wip_mail/mail/gating.d.ts +45 -0
  263. package/dist/api/routes/mail/_pa_wip_mail/mail/gating.d.ts.map +1 -0
  264. package/dist/api/routes/mail/_pa_wip_mail/mail/gating.js +98 -0
  265. package/dist/api/routes/mail/_pa_wip_mail/mail/gating.js.map +1 -0
  266. package/dist/api/routes/mail/_pa_wip_mail/mail/index.d.ts +18 -0
  267. package/dist/api/routes/mail/_pa_wip_mail/mail/index.d.ts.map +1 -0
  268. package/dist/api/routes/mail/_pa_wip_mail/mail/index.js +40 -0
  269. package/dist/api/routes/mail/_pa_wip_mail/mail/index.js.map +1 -0
  270. package/dist/api/routes/mail/_pa_wip_mail/mail/messages.d.ts +15 -0
  271. package/dist/api/routes/mail/_pa_wip_mail/mail/messages.d.ts.map +1 -0
  272. package/dist/api/routes/mail/_pa_wip_mail/mail/messages.js +239 -0
  273. package/dist/api/routes/mail/_pa_wip_mail/mail/messages.js.map +1 -0
  274. package/dist/api/routes/mail/_pa_wip_mail/mail/outlook-config.d.ts +4 -0
  275. package/dist/api/routes/mail/_pa_wip_mail/mail/outlook-config.d.ts.map +1 -0
  276. package/dist/api/routes/mail/_pa_wip_mail/mail/outlook-config.js +73 -0
  277. package/dist/api/routes/mail/_pa_wip_mail/mail/outlook-config.js.map +1 -0
  278. package/dist/api/routes/mail/_pa_wip_mail/mail/provider-resolver.d.ts +64 -0
  279. package/dist/api/routes/mail/_pa_wip_mail/mail/provider-resolver.d.ts.map +1 -0
  280. package/dist/api/routes/mail/_pa_wip_mail/mail/provider-resolver.js +286 -0
  281. package/dist/api/routes/mail/_pa_wip_mail/mail/provider-resolver.js.map +1 -0
  282. package/dist/api/routes/mail/_pa_wip_mail/mail/providers.d.ts +4 -0
  283. package/dist/api/routes/mail/_pa_wip_mail/mail/providers.d.ts.map +1 -0
  284. package/dist/api/routes/mail/_pa_wip_mail/mail/providers.js +73 -0
  285. package/dist/api/routes/mail/_pa_wip_mail/mail/providers.js.map +1 -0
  286. package/dist/api/routes/mail/_pa_wip_mail/mail/tags-folders.d.ts +5 -0
  287. package/dist/api/routes/mail/_pa_wip_mail/mail/tags-folders.d.ts.map +1 -0
  288. package/dist/api/routes/mail/_pa_wip_mail/mail/tags-folders.js +35 -0
  289. package/dist/api/routes/mail/_pa_wip_mail/mail/tags-folders.js.map +1 -0
  290. package/dist/api/routes/mail/_pa_wip_mail/mail/validators.d.ts +23 -0
  291. package/dist/api/routes/mail/_pa_wip_mail/mail/validators.d.ts.map +1 -0
  292. package/dist/api/routes/mail/_pa_wip_mail/mail/validators.js +131 -0
  293. package/dist/api/routes/mail/_pa_wip_mail/mail/validators.js.map +1 -0
  294. package/dist/api/routes/mail/_pa_wip_mail/provider-resolver.d.ts +64 -0
  295. package/dist/api/routes/mail/_pa_wip_mail/provider-resolver.d.ts.map +1 -0
  296. package/dist/api/routes/mail/_pa_wip_mail/provider-resolver.js +286 -0
  297. package/dist/api/routes/mail/_pa_wip_mail/provider-resolver.js.map +1 -0
  298. package/dist/api/routes/mail/_pa_wip_mail/search-health.d.ts +4 -0
  299. package/dist/api/routes/mail/_pa_wip_mail/search-health.d.ts.map +1 -0
  300. package/dist/api/routes/mail/_pa_wip_mail/search-health.js +131 -0
  301. package/dist/api/routes/mail/_pa_wip_mail/search-health.js.map +1 -0
  302. package/dist/api/routes/mail/_pa_wip_mail/validators.d.ts +23 -0
  303. package/dist/api/routes/mail/_pa_wip_mail/validators.d.ts.map +1 -0
  304. package/dist/api/routes/mail/_pa_wip_mail/validators.js +131 -0
  305. package/dist/api/routes/mail/_pa_wip_mail/validators.js.map +1 -0
  306. package/dist/api/routes/mail/accounts.d.ts +4 -0
  307. package/dist/api/routes/mail/accounts.d.ts.map +1 -0
  308. package/dist/api/routes/mail/accounts.js +289 -0
  309. package/dist/api/routes/mail/accounts.js.map +1 -0
  310. package/dist/api/routes/mail/app-password.d.ts +4 -0
  311. package/dist/api/routes/mail/app-password.d.ts.map +1 -0
  312. package/dist/api/routes/mail/app-password.js +192 -0
  313. package/dist/api/routes/mail/app-password.js.map +1 -0
  314. package/dist/api/routes/mail/body-helpers.d.ts +56 -0
  315. package/dist/api/routes/mail/body-helpers.d.ts.map +1 -0
  316. package/dist/api/routes/mail/body-helpers.js +91 -0
  317. package/dist/api/routes/mail/body-helpers.js.map +1 -0
  318. package/dist/api/routes/mail/dependencies.d.ts +36 -0
  319. package/dist/api/routes/mail/dependencies.d.ts.map +1 -0
  320. package/dist/api/routes/mail/dependencies.js +2 -0
  321. package/dist/api/routes/mail/dependencies.js.map +1 -0
  322. package/dist/api/routes/mail/drafts.d.ts +5 -0
  323. package/dist/api/routes/mail/drafts.d.ts.map +1 -0
  324. package/dist/api/routes/mail/drafts.js +139 -0
  325. package/dist/api/routes/mail/drafts.js.map +1 -0
  326. package/dist/api/routes/mail/gating.d.ts +45 -0
  327. package/dist/api/routes/mail/gating.d.ts.map +1 -0
  328. package/dist/api/routes/mail/gating.js +99 -0
  329. package/dist/api/routes/mail/gating.js.map +1 -0
  330. package/dist/api/routes/mail/index.d.ts +18 -0
  331. package/dist/api/routes/mail/index.d.ts.map +1 -0
  332. package/dist/api/routes/mail/index.js +40 -0
  333. package/dist/api/routes/mail/index.js.map +1 -0
  334. package/dist/api/routes/mail/messages.d.ts +15 -0
  335. package/dist/api/routes/mail/messages.d.ts.map +1 -0
  336. package/dist/api/routes/mail/messages.js +239 -0
  337. package/dist/api/routes/mail/messages.js.map +1 -0
  338. package/dist/api/routes/mail/outlook-config.d.ts +4 -0
  339. package/dist/api/routes/mail/outlook-config.d.ts.map +1 -0
  340. package/dist/api/routes/mail/outlook-config.js +73 -0
  341. package/dist/api/routes/mail/outlook-config.js.map +1 -0
  342. package/dist/api/routes/mail/provider-resolver.d.ts +64 -0
  343. package/dist/api/routes/mail/provider-resolver.d.ts.map +1 -0
  344. package/dist/api/routes/mail/provider-resolver.js +286 -0
  345. package/dist/api/routes/mail/provider-resolver.js.map +1 -0
  346. package/dist/api/routes/mail/providers.d.ts +4 -0
  347. package/dist/api/routes/mail/providers.d.ts.map +1 -0
  348. package/dist/api/routes/mail/providers.js +73 -0
  349. package/dist/api/routes/mail/providers.js.map +1 -0
  350. package/dist/api/routes/mail/search-health.d.ts +4 -0
  351. package/dist/api/routes/mail/search-health.d.ts.map +1 -0
  352. package/dist/api/routes/mail/search-health.js +131 -0
  353. package/dist/api/routes/mail/search-health.js.map +1 -0
  354. package/dist/api/routes/mail/tags-folders.d.ts +5 -0
  355. package/dist/api/routes/mail/tags-folders.d.ts.map +1 -0
  356. package/dist/api/routes/mail/tags-folders.js +35 -0
  357. package/dist/api/routes/mail/tags-folders.js.map +1 -0
  358. package/dist/api/routes/mail/validators.d.ts +23 -0
  359. package/dist/api/routes/mail/validators.d.ts.map +1 -0
  360. package/dist/api/routes/mail/validators.js +131 -0
  361. package/dist/api/routes/mail/validators.js.map +1 -0
  362. package/dist/api/routes/mail.d.ts.map +1 -1
  363. package/dist/api/routes/mail.js +259 -67
  364. package/dist/api/routes/mail.js.map +1 -1
  365. package/dist/api/routes/managed-tasks.d.ts.map +1 -1
  366. package/dist/api/routes/managed-tasks.js +142 -54
  367. package/dist/api/routes/managed-tasks.js.map +1 -1
  368. package/dist/api/routes/mcp.d.ts.map +1 -1
  369. package/dist/api/routes/mcp.js +115 -47
  370. package/dist/api/routes/mcp.js.map +1 -1
  371. package/dist/api/routes/metrics.d.ts +1 -1
  372. package/dist/api/routes/metrics.js +2 -2
  373. package/dist/api/routes/notion.d.ts.map +1 -1
  374. package/dist/api/routes/notion.js +230 -54
  375. package/dist/api/routes/notion.js.map +1 -1
  376. package/dist/api/routes/observations.d.ts.map +1 -1
  377. package/dist/api/routes/observations.js +40 -169
  378. package/dist/api/routes/observations.js.map +1 -1
  379. package/dist/api/routes/obsidian.d.ts.map +1 -1
  380. package/dist/api/routes/obsidian.js +193 -32
  381. package/dist/api/routes/obsidian.js.map +1 -1
  382. package/dist/api/routes/profile-questions.d.ts.map +1 -1
  383. package/dist/api/routes/profile-questions.js +19 -3
  384. package/dist/api/routes/profile-questions.js.map +1 -1
  385. package/dist/api/routes/receipts.d.ts.map +1 -1
  386. package/dist/api/routes/receipts.js +64 -24
  387. package/dist/api/routes/receipts.js.map +1 -1
  388. package/dist/api/routes/recurring-schedules.d.ts.map +1 -1
  389. package/dist/api/routes/recurring-schedules.js +243 -13
  390. package/dist/api/routes/recurring-schedules.js.map +1 -1
  391. package/dist/api/routes/repositories.d.ts.map +1 -1
  392. package/dist/api/routes/repositories.js +278 -104
  393. package/dist/api/routes/repositories.js.map +1 -1
  394. package/dist/api/routes/schedule-model-resolver.d.ts +153 -0
  395. package/dist/api/routes/schedule-model-resolver.d.ts.map +1 -0
  396. package/dist/api/routes/schedule-model-resolver.js +282 -0
  397. package/dist/api/routes/schedule-model-resolver.js.map +1 -0
  398. package/dist/api/routes/schedule-options.d.ts +25 -0
  399. package/dist/api/routes/schedule-options.d.ts.map +1 -0
  400. package/dist/api/routes/schedule-options.js +77 -0
  401. package/dist/api/routes/schedule-options.js.map +1 -0
  402. package/dist/api/routes/schedule-validation.d.ts +146 -0
  403. package/dist/api/routes/schedule-validation.d.ts.map +1 -0
  404. package/dist/api/routes/schedule-validation.js +153 -0
  405. package/dist/api/routes/schedule-validation.js.map +1 -0
  406. package/dist/api/routes/setup.d.ts.map +1 -1
  407. package/dist/api/routes/setup.js +100 -26
  408. package/dist/api/routes/setup.js.map +1 -1
  409. package/dist/api/routes/skills.d.ts.map +1 -1
  410. package/dist/api/routes/skills.js +81 -30
  411. package/dist/api/routes/skills.js.map +1 -1
  412. package/dist/api/routes/sot-bindings.d.ts.map +1 -1
  413. package/dist/api/routes/sot-bindings.js +46 -11
  414. package/dist/api/routes/sot-bindings.js.map +1 -1
  415. package/dist/api/routes/sse.d.ts.map +1 -1
  416. package/dist/api/routes/sse.js +6 -1
  417. package/dist/api/routes/sse.js.map +1 -1
  418. package/dist/api/routes/system.d.ts.map +1 -1
  419. package/dist/api/routes/system.js +15 -2
  420. package/dist/api/routes/system.js.map +1 -1
  421. package/dist/api/routes/travel-bookings.d.ts.map +1 -1
  422. package/dist/api/routes/travel-bookings.js +26 -9
  423. package/dist/api/routes/travel-bookings.js.map +1 -1
  424. package/dist/api/routes/travel-time.d.ts.map +1 -1
  425. package/dist/api/routes/travel-time.js +50 -10
  426. package/dist/api/routes/travel-time.js.map +1 -1
  427. package/dist/api/routes/wiki.d.ts.map +1 -1
  428. package/dist/api/routes/wiki.js +49 -8
  429. package/dist/api/routes/wiki.js.map +1 -1
  430. package/dist/api/server.d.ts +15 -3
  431. package/dist/api/server.d.ts.map +1 -1
  432. package/dist/api/server.js +32 -10
  433. package/dist/api/server.js.map +1 -1
  434. package/dist/bootstrap/adapters.d.ts.map +1 -1
  435. package/dist/bootstrap/adapters.js +7 -4
  436. package/dist/bootstrap/adapters.js.map +1 -1
  437. package/dist/bootstrap/api.d.ts +205 -0
  438. package/dist/bootstrap/api.d.ts.map +1 -0
  439. package/dist/bootstrap/api.js +443 -0
  440. package/dist/bootstrap/api.js.map +1 -0
  441. package/dist/bootstrap/db.d.ts +119 -0
  442. package/dist/bootstrap/db.d.ts.map +1 -0
  443. package/dist/bootstrap/db.js +294 -0
  444. package/dist/bootstrap/db.js.map +1 -0
  445. package/dist/bootstrap/event-pipeline.d.ts +308 -0
  446. package/dist/bootstrap/event-pipeline.d.ts.map +1 -0
  447. package/dist/bootstrap/event-pipeline.js +704 -0
  448. package/dist/bootstrap/event-pipeline.js.map +1 -0
  449. package/dist/bootstrap/observers.d.ts +148 -0
  450. package/dist/bootstrap/observers.d.ts.map +1 -0
  451. package/dist/bootstrap/observers.js +558 -0
  452. package/dist/bootstrap/observers.js.map +1 -0
  453. package/dist/bootstrap/schedule-helpers.d.ts +122 -0
  454. package/dist/bootstrap/schedule-helpers.d.ts.map +1 -1
  455. package/dist/bootstrap/schedule-helpers.js +202 -4
  456. package/dist/bootstrap/schedule-helpers.js.map +1 -1
  457. package/dist/config.d.ts.map +1 -1
  458. package/dist/config.js +20 -3
  459. package/dist/config.js.map +1 -1
  460. package/dist/core/abort-utils.d.ts +14 -0
  461. package/dist/core/abort-utils.d.ts.map +1 -0
  462. package/dist/core/abort-utils.js +36 -0
  463. package/dist/core/abort-utils.js.map +1 -0
  464. package/dist/core/agent-core.d.ts +22 -3
  465. package/dist/core/agent-core.d.ts.map +1 -1
  466. package/dist/core/agent-core.js +3 -1
  467. package/dist/core/agent-core.js.map +1 -1
  468. package/dist/core/backends/auth-health-monitor.js +2 -3
  469. package/dist/core/backends/auth-health-monitor.js.map +1 -1
  470. package/dist/core/backends/backend-router.d.ts +11 -1
  471. package/dist/core/backends/backend-router.d.ts.map +1 -1
  472. package/dist/core/backends/backend-router.js +97 -2
  473. package/dist/core/backends/backend-router.js.map +1 -1
  474. package/dist/core/backends/claude-code-core.d.ts +51 -0
  475. package/dist/core/backends/claude-code-core.d.ts.map +1 -1
  476. package/dist/core/backends/claude-code-core.js +134 -11
  477. package/dist/core/backends/claude-code-core.js.map +1 -1
  478. package/dist/core/backends/claude-tool-collection.js +1 -1
  479. package/dist/core/backends/codex-core.d.ts +13 -1
  480. package/dist/core/backends/codex-core.d.ts.map +1 -1
  481. package/dist/core/backends/codex-core.js +436 -22
  482. package/dist/core/backends/codex-core.js.map +1 -1
  483. package/dist/core/backends/gemini-cli-core.d.ts +5 -1
  484. package/dist/core/backends/gemini-cli-core.d.ts.map +1 -1
  485. package/dist/core/backends/gemini-cli-core.js +298 -15
  486. package/dist/core/backends/gemini-cli-core.js.map +1 -1
  487. package/dist/core/backends/install-methods.d.ts.map +1 -1
  488. package/dist/core/backends/install-methods.js +22 -0
  489. package/dist/core/backends/install-methods.js.map +1 -1
  490. package/dist/core/backends/model-registry.d.ts +9 -4
  491. package/dist/core/backends/model-registry.d.ts.map +1 -1
  492. package/dist/core/backends/model-registry.js +153 -23
  493. package/dist/core/backends/model-registry.js.map +1 -1
  494. package/dist/core/backends/native-skill-discovery-probe.d.ts +80 -0
  495. package/dist/core/backends/native-skill-discovery-probe.d.ts.map +1 -0
  496. package/dist/core/backends/native-skill-discovery-probe.js +175 -0
  497. package/dist/core/backends/native-skill-discovery-probe.js.map +1 -0
  498. package/dist/core/backends/opencode-basic-auth-fetch.d.ts +27 -0
  499. package/dist/core/backends/opencode-basic-auth-fetch.d.ts.map +1 -0
  500. package/dist/core/backends/opencode-basic-auth-fetch.js +40 -0
  501. package/dist/core/backends/opencode-basic-auth-fetch.js.map +1 -0
  502. package/dist/core/backends/opencode-config-builder.d.ts +86 -0
  503. package/dist/core/backends/opencode-config-builder.d.ts.map +1 -0
  504. package/dist/core/backends/opencode-config-builder.js +172 -0
  505. package/dist/core/backends/opencode-config-builder.js.map +1 -0
  506. package/dist/core/backends/opencode-core.d.ts +316 -0
  507. package/dist/core/backends/opencode-core.d.ts.map +1 -0
  508. package/dist/core/backends/opencode-core.js +1502 -0
  509. package/dist/core/backends/opencode-core.js.map +1 -0
  510. package/dist/core/backends/opencode-event-mapper.d.ts +133 -0
  511. package/dist/core/backends/opencode-event-mapper.d.ts.map +1 -0
  512. package/dist/core/backends/opencode-event-mapper.js +198 -0
  513. package/dist/core/backends/opencode-event-mapper.js.map +1 -0
  514. package/dist/core/backends/opencode-mcp.d.ts +82 -0
  515. package/dist/core/backends/opencode-mcp.d.ts.map +1 -0
  516. package/dist/core/backends/opencode-mcp.js +165 -0
  517. package/dist/core/backends/opencode-mcp.js.map +1 -0
  518. package/dist/core/backends/opencode-server-manager.d.ts +114 -0
  519. package/dist/core/backends/opencode-server-manager.d.ts.map +1 -0
  520. package/dist/core/backends/opencode-server-manager.js +222 -0
  521. package/dist/core/backends/opencode-server-manager.js.map +1 -0
  522. package/dist/core/backends/opencode-types.d.ts +46 -0
  523. package/dist/core/backends/opencode-types.d.ts.map +1 -0
  524. package/dist/core/backends/opencode-types.js +14 -0
  525. package/dist/core/backends/opencode-types.js.map +1 -0
  526. package/dist/core/backends/plan-presets.d.ts +18 -5
  527. package/dist/core/backends/plan-presets.d.ts.map +1 -1
  528. package/dist/core/backends/plan-presets.js +144 -23
  529. package/dist/core/backends/plan-presets.js.map +1 -1
  530. package/dist/core/backends/process-config-cascade.d.ts +35 -0
  531. package/dist/core/backends/process-config-cascade.d.ts.map +1 -1
  532. package/dist/core/backends/process-config-cascade.js +35 -1
  533. package/dist/core/backends/process-config-cascade.js.map +1 -1
  534. package/dist/core/backends/prompt-utils.d.ts.map +1 -1
  535. package/dist/core/backends/prompt-utils.js +0 -2
  536. package/dist/core/backends/prompt-utils.js.map +1 -1
  537. package/dist/core/backends/quota-reset-hints.d.ts +44 -0
  538. package/dist/core/backends/quota-reset-hints.d.ts.map +1 -0
  539. package/dist/core/backends/quota-reset-hints.js +117 -0
  540. package/dist/core/backends/quota-reset-hints.js.map +1 -0
  541. package/dist/core/bang-commands/commands-close.d.ts +24 -0
  542. package/dist/core/bang-commands/commands-close.d.ts.map +1 -0
  543. package/dist/core/bang-commands/commands-close.js +24 -0
  544. package/dist/core/bang-commands/commands-close.js.map +1 -0
  545. package/dist/core/bang-commands/commands-cost.d.ts.map +1 -1
  546. package/dist/core/bang-commands/commands-cost.js +13 -0
  547. package/dist/core/bang-commands/commands-cost.js.map +1 -1
  548. package/dist/core/bang-commands/commands-help.d.ts.map +1 -1
  549. package/dist/core/bang-commands/commands-help.js +44 -5
  550. package/dist/core/bang-commands/commands-help.js.map +1 -1
  551. package/dist/core/bang-commands/commands-report.d.ts.map +1 -1
  552. package/dist/core/bang-commands/commands-report.js +1 -0
  553. package/dist/core/bang-commands/commands-report.js.map +1 -1
  554. package/dist/core/bang-commands/commands-stop-start.d.ts.map +1 -1
  555. package/dist/core/bang-commands/commands-stop-start.js +2 -0
  556. package/dist/core/bang-commands/commands-stop-start.js.map +1 -1
  557. package/dist/core/bang-commands/commands-wiki.d.ts.map +1 -1
  558. package/dist/core/bang-commands/commands-wiki.js +12 -1
  559. package/dist/core/bang-commands/commands-wiki.js.map +1 -1
  560. package/dist/core/bang-commands/format-utils.d.ts +13 -1
  561. package/dist/core/bang-commands/format-utils.d.ts.map +1 -1
  562. package/dist/core/bang-commands/format-utils.js +21 -2
  563. package/dist/core/bang-commands/format-utils.js.map +1 -1
  564. package/dist/core/bang-commands/index.d.ts +1 -0
  565. package/dist/core/bang-commands/index.d.ts.map +1 -1
  566. package/dist/core/bang-commands/index.js +3 -0
  567. package/dist/core/bang-commands/index.js.map +1 -1
  568. package/dist/core/bang-commands/registry.d.ts +50 -0
  569. package/dist/core/bang-commands/registry.d.ts.map +1 -1
  570. package/dist/core/bang-commands/registry.js +164 -19
  571. package/dist/core/bang-commands/registry.js.map +1 -1
  572. package/dist/core/channel-timeline.d.ts +18 -1
  573. package/dist/core/channel-timeline.d.ts.map +1 -1
  574. package/dist/core/channel-timeline.js +44 -0
  575. package/dist/core/channel-timeline.js.map +1 -1
  576. package/dist/core/context/activity-view-runner.js +9 -1
  577. package/dist/core/context/activity-view-runner.js.map +1 -1
  578. package/dist/core/context/default-schedules-runner.js +44 -4
  579. package/dist/core/context/default-schedules-runner.js.map +1 -1
  580. package/dist/core/context/domain-index-runner.js +9 -1
  581. package/dist/core/context/domain-index-runner.js.map +1 -1
  582. package/dist/core/context/entity-source-rename.d.ts.map +1 -1
  583. package/dist/core/context/entity-source-rename.js +9 -1
  584. package/dist/core/context/entity-source-rename.js.map +1 -1
  585. package/dist/core/context/policy-index-runner.js +9 -1
  586. package/dist/core/context/policy-index-runner.js.map +1 -1
  587. package/dist/core/context/reconciler-runner.js +9 -1
  588. package/dist/core/context/reconciler-runner.js.map +1 -1
  589. package/dist/core/context-builder.d.ts +97 -2
  590. package/dist/core/context-builder.d.ts.map +1 -1
  591. package/dist/core/context-builder.js +303 -30
  592. package/dist/core/context-builder.js.map +1 -1
  593. package/dist/core/context-frontmatter.d.ts +6 -0
  594. package/dist/core/context-frontmatter.d.ts.map +1 -1
  595. package/dist/core/context-frontmatter.js +120 -8
  596. package/dist/core/context-frontmatter.js.map +1 -1
  597. package/dist/core/context-health.js +21 -9
  598. package/dist/core/context-health.js.map +1 -1
  599. package/dist/core/context-validation/_pa_wip_context_validation/index.d.ts +19 -0
  600. package/dist/core/context-validation/_pa_wip_context_validation/index.d.ts.map +1 -0
  601. package/dist/core/context-validation/_pa_wip_context_validation/index.js +19 -0
  602. package/dist/core/context-validation/_pa_wip_context_validation/index.js.map +1 -0
  603. package/dist/core/context-validation/_pa_wip_context_validation/prepare-write.d.ts +94 -0
  604. package/dist/core/context-validation/_pa_wip_context_validation/prepare-write.d.ts.map +1 -0
  605. package/dist/core/context-validation/_pa_wip_context_validation/prepare-write.js +130 -0
  606. package/dist/core/context-validation/_pa_wip_context_validation/prepare-write.js.map +1 -0
  607. package/dist/core/context-validation/_pa_wip_context_validation/routine-rulebook.d.ts +60 -0
  608. package/dist/core/context-validation/_pa_wip_context_validation/routine-rulebook.d.ts.map +1 -0
  609. package/dist/core/context-validation/_pa_wip_context_validation/routine-rulebook.js +156 -0
  610. package/dist/core/context-validation/_pa_wip_context_validation/routine-rulebook.js.map +1 -0
  611. package/dist/core/context-validation/_pa_wip_context_validation/section.d.ts +41 -0
  612. package/dist/core/context-validation/_pa_wip_context_validation/section.d.ts.map +1 -0
  613. package/dist/core/context-validation/_pa_wip_context_validation/section.js +82 -0
  614. package/dist/core/context-validation/_pa_wip_context_validation/section.js.map +1 -0
  615. package/dist/core/context-validation/_pa_wip_context_validation/snapshot-debounce.d.ts +52 -0
  616. package/dist/core/context-validation/_pa_wip_context_validation/snapshot-debounce.d.ts.map +1 -0
  617. package/dist/core/context-validation/_pa_wip_context_validation/snapshot-debounce.js +110 -0
  618. package/dist/core/context-validation/_pa_wip_context_validation/snapshot-debounce.js.map +1 -0
  619. package/dist/core/context-validation/_pa_wip_context_validation/today.d.ts +85 -0
  620. package/dist/core/context-validation/_pa_wip_context_validation/today.d.ts.map +1 -0
  621. package/dist/core/context-validation/_pa_wip_context_validation/today.js +162 -0
  622. package/dist/core/context-validation/_pa_wip_context_validation/today.js.map +1 -0
  623. package/dist/core/context-validation/index.d.ts +19 -0
  624. package/dist/core/context-validation/index.d.ts.map +1 -0
  625. package/dist/core/context-validation/index.js +19 -0
  626. package/dist/core/context-validation/index.js.map +1 -0
  627. package/dist/core/context-validation/prepare-write.d.ts +95 -0
  628. package/dist/core/context-validation/prepare-write.d.ts.map +1 -0
  629. package/dist/core/context-validation/prepare-write.js +135 -0
  630. package/dist/core/context-validation/prepare-write.js.map +1 -0
  631. package/dist/core/context-validation/routine-rulebook.d.ts +60 -0
  632. package/dist/core/context-validation/routine-rulebook.d.ts.map +1 -0
  633. package/dist/core/context-validation/routine-rulebook.js +156 -0
  634. package/dist/core/context-validation/routine-rulebook.js.map +1 -0
  635. package/dist/core/context-validation/section.d.ts +41 -0
  636. package/dist/core/context-validation/section.d.ts.map +1 -0
  637. package/dist/core/context-validation/section.js +82 -0
  638. package/dist/core/context-validation/section.js.map +1 -0
  639. package/dist/core/context-validation/snapshot-debounce.d.ts +52 -0
  640. package/dist/core/context-validation/snapshot-debounce.d.ts.map +1 -0
  641. package/dist/core/context-validation/snapshot-debounce.js +110 -0
  642. package/dist/core/context-validation/snapshot-debounce.js.map +1 -0
  643. package/dist/core/context-validation/today.d.ts +85 -0
  644. package/dist/core/context-validation/today.d.ts.map +1 -0
  645. package/dist/core/context-validation/today.js +168 -0
  646. package/dist/core/context-validation/today.js.map +1 -0
  647. package/dist/core/daemon-api-cli.d.ts +6 -5
  648. package/dist/core/daemon-api-cli.d.ts.map +1 -1
  649. package/dist/core/daemon-api-cli.js +73 -32
  650. package/dist/core/daemon-api-cli.js.map +1 -1
  651. package/dist/core/dispatcher-error-handling.d.ts +13 -0
  652. package/dist/core/dispatcher-error-handling.d.ts.map +1 -1
  653. package/dist/core/dispatcher-error-handling.js +69 -0
  654. package/dist/core/dispatcher-error-handling.js.map +1 -1
  655. package/dist/core/dispatcher-hourly-check.d.ts +73 -1
  656. package/dist/core/dispatcher-hourly-check.d.ts.map +1 -1
  657. package/dist/core/dispatcher-hourly-check.js +249 -151
  658. package/dist/core/dispatcher-hourly-check.js.map +1 -1
  659. package/dist/core/dispatcher-message-handler.d.ts +11 -1
  660. package/dist/core/dispatcher-message-handler.d.ts.map +1 -1
  661. package/dist/core/dispatcher-message-handler.js +165 -47
  662. package/dist/core/dispatcher-message-handler.js.map +1 -1
  663. package/dist/core/dispatcher-morning-routine.d.ts +38 -30
  664. package/dist/core/dispatcher-morning-routine.d.ts.map +1 -1
  665. package/dist/core/dispatcher-morning-routine.js +162 -104
  666. package/dist/core/dispatcher-morning-routine.js.map +1 -1
  667. package/dist/core/dispatcher-prompt.d.ts +4 -1
  668. package/dist/core/dispatcher-prompt.d.ts.map +1 -1
  669. package/dist/core/dispatcher-prompt.js +18 -2
  670. package/dist/core/dispatcher-prompt.js.map +1 -1
  671. package/dist/core/dispatcher-repository-helpers.d.ts.map +1 -1
  672. package/dist/core/dispatcher-repository-helpers.js +5 -1
  673. package/dist/core/dispatcher-repository-helpers.js.map +1 -1
  674. package/dist/core/dispatcher-result-processor.d.ts.map +1 -1
  675. package/dist/core/dispatcher-result-processor.js +9 -4
  676. package/dist/core/dispatcher-result-processor.js.map +1 -1
  677. package/dist/core/dispatcher-scheduled-tasks.d.ts +1 -1
  678. package/dist/core/dispatcher-scheduled-tasks.d.ts.map +1 -1
  679. package/dist/core/dispatcher-scheduled-tasks.js +79 -16
  680. package/dist/core/dispatcher-scheduled-tasks.js.map +1 -1
  681. package/dist/core/dispatcher-types.d.ts +84 -12
  682. package/dist/core/dispatcher-types.d.ts.map +1 -1
  683. package/dist/core/dispatcher-types.js.map +1 -1
  684. package/dist/core/dispatcher.d.ts +50 -1
  685. package/dist/core/dispatcher.d.ts.map +1 -1
  686. package/dist/core/dispatcher.js +143 -8
  687. package/dist/core/dispatcher.js.map +1 -1
  688. package/dist/core/dm-freshness-metrics.d.ts +6 -5
  689. package/dist/core/dm-freshness-metrics.d.ts.map +1 -1
  690. package/dist/core/dm-freshness-metrics.js +7 -6
  691. package/dist/core/dm-freshness-metrics.js.map +1 -1
  692. package/dist/core/evening-review-verify.d.ts +164 -0
  693. package/dist/core/evening-review-verify.d.ts.map +1 -0
  694. package/dist/core/evening-review-verify.js +637 -0
  695. package/dist/core/evening-review-verify.js.map +1 -0
  696. package/dist/core/fetch-window-prompt-loader.d.ts +47 -0
  697. package/dist/core/fetch-window-prompt-loader.d.ts.map +1 -0
  698. package/dist/core/fetch-window-prompt-loader.js +72 -0
  699. package/dist/core/fetch-window-prompt-loader.js.map +1 -0
  700. package/dist/core/management-md.d.ts.map +1 -1
  701. package/dist/core/management-md.js +23 -9
  702. package/dist/core/management-md.js.map +1 -1
  703. package/dist/core/management-registry.d.ts +13 -21
  704. package/dist/core/management-registry.d.ts.map +1 -1
  705. package/dist/core/management-registry.js +27 -48
  706. package/dist/core/management-registry.js.map +1 -1
  707. package/dist/core/metrics.d.ts +88 -1
  708. package/dist/core/metrics.d.ts.map +1 -1
  709. package/dist/core/metrics.js +78 -2
  710. package/dist/core/metrics.js.map +1 -1
  711. package/dist/core/morning/agent-journal-appender.d.ts +197 -0
  712. package/dist/core/morning/agent-journal-appender.d.ts.map +1 -0
  713. package/dist/core/morning/agent-journal-appender.js +458 -0
  714. package/dist/core/morning/agent-journal-appender.js.map +1 -0
  715. package/dist/core/morning/handoff-parser.d.ts +45 -0
  716. package/dist/core/morning/handoff-parser.d.ts.map +1 -0
  717. package/dist/core/morning/handoff-parser.js +117 -0
  718. package/dist/core/morning/handoff-parser.js.map +1 -0
  719. package/dist/core/morning/journal-skeleton-builder.d.ts +157 -0
  720. package/dist/core/morning/journal-skeleton-builder.d.ts.map +1 -0
  721. package/dist/core/morning/journal-skeleton-builder.js +303 -0
  722. package/dist/core/morning/journal-skeleton-builder.js.map +1 -0
  723. package/dist/core/morning/orchestrator.d.ts +312 -0
  724. package/dist/core/morning/orchestrator.d.ts.map +1 -0
  725. package/dist/core/morning/orchestrator.js +827 -0
  726. package/dist/core/morning/orchestrator.js.map +1 -0
  727. package/dist/core/morning/parent-audit-emitter.d.ts +82 -0
  728. package/dist/core/morning/parent-audit-emitter.d.ts.map +1 -0
  729. package/dist/core/morning/parent-audit-emitter.js +120 -0
  730. package/dist/core/morning/parent-audit-emitter.js.map +1 -0
  731. package/dist/core/morning/roadmap-skeleton-builder.d.ts +159 -0
  732. package/dist/core/morning/roadmap-skeleton-builder.d.ts.map +1 -0
  733. package/dist/core/morning/roadmap-skeleton-builder.js +338 -0
  734. package/dist/core/morning/roadmap-skeleton-builder.js.map +1 -0
  735. package/dist/core/output-language-policy.js +1 -1
  736. package/dist/core/output-language-policy.js.map +1 -1
  737. package/dist/core/policy-files.d.ts +19 -2
  738. package/dist/core/policy-files.d.ts.map +1 -1
  739. package/dist/core/policy-files.js +65 -7
  740. package/dist/core/policy-files.js.map +1 -1
  741. package/dist/core/pre-pass-freshness.d.ts +28 -0
  742. package/dist/core/pre-pass-freshness.d.ts.map +1 -0
  743. package/dist/core/pre-pass-freshness.js +10 -0
  744. package/dist/core/pre-pass-freshness.js.map +1 -0
  745. package/dist/core/previous-week-digest.d.ts +130 -0
  746. package/dist/core/previous-week-digest.d.ts.map +1 -0
  747. package/dist/core/previous-week-digest.js +257 -0
  748. package/dist/core/previous-week-digest.js.map +1 -0
  749. package/dist/core/prompts.js +3 -3
  750. package/dist/core/prompts.js.map +1 -1
  751. package/dist/core/quiet-hours-sync.d.ts.map +1 -1
  752. package/dist/core/quiet-hours-sync.js +7 -0
  753. package/dist/core/quiet-hours-sync.js.map +1 -1
  754. package/dist/core/recurrence.d.ts +13 -0
  755. package/dist/core/recurrence.d.ts.map +1 -1
  756. package/dist/core/recurrence.js +108 -13
  757. package/dist/core/recurrence.js.map +1 -1
  758. package/dist/core/release-assets.d.ts +21 -1
  759. package/dist/core/release-assets.d.ts.map +1 -1
  760. package/dist/core/release-assets.js +58 -3
  761. package/dist/core/release-assets.js.map +1 -1
  762. package/dist/core/repository-management-docs.d.ts.map +1 -1
  763. package/dist/core/repository-management-docs.js +14 -4
  764. package/dist/core/repository-management-docs.js.map +1 -1
  765. package/dist/core/review-context.d.ts.map +1 -1
  766. package/dist/core/review-context.js +29 -1
  767. package/dist/core/review-context.js.map +1 -1
  768. package/dist/core/roadmap-maintenance.d.ts +213 -0
  769. package/dist/core/roadmap-maintenance.d.ts.map +1 -0
  770. package/dist/core/roadmap-maintenance.js +706 -0
  771. package/dist/core/roadmap-maintenance.js.map +1 -0
  772. package/dist/core/roadmap-validate.d.ts +5 -0
  773. package/dist/core/roadmap-validate.d.ts.map +1 -1
  774. package/dist/core/roadmap-validate.js +6 -69
  775. package/dist/core/roadmap-validate.js.map +1 -1
  776. package/dist/core/routine-acquisition-plan.d.ts +43 -7
  777. package/dist/core/routine-acquisition-plan.d.ts.map +1 -1
  778. package/dist/core/routine-acquisition-plan.js +99 -8
  779. package/dist/core/routine-acquisition-plan.js.map +1 -1
  780. package/dist/core/routine-fetch-window-retry.d.ts +41 -2
  781. package/dist/core/routine-fetch-window-retry.d.ts.map +1 -1
  782. package/dist/core/routine-fetch-window-retry.js +91 -8
  783. package/dist/core/routine-fetch-window-retry.js.map +1 -1
  784. package/dist/core/routine-fetch-window-runner.d.ts +55 -21
  785. package/dist/core/routine-fetch-window-runner.d.ts.map +1 -1
  786. package/dist/core/routine-fetch-window-runner.js +258 -35
  787. package/dist/core/routine-fetch-window-runner.js.map +1 -1
  788. package/dist/core/routine-windows.d.ts +17 -13
  789. package/dist/core/routine-windows.d.ts.map +1 -1
  790. package/dist/core/routine-windows.js +78 -36
  791. package/dist/core/routine-windows.js.map +1 -1
  792. package/dist/core/scheduler.d.ts +121 -37
  793. package/dist/core/scheduler.d.ts.map +1 -1
  794. package/dist/core/scheduler.js +359 -80
  795. package/dist/core/scheduler.js.map +1 -1
  796. package/dist/core/session-manager.d.ts +25 -6
  797. package/dist/core/session-manager.d.ts.map +1 -1
  798. package/dist/core/session-manager.js +32 -15
  799. package/dist/core/session-manager.js.map +1 -1
  800. package/dist/core/skeleton.d.ts.map +1 -1
  801. package/dist/core/skeleton.js +23 -23
  802. package/dist/core/skeleton.js.map +1 -1
  803. package/dist/core/skills-compiler.d.ts +275 -25
  804. package/dist/core/skills-compiler.d.ts.map +1 -1
  805. package/dist/core/skills-compiler.js +844 -205
  806. package/dist/core/skills-compiler.js.map +1 -1
  807. package/dist/core/skills-manifest.d.ts +104 -0
  808. package/dist/core/skills-manifest.d.ts.map +1 -1
  809. package/dist/core/skills-manifest.js +350 -39
  810. package/dist/core/skills-manifest.js.map +1 -1
  811. package/dist/core/wiki/git-precompile.d.ts +9 -0
  812. package/dist/core/wiki/git-precompile.d.ts.map +1 -1
  813. package/dist/core/wiki/git-precompile.js +7 -1
  814. package/dist/core/wiki/git-precompile.js.map +1 -1
  815. package/dist/core/workdir.d.ts +30 -1
  816. package/dist/core/workdir.d.ts.map +1 -1
  817. package/dist/core/workdir.js +140 -15
  818. package/dist/core/workdir.js.map +1 -1
  819. package/dist/db/entities-store.d.ts +5 -5
  820. package/dist/db/entities-store.js +5 -5
  821. package/dist/db/hourly-check-signals.d.ts.map +1 -1
  822. package/dist/db/hourly-check-signals.js +121 -35
  823. package/dist/db/hourly-check-signals.js.map +1 -1
  824. package/dist/db/observations.d.ts +1 -1
  825. package/dist/db/observations.js +1 -1
  826. package/dist/db/observations.js.map +1 -1
  827. package/dist/db/recurring-schedules.d.ts +32 -1
  828. package/dist/db/recurring-schedules.d.ts.map +1 -1
  829. package/dist/db/recurring-schedules.js +29 -10
  830. package/dist/db/recurring-schedules.js.map +1 -1
  831. package/dist/db/repositories-store.d.ts +2 -1
  832. package/dist/db/repositories-store.d.ts.map +1 -1
  833. package/dist/db/repositories-store.js +38 -3
  834. package/dist/db/repositories-store.js.map +1 -1
  835. package/dist/db/schema.d.ts.map +1 -1
  836. package/dist/db/schema.js +157 -51
  837. package/dist/db/schema.js.map +1 -1
  838. package/dist/db/wiki-store.d.ts.map +1 -1
  839. package/dist/db/wiki-store.js +3 -0
  840. package/dist/db/wiki-store.js.map +1 -1
  841. package/dist/index.js +308 -1480
  842. package/dist/index.js.map +1 -1
  843. package/dist/messaging/magic-phrase.d.ts +16 -0
  844. package/dist/messaging/magic-phrase.d.ts.map +1 -1
  845. package/dist/messaging/magic-phrase.js +53 -0
  846. package/dist/messaging/magic-phrase.js.map +1 -1
  847. package/dist/messaging/owner-channels.d.ts +24 -0
  848. package/dist/messaging/owner-channels.d.ts.map +1 -1
  849. package/dist/messaging/owner-channels.js +38 -0
  850. package/dist/messaging/owner-channels.js.map +1 -1
  851. package/dist/observers/calendar-poller.d.ts +2 -0
  852. package/dist/observers/calendar-poller.d.ts.map +1 -1
  853. package/dist/observers/calendar-poller.js +76 -54
  854. package/dist/observers/calendar-poller.js.map +1 -1
  855. package/dist/observers/delegated-sync-worker.d.ts +62 -0
  856. package/dist/observers/delegated-sync-worker.d.ts.map +1 -1
  857. package/dist/observers/delegated-sync-worker.js +128 -1
  858. package/dist/observers/delegated-sync-worker.js.map +1 -1
  859. package/dist/observers/git-watcher.d.ts +22 -0
  860. package/dist/observers/git-watcher.d.ts.map +1 -1
  861. package/dist/observers/git-watcher.js +31 -7
  862. package/dist/observers/git-watcher.js.map +1 -1
  863. package/dist/observers/imminent-event-scheduler.d.ts +2 -0
  864. package/dist/observers/imminent-event-scheduler.d.ts.map +1 -1
  865. package/dist/observers/imminent-event-scheduler.js +29 -0
  866. package/dist/observers/imminent-event-scheduler.js.map +1 -1
  867. package/dist/observers/notion-poller.d.ts +2 -0
  868. package/dist/observers/notion-poller.d.ts.map +1 -1
  869. package/dist/observers/notion-poller.js +44 -6
  870. package/dist/observers/notion-poller.js.map +1 -1
  871. package/dist/observers/poll-guard.d.ts +63 -0
  872. package/dist/observers/poll-guard.d.ts.map +1 -0
  873. package/dist/observers/poll-guard.js +89 -0
  874. package/dist/observers/poll-guard.js.map +1 -0
  875. package/dist/safety/absolute-block-audit.d.ts +17 -0
  876. package/dist/safety/absolute-block-audit.d.ts.map +1 -1
  877. package/dist/safety/absolute-block-audit.js +28 -2
  878. package/dist/safety/absolute-block-audit.js.map +1 -1
  879. package/dist/safety/agent-write-tracker.d.ts +42 -1
  880. package/dist/safety/agent-write-tracker.d.ts.map +1 -1
  881. package/dist/safety/agent-write-tracker.js +81 -1
  882. package/dist/safety/agent-write-tracker.js.map +1 -1
  883. package/dist/safety/always-disallowed.d.ts +34 -0
  884. package/dist/safety/always-disallowed.d.ts.map +1 -1
  885. package/dist/safety/always-disallowed.js +114 -7
  886. package/dist/safety/always-disallowed.js.map +1 -1
  887. package/dist/safety/audit.d.ts +20 -0
  888. package/dist/safety/audit.d.ts.map +1 -1
  889. package/dist/safety/audit.js +126 -0
  890. package/dist/safety/audit.js.map +1 -1
  891. package/dist/safety/risk-classifier.d.ts +17 -1
  892. package/dist/safety/risk-classifier.d.ts.map +1 -1
  893. package/dist/safety/risk-classifier.js +75 -7
  894. package/dist/safety/risk-classifier.js.map +1 -1
  895. package/dist/safety/subprocess-block-scanner.d.ts +89 -0
  896. package/dist/safety/subprocess-block-scanner.d.ts.map +1 -0
  897. package/dist/safety/subprocess-block-scanner.js +177 -0
  898. package/dist/safety/subprocess-block-scanner.js.map +1 -0
  899. package/dist/scheduler/hourly-check-gate.d.ts +23 -9
  900. package/dist/scheduler/hourly-check-gate.d.ts.map +1 -1
  901. package/dist/scheduler/hourly-check-gate.js +11 -6
  902. package/dist/scheduler/hourly-check-gate.js.map +1 -1
  903. package/dist/secrets/backend-api-key-env.d.ts.map +1 -1
  904. package/dist/secrets/backend-api-key-env.js +1 -0
  905. package/dist/secrets/backend-api-key-env.js.map +1 -1
  906. package/dist/services/delegated-backend-invoker.d.ts.map +1 -1
  907. package/dist/services/delegated-backend-invoker.js +8 -1
  908. package/dist/services/delegated-backend-invoker.js.map +1 -1
  909. package/dist/services/delegated-invoker-audit.d.ts.map +1 -1
  910. package/dist/services/delegated-invoker-audit.js +5 -1
  911. package/dist/services/delegated-invoker-audit.js.map +1 -1
  912. package/dist/services/delegated-proxy-config.d.ts +3 -2
  913. package/dist/services/delegated-proxy-config.d.ts.map +1 -1
  914. package/dist/services/delegated-proxy-config.js.map +1 -1
  915. package/dist/services/integrations/extract-write-item-id.d.ts +5 -2
  916. package/dist/services/integrations/extract-write-item-id.d.ts.map +1 -1
  917. package/dist/services/integrations/extract-write-item-id.js.map +1 -1
  918. package/dist/services/mcp/generators/index.d.ts +1 -0
  919. package/dist/services/mcp/generators/index.d.ts.map +1 -1
  920. package/dist/services/mcp/generators/index.js +3 -0
  921. package/dist/services/mcp/generators/index.js.map +1 -1
  922. package/dist/services/mcp/sdk-observations-server.d.ts +60 -0
  923. package/dist/services/mcp/sdk-observations-server.d.ts.map +1 -0
  924. package/dist/services/mcp/sdk-observations-server.js +161 -0
  925. package/dist/services/mcp/sdk-observations-server.js.map +1 -0
  926. package/dist/services/mcp/session-materializer.d.ts.map +1 -1
  927. package/dist/services/mcp/session-materializer.js +13 -9
  928. package/dist/services/mcp/session-materializer.js.map +1 -1
  929. package/dist/services/mcp/types.d.ts +1 -0
  930. package/dist/services/mcp/types.d.ts.map +1 -1
  931. package/dist/services/notion.d.ts +19 -1
  932. package/dist/services/notion.d.ts.map +1 -1
  933. package/dist/services/notion.js +41 -2
  934. package/dist/services/notion.js.map +1 -1
  935. package/dist/services/observations-batch.d.ts +100 -0
  936. package/dist/services/observations-batch.d.ts.map +1 -0
  937. package/dist/services/observations-batch.js +258 -0
  938. package/dist/services/observations-batch.js.map +1 -0
  939. package/dist/services/voice/transcriber.d.ts +23 -0
  940. package/dist/services/voice/transcriber.d.ts.map +1 -1
  941. package/dist/services/voice/transcriber.js +55 -0
  942. package/dist/services/voice/transcriber.js.map +1 -1
  943. package/dist/settings/runtime-settings.d.ts +9 -6
  944. package/dist/settings/runtime-settings.d.ts.map +1 -1
  945. package/dist/settings/runtime-settings.js +50 -17
  946. package/dist/settings/runtime-settings.js.map +1 -1
  947. package/package.json +3 -2
  948. package/dist/api/delegated-proxy-helper.d.ts +0 -33
  949. package/dist/api/delegated-proxy-helper.d.ts.map +0 -1
  950. package/dist/api/delegated-proxy-helper.js +0 -54
  951. package/dist/api/delegated-proxy-helper.js.map +0 -1
  952. package/dist/core/roadmap-merge.d.ts +0 -7
  953. package/dist/core/roadmap-merge.d.ts.map +0 -1
  954. package/dist/core/roadmap-merge.js +0 -187
  955. package/dist/core/roadmap-merge.js.map +0 -1
  956. package/dist/db/test-schemas.d.ts +0 -23
  957. package/dist/db/test-schemas.d.ts.map +0 -1
  958. package/dist/db/test-schemas.js +0 -111
  959. package/dist/db/test-schemas.js.map +0 -1
@@ -2,23 +2,23 @@ import { Hono } from "hono";
2
2
  import { readFileSync, existsSync, statSync, readdirSync, unlinkSync, realpathSync, lstatSync, readlinkSync, } from "node:fs";
3
3
  import { basename, join, dirname, resolve, relative, isAbsolute } from "node:path";
4
4
  import { writeFileAtomically } from "../../core/atomic-write.js";
5
- import { contextPutSchema, contextPatchSchema, getAgentDayDateStr, localDateStr, nowInTimezone, } from "@aitne/shared";
5
+ import { contextPutSchema, contextPatchSchema, getAgentDayDateStr, localDateStr, } from "@aitne/shared";
6
6
  import { getContextDir } from "../../config.js";
7
7
  import { getDegradedMode } from "../../db/runtime-state.js";
8
8
  import { InMemoryTodayWriteLockManager, getTodayWriteLockTimeoutMs, } from "../../core/today-write-lock.js";
9
9
  import { InMemoryRoadmapWriteLockManager, getRoadmapWriteLockTimeoutMs, } from "../../core/roadmap-write-lock.js";
10
10
  import { CONTEXT_BASE_FILE_STEMS, CONTEXT_FILE_EXTENSIONS, } from "../../core/context-paths.js";
11
11
  import { REPAIRABLE_STUB_TARGETS, buildContextHealthReport, normalizeRepairStubPath, } from "../../core/context-health.js";
12
- import { validateContextFileFrontmatter } from "../../core/context-frontmatter.js";
12
+ import { validateDailySkeletonFrontmatter } from "../../core/context-frontmatter.js";
13
13
  import { classifyContextWriteStaleness } from "../../core/context-staleness.js";
14
14
  import { resolveTemplatesRoot } from "../../core/skeleton.js";
15
- import { parseCustomRoutineSpec, } from "../../core/custom-routine-scheduler.js";
16
- import { normalizeRoadmapForWrite, validateRoadmap, validateRoadmapTransition, } from "../../core/roadmap-validate.js";
17
15
  import { isValidYmd, } from "../../core/roadmap-horizon.js";
18
16
  import { extractRoadmapIds, generateRoadmapId, RoadmapIdGenerationError, } from "../../core/roadmap-ids.js";
19
17
  import { buildTodayAgentPlanMetadata, extractTodayAgentPlanRows, extractTodayDate, readTodayAgentPlanMetadata, } from "../../core/today-agent-plan.js";
18
+ import { SNAPSHOT_DEBOUNCE_MS, clearEntriesBefore, findSection, getAvailableSections, isLegacyTodayContent, prepareContextContentForWrite, toTodayScheduleCandidate, trimBulletEntries, validateContextContent, validateTodayContent, } from "../../core/context-validation/index.js";
20
19
  import { createLogger } from "../../logging.js";
21
20
  import { readJsonBody } from "../json-body.js";
21
+ import { composeIssue, respondWithAgentError, } from "../helpers/agent-errors.js";
22
22
  const logger = createLogger("context-api");
23
23
  const CONTEXT_BASE_FILE_STEM_SET = new Set(CONTEXT_BASE_FILE_STEMS);
24
24
  function resolveContextTarget(userPath) {
@@ -311,140 +311,6 @@ function notifyPromptContextChanged(deps, path, reason, input) {
311
311
  logger.warn({ err, path, method: input.method }, "Failed to record context_write agent_actions row (Stage C metrics)");
312
312
  }
313
313
  }
314
- /**
315
- * Normalize a section name for matching:
316
- * lowercase, spaces → underscores, strip leading ##
317
- */
318
- function normalizeSection(name) {
319
- return name
320
- .replace(/^#+\s*/, "")
321
- .toLowerCase()
322
- .replace(/\s+/g, "_");
323
- }
324
- /**
325
- * Find a section in markdown content and return its boundaries.
326
- * Returns [startOfBody, endOfBody] where body is between this ## and next ##.
327
- */
328
- function findSection(content, sectionName) {
329
- const normalized = normalizeSection(sectionName);
330
- const lines = content.split("\n");
331
- let sectionStart = -1;
332
- let headerEnd = -1;
333
- for (let i = 0; i < lines.length; i++) {
334
- if (lines[i].startsWith("## ")) {
335
- const lineNormalized = normalizeSection(lines[i]);
336
- if (lineNormalized === normalized) {
337
- sectionStart = i;
338
- const lineStart = sumLength(lines, i);
339
- const nlPos = content.indexOf("\n", lineStart);
340
- // Handle file ending without trailing newline
341
- headerEnd = nlPos === -1 ? content.length : nlPos + 1;
342
- break;
343
- }
344
- }
345
- }
346
- if (sectionStart === -1)
347
- return null;
348
- // Find end: next ## header or EOF
349
- let sectionEnd = content.length;
350
- for (let i = sectionStart + 1; i < lines.length; i++) {
351
- if (lines[i].startsWith("## ")) {
352
- sectionEnd = sumLength(lines, i);
353
- break;
354
- }
355
- }
356
- return { start: headerEnd, end: sectionEnd, headerEnd };
357
- }
358
- function sumLength(lines, upToIndex) {
359
- let len = 0;
360
- for (let i = 0; i < upToIndex; i++) {
361
- len += lines[i].length + 1; // +1 for \n
362
- }
363
- return len;
364
- }
365
- function getAvailableSections(content) {
366
- return content
367
- .split("\n")
368
- .filter((l) => l.startsWith("## "))
369
- .map((l) => normalizeSection(l));
370
- }
371
- /**
372
- * Parse a timestamp from a bullet entry like `- [2026-04-10 02:32:59] ...`
373
- * Returns the timestamp string or null if the line doesn't match.
374
- */
375
- const ENTRY_TIMESTAMP_RE = /^- \[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\]/;
376
- function parseEntryTimestamp(line) {
377
- const match = ENTRY_TIMESTAMP_RE.exec(line);
378
- return match ? match[1] : null;
379
- }
380
- /**
381
- * Remove entries whose `- [YYYY-MM-DD HH:MM:SS]` timestamp is ≤ cutoff.
382
- * Non-matching lines (blank lines, continuation lines) are preserved.
383
- * Returns the remaining section body and the count of removed entries.
384
- */
385
- function clearEntriesBefore(sectionBody, cutoff) {
386
- const lines = sectionBody.split("\n");
387
- const kept = [];
388
- let removedCount = 0;
389
- let skipContinuation = false;
390
- for (const line of lines) {
391
- const ts = parseEntryTimestamp(line);
392
- if (ts !== null) {
393
- // This is a timestamped entry
394
- if (ts <= cutoff) {
395
- removedCount++;
396
- skipContinuation = true;
397
- continue;
398
- }
399
- skipContinuation = false;
400
- kept.push(line);
401
- }
402
- else if (skipContinuation && (line.startsWith(" ") || line.trim() === "")) {
403
- // Continuation or trailing blank line of a removed entry
404
- continue;
405
- }
406
- else {
407
- skipContinuation = false;
408
- kept.push(line);
409
- }
410
- }
411
- return { remaining: kept.join("\n"), removedCount };
412
- }
413
- /**
414
- * Trim oldest bullet entries (`- ...` lines) from the top of a section
415
- * body to keep at most `maxEntries` entries. Non-bullet lines (blank
416
- * lines, non-`- ` prefixed lines) are preserved.
417
- */
418
- function trimBulletEntries(body, maxEntries) {
419
- const lines = body.split("\n");
420
- // Collect indices of bullet entry start lines
421
- const bulletIndices = [];
422
- for (let i = 0; i < lines.length; i++) {
423
- if (lines[i].startsWith("- ")) {
424
- bulletIndices.push(i);
425
- }
426
- }
427
- const excess = bulletIndices.length - maxEntries;
428
- if (excess <= 0) {
429
- return { body, trimmed: 0 };
430
- }
431
- // Remove the oldest (topmost) `excess` entries and their continuations.
432
- // Also remove blank lines between consecutive removed entries to avoid
433
- // orphaned whitespace accumulating over many trim cycles.
434
- const removeSet = new Set();
435
- for (let i = 0; i < excess; i++) {
436
- const start = bulletIndices[i];
437
- const end = i + 1 < bulletIndices.length ? bulletIndices[i + 1] : lines.length;
438
- for (let j = start; j < end; j++) {
439
- if (j === start || lines[j].startsWith(" ") || lines[j].trim() === "") {
440
- removeSet.add(j);
441
- }
442
- }
443
- }
444
- const kept = lines.filter((_, i) => !removeSet.has(i));
445
- return { body: kept.join("\n"), trimmed: excess };
446
- }
447
- const SNAPSHOT_DEBOUNCE_MS = 5 * 60 * 1000; // 5 minutes
448
314
  /**
449
315
  * Cap on the JSON body accepted by the Context PUT/PATCH endpoints.
450
316
  *
@@ -494,12 +360,18 @@ export function createContextRoutes(deps) {
494
360
  app.use("/context/*", async (c, next) => {
495
361
  const state = getDegradedMode(db);
496
362
  if (state) {
497
- return c.json({
498
- error: "primary_vault_unreachable",
499
- reason: state.reason,
500
- path: state.path,
501
- since: state.since,
502
- }, 503);
363
+ return respondWithAgentError(c, 503, [
364
+ composeIssue("context.vault_unreachable", {
365
+ field: "primaryVault",
366
+ received: { reason: state.reason, path: state.path, since: state.since },
367
+ }),
368
+ ], {
369
+ legacyFields: {
370
+ reason: state.reason,
371
+ path: state.path,
372
+ since: state.since,
373
+ },
374
+ });
503
375
  }
504
376
  // Phase 2 — global context-write gate engaged during a
505
377
  // /api/setup/migrate-context run. Refuses WRITES (not reads)
@@ -508,11 +380,17 @@ export function createContextRoutes(deps) {
508
380
  const writeMethods = new Set(["POST", "PUT", "PATCH", "DELETE"]);
509
381
  if (deps.contextWriteGate?.isEngaged() && writeMethods.has(c.req.method)) {
510
382
  const gateState = deps.contextWriteGate.getState();
511
- return c.json({
512
- error: "migration_in_progress",
513
- reason: gateState.reason,
514
- since: gateState.since,
515
- }, 503);
383
+ return respondWithAgentError(c, 503, [
384
+ composeIssue("context.migration_in_progress", {
385
+ field: "method",
386
+ received: { method: c.req.method, reason: gateState.reason, since: gateState.since },
387
+ }),
388
+ ], {
389
+ legacyFields: {
390
+ reason: gateState.reason,
391
+ since: gateState.since,
392
+ },
393
+ });
516
394
  }
517
395
  await next();
518
396
  });
@@ -581,10 +459,12 @@ export function createContextRoutes(deps) {
581
459
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
582
460
  return {
583
461
  ok: false,
584
- response: c.json({
585
- error: "validation_error",
586
- message: "JSON body must be an object.",
587
- }, 400),
462
+ response: respondWithAgentError(c, 400, [
463
+ composeIssue("context.body_not_object", {
464
+ field: "body",
465
+ received: parsed === null ? "null" : Array.isArray(parsed) ? "array" : typeof parsed,
466
+ }),
467
+ ]),
588
468
  };
589
469
  }
590
470
  return { ok: true, body: parsed };
@@ -594,7 +474,12 @@ export function createContextRoutes(deps) {
594
474
  logger.warn({ path: c.req.path, method: c.req.method, detail }, "Request rejected — body is not valid JSON");
595
475
  return {
596
476
  ok: false,
597
- response: c.json({ error: "invalid_json_body", message: detail }, 400),
477
+ response: respondWithAgentError(c, 400, [
478
+ composeIssue("context.invalid_json_body", {
479
+ field: "body",
480
+ received: detail,
481
+ }),
482
+ ]),
598
483
  };
599
484
  }
600
485
  }
@@ -603,7 +488,12 @@ export function createContextRoutes(deps) {
603
488
  app.post("/context/lock/morning-routine", (c) => {
604
489
  const result = morningRoutineLock.acquire();
605
490
  if (!result.ok) {
606
- return c.json({ error: "lock_held", holder: result.holder }, 409);
491
+ return respondWithAgentError(c, 409, [
492
+ composeIssue("context.lock_held", {
493
+ field: "morningRoutineLock",
494
+ received: { holder: result.holder },
495
+ }),
496
+ ]);
607
497
  }
608
498
  return c.json({ status: "acquired", lockId: result.lockId });
609
499
  });
@@ -614,7 +504,12 @@ export function createContextRoutes(deps) {
614
504
  if (lockId && morningRoutineLock.release(lockId)) {
615
505
  return c.json({ status: "released" });
616
506
  }
617
- return c.json({ error: "lock_not_held" }, 400);
507
+ return respondWithAgentError(c, 400, [
508
+ composeIssue("context.lock_not_held", {
509
+ field: "lockId",
510
+ received: lockId ?? "<missing>",
511
+ }),
512
+ ]);
618
513
  });
619
514
  // POST /context/lock/roadmap — Acquire exclusive roadmap write lock
620
515
  // Dispatcher auto-acquires this for `routine.roadmap_refresh`; other
@@ -623,7 +518,12 @@ export function createContextRoutes(deps) {
623
518
  app.post("/context/lock/roadmap", (c) => {
624
519
  const result = roadmapWriteLock.acquire();
625
520
  if (!result.ok) {
626
- return c.json({ error: "roadmap_write_lock_held", holder: result.holder }, 409);
521
+ return respondWithAgentError(c, 409, [
522
+ composeIssue("context.roadmap_write_lock_held", {
523
+ field: "roadmapWriteLock",
524
+ received: { holder: result.holder },
525
+ }),
526
+ ]);
627
527
  }
628
528
  return c.json({ status: "acquired", lockId: result.lockId });
629
529
  });
@@ -634,7 +534,12 @@ export function createContextRoutes(deps) {
634
534
  if (lockId && roadmapWriteLock.release(lockId)) {
635
535
  return c.json({ status: "released" });
636
536
  }
637
- return c.json({ error: "lock_not_held" }, 400);
537
+ return respondWithAgentError(c, 400, [
538
+ composeIssue("context.lock_not_held", {
539
+ field: "lockId",
540
+ received: lockId ?? "<missing>",
541
+ }),
542
+ ]);
638
543
  });
639
544
  // POST /context/roadmap/id — Mint a stable daemon-owned roadmap entry id.
640
545
  app.post("/context/roadmap/id", async (c) => {
@@ -642,7 +547,12 @@ export function createContextRoutes(deps) {
642
547
  const lockId = c.req.header("X-Lock-Id");
643
548
  if (!roadmapWriteLock.isHeldBy(lockId)) {
644
549
  logger.info({ path: "roadmap" }, "Roadmap id mint rejected — roadmap write lock held");
645
- return c.json({ error: "roadmap_write_lock_held" }, 409);
550
+ return respondWithAgentError(c, 409, [
551
+ composeIssue("context.roadmap_write_lock_held", {
552
+ field: "X-Lock-Id",
553
+ received: lockId ?? "<missing>",
554
+ }),
555
+ ]);
646
556
  }
647
557
  }
648
558
  const parsedBody = await readOptionalJsonBody(c);
@@ -653,16 +563,23 @@ export function createContextRoutes(deps) {
653
563
  ? requestedDate
654
564
  : localDateStr(new Date(), config.timezone || undefined);
655
565
  if (!isValidYmd(creationDate)) {
656
- return c.json({
657
- error: "validation_error",
658
- message: "creationDate must be YYYY-MM-DD.",
659
- }, 400);
566
+ return respondWithAgentError(c, 400, [
567
+ composeIssue("context.creation_date_invalid", {
568
+ field: "creationDate",
569
+ received: creationDate,
570
+ }),
571
+ ]);
660
572
  }
661
573
  return withWriteLock(() => {
662
574
  const contextDir = getCurrentContextDir();
663
575
  const fullPath = safePath(contextDir, "roadmap");
664
576
  if (!fullPath) {
665
- return c.json({ error: "invalid_path", path: "roadmap" }, 400);
577
+ return respondWithAgentError(c, 400, [
578
+ composeIssue("context.path_invalid", {
579
+ field: "path",
580
+ received: "roadmap",
581
+ }),
582
+ ]);
666
583
  }
667
584
  const content = existsSync(fullPath)
668
585
  ? readFileSync(fullPath, "utf-8")
@@ -679,7 +596,12 @@ export function createContextRoutes(deps) {
679
596
  }
680
597
  catch (err) {
681
598
  if (err instanceof RoadmapIdGenerationError) {
682
- return c.json({ error: "roadmap_id_generation_failed" }, 503);
599
+ return respondWithAgentError(c, 503, [
600
+ composeIssue("context.roadmap_id_generation_failed", {
601
+ field: "id",
602
+ received: { existingIdCount: existingIds.length, creationDate },
603
+ }),
604
+ ]);
683
605
  }
684
606
  throw err;
685
607
  }
@@ -697,7 +619,12 @@ export function createContextRoutes(deps) {
697
619
  const contextDir = getCurrentContextDir();
698
620
  const todayPath = join(contextDir, "today.md");
699
621
  if (!existsSync(todayPath)) {
700
- return c.json({ error: "not_found", path: "today" }, 404);
622
+ return respondWithAgentError(c, 404, [
623
+ composeIssue("context.path_not_found", {
624
+ field: "path",
625
+ received: "today",
626
+ }),
627
+ ]);
701
628
  }
702
629
  const content = readFileSync(todayPath, "utf-8");
703
630
  const dateStr = content.match(/^#.*(\d{4}-\d{2}-\d{2})/)?.[1] ??
@@ -720,46 +647,87 @@ export function createContextRoutes(deps) {
720
647
  // row back onto disk. The current on-disk file (if any) is snapshotted
721
648
  // first so the restore itself is reversible from the Knowledge page.
722
649
  app.post("/context/restore-snapshot/:id", (c) => {
723
- const id = Number(c.req.param("id"));
650
+ const idRaw = c.req.param("id");
651
+ const id = Number(idRaw);
724
652
  if (!Number.isSafeInteger(id) || id <= 0) {
725
- return c.json({ error: "invalid_id" }, 400);
653
+ return respondWithAgentError(c, 400, [
654
+ composeIssue("context.snapshot_id_invalid", {
655
+ field: "id",
656
+ received: idRaw,
657
+ }),
658
+ ]);
726
659
  }
727
660
  const row = db
728
661
  .prepare("SELECT id, file_path, content FROM md_file_snapshots WHERE id = ?")
729
662
  .get(id);
730
663
  if (!row) {
731
- return c.json({ error: "not_found" }, 404);
664
+ return respondWithAgentError(c, 404, [
665
+ composeIssue("context.snapshot_not_found", {
666
+ field: "id",
667
+ received: id,
668
+ }),
669
+ ]);
732
670
  }
733
671
  const target = resolveContextTarget(row.file_path);
734
672
  const path = target.base;
735
673
  const contextDir = getCurrentContextDir();
736
674
  const fullPath = safePath(contextDir, row.file_path);
737
675
  if (!fullPath) {
738
- return c.json({ error: "invalid_path", path }, 400);
676
+ return respondWithAgentError(c, 400, [
677
+ composeIssue("context.path_invalid", {
678
+ field: "path",
679
+ received: path,
680
+ }),
681
+ ]);
739
682
  }
740
683
  if (!isWriteAllowed(path, "PUT") && !isWriteAllowed(path, "PATCH")) {
741
684
  logger.warn({ path, method: "RESTORE" }, "Snapshot restore forbidden");
742
- return c.json({ error: "forbidden", path, method: "RESTORE" }, 403);
685
+ return respondWithAgentError(c, 403, [
686
+ composeIssue("context.write_forbidden", {
687
+ field: "path",
688
+ received: { path, method: "RESTORE" },
689
+ }),
690
+ ]);
743
691
  }
744
692
  if (morningRoutineLock.getHolder() && path === "today") {
745
693
  const lockId = c.req.header("X-Lock-Id");
746
694
  if (!morningRoutineLock.isHeldBy(lockId)) {
747
695
  logger.info({ path }, "Snapshot restore rejected — morning routine lock held");
748
- return c.json({ error: "morning_routine_lock_held" }, 409);
696
+ return respondWithAgentError(c, 409, [
697
+ composeIssue("context.morning_routine_lock_held", {
698
+ field: "X-Lock-Id",
699
+ received: lockId ?? "<missing>",
700
+ }),
701
+ ]);
749
702
  }
750
703
  }
751
704
  if (roadmapWriteLock.getHolder() && path === "roadmap") {
752
705
  const lockId = c.req.header("X-Lock-Id");
753
706
  if (!roadmapWriteLock.isHeldBy(lockId)) {
754
707
  logger.info({ path }, "Snapshot restore rejected — roadmap write lock held");
755
- return c.json({ error: "roadmap_write_lock_held" }, 409);
708
+ return respondWithAgentError(c, 409, [
709
+ composeIssue("context.roadmap_write_lock_held", {
710
+ field: "X-Lock-Id",
711
+ received: lockId ?? "<missing>",
712
+ }),
713
+ ]);
756
714
  }
757
715
  }
758
716
  const contentError = validateContextContent(target, row.content, {
759
717
  skipFrontmatterValidation: true,
760
718
  });
761
719
  if (contentError) {
762
- return c.json({ error: "validation_error", message: contentError.message }, contentError.status);
720
+ return respondWithAgentError(c, contentError.status, [
721
+ composeIssue("context.content_validation_failed", {
722
+ field: contentError.path ?? "content",
723
+ received: contentError.message,
724
+ }),
725
+ ], {
726
+ legacyFields: {
727
+ message: contentError.message,
728
+ path: contentError.path,
729
+ },
730
+ });
763
731
  }
764
732
  return withWriteLock(() => {
765
733
  let backupSnapshotId = null;
@@ -811,7 +779,12 @@ export function createContextRoutes(deps) {
811
779
  "inbox",
812
780
  ];
813
781
  if (!allowedDirs.includes(dir)) {
814
- return c.json({ error: "invalid_directory", allowed: allowedDirs }, 400);
782
+ return respondWithAgentError(c, 400, [
783
+ composeIssue("context.directory_invalid", {
784
+ field: "dir",
785
+ received: { dir, allowed: allowedDirs },
786
+ }),
787
+ ]);
815
788
  }
816
789
  const contextDir = getCurrentContextDir();
817
790
  const dirPath = join(contextDir, dir);
@@ -908,10 +881,20 @@ export function createContextRoutes(deps) {
908
881
  const contextDir = getCurrentContextDir();
909
882
  const fullPath = safePath(contextDir, "today");
910
883
  if (!fullPath) {
911
- return c.json({ error: "invalid_path", path: "today" }, 400);
884
+ return respondWithAgentError(c, 400, [
885
+ composeIssue("context.path_invalid", {
886
+ field: "path",
887
+ received: "today",
888
+ }),
889
+ ]);
912
890
  }
913
891
  if (!existsSync(fullPath)) {
914
- return c.json({ error: "not_found", path: "today" }, 404);
892
+ return respondWithAgentError(c, 404, [
893
+ composeIssue("context.path_not_found", {
894
+ field: "path",
895
+ received: "today",
896
+ }),
897
+ ]);
915
898
  }
916
899
  const content = readFileSync(fullPath, "utf-8");
917
900
  const validationError = validateTodayContent(content);
@@ -1006,41 +989,57 @@ export function createContextRoutes(deps) {
1006
989
  return parsedBody.response;
1007
990
  const rawPath = parsedBody.body.path;
1008
991
  if (typeof rawPath !== "string") {
1009
- return c.json({
1010
- error: "validation_error",
1011
- message: "path must be a string.",
1012
- }, 400);
992
+ return respondWithAgentError(c, 400, [
993
+ composeIssue("context.path_required", {
994
+ field: "path",
995
+ received: typeof rawPath,
996
+ }),
997
+ ], {
998
+ // repair-stub previously returned `error: "validation_error"` for
999
+ // the missing-path branch (not `"path_required"`); preserve that
1000
+ // legacy alias so dashboard / older tests don't break.
1001
+ legacyErrorCode: "validation_error",
1002
+ });
1013
1003
  }
1014
1004
  const normalizedPath = normalizeRepairStubPath(rawPath);
1015
1005
  if (!normalizedPath || !REPAIRABLE_STUB_TARGETS.has(normalizedPath)) {
1016
- return c.json({
1017
- error: "unsupported_stub_target",
1018
- message: "Only known context stub targets can be repaired.",
1019
- path: rawPath,
1020
- }, 400);
1006
+ return respondWithAgentError(c, 400, [
1007
+ composeIssue("context.stub_target_unsupported", {
1008
+ field: "path",
1009
+ received: { path: rawPath, allowed: Array.from(REPAIRABLE_STUB_TARGETS) },
1010
+ }),
1011
+ ]);
1021
1012
  }
1022
1013
  const templatesRoot = resolveTemplatesRoot(config.workspaceDir);
1023
1014
  /* c8 ignore next 9 — resolveTemplatesRoot always succeeds via import.meta.url
1024
1015
  * fallback in tests; the 503 branch requires a broken install where the
1025
1016
  * agent-assets directory is absent from every candidate path. */
1026
1017
  if (!templatesRoot) {
1027
- return c.json({
1028
- error: "templates_unavailable",
1029
- message: "agent-assets/templates could not be located.",
1030
- }, 503);
1018
+ return respondWithAgentError(c, 503, [
1019
+ composeIssue("context.template_unavailable", {
1020
+ field: "templatesRoot",
1021
+ received: "<unresolved>",
1022
+ }),
1023
+ ]);
1031
1024
  }
1032
1025
  const templatePath = join(templatesRoot, normalizedPath);
1033
1026
  if (!existsSync(templatePath)) {
1034
- return c.json({
1035
- error: "template_not_found",
1036
- message: `No template exists for ${normalizedPath}.`,
1037
- path: normalizedPath,
1038
- }, 404);
1027
+ return respondWithAgentError(c, 404, [
1028
+ composeIssue("context.template_not_found", {
1029
+ field: "path",
1030
+ received: { path: normalizedPath, templatePath },
1031
+ }),
1032
+ ]);
1039
1033
  }
1040
1034
  const contextDir = getCurrentContextDir();
1041
1035
  const fullPath = safePath(contextDir, normalizedPath);
1042
1036
  if (!fullPath) {
1043
- return c.json({ error: "invalid_path", path: normalizedPath }, 400);
1037
+ return respondWithAgentError(c, 400, [
1038
+ composeIssue("context.path_invalid", {
1039
+ field: "path",
1040
+ received: normalizedPath,
1041
+ }),
1042
+ ]);
1044
1043
  }
1045
1044
  return withWriteLock(() => {
1046
1045
  if (existsSync(fullPath)) {
@@ -1077,16 +1076,31 @@ export function createContextRoutes(deps) {
1077
1076
  app.get("/context/*", (c) => {
1078
1077
  const rawPath = c.req.path.replace("/api/context/", "");
1079
1078
  if (!rawPath || rawPath === "list") {
1080
- return c.json({ error: "path_required" }, 400);
1079
+ return respondWithAgentError(c, 400, [
1080
+ composeIssue("context.path_required", {
1081
+ field: "path",
1082
+ received: rawPath === "list" ? "list (route ambiguous with /list/:dir)" : "<empty>",
1083
+ }),
1084
+ ]);
1081
1085
  }
1082
1086
  const path = normalizeContextPath(rawPath);
1083
1087
  const contextDir = getCurrentContextDir();
1084
1088
  const fullPath = safePath(contextDir, rawPath);
1085
1089
  if (!fullPath) {
1086
- return c.json({ error: "invalid_path", path }, 400);
1090
+ return respondWithAgentError(c, 400, [
1091
+ composeIssue("context.path_invalid", {
1092
+ field: "path",
1093
+ received: path,
1094
+ }),
1095
+ ]);
1087
1096
  }
1088
1097
  if (!existsSync(fullPath)) {
1089
- return c.json({ error: "not_found", path }, 404);
1098
+ return respondWithAgentError(c, 404, [
1099
+ composeIssue("context.path_not_found", {
1100
+ field: "path",
1101
+ received: path,
1102
+ }),
1103
+ ]);
1090
1104
  }
1091
1105
  const content = readFileSync(fullPath, "utf-8");
1092
1106
  const stat = statSync(fullPath);
@@ -1123,18 +1137,33 @@ export function createContextRoutes(deps) {
1123
1137
  const contextDir = getCurrentContextDir();
1124
1138
  const fullPath = safePath(contextDir, rawPath);
1125
1139
  if (!fullPath) {
1126
- return c.json({ error: "invalid_path", path }, 400);
1140
+ return respondWithAgentError(c, 400, [
1141
+ composeIssue("context.path_invalid", {
1142
+ field: "path",
1143
+ received: path,
1144
+ }),
1145
+ ]);
1127
1146
  }
1128
1147
  if (!isWriteAllowed(path, "PUT")) {
1129
1148
  logger.warn({ path, method: "PUT" }, "Context write forbidden");
1130
- return c.json({ error: "forbidden", path, method: "PUT" }, 403);
1149
+ return respondWithAgentError(c, 403, [
1150
+ composeIssue("context.write_forbidden", {
1151
+ field: "path",
1152
+ received: { path, method: "PUT" },
1153
+ }),
1154
+ ]);
1131
1155
  }
1132
1156
  // Morning Routine lock: reject writes to today while lock is held
1133
1157
  if (morningRoutineLock.getHolder() && path === "today") {
1134
1158
  const lockId = c.req.header("X-Lock-Id");
1135
1159
  if (!morningRoutineLock.isHeldBy(lockId)) {
1136
1160
  logger.info({ path }, "Context PUT rejected — morning routine lock held");
1137
- return c.json({ error: "morning_routine_lock_held" }, 409);
1161
+ return respondWithAgentError(c, 409, [
1162
+ composeIssue("context.morning_routine_lock_held", {
1163
+ field: "X-Lock-Id",
1164
+ received: lockId ?? "<missing>",
1165
+ }),
1166
+ ]);
1138
1167
  }
1139
1168
  }
1140
1169
  // Roadmap write lock: reject writes to roadmap while another session holds it
@@ -1142,7 +1171,12 @@ export function createContextRoutes(deps) {
1142
1171
  const lockId = c.req.header("X-Lock-Id");
1143
1172
  if (!roadmapWriteLock.isHeldBy(lockId)) {
1144
1173
  logger.info({ path }, "Context PUT rejected — roadmap write lock held");
1145
- return c.json({ error: "roadmap_write_lock_held" }, 409);
1174
+ return respondWithAgentError(c, 409, [
1175
+ composeIssue("context.roadmap_write_lock_held", {
1176
+ field: "X-Lock-Id",
1177
+ received: lockId ?? "<missing>",
1178
+ }),
1179
+ ]);
1146
1180
  }
1147
1181
  }
1148
1182
  const parsedBody = await readJsonBody(c, { maxBytes: CONTEXT_BODY_MAX_BYTES });
@@ -1151,7 +1185,12 @@ export function createContextRoutes(deps) {
1151
1185
  const body = parsedBody.body;
1152
1186
  const parsed = contextPutSchema.safeParse(body);
1153
1187
  if (!parsed.success) {
1154
- return c.json({ error: "validation_error", details: parsed.error }, 400);
1188
+ return respondWithAgentError(c, 400, [
1189
+ composeIssue("context.body_not_object", {
1190
+ field: "body",
1191
+ received: parsed.error.issues.map((i) => i.message).join("; "),
1192
+ }),
1193
+ ]);
1155
1194
  }
1156
1195
  const roadmapValidationOff = isRoadmapValidationDisabled(path, c.req.header("X-Roadmap-Validation"));
1157
1196
  if (roadmapValidationOff) {
@@ -1167,11 +1206,37 @@ export function createContextRoutes(deps) {
1167
1206
  expectedAgentDay,
1168
1207
  });
1169
1208
  if (!preflight.ok) {
1170
- return c.json({
1171
- error: "validation_error",
1172
- message: preflight.message,
1173
- path: preflight.path,
1174
- }, preflight.status);
1209
+ return respondWithAgentError(c, preflight.status, [
1210
+ composeIssue("context.content_validation_failed", {
1211
+ field: preflight.path ?? "content",
1212
+ received: preflight.message,
1213
+ }),
1214
+ ], {
1215
+ legacyFields: {
1216
+ message: preflight.message,
1217
+ path: preflight.path,
1218
+ },
1219
+ });
1220
+ }
1221
+ // morning-routine-optimization.md §"PUT /api/context/daily/<date>
1222
+ // skeleton-preservation validator" — only runs once generic
1223
+ // frontmatter validation (type/owner/updated/H1) has passed.
1224
+ // Returns per-field structured drift errors for the five
1225
+ // skeleton-owned frontmatter fields (date, weekday,
1226
+ // agent_generated, calendar_events, messages_handled) so Stage B
1227
+ // can fix every missing/malformed field in a single retry rather
1228
+ // than discovering them one at a time. Body is NOT validated —
1229
+ // Stage B authors body per rules/journal-format.md.
1230
+ if (target.base.startsWith("daily/")) {
1231
+ const dailyRelativePath = `${target.base}${target.ext}`;
1232
+ const driftErrors = validateDailySkeletonFrontmatter(preflight.content, dailyRelativePath);
1233
+ if (driftErrors.length > 0) {
1234
+ return respondWithAgentError(c, 422, driftErrors.map((drift) => composeIssue("context.daily_skeleton_field_drift", {
1235
+ field: drift.field,
1236
+ received: drift.received ?? "<missing>",
1237
+ expected: drift.expected,
1238
+ })));
1239
+ }
1175
1240
  }
1176
1241
  const sessionId = c.req.header("X-Session-Id");
1177
1242
  return withWriteLock(() => {
@@ -1182,11 +1247,12 @@ export function createContextRoutes(deps) {
1182
1247
  // outer existsSync check and then sequentially overwrite.
1183
1248
  if (CREATE_ONLY_PUT.has(path) && existsSync(fullPath)) {
1184
1249
  logger.warn({ path }, "Context PUT rejected — file exists, use PATCH to append");
1185
- return c.json({
1186
- error: "append_only",
1187
- message: `${path} already exists. Use PATCH to append new sections.`,
1188
- path,
1189
- }, 409);
1250
+ return respondWithAgentError(c, 409, [
1251
+ composeIssue("context.append_only_violation", {
1252
+ field: "path",
1253
+ received: { path, hint: `Use PATCH to append new sections to ${path}.` },
1254
+ }),
1255
+ ]);
1190
1256
  }
1191
1257
  // Optimistic concurrency check: if client supplied expectedMtime,
1192
1258
  // compare against the current file. On mismatch, return 409 with
@@ -1202,7 +1268,16 @@ export function createContextRoutes(deps) {
1202
1268
  parsed.data.expectedMtime !== currentMtime) {
1203
1269
  logger.info({ path, expectedMtime: parsed.data.expectedMtime, currentMtime }, "Context PUT conflict");
1204
1270
  return c.json({
1271
+ ok: false,
1205
1272
  error: "conflict",
1273
+ summary: `PUT conflict on ${path}: expectedMtime ${parsed.data.expectedMtime} did not match current ${currentMtime}. GET the file, replay your change, and retry.`,
1274
+ errors: [
1275
+ composeIssue("context.write_conflict", {
1276
+ field: "expectedMtime",
1277
+ received: { expectedMtime: parsed.data.expectedMtime, currentMtime },
1278
+ }),
1279
+ ],
1280
+ retryable: true,
1206
1281
  currentMtime,
1207
1282
  currentContent: existing,
1208
1283
  }, 409);
@@ -1216,11 +1291,17 @@ export function createContextRoutes(deps) {
1216
1291
  expectedAgentDay,
1217
1292
  });
1218
1293
  if (!prepared.ok) {
1219
- return c.json({
1220
- error: "validation_error",
1221
- message: prepared.message,
1222
- path: prepared.path,
1223
- }, prepared.status);
1294
+ return respondWithAgentError(c, prepared.status, [
1295
+ composeIssue("context.content_validation_failed", {
1296
+ field: prepared.path ?? "content",
1297
+ received: prepared.message,
1298
+ }),
1299
+ ], {
1300
+ legacyFields: {
1301
+ message: prepared.message,
1302
+ path: prepared.path,
1303
+ },
1304
+ });
1224
1305
  }
1225
1306
  contentToWrite = prepared.content;
1226
1307
  snapshotId = saveSnapshot(path, existing, "api_put", true, sessionId);
@@ -1228,7 +1309,16 @@ export function createContextRoutes(deps) {
1228
1309
  else if (parsed.data.expectedMtime !== undefined) {
1229
1310
  // Client expected a specific mtime but the file is gone
1230
1311
  return c.json({
1312
+ ok: false,
1231
1313
  error: "conflict",
1314
+ summary: `PUT conflict on ${path}: expectedMtime ${parsed.data.expectedMtime} but file no longer exists.`,
1315
+ errors: [
1316
+ composeIssue("context.write_conflict", {
1317
+ field: "expectedMtime",
1318
+ received: { expectedMtime: parsed.data.expectedMtime, currentMtime: "" },
1319
+ }),
1320
+ ],
1321
+ retryable: true,
1232
1322
  currentMtime: "",
1233
1323
  currentContent: "",
1234
1324
  }, 409);
@@ -1261,18 +1351,33 @@ export function createContextRoutes(deps) {
1261
1351
  const contextDir = getCurrentContextDir();
1262
1352
  const fullPath = safePath(contextDir, rawPath);
1263
1353
  if (!fullPath) {
1264
- return c.json({ error: "invalid_path", path }, 400);
1354
+ return respondWithAgentError(c, 400, [
1355
+ composeIssue("context.path_invalid", {
1356
+ field: "path",
1357
+ received: path,
1358
+ }),
1359
+ ]);
1265
1360
  }
1266
1361
  if (!isWriteAllowed(path, "PATCH")) {
1267
1362
  logger.warn({ path, method: "PATCH" }, "Context write forbidden");
1268
- return c.json({ error: "forbidden", path, method: "PATCH" }, 403);
1363
+ return respondWithAgentError(c, 403, [
1364
+ composeIssue("context.write_forbidden", {
1365
+ field: "path",
1366
+ received: { path, method: "PATCH" },
1367
+ }),
1368
+ ]);
1269
1369
  }
1270
1370
  // Morning Routine lock: reject writes to today while lock is held
1271
1371
  if (morningRoutineLock.getHolder() && path === "today") {
1272
1372
  const lockId = c.req.header("X-Lock-Id");
1273
1373
  if (!morningRoutineLock.isHeldBy(lockId)) {
1274
1374
  logger.info({ path }, "Context PATCH rejected — morning routine lock held");
1275
- return c.json({ error: "morning_routine_lock_held" }, 409);
1375
+ return respondWithAgentError(c, 409, [
1376
+ composeIssue("context.morning_routine_lock_held", {
1377
+ field: "X-Lock-Id",
1378
+ received: lockId ?? "<missing>",
1379
+ }),
1380
+ ]);
1276
1381
  }
1277
1382
  }
1278
1383
  // Roadmap write lock: reject writes to roadmap while another session holds it
@@ -1280,7 +1385,12 @@ export function createContextRoutes(deps) {
1280
1385
  const lockId = c.req.header("X-Lock-Id");
1281
1386
  if (!roadmapWriteLock.isHeldBy(lockId)) {
1282
1387
  logger.info({ path }, "Context PATCH rejected — roadmap write lock held");
1283
- return c.json({ error: "roadmap_write_lock_held" }, 409);
1388
+ return respondWithAgentError(c, 409, [
1389
+ composeIssue("context.roadmap_write_lock_held", {
1390
+ field: "X-Lock-Id",
1391
+ received: lockId ?? "<missing>",
1392
+ }),
1393
+ ]);
1284
1394
  }
1285
1395
  }
1286
1396
  const parsedBody = await readJsonBody(c, { maxBytes: CONTEXT_BODY_MAX_BYTES });
@@ -1289,13 +1399,20 @@ export function createContextRoutes(deps) {
1289
1399
  const body = parsedBody.body;
1290
1400
  const parsed = contextPatchSchema.safeParse(body);
1291
1401
  if (!parsed.success) {
1292
- return c.json({ error: "validation_error", details: parsed.error }, 400);
1402
+ return respondWithAgentError(c, 400, [
1403
+ composeIssue("context.body_not_object", {
1404
+ field: "body",
1405
+ received: parsed.error.issues.map((i) => i.message).join("; "),
1406
+ }),
1407
+ ]);
1293
1408
  }
1294
1409
  if (target.ext === ".base") {
1295
- return c.json({
1296
- error: "unsupported_operation",
1297
- message: "PATCH is not supported for .base files; use PUT to replace the file.",
1298
- }, 400);
1410
+ return respondWithAgentError(c, 400, [
1411
+ composeIssue("context.unsupported_operation", {
1412
+ field: "method",
1413
+ received: { method: "PATCH", ext: ".base", hint: "Use PUT to replace .base files." },
1414
+ }),
1415
+ ]);
1299
1416
  }
1300
1417
  const { section, mode, content: newContent, cutoff, maxEntries } = parsed.data;
1301
1418
  const sessionId = c.req.header("X-Session-Id");
@@ -1308,7 +1425,12 @@ export function createContextRoutes(deps) {
1308
1425
  : undefined;
1309
1426
  return withWriteLock(() => {
1310
1427
  if (!existsSync(fullPath)) {
1311
- return c.json({ error: "not_found", path }, 404);
1428
+ return respondWithAgentError(c, 404, [
1429
+ composeIssue("context.path_not_found", {
1430
+ field: "path",
1431
+ received: path,
1432
+ }),
1433
+ ]);
1312
1434
  }
1313
1435
  const fileContent = readFileSync(fullPath, "utf-8");
1314
1436
  // ── append_to_file: append content to end of file (no section lookup) ──
@@ -1329,11 +1451,17 @@ export function createContextRoutes(deps) {
1329
1451
  expectedAgentDay,
1330
1452
  });
1331
1453
  if (!prepared.ok) {
1332
- return c.json({
1333
- error: "validation_error",
1334
- message: prepared.message,
1335
- path: prepared.path,
1336
- }, prepared.status);
1454
+ return respondWithAgentError(c, prepared.status, [
1455
+ composeIssue("context.content_validation_failed", {
1456
+ field: prepared.path ?? "content",
1457
+ received: prepared.message,
1458
+ }),
1459
+ ], {
1460
+ legacyFields: {
1461
+ message: prepared.message,
1462
+ path: prepared.path,
1463
+ },
1464
+ });
1337
1465
  }
1338
1466
  saveSnapshot(path, fileContent, "api_patch", false, sessionId);
1339
1467
  writeFileAtomically(fullPath, prepared.content);
@@ -1358,11 +1486,18 @@ export function createContextRoutes(deps) {
1358
1486
  // ── Section-based modes: require section lookup ──
1359
1487
  const sectionBounds = findSection(fileContent, section);
1360
1488
  if (!sectionBounds) {
1361
- return c.json({
1362
- error: "section_not_found",
1363
- section,
1364
- availableSections: getAvailableSections(fileContent),
1365
- }, 400);
1489
+ const availableSections = getAvailableSections(fileContent);
1490
+ return respondWithAgentError(c, 400, [
1491
+ composeIssue("context.section_not_found", {
1492
+ field: "section",
1493
+ received: { section, availableSections },
1494
+ }),
1495
+ ], {
1496
+ legacyFields: {
1497
+ section,
1498
+ availableSections,
1499
+ },
1500
+ });
1366
1501
  }
1367
1502
  let updated;
1368
1503
  const before = fileContent.slice(0, sectionBounds.start);
@@ -1394,10 +1529,13 @@ export function createContextRoutes(deps) {
1394
1529
  // Schema refinements validate format, but defense-in-depth for
1395
1530
  // direct API callers that bypass schema validation.
1396
1531
  if (!cutoff || !/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(cutoff)) {
1397
- return c.json({
1398
- error: "cutoff_required",
1399
- message: "clear_before requires cutoff in 'YYYY-MM-DD HH:MM:SS' format (zero-padded)",
1400
- }, 400);
1532
+ return respondWithAgentError(c, 400, [
1533
+ composeIssue("context.cutoff_required", {
1534
+ field: "cutoff",
1535
+ received: cutoff ?? "<missing>",
1536
+ expected: "'YYYY-MM-DD HH:MM:SS' format (zero-padded)",
1537
+ }),
1538
+ ]);
1401
1539
  }
1402
1540
  const clearResult = clearEntriesBefore(currentBody, cutoff);
1403
1541
  updated = before + clearResult.remaining + after;
@@ -1415,11 +1553,17 @@ export function createContextRoutes(deps) {
1415
1553
  expectedAgentDay,
1416
1554
  });
1417
1555
  if (!prepared.ok) {
1418
- return c.json({
1419
- error: "validation_error",
1420
- message: prepared.message,
1421
- path: prepared.path,
1422
- }, prepared.status);
1556
+ return respondWithAgentError(c, prepared.status, [
1557
+ composeIssue("context.content_validation_failed", {
1558
+ field: prepared.path ?? "content",
1559
+ received: prepared.message,
1560
+ }),
1561
+ ], {
1562
+ legacyFields: {
1563
+ message: prepared.message,
1564
+ path: prepared.path,
1565
+ },
1566
+ });
1423
1567
  }
1424
1568
  // Force snapshot on replace (bypass debounce) to ensure recovery
1425
1569
  // from accidental overwrites. Other modes use normal debounce.
@@ -1455,15 +1599,30 @@ export function createContextRoutes(deps) {
1455
1599
  const contextDir = getCurrentContextDir();
1456
1600
  const fullPath = safePath(contextDir, path);
1457
1601
  if (!fullPath) {
1458
- return c.json({ error: "invalid_path", path }, 400);
1602
+ return respondWithAgentError(c, 400, [
1603
+ composeIssue("context.path_invalid", {
1604
+ field: "path",
1605
+ received: path,
1606
+ }),
1607
+ ]);
1459
1608
  }
1460
1609
  if (!isWriteAllowed(path, "DELETE")) {
1461
1610
  logger.warn({ path, method: "DELETE" }, "Context delete forbidden");
1462
- return c.json({ error: "forbidden", path, method: "DELETE" }, 403);
1611
+ return respondWithAgentError(c, 403, [
1612
+ composeIssue("context.write_forbidden", {
1613
+ field: "path",
1614
+ received: { path, method: "DELETE" },
1615
+ }),
1616
+ ]);
1463
1617
  }
1464
1618
  return withWriteLock(() => {
1465
1619
  if (!existsSync(fullPath)) {
1466
- return c.json({ error: "not_found", path }, 404);
1620
+ return respondWithAgentError(c, 404, [
1621
+ composeIssue("context.path_not_found", {
1622
+ field: "path",
1623
+ received: path,
1624
+ }),
1625
+ ]);
1467
1626
  }
1468
1627
  const existing = readFileSync(fullPath, "utf-8");
1469
1628
  const snapshotId = saveSnapshot(path, existing, "api_delete", true);
@@ -1478,311 +1637,9 @@ export function createContextRoutes(deps) {
1478
1637
  });
1479
1638
  return app;
1480
1639
  }
1481
- function validateContextContent(target, content, options) {
1482
- if (target.base === "today") {
1483
- const message = validateTodayContent(content, {
1484
- allowLegacyToday: options?.allowLegacyToday ?? false,
1485
- expectedAgentDay: options?.expectedAgentDay,
1486
- });
1487
- return message ? { message, status: 400 } : null;
1488
- }
1489
- if (target.base === "roadmap") {
1490
- const result = validateRoadmap(content);
1491
- if (!result.ok && result.error) {
1492
- return {
1493
- message: formatRoadmapValidationError(result.error),
1494
- status: 400,
1495
- path: result.error.path,
1496
- };
1497
- }
1498
- return null;
1499
- }
1500
- if (target.base.startsWith("routines/custom/")) {
1501
- const slug = target.base.slice("routines/custom/".length);
1502
- const result = parseCustomRoutineSpec(slug, content);
1503
- if (!result.ok) {
1504
- return {
1505
- message: explainCustomRoutineValidationError(result.error),
1506
- status: 400,
1507
- };
1508
- }
1509
- return null;
1510
- }
1511
- if (target.base.startsWith("routines/") && target.base !== "routines/_index") {
1512
- const message = validateBuiltInRoutineRulebook(target.base, content);
1513
- return message ? { message, status: 400 } : null;
1514
- }
1515
- const relativePath = `${target.base}${target.ext}`;
1516
- if (!options?.skipFrontmatterValidation) {
1517
- const frontmatterError = validateContextFileFrontmatter(content, relativePath);
1518
- if (frontmatterError) {
1519
- return { message: frontmatterError.message, status: 422 };
1520
- }
1521
- }
1522
- if (target.ext !== ".base")
1523
- return null;
1524
- const message = validateBaseYamlSyntax(content);
1525
- return message ? { message, status: 400 } : null;
1526
- }
1527
- const TODAY_REQUIRED_SECTIONS = [
1528
- "User Schedule",
1529
- "User Tasks",
1530
- "Agent Plan",
1531
- "Agent Notes",
1532
- "Agent Log",
1533
- "Handoff",
1534
- ];
1535
- const TODAY_H1_RE = /^# \d{4}-\d{2}-\d{2}(?: \([^)]+\))?$/;
1536
- const TODAY_DAY_TYPE_RE = /^> Day type: (Weekday|Weekend) \| Work focus: (on|off) \| Study focus: (on|off) \| Personal focus: (on|off)$/;
1537
- function isLegacyTodayContent(content) {
1538
- const lines = content.split(/\r?\n/);
1539
- return (lines[0] ?? "").trim() === "# Today";
1540
- }
1541
- function validateTodayContent(content, options = {}) {
1542
- if (options.allowLegacyToday && isLegacyTodayContent(content))
1543
- return null;
1544
- const lines = content.split(/\r?\n/);
1545
- const firstLine = (lines[0] ?? "").trim();
1546
- if (!TODAY_H1_RE.test(firstLine)) {
1547
- return ("today.md line 1 must be `# YYYY-MM-DD (day-of-week)`. " +
1548
- "The date and dashes are ASCII English; only the weekday inside " +
1549
- "`(...)` may be localized. Do NOT translate the literal `# ` prefix " +
1550
- "or change the date separator. See the today skill for the full " +
1551
- "skeleton contract.");
1552
- }
1553
- if (!TODAY_DAY_TYPE_RE.test((lines[1] ?? "").trim())) {
1554
- return ("today.md line 2 must be `> Day type: Weekday|Weekend | Work focus: on|off | Study focus: on|off | Personal focus: on|off`. " +
1555
- "This line is parsed by every downstream event handler — keep it " +
1556
- "exact English ASCII with the casing, pipe separators (` | `), and " +
1557
- "leading `> ` shown above. Do NOT translate `Day type` / `Weekday` / " +
1558
- "`Work focus` / `on` / `off` etc. into the user's primary_language; " +
1559
- "the `<output_language_policy>` skeleton-precedence rule covers this " +
1560
- "line. Example: " +
1561
- "`> Day type: Weekday | Work focus: on | Study focus: on | Personal focus: on`.");
1562
- }
1563
- // Agent-day-date check — rejects wrong-date H1 with a clear error echoing
1564
- // both values. Without this, a wrong-date PUT silently succeeds (regex
1565
- // passes) and the dispatcher's post-run hasCurrentAgentDayTodayMd() check
1566
- // schedules a retry while the same session still has the prompt context
1567
- // loaded, wasting a heavy-tier turn cycle. With this guard the agent gets
1568
- // immediate feedback and corrects in-session.
1569
- if (options.expectedAgentDay) {
1570
- // TODAY_H1_RE already matched, so the YYYY-MM-DD capture is guaranteed.
1571
- // No optional-chain — the regex precondition guarantees `[1]` is set.
1572
- const writtenDate = firstLine.match(/^# (\d{4}-\d{2}-\d{2})/)[1];
1573
- if (writtenDate !== options.expectedAgentDay) {
1574
- return (`today.md line 1 date '${writtenDate}' does not match the current ` +
1575
- `agent-day date '${options.expectedAgentDay}'. ` +
1576
- `Use the date from <current_agent_day date="..."> in your prompt context — ` +
1577
- `the agent-day differs from calendar today before the day-boundary hour.`);
1578
- }
1579
- }
1580
- let previousSectionIndex = 1;
1581
- for (const section of TODAY_REQUIRED_SECTIONS) {
1582
- const index = lines.findIndex((line, lineIndex) => lineIndex > previousSectionIndex && line.trim() === `## ${section}`);
1583
- if (index < 0) {
1584
- return `today.md requires \`## ${section}\` in canonical order.`;
1585
- }
1586
- previousSectionIndex = index;
1587
- }
1588
- const parsed = extractTodayAgentPlanRows(content);
1589
- if (parsed.invalidRows.length > 0) {
1590
- const first = parsed.invalidRows[0];
1591
- return (`today.md Agent Plan line ${first.line} must match ` +
1592
- `\`- [ ] HH:MM <action> [work|study|personal|home] →DM|→notify|→check-in|→wake\`. ` +
1593
- `Got: ${JSON.stringify(first.raw)}`);
1594
- }
1595
- return null;
1596
- }
1597
- function toTodayScheduleCandidate(row, timezone) {
1598
- const scheduledAt = parseScheduleDate(row.scheduled_for);
1599
- if (Number.isNaN(scheduledAt.getTime()))
1600
- return null;
1601
- const local = nowInTimezone(timezone, scheduledAt);
1602
- const localDate = `${local.year}-${String(local.month).padStart(2, "0")}-${String(local.day).padStart(2, "0")}`;
1603
- const localTime = `${String(local.hours).padStart(2, "0")}:${String(local.minutes).padStart(2, "0")}`;
1604
- return {
1605
- id: row.id,
1606
- scheduledFor: row.scheduled_for,
1607
- localDate,
1608
- localTime,
1609
- taskType: row.task_type,
1610
- status: row.status,
1611
- description: row.task_description,
1612
- taskContext: parseJsonObject(row.task_context),
1613
- };
1614
- }
1615
- function parseScheduleDate(value) {
1616
- return new Date(value.includes("T") ? value : value.replace(" ", "T") + "Z");
1617
- }
1618
- function parseJsonObject(raw) {
1619
- if (!raw)
1620
- return {};
1621
- try {
1622
- const parsed = JSON.parse(raw);
1623
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
1624
- return parsed;
1625
- }
1626
- }
1627
- catch {
1628
- // Ignore corrupt metadata for reconciliation diagnostics.
1629
- }
1630
- return {};
1631
- }
1632
- function prepareContextContentForWrite(target, content, options) {
1633
- if (target.base !== "roadmap") {
1634
- const contentError = validateContextContent(target, content, {
1635
- allowLegacyToday: options?.allowLegacyToday,
1636
- expectedAgentDay: options?.expectedAgentDay,
1637
- });
1638
- if (contentError) {
1639
- return {
1640
- ok: false,
1641
- message: contentError.message,
1642
- status: contentError.status,
1643
- path: contentError.path,
1644
- };
1645
- }
1646
- return { ok: true, content };
1647
- }
1648
- if (options?.disableRoadmapValidation) {
1649
- return { ok: true, content };
1650
- }
1651
- const normalized = normalizeRoadmapForWrite(content, {
1652
- timezone: options?.timezone,
1653
- defaultLongTermPlanSource: options?.defaultLongTermPlanSource ?? "manual",
1654
- });
1655
- const result = validateRoadmap(normalized.content);
1656
- if (!result.ok && result.error) {
1657
- return {
1658
- ok: false,
1659
- message: formatRoadmapValidationError(result.error),
1660
- status: 400,
1661
- path: result.error.path,
1662
- };
1663
- }
1664
- if (options?.previousRoadmapContent !== undefined) {
1665
- const transition = validateRoadmapTransition(options.previousRoadmapContent, normalized.content, {
1666
- today: options.today,
1667
- timezone: options.timezone,
1668
- });
1669
- if (!transition.ok && transition.error) {
1670
- return {
1671
- ok: false,
1672
- message: formatRoadmapValidationError(transition.error),
1673
- status: 400,
1674
- path: transition.error.path,
1675
- };
1676
- }
1677
- }
1678
- return { ok: true, content: normalized.content };
1679
- }
1680
- function formatRoadmapValidationError(error) {
1681
- const line = error.line ? `line ${error.line}: ` : "";
1682
- return `${line}${error.message}`;
1683
- }
1684
- function validateBuiltInRoutineRulebook(path, content) {
1685
- const frontmatter = extractRoutineFrontmatter(content);
1686
- if (frontmatter === null) {
1687
- return "Routine rulebooks require YAML frontmatter.";
1688
- }
1689
- const expectedSlug = path.slice("routines/".length);
1690
- const typeRaw = readRoutineFrontmatterScalar(frontmatter, "type");
1691
- if (!typeRaw) {
1692
- return "Routine rulebooks require `type: rule` in frontmatter.";
1693
- }
1694
- if (typeRaw !== "rule") {
1695
- return "Routine rulebooks must declare `type: rule`.";
1696
- }
1697
- const slugRaw = readRoutineFrontmatterScalar(frontmatter, "slug");
1698
- if (!slugRaw) {
1699
- return "Routine rulebooks require a `slug` frontmatter field.";
1700
- }
1701
- if (slugRaw !== expectedSlug) {
1702
- return `Routine rulebook slug must match the filename (${expectedSlug}).`;
1703
- }
1704
- if (!/^##\s+Checks\s*$/m.test(content)) {
1705
- return "Routine rulebooks require a `## Checks` section.";
1706
- }
1707
- return null;
1708
- }
1709
- function explainCustomRoutineValidationError(error) {
1710
- switch (error.kind) {
1711
- case "missing_field":
1712
- return `Custom routine files require \`${error.field}\` in frontmatter.`;
1713
- case "invalid_cron":
1714
- return `Invalid cron expression: \`${error.value}\`.`;
1715
- case "invalid_slug":
1716
- return `Custom routine slug is invalid or does not match the filename: \`${error.value}\`.`;
1717
- case "invalid_type":
1718
- return `Custom routines must declare \`type: rule\`, got \`${error.value}\`.`;
1719
- case "invalid_process_key":
1720
- return `Custom routine \`process_key\` must match the filename-derived key, got \`${error.value}\`.`;
1721
- case "invalid_enabled":
1722
- return `Custom routine \`enabled\` must be \`true\` or \`false\`, got \`${error.value}\`.`;
1723
- case "invalid_tier":
1724
- return `Custom routine \`backend_tier\` must be \`light\` or \`heavy\`, got \`${error.value}\`.`;
1725
- case "invalid_budget":
1726
- return `Custom routine \`max_budget_usd\` must be a positive number, got \`${error.value}\`.`;
1727
- case "missing_checks_section":
1728
- return "Custom routines require a `## Checks` section.";
1729
- case "no_frontmatter":
1730
- return "Custom routines require YAML frontmatter.";
1731
- }
1732
- }
1733
- function extractRoutineFrontmatter(content) {
1734
- if (!content.startsWith("---\n") && !content.startsWith("---\r\n")) {
1735
- return null;
1736
- }
1737
- const afterOpen = content.startsWith("---\r\n") ? 5 : 4;
1738
- const endIdx = content.indexOf("\n---", afterOpen - 1);
1739
- if (endIdx < 0)
1740
- return null;
1741
- return content.slice(afterOpen, endIdx);
1742
- }
1743
- function readRoutineFrontmatterScalar(frontmatter, field) {
1744
- const re = new RegExp(`^${field}\\s*:\\s*(.+?)\\s*$`, "m");
1745
- const match = frontmatter.match(re);
1746
- if (!match)
1747
- return null;
1748
- let value = match[1].trim();
1749
- if ((value.startsWith('"') && value.endsWith('"')) ||
1750
- (value.startsWith("'") && value.endsWith("'"))) {
1751
- value = value.slice(1, -1);
1752
- }
1753
- return value;
1754
- }
1755
- function validateBaseYamlSyntax(content) {
1756
- if (content.trim().length === 0) {
1757
- return ".base files must not be empty.";
1758
- }
1759
- const lines = content.split("\n");
1760
- let sawMeaningfulLine = false;
1761
- for (let index = 0; index < lines.length; index++) {
1762
- const raw = lines[index];
1763
- const lineNo = index + 1;
1764
- if (raw.includes("\t")) {
1765
- return `.base YAML may not contain tab indentation (line ${lineNo}).`;
1766
- }
1767
- const trimmed = raw.trim();
1768
- if (!trimmed || trimmed.startsWith("#"))
1769
- continue;
1770
- sawMeaningfulLine = true;
1771
- const indent = raw.length - raw.trimStart().length;
1772
- if (indent % 2 !== 0) {
1773
- return `.base YAML uses 2-space indentation (line ${lineNo}).`;
1774
- }
1775
- const isListItem = /^-\s+\S/.test(trimmed);
1776
- const isMapping = /^[^:#][^:]*:\s*(?:.*)?$/.test(trimmed);
1777
- if (!isListItem && !isMapping) {
1778
- return `Invalid .base YAML structure on line ${lineNo}.`;
1779
- }
1780
- }
1781
- if (!sawMeaningfulLine) {
1782
- return ".base files must contain at least one mapping entry.";
1783
- }
1784
- return null;
1785
- }
1786
- // Export for testing
1787
- export { normalizeSection, findSection, isWriteAllowed, safePath, resolveContextTarget, validateBaseYamlSyntax, validateTodayContent, clearEntriesBefore, trimBulletEntries, parseEntryTimestamp, };
1640
+ // Path/permission helpers stay test-exported until PR 4 moves them into
1641
+ // `routes/context/{path-resolve,permissions}.ts`. The validator surface
1642
+ // previously exported here now lives in `core/context-validation/` and
1643
+ // is tested at its source.
1644
+ export { isWriteAllowed, safePath, resolveContextTarget };
1788
1645
  //# sourceMappingURL=context.js.map