@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
@@ -1,10 +1,11 @@
1
1
  import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync, } from "node:fs";
2
2
  import { dirname, join, relative } from "node:path";
3
3
  import { APP_NAME, BACKEND_IDS, INTEGRATION_DESCRIPTORS, INTEGRATION_KEYS, applyIntegrationModeFilter, collectSessionDeniedTools, filterDeniedToolsForBackend, selectSkillVariantFile, selectTaskFlowVariantSuffix, substituteBrandTokens, } from "@aitne/shared";
4
- import { getProfileForEvent, getProfileForProcess, getSkillsForEvent, getSkillsForProcess } from "./skills-manifest.js";
4
+ import { getProfileForEvent, getProfileForProcess, resolveSkillManifest, resolveSkillManifestForProcess, } from "./skills-manifest.js";
5
5
  import { applyCharacterBlockRewrite, buildCharacterBlock } from "./character-block.js";
6
6
  import { applyOutputLanguagePointerRewrite, renderOutputLanguagePolicyPointer, } from "./output-language-policy.js";
7
7
  import { createLogger } from "../logging.js";
8
+ import { loadFetchWindowSystemPrompt } from "./fetch-window-prompt-loader.js";
8
9
  import { substituteIntegrationRoutingTables } from "./management-md.js";
9
10
  import { loadCurationDeclaration, } from "./skill-curation/declarations.js";
10
11
  import { listBuiltinSlugs, resolveBuiltinSkillDir, } from "./skill-source-paths.js";
@@ -13,6 +14,18 @@ import { hasCurationAnchors, spliceCurationAnchors, } from "./skill-curation/spl
13
14
  // Exported so tests can spy on `logger.warn` (e.g. the missing-reference
14
15
  // branch of `renderReferenceIncludes`). Production callers do not import it.
15
16
  export const logger = createLogger("skills-compiler");
17
+ // docs/design/appendices/fetch-window-cost-reduction.md Phase 1.5 — single shared constant
18
+ // for the pre-pass process key. Typed as `ProcessKey` (not the inferred
19
+ // string literal) so a rename in `@aitne/shared/process-key.ts` lights up
20
+ // here rather than silently dead-branching the slim materializer.
21
+ const FETCH_WINDOW_PROCESS_KEY = "routine.fetch_window";
22
+ // Single skill kept in the slim fetch_window CLI session: the
23
+ // `observations` SKILL.md is the POST contract for
24
+ // `/api/observations/batch` and the fetcher's only structural assertion.
25
+ // The other skills the wide path inlines (`mail`, `notion`,
26
+ // `external-services`, `attach`) are already restated by the integration
27
+ // partial the runner inlines into the user prompt.
28
+ const FETCH_WINDOW_SLIM_SKILL = "observations";
16
29
  /**
17
30
  * Check whether the skill AND task-flow variants a given integration would
18
31
  * require when delegated to `delegatedBackend` are all present on disk.
@@ -151,7 +164,7 @@ function missingVariantsForMode(workspaceDir, integrationKey, pinnedState) {
151
164
  // required.
152
165
  const sessionBackendsToCheck = pinnedState.mode === "native"
153
166
  ? [pinnedState.nativeBackend]
154
- : BACKEND_IDS;
167
+ : BACKEND_IDS.filter((backend) => backend !== "opencode");
155
168
  // De-dup with sets — the same file path can come up under multiple
156
169
  // session backends when descriptors share a slug.
157
170
  const skills = new Set();
@@ -357,9 +370,20 @@ export class SkillsCompiler {
357
370
  const profileName = params.processKey
358
371
  ? getProfileForProcess(params.processKey)
359
372
  : getProfileForEvent(params.eventType);
373
+ // `evening-review-slimdown.md` §2.1 — route through the predicate-aware
374
+ // wrapper so the evening rulebook gate (and any future per-event
375
+ // predicate) is consulted exactly once per session, at materialization
376
+ // time. The wrapper passes non-conditional events through verbatim, so
377
+ // every other process key keeps its old behaviour.
378
+ const manifestOpts = {
379
+ ...(params.contextDir ? { contextDir: params.contextDir } : {}),
380
+ ...(params.db !== undefined ? { db: params.db } : {}),
381
+ ...(params.messageText !== undefined ? { messageText: params.messageText } : {}),
382
+ };
383
+ const hasManifestOpts = Object.keys(manifestOpts).length > 0;
360
384
  const manifestSkills = params.processKey
361
- ? getSkillsForProcess(params.processKey)
362
- : getSkillsForEvent(params.eventType);
385
+ ? resolveSkillManifestForProcess(params.processKey, hasManifestOpts ? manifestOpts : undefined)
386
+ : resolveSkillManifest(params.eventType, hasManifestOpts ? manifestOpts : undefined);
363
387
  // Custom bang command override: when the dispatcher passes a slug array
364
388
  // we use it verbatim, ignoring the manifest. Empty array is allowed and
365
389
  // means "no skills." `null` keeps manifest behavior — the override is a
@@ -378,13 +402,32 @@ export class SkillsCompiler {
378
402
  // adds their first account mid-session (0→N transition). Filtering
379
403
  // here would leave the skill dir absent forever since refresh only
380
404
  // writes into existing dirs.
405
+ // docs/design/appendices/opencode-backend.md §6.5 / Phase 4 — opencode discovers
406
+ // skills via cwd auto-discovery from `.claude/skills/` (V2) AND uses
407
+ // a per-process agent file at `.opencode/agent/<slug>.md` (V5,
408
+ // singular `agent/`). Routing through `materializeCliSession` would
409
+ // inline skill bodies into AGENTS.md, which we explicitly do NOT
410
+ // want for opencode (skills are auto-discovered by the `skill` tool).
381
411
  if (params.backendId === "claude") {
382
412
  this.materializeClaudeSession(params.sessionDir, profileName, skills, profileBodyOverride, params.processKey ?? params.eventType, params.wikiWorkspaceName);
383
413
  }
414
+ else if (params.backendId === "opencode") {
415
+ this.materializeOpencodeSession(params.sessionDir, profileName, skills, profileBodyOverride, params.processKey ?? params.eventType, params.wikiWorkspaceName);
416
+ }
384
417
  else {
385
418
  this.materializeCliSession(params.sessionDir, profileName, skills, params.backendId, params.processKey ?? params.eventType, profileBodyOverride, params.wikiWorkspaceName);
386
419
  }
387
- return { profile: profileName, skills };
420
+ // docs/design/appendices/fetch-window-cost-reduction.md Phase 1.5 the slim
421
+ // CLI materializer drops every manifest skill except `observations`.
422
+ // The Claude path is wide for fetch_window today (Phase 1 swaps only
423
+ // the system prompt, not the workdir layout). Report what was
424
+ // actually written so log lines / callers see truth, not the
425
+ // manifest's pre-narrow list.
426
+ const effectiveSkills = params.backendId !== "claude"
427
+ && (params.processKey ?? params.eventType) === FETCH_WINDOW_PROCESS_KEY
428
+ ? [FETCH_WINDOW_SLIM_SKILL]
429
+ : skills;
430
+ return { profile: profileName, skills: effectiveSkills };
388
431
  }
389
432
  /** Read raw profile .md without safety injection. */
390
433
  readProfile(profileName) {
@@ -492,8 +535,39 @@ export class SkillsCompiler {
492
535
  mkdirSync(dirname(join(sessionDir, "CLAUDE.md")), { recursive: true });
493
536
  writeFileSync(join(sessionDir, "CLAUDE.md"), profileContent, "utf-8");
494
537
  }
538
+ this.writeSkillsDir(sessionDir, join(".claude", "skills"), skillSlugs, "claude", processKey, wikiWorkspaceName);
539
+ }
540
+ /**
541
+ * docs/design/appendices/skills-unification.md Phase 1 — per-backend skill-dir writer.
542
+ *
543
+ * Writes `<sessionDir>/<destSkillsRootRelative>/<slug>/SKILL.md` for each
544
+ * slug, applying the full per-skill transformation pipeline:
545
+ * variant resolution → brand tokens → partial / reference inlining →
546
+ * service strip → mode filter → deny filter → curation splice → mail
547
+ * `accounts.md`. The destination directory is the only thing that varies
548
+ * across backends:
549
+ *
550
+ * - Claude → `.claude/skills`
551
+ * - OpenCode → `.opencode/skills`
552
+ * - Codex → `.codex/skills`
553
+ * - Gemini → `.gemini/skills`
554
+ *
555
+ * For Codex sessions, this method ALSO prepends a one-line read-sensitive
556
+ * banner to each materialised SKILL.md whose body references a read-
557
+ * sensitive `/api/*` endpoint (those endpoints 401 on Codex because the
558
+ * Codex backend does not hold the read-sensitive token). The banner
559
+ * points the agent at the `## Read-sensitive endpoints are UNAVAILABLE`
560
+ * section already rendered into `AGENTS.md`.
561
+ *
562
+ * Returns the list of slugs that ended up on disk (slugs whose variant
563
+ * resolved to `null` for same-backend native MCP and slugs whose source
564
+ * SKILL.md was missing are excluded). Callers use this list to render
565
+ * the `<skill-index>` block from a stable, post-materialisation source.
566
+ */
567
+ writeSkillsDir(sessionDir, destSkillsRootRelative, skillSlugs, sessionBackend, processKey, wikiWorkspaceName) {
568
+ const materialised = [];
495
569
  const skillsRoot = this.getSourceSkillsRoot();
496
- const destSkillsRoot = join(sessionDir, ".claude", "skills");
570
+ const destSkillsRoot = join(sessionDir, destSkillsRootRelative);
497
571
  mkdirSync(destSkillsRoot, { recursive: true });
498
572
  // Re-materialize cleanup: a previous turn (especially one with a wider
499
573
  // skill set or a different custom-command override) may have left
@@ -504,11 +578,19 @@ export class SkillsCompiler {
504
578
  // `syncAllUserSkills` is the authoritative writer for that subset.
505
579
  pruneStaleBuiltinSkillDirs(destSkillsRoot, skillsRoot, skillSlugs);
506
580
  for (const skillSlug of skillSlugs) {
581
+ // docs/design/appendices/opencode-backend.md §10 D6 / Phase 4 — slug must match
582
+ // opencode's skill-name lint regex `[a-z0-9-]{1,64}` because a
583
+ // future opencode release may reject names that fall outside it.
584
+ // Warn at materialisation; do not strip the skill (every Aitne
585
+ // built-in slug already conforms — see audit acceptance criterion).
586
+ if (!isValidSkillSlug(skillSlug)) {
587
+ logger.warn({ skillSlug, expected: "[a-z0-9-]{1,64}" }, "skills_compiler.skill_slug_invalid");
588
+ }
507
589
  const src = resolveBuiltinSkillDir(skillsRoot, skillSlug);
508
590
  if (!existsSync(join(src, "SKILL.md"))) {
509
591
  continue;
510
592
  }
511
- const variantFile = this.resolveSkillVariantFile(skillSlug, "claude");
593
+ const variantFile = this.resolveSkillVariantFile(skillSlug, sessionBackend);
512
594
  const destDir = join(destSkillsRoot, skillSlug);
513
595
  // DELEGATED-MODE-V2-DESIGN.md §4.1.2 — same-backend native MCP. The
514
596
  // agent already has the connector's tools in its inventory; a skill
@@ -545,10 +627,10 @@ export class SkillsCompiler {
545
627
  //
546
628
  // Order: refs BEFORE strip-services. The CLI paths
547
629
  // (`materializeCliSession` inline + directory copy) both run refs
548
- // before strip; aligning Claude here preserves the byte-equivalence
630
+ // before strip; aligning here preserves the byte-equivalence
549
631
  // contract (plan §3.1) for the case where a reference file carries
550
632
  // `<!-- service:* -->` markers — strip-first would leak those on
551
- // Claude while CLI scrubs them.
633
+ // Claude/OpenCode while CLI scrubs them.
552
634
  const destSkillMdForRefs = join(destDir, "SKILL.md");
553
635
  if (existsSync(destSkillMdForRefs)) {
554
636
  const raw = readFileSync(destSkillMdForRefs, "utf-8");
@@ -578,18 +660,20 @@ export class SkillsCompiler {
578
660
  const destSkillMdForMode = join(destDir, "SKILL.md");
579
661
  if (existsSync(destSkillMdForMode)) {
580
662
  const raw = readFileSync(destSkillMdForMode, "utf-8");
581
- const filtered = applyIntegrationModeFilter(raw, this.integrations, "claude");
663
+ const filtered = applyIntegrationModeFilter(raw, this.integrations, sessionBackend);
582
664
  if (filtered !== raw) {
583
665
  writeFileSync(destSkillMdForMode, filtered, "utf-8");
584
666
  }
585
667
  }
586
668
  // §7.7 — apply tool-deny policy AFTER partial includes and
587
- // service-section stripping. For Claude this rewrites the
588
- // `allowed-tools` frontmatter; the SDK enforces hard.
669
+ // service-section stripping. For the Claude SDK this rewrites the
670
+ // `allowed-tools` frontmatter (hard); for opencode the rewrite is
671
+ // a soft-enforcement prose body addition that the runtime config
672
+ // doubles up via `permission.bash.deny` rules.
589
673
  const destSkillMdForDeny = join(destDir, "SKILL.md");
590
674
  if (existsSync(destSkillMdForDeny)) {
591
675
  const raw = readFileSync(destSkillMdForDeny, "utf-8");
592
- const filtered = applyAllDeniedToolsForSkill(raw, skillSlug, "claude", this.integrations);
676
+ const filtered = applyAllDeniedToolsForSkill(raw, skillSlug, sessionBackend, this.integrations);
593
677
  if (filtered !== raw) {
594
678
  writeFileSync(destSkillMdForDeny, filtered, "utf-8");
595
679
  }
@@ -608,7 +692,141 @@ export class SkillsCompiler {
608
692
  ? renderMailAccountsMd(this.mailAccounts)
609
693
  : EMPTY_MAIL_ACCOUNTS_MD, "utf-8");
610
694
  }
695
+ // Phase 1 §"Codex read-sensitive banner inheritance" — prepend the
696
+ // 3-line caveat banner to every Codex skill body that touches a
697
+ // read-sensitive `/api/*` endpoint. Skipped for the other three
698
+ // backends: Claude / Gemini hold the read-sensitive token; OpenCode
699
+ // surfaces those routes via its own credential flow.
700
+ if (sessionBackend === "codex") {
701
+ prependCodexReadSensitiveBanner(join(destDir, "SKILL.md"));
702
+ }
703
+ materialised.push(skillSlug);
611
704
  }
705
+ return materialised;
706
+ }
707
+ /**
708
+ * docs/design/appendices/opencode-backend.md §6.5 / Phase 4 — opencode-specific
709
+ * materialisation.
710
+ *
711
+ * Three on-disk artefacts are written per session:
712
+ * 1. `AGENTS.md` (cwd-auto-discovered by opencode per V1) — same
713
+ * shape as `materializeCliSession` produces for Codex EXCEPT
714
+ * skill bodies are NOT inlined (skills auto-discover from
715
+ * `.claude/skills/` via opencode's `skill` tool — V2). Includes
716
+ * safety, character, behavioral rules, daemon-API, integration
717
+ * routing tables, and the runtime profile body.
718
+ * 2. `.opencode/agent/<profile-slug>.md` (singular `agent/` per V5)
719
+ * — the per-process agent persona with V5-correct frontmatter
720
+ * (`mode: primary`, `permission` block keyed only on
721
+ * `edit/bash/webfetch/doom_loop/external_directory` — NO `read`
722
+ * key per V5 contract). Body is the profile body; opencode
723
+ * invokes this via `session.prompt({ body: { agent: <slug> } })`
724
+ * so the per-agent permission overrides the server-level
725
+ * defaults.
726
+ * 3. `.opencode/skills/<slug>/` via `writeSkillsDir` — every
727
+ * manifest skill becomes a discoverable SKILL.md tree opencode
728
+ * reads on `skill` tool activation. `.claude/skills/` is
729
+ * intentionally NOT written: docs/design/appendices/skills-unification.md Phase 1
730
+ * flipped opencode from V2 path (b) (`.claude/skills/`
731
+ * redundancy-avoiding alias) to V2 path (c) (`.opencode/skills/`)
732
+ * so each backend lives under its own brand-aligned namespace.
733
+ *
734
+ * The dispatcher passes `agent: <slug>` (where `<slug>` matches the
735
+ * profile filename without `.md`) on every `session.prompt` call so
736
+ * the right agent file is selected.
737
+ */
738
+ materializeOpencodeSession(sessionDir, profileName, skillSlugs, profileBodyOverride, processKey, wikiWorkspaceName) {
739
+ // ── 1. AGENTS.md — cwd context (no skill inlining) ──
740
+ let profileContent = profileBodyOverride !== null
741
+ ? profileBodyOverride.trim()
742
+ : (this.readProfile(profileName) ?? "");
743
+ profileContent = substituteWikiWorkspaceTokens(profileContent, processKey, wikiWorkspaceName);
744
+ const safetyContent = this.readSafetyPreamble();
745
+ const characterBlock = buildCharacterBlock(this.character);
746
+ // DELEGATED-MODE-V2-DESIGN.md §4.3.3-§4.3.4 — same-backend deny prose.
747
+ // Opencode's MCP-tool deny is server-level only (§5.6 v1: drop the
748
+ // server from config to deny). The prose duplicates intent so the
749
+ // agent doesn't waste tokens drafting calls that will be dropped.
750
+ const sameBackendDenyBlock = buildSameBackendDenyBlock(this.integrations, "opencode");
751
+ const rawInstruction = renderCliInstructionFile({
752
+ backendId: "opencode",
753
+ processKey,
754
+ profileName,
755
+ profileContent,
756
+ safetyContent,
757
+ characterBlock,
758
+ skillSlugs,
759
+ // R3 — OpenCode never gets a `<skill-index>` block. The cwd
760
+ // auto-discovery loader is the source of truth; emitting an index
761
+ // here would inject a second listing the runtime ignores and the
762
+ // agent could mistake for canonical. The `## Skills` slug manifest
763
+ // (no path, no inlined bodies) survives as a turn-scope hint.
764
+ skillPreamble: null,
765
+ skillIndexBlock: null,
766
+ sameBackendDenyBlock,
767
+ });
768
+ const instruction = substituteWikiWorkspaceTokens(substituteIntegrationRoutingTables(rawInstruction, this.integrations), processKey, wikiWorkspaceName);
769
+ writeFileSync(join(sessionDir, "AGENTS.md"), instruction, "utf-8");
770
+ // ── 2. .opencode/agent/<profileName>.md — V5 frontmatter wrapper ──
771
+ this.writeOpencodeAgentFile(sessionDir, profileName, profileContent, safetyContent, characterBlock);
772
+ // ── 3. .opencode/skills/ — auto-discovered by opencode 1.14+ ──
773
+ // docs/design/appendices/skills-unification.md Phase 1 — opencode 1.14+ auto-discovers
774
+ // skills from `.opencode/skills/<slug>/SKILL.md` (V2 path (c),
775
+ // empirically verified). The earlier path (b) (`.claude/skills/`)
776
+ // worked as a redundancy-avoiding alias; per-backend brand-aligned
777
+ // naming now picks (c) explicitly.
778
+ this.writeSkillsDir(sessionDir, join(".opencode", "skills"), skillSlugs, "opencode", processKey, wikiWorkspaceName);
779
+ }
780
+ /**
781
+ * docs/design/appendices/opencode-backend.md §6.5 / V5 — write the per-process agent
782
+ * profile to `.opencode/agent/<slug>.md` (singular `agent/`; the
783
+ * plural form does NOT register per V5).
784
+ *
785
+ * Frontmatter shape (V5-correct keys only):
786
+ * - `mode: primary` — opencode's primary-agent mode; subagent is
787
+ * reserved for the disabled `task` tool path.
788
+ * - NO `permission` block here — the server-level
789
+ * `OpencodeRuntimeConfig.permission` is the per-session truth and
790
+ * is stricter for narrow agents (delegated runs use a separate
791
+ * `delegated-<callId>` agent file with its own tight permission).
792
+ * Emitting `permission: {}` here would NOT widen anything (the
793
+ * server-level deny still wins), but the absence keeps the
794
+ * frontmatter a manifest and avoids drift between two seats.
795
+ * - NO `model` field — opencode falls back to `OPENCODE_CONFIG_CONTENT.model`
796
+ * (set per-session by `OpencodeCore`'s runtime-config builder),
797
+ * and the dispatcher additionally overrides per `session.prompt`
798
+ * body. Pinning here would either drift from the per-call value
799
+ * or duplicate it.
800
+ *
801
+ * Body composition mirrors AGENTS.md (safety + character + profile)
802
+ * so an `agent: <slug>` invocation that REPLACES opencode's default
803
+ * cwd context still gets safety/character rules — V5 confirmed the
804
+ * agent body becomes the system prompt for that turn.
805
+ */
806
+ writeOpencodeAgentFile(sessionDir, profileName, profileBody, safetyContent, characterBlock) {
807
+ const agentDir = join(sessionDir, ".opencode", "agent");
808
+ mkdirSync(agentDir, { recursive: true });
809
+ // Strip a description from the profile body's first paragraph for
810
+ // the frontmatter `description` field. Opencode displays this in
811
+ // its agent picker; we use a stable phrasing so re-renders produce
812
+ // identical bytes.
813
+ const description = `${APP_NAME} ${profileName} — per-process persona`;
814
+ const frontmatter = [
815
+ "---",
816
+ `description: ${description}`,
817
+ "mode: primary",
818
+ "---",
819
+ "",
820
+ ].join("\n");
821
+ const bodySections = [];
822
+ if (safetyContent)
823
+ bodySections.push(safetyContent);
824
+ if (characterBlock)
825
+ bodySections.push(characterBlock);
826
+ if (profileBody.trim())
827
+ bodySections.push(profileBody.trim());
828
+ const body = bodySections.join("\n\n");
829
+ writeFileSync(join(agentDir, `${profileName}.md`), `${frontmatter}${body}\n`, "utf-8");
612
830
  }
613
831
  /**
614
832
  * P22 §1.5 — splice CURATION anchors in a single skill's materialized
@@ -648,64 +866,121 @@ export class SkillsCompiler {
648
866
  writeFileSync(skillMdPath, result.body, "utf-8");
649
867
  }
650
868
  }
651
- materializeCliSession(sessionDir, profileName, skillSlugs, backendId, processKey, profileBodyOverride, wikiWorkspaceName) {
652
- // Skills are inlined in the instruction file (AGENTS.md / GEMINI.md) for
653
- // guaranteed availability AND copied to the backend-specific skill
654
- // directory for native CLI skill discovery. The directory copy only adds
655
- // ~20 tokens per skill at session start (name + description); full body
656
- // is lazy-loaded on activation. Belt-and-suspenders: inline ensures task
657
- // flow prompts always have API references in context; directories let the
658
- // CLI's native skill activation and tooling work.
869
+ /**
870
+ * docs/design/appendices/skills-unification.md Phase 1 item 15 the slim path does NOT
871
+ * emit a `<skill-index>` block or the skill-discovery preamble. The
872
+ * fetch_window system prompt is a self-contained operational contract
873
+ * (one-window-one-curl, no sub-tasks, exactly-one JSON-on-stdout) and
874
+ * the only skill copied (`observations`) is referenced inline by the
875
+ * runner-emitted user prompt. Adding the index would mis-signal the
876
+ * fetcher to scan for skills before executing the acquisition plan.
877
+ *
878
+ * docs/design/appendices/fetch-window-cost-reduction.md Phase 1.5 — slim instruction-file
879
+ * materializer for `routine.fetch_window` on Codex / Gemini CLI.
880
+ *
881
+ * Mirrors the Claude SDK's Phase 1 systemPrompt swap (the same
882
+ * `agent-assets/system-prompts/routine-fetch-window.md` template is the
883
+ * single source of truth): write the slim body verbatim as AGENTS.md /
884
+ * GEMINI.md and copy only the `observations` skill — the
885
+ * `/api/observations/batch` POST contract is the fetcher's sole
886
+ * structural assertion. The integration partial inlined by the runner
887
+ * (`routine-fetch-window-runner.ts:reassemblePrompt`) covers the
888
+ * per-attempt call shape, so `mail` / `notion` / `external-services` /
889
+ * `attach` skill bodies are deliberately omitted.
890
+ *
891
+ * No safety preamble / character / behavioral-rules / daemon-API
892
+ * sections — the slim template restates the only rules the fetcher
893
+ * needs (localhost-only curl, no sub-tasks, no context writes, no
894
+ * notify, JSON-on-stdout-and-exit). The destructive-action policy layer
895
+ * (absolute-block list, Codex sandbox, Gemini admin TOML) still applies
896
+ * unchanged at runtime.
897
+ *
898
+ * The `<mcp-servers>` section is appended downstream by
899
+ * `services/mcp/session-materializer.ts:appendMcpSection` exactly as on
900
+ * the wide path — Phase 3's allowlist filter, when it lands, will scope
901
+ * that section without further changes here.
902
+ */
903
+ materializeFetchWindowCliSession(sessionDir, backendId) {
904
+ mkdirSync(sessionDir, { recursive: true });
905
+ const slim = loadFetchWindowSystemPrompt();
906
+ writeFileSync(join(sessionDir, cliInstructionFileName(backendId)), slim, "utf-8");
907
+ // Copy ONLY the `observations` skill dir. The wide path's prune step
908
+ // is replaced by an explicit single-slug list — `pruneStaleBuiltinSkillDirs`
909
+ // removes any other built-in skill dir that a prior re-materialization
910
+ // (e.g. a fallback-driven wide path on the same workdir) may have left.
911
+ const cliSkillsRoot = cliSkillsDirName(backendId);
912
+ if (cliSkillsRoot === null)
913
+ return; // Claude-only — fetch_window slim runs on Claude SDK natively.
659
914
  const skillsRoot = this.getSourceSkillsRoot();
660
- const skillContents = {};
661
- for (const skillSlug of skillSlugs) {
662
- const src = resolveBuiltinSkillDir(skillsRoot, skillSlug);
663
- const variantFile = this.resolveSkillVariantFile(skillSlug, backendId);
664
- // DELEGATED-MODE-V2-DESIGN.md §4.1.2 same-backend native MCP path:
665
- // skip the inline. The connector's own tool descriptions, present in
666
- // the CLI's tool inventory at session-init, are the authoritative
667
- // surface for the agent.
668
- if (variantFile === null)
669
- continue;
670
- const skillMdPath = join(src, variantFile);
671
- if (!existsSync(skillMdPath)) {
672
- continue;
673
- }
674
- let raw = substituteBrandTokens(readFileSync(skillMdPath, "utf-8"));
675
- // Resolve {{> base }} partials before inlining. Wrap the result
676
- // SKILL.base.md is read directly from src and would slip past the
677
- // single-point-of-change contract if it grew an `{APP_NAME}` token.
678
- raw = substituteBrandTokens(renderPartialIncludes(raw, join(src, "SKILL.base.md")));
679
- // Resolve `{{> ref:<name> }}` directives by inlining
680
- // `references/<name>.md` from the source skill dir. Runs AFTER the
681
- // base-partial resolver so a base-partial fragment can itself carry
682
- // `{{> ref:* }}` markers (one-level nesting cap; references inside
683
- // references are intentionally NOT resolved per §4.7 / NG5). Same
684
- // src-bypass concern as above wrap the result.
685
- raw = substituteBrandTokens(renderReferenceIncludes(raw, src));
686
- raw = substituteWikiWorkspaceTokens(raw, processKey, wikiWorkspaceName);
687
- // Strip unconfigured service sections before inlining
688
- if (skillSlug === "external-services" && this.configuredServices.size > 0) {
689
- raw = stripUnconfiguredServices(raw, this.configuredServices);
690
- }
691
- // Mode-conditional sectionssee materializeClaudeSession for the
692
- // ordering rationale. Same filter, same ordering: service-strip
693
- // then mode-filter then deny.
694
- raw = applyIntegrationModeFilter(raw, this.integrations, backendId);
695
- // §7.7 — apply tool-deny policy. For CLI backends this appends the
696
- // soft-enforcement prose block; the inline-into-AGENTS.md path
697
- // strips frontmatter below, so the deny block must already be in
698
- // body content before that strip.
699
- raw = applyAllDeniedToolsForSkill(raw, skillSlug, backendId, this.integrations);
700
- // Inline content for instruction file strip frontmatter (Claude-specific
701
- // YAML metadata like allowed-tools has no meaning for CLI backends).
702
- skillContents[skillSlug] = stripFrontmatter(raw);
915
+ const destSkillsRoot = join(sessionDir, cliSkillsRoot, "skills");
916
+ mkdirSync(destSkillsRoot, { recursive: true });
917
+ pruneStaleBuiltinSkillDirs(destSkillsRoot, skillsRoot, [FETCH_WINDOW_SLIM_SKILL]);
918
+ const src = resolveBuiltinSkillDir(skillsRoot, FETCH_WINDOW_SLIM_SKILL);
919
+ const skillMdPath = join(src, "SKILL.md");
920
+ if (!existsSync(skillMdPath))
921
+ return;
922
+ const destDir = join(destSkillsRoot, FETCH_WINDOW_SLIM_SKILL);
923
+ cpSync(src, destDir, { recursive: true });
924
+ substituteBrandTokensInDir(destDir);
925
+ // No `substituteWikiWorkspaceTokensInDir` fetch_window never touches
926
+ // wiki workspace state, and the resolver is a no-op for non-wiki
927
+ // process keys anyway.
928
+ let adapted = substituteBrandTokens(readFileSync(skillMdPath, "utf-8"));
929
+ // observations/SKILL.md ships no `{{> base }}` or `{{> ref:* }}`
930
+ // directives today, but run the resolvers anyway so a future curation
931
+ // edit cannot silently drop content. Idempotent on plain content.
932
+ adapted = substituteBrandTokens(renderPartialIncludes(adapted, join(src, "SKILL.base.md")));
933
+ adapted = substituteBrandTokens(renderReferenceIncludes(adapted, src));
934
+ // Mode-conditional filter observations/SKILL.md carries
935
+ // `<!-- mode:<predicate>:notion -->` markers (lines 273-345 today)
936
+ // because the source / consume contract differs across `direct` /
937
+ // `delegated-same` / `delegated-cross` / `native` / `disabled`. The
938
+ // wide path applies this filter at `materializeCliSession`; the
939
+ // slim path must match so the agent doesn't get every mode's prose
940
+ // for every integration. Idempotent on bodies that lack markers.
941
+ adapted = applyIntegrationModeFilter(adapted, this.integrations, backendId);
942
+ // Tool-deny policy stays in force — even though the fetcher is fed a
943
+ // narrow allowlist, the soft-enforcement prose lands in the body
944
+ // BEFORE the CLI frontmatter strip so it's not lost.
945
+ adapted = applyAllDeniedToolsForSkill(adapted, FETCH_WINDOW_SLIM_SKILL, backendId, this.integrations);
946
+ // docs/design/appendices/skills-unification.md Phase 1 §R6 frontmatter stays intact
947
+ // across all backends. `adaptSkillForCli` is gone; the source body's
948
+ // YAML preamble flows through verbatim.
949
+ writeFileSync(join(destDir, "SKILL.md"), adapted, "utf-8");
950
+ this.spliceCurationAnchorsInSkill(destDir, FETCH_WINDOW_SLIM_SKILL);
951
+ }
952
+ materializeCliSession(sessionDir, profileName, skillSlugs, backendId, processKey, profileBodyOverride, wikiWorkspaceName) {
953
+ // docs/design/appendices/fetch-window-cost-reduction.md Phase 1.5 divert
954
+ // `routine.fetch_window` to a slim materializer that mirrors the
955
+ // Claude SDK's Phase 1 systemPrompt swap. Custom bang commands cannot
956
+ // reach this branch (they bind to `messaging.custom_command`), so
957
+ // `profileBodyOverride` is intentionally NOT forwarded.
958
+ if (processKey === FETCH_WINDOW_PROCESS_KEY) {
959
+ this.materializeFetchWindowCliSession(sessionDir, backendId);
960
+ return;
703
961
  }
962
+ // docs/design/appendices/skills-unification.md Phase 1 — directory-based skill delivery.
963
+ // The Codex / Gemini CLIs have no native cwd auto-discovery today, so
964
+ // the instruction file (AGENTS.md / GEMINI.md) carries a compact
965
+ // `<skill-index>` block and the agent `Read`s each `SKILL.md` from the
966
+ // per-backend dir on demand. Skill bodies are NEVER inlined into the
967
+ // instruction file.
968
+ //
969
+ // OpenCode reaches `materializeOpencodeSession` instead, so this method
970
+ // only handles Codex and Gemini. The defensive `null` check below
971
+ // protects future backends that might temporarily route through here
972
+ // before getting their own materialiser.
973
+ const cliSkillsDir = cliSkillsDirName(backendId);
974
+ if (cliSkillsDir === null) {
975
+ throw new Error(`materializeCliSession: no skills directory mapped for backend "${backendId}"`);
976
+ }
977
+ const destSkillsRootRelative = join(cliSkillsDir, "skills");
978
+ const materialisedSlugs = this.writeSkillsDir(sessionDir, destSkillsRootRelative, skillSlugs, backendId, processKey, wikiWorkspaceName);
704
979
  // Read profile and safety separately so renderCliInstructionFile can
705
980
  // place safety at the top level for prominence (instead of burying it
706
981
  // inside the profile section). For custom bang commands the dispatcher
707
982
  // passes a `profileBodyOverride` that replaces the persona body; the
708
- // safety + character + skills sections still wrap around it via
983
+ // safety + character + skill index sections still wrap around it via
709
984
  // `renderCliInstructionFile`.
710
985
  let profileContent = profileBodyOverride !== null
711
986
  ? profileBodyOverride.trim()
@@ -721,6 +996,18 @@ export class SkillsCompiler {
721
996
  // prose duplicates intent so the agent doesn't waste tokens drafting
722
997
  // calls that will be denied at the policy layer.
723
998
  const sameBackendDenyBlock = buildSameBackendDenyBlock(this.integrations, backendId);
999
+ // docs/design/appendices/skills-unification.md Phase 1 §"Skill preamble" — render the
1000
+ // universal preamble + `<skill-index>` block. The index is derived
1001
+ // from the **materialised** SKILL.md frontmatter on disk so curation /
1002
+ // mode-filter / deny passes are reflected. Reading post-materialisation
1003
+ // also keeps user-authored slugs synced by `syncAllUserSkills` (which
1004
+ // runs LATER from the workdir layer) out of the index — those land in
1005
+ // the same dir but are appended after this render. The
1006
+ // `refreshSkillIndexBlock` helper (called by workdir.ts post-sync) is
1007
+ // responsible for splicing user-authored slugs into the block.
1008
+ const skillPreamble = loadSkillIndexPreamble(this.workspaceDir);
1009
+ const destSkillsRootAbs = join(sessionDir, destSkillsRootRelative);
1010
+ const skillIndexBlock = renderSkillIndexBlock(destSkillsRootAbs, destSkillsRootRelative);
724
1011
  const rawInstruction = renderCliInstructionFile({
725
1012
  backendId,
726
1013
  processKey,
@@ -728,89 +1015,18 @@ export class SkillsCompiler {
728
1015
  profileContent,
729
1016
  safetyContent,
730
1017
  characterBlock,
731
- skillSlugs,
732
- skillContents,
1018
+ skillSlugs: materialisedSlugs,
1019
+ skillPreamble,
1020
+ skillIndexBlock,
733
1021
  sameBackendDenyBlock,
734
1022
  });
735
1023
  // INTEGRATION_NATIVE_MODE_DESIGN.md §7.3 — substitute the
736
1024
  // `<integration-routing-table>` placeholder in the rendered
737
1025
  // instruction file. Runs after the whole document is assembled so
738
- // placeholders anywhere (profile body, inlined skill bodies,
739
- // safety preamble) all resolve in one pass. No-op when neither
740
- // placeholder string is present.
1026
+ // placeholders anywhere (profile body, preamble, index) all resolve
1027
+ // in one pass.
741
1028
  const instruction = substituteWikiWorkspaceTokens(substituteIntegrationRoutingTables(rawInstruction, this.integrations), processKey, wikiWorkspaceName);
742
- writeFileSync(join(sessionDir, backendId === "codex" ? "AGENTS.md" : "GEMINI.md"), instruction, "utf-8");
743
- // Copy skills to the backend-specific skill directory for native CLI
744
- // discovery: .codex/skills/<slug>/ or .gemini/skills/<slug>/
745
- const cliSkillsDir = cliSkillsDirName(backendId);
746
- const destSkillsRoot = join(sessionDir, cliSkillsDir, "skills");
747
- mkdirSync(destSkillsRoot, { recursive: true });
748
- // See `materializeClaudeSession` — same prune contract for CLI workdirs.
749
- pruneStaleBuiltinSkillDirs(destSkillsRoot, skillsRoot, skillSlugs);
750
- for (const skillSlug of skillSlugs) {
751
- const src = resolveBuiltinSkillDir(skillsRoot, skillSlug);
752
- const variantFile = this.resolveSkillVariantFile(skillSlug, backendId);
753
- const destDir = join(destSkillsRoot, skillSlug);
754
- // §4.1.2 same-backend short-circuit: no SKILL.md / .codex/skills/<slug>
755
- // / .gemini/skills/<slug> directory written. The connector ships its
756
- // own descriptions; injecting prose only confuses the dispatch.
757
- // Remove any prior-materialization leftovers so a mode flip doesn't
758
- // leak stale prose into the workdir.
759
- if (variantFile === null) {
760
- if (existsSync(destDir)) {
761
- rmSync(destDir, { recursive: true, force: true });
762
- }
763
- continue;
764
- }
765
- const variantPath = join(src, variantFile);
766
- if (!existsSync(variantPath)) {
767
- continue;
768
- }
769
- // Copy the whole skill directory (scripts/, references/, etc.)
770
- cpSync(src, destDir, { recursive: true });
771
- // Resolve `{APP_NAME}` brand tokens in the verbatim copy before any
772
- // downstream transform reads them. Source-of-truth: branding.ts.
773
- substituteBrandTokensInDir(destDir);
774
- substituteWikiWorkspaceTokensInDir(destDir, processKey, wikiWorkspaceName);
775
- // Render variant (resolving partials), adapt frontmatter for CLI, and
776
- // write as SKILL.md in the dest dir.
777
- let adapted = substituteBrandTokens(readFileSync(variantPath, "utf-8"));
778
- // SKILL.base.md and references/*.md are read directly from src by these
779
- // inliners; wrap the results so future tokens added to those files still
780
- // reach single-point-of-change. Idempotent.
781
- adapted = substituteBrandTokens(renderPartialIncludes(adapted, join(src, "SKILL.base.md")));
782
- // Resolve `{{> ref:<name> }}` directives — keeps the
783
- // `.codex/skills/<slug>/SKILL.md` and `.gemini/skills/<slug>/SKILL.md`
784
- // bodies byte-identical to the inline-into-AGENTS.md / GEMINI.md
785
- // copy emitted above (modulo CLI frontmatter strip), preserving the
786
- // "guaranteed availability" contract that motivated this resolver.
787
- adapted = substituteBrandTokens(renderReferenceIncludes(adapted, src));
788
- adapted = substituteWikiWorkspaceTokens(adapted, processKey, wikiWorkspaceName);
789
- if (skillSlug === "external-services" && this.configuredServices.size > 0) {
790
- adapted = stripUnconfiguredServices(adapted, this.configuredServices);
791
- }
792
- // Mode-conditional filter — keep this dest-dir copy byte-aligned with
793
- // the inline copy emitted into AGENTS.md / GEMINI.md (modulo
794
- // adaptSkillForCli's frontmatter strip). The filter is idempotent so
795
- // running it on both copies independently is safe.
796
- adapted = applyIntegrationModeFilter(adapted, this.integrations, backendId);
797
- // §7.7 — apply tool-deny policy BEFORE adaptSkillForCli strips
798
- // frontmatter so the soft-enforcement prose block lands in body
799
- // content (CLI skills carry only `name` + `description` in
800
- // frontmatter, no `allowed-tools` to filter).
801
- adapted = applyAllDeniedToolsForSkill(adapted, skillSlug, backendId, this.integrations);
802
- adapted = adaptSkillForCli(adapted);
803
- writeFileSync(join(destDir, "SKILL.md"), adapted, "utf-8");
804
- // P22 — splice CURATION anchors against overlay/seed JSON so the
805
- // CLI-side .codex/.gemini skill copy stays byte-equivalent to the
806
- // Claude-side copy after curation. No-op when no curation context.
807
- this.spliceCurationAnchorsInSkill(destDir, skillSlug);
808
- if (skillSlug === "mail") {
809
- writeFileSync(join(destDir, "accounts.md"), this.mailAccounts.length > 0
810
- ? renderMailAccountsMd(this.mailAccounts)
811
- : EMPTY_MAIL_ACCOUNTS_MD, "utf-8");
812
- }
813
- }
1029
+ writeFileSync(join(sessionDir, cliInstructionFileName(backendId)), instruction, "utf-8");
814
1030
  }
815
1031
  }
816
1032
  export const EMPTY_MAIL_ACCOUNTS_MD = [
@@ -843,16 +1059,171 @@ export function renderMailAccountsMd(accounts) {
843
1059
  ].join("\n");
844
1060
  }
845
1061
  /**
846
- * Return the backend-specific skills directory name for a given backend.
847
- * Returns null for Claude (which uses `.claude/skills/` managed separately).
1062
+ * docs/design/appendices/opencode-backend.md §10 D6 opencode 1.14.50 documents
1063
+ * `[a-z0-9-]{1,64}` as the legal skill-slug pattern. Aitne's existing
1064
+ * built-ins all conform; this helper is the predicate the build-time
1065
+ * validator (`validateBuiltinSkillSourceTree`) and the user-skill PUT
1066
+ * endpoint both gate on.
1067
+ *
1068
+ * docs/design/appendices/skills-unification.md Phase 1 §R5 / item 6 — promoted from a
1069
+ * runtime warn to a build-time throw at SkillsCompiler construction so
1070
+ * a malformed source tree refuses to boot the daemon.
1071
+ *
1072
+ * Exported for unit testing (`skills-compiler.test.ts` regression).
1073
+ */
1074
+ export function isValidSkillSlug(slug) {
1075
+ return /^[a-z0-9-]{1,64}$/.test(slug);
1076
+ }
1077
+ /**
1078
+ * docs/design/appendices/skills-unification.md Phase 1 §R5 / item 6 — build-time invariant
1079
+ * pass over `agent-assets/skills/`. Throws on:
1080
+ * - Any built-in slug that doesn't match `[a-z0-9-]{1,64}`.
1081
+ * - Any SKILL.md (incl. variants like `SKILL.delegated.<backend>.md`)
1082
+ * whose `description` exceeds `SKILL_DESCRIPTION_MAX_LENGTH`.
1083
+ * - Any SKILL.md missing `name` or `description`.
1084
+ *
1085
+ * No-op when the source tree is absent (test workspaces / partial-clone
1086
+ * scenarios). Memoised per workspace dir + skill-tree fingerprint so
1087
+ * repeated SkillsCompiler constructions in the same process don't pay
1088
+ * the walk cost twice; tests that mutate source between constructions
1089
+ * get fresh validation because the fingerprint shifts.
1090
+ *
1091
+ * Exported for tests that exercise the failure paths in isolation.
1092
+ */
1093
+ export function validateBuiltinSkillSourceTree(skillsRoot) {
1094
+ if (!existsSync(skillsRoot))
1095
+ return;
1096
+ const fingerprint = computeSkillTreeFingerprint(skillsRoot);
1097
+ const cached = validatedTreeCache.get(skillsRoot);
1098
+ if (cached === fingerprint)
1099
+ return;
1100
+ for (const slug of listBuiltinSlugs(skillsRoot)) {
1101
+ if (!isValidSkillSlug(slug)) {
1102
+ throw new Error(`skills_compiler.invalid_slug: ${slug} (expected [a-z0-9-]{1,64})`);
1103
+ }
1104
+ const skillDir = resolveBuiltinSkillDir(skillsRoot, slug);
1105
+ const skillMdPath = join(skillDir, "SKILL.md");
1106
+ if (!existsSync(skillMdPath))
1107
+ continue; // skip slugs that ship only a variant
1108
+ const primaryContent = readFileSync(skillMdPath, "utf-8");
1109
+ const primaryFm = parseSkillFrontmatter(primaryContent);
1110
+ // Stub primary (no frontmatter) — treat the whole skill as a test
1111
+ // scaffold and skip its variants too. Production builds always have
1112
+ // proper frontmatter; the fingerprint cache picks up any future
1113
+ // primary-content fix automatically.
1114
+ if (!primaryFm.name && !primaryFm.description)
1115
+ continue;
1116
+ if (!primaryFm.name) {
1117
+ throw new Error(`skills_compiler.missing_frontmatter_name: ${slug}/SKILL.md`);
1118
+ }
1119
+ if (!primaryFm.description) {
1120
+ throw new Error(`skills_compiler.missing_frontmatter_description: ${slug}/SKILL.md`);
1121
+ }
1122
+ if (primaryFm.description.length > SKILL_DESCRIPTION_MAX_LENGTH) {
1123
+ throw new Error(`skills_compiler.description_too_long: ${slug}/SKILL.md `
1124
+ + `(${primaryFm.description.length} > ${SKILL_DESCRIPTION_MAX_LENGTH})`);
1125
+ }
1126
+ // Variant validation — only run when the primary is well-formed. Each
1127
+ // variant is shipped to the model the same way the primary is, so the
1128
+ // same description-length cap applies. Variants that are stub
1129
+ // sentinels in tests are caught by the primary-stub short-circuit
1130
+ // above (this loop never runs for those).
1131
+ const entries = readdirSync(skillDir, { withFileTypes: true });
1132
+ for (const entry of entries) {
1133
+ if (!entry.isFile())
1134
+ continue;
1135
+ const name = entry.name;
1136
+ if (!name.startsWith("SKILL.") || !name.endsWith(".md"))
1137
+ continue;
1138
+ if (name === "SKILL.base.md")
1139
+ continue; // base partial — frontmatter optional
1140
+ const variantContent = readFileSync(join(skillDir, name), "utf-8");
1141
+ const variantFm = parseSkillFrontmatter(variantContent);
1142
+ if (!variantFm.name || !variantFm.description) {
1143
+ throw new Error(`skills_compiler.variant_missing_frontmatter: ${slug}/${name}`);
1144
+ }
1145
+ if (variantFm.description.length > SKILL_DESCRIPTION_MAX_LENGTH) {
1146
+ throw new Error(`skills_compiler.description_too_long: ${slug}/${name} `
1147
+ + `(${variantFm.description.length} > ${SKILL_DESCRIPTION_MAX_LENGTH})`);
1148
+ }
1149
+ }
1150
+ }
1151
+ validatedTreeCache.set(skillsRoot, fingerprint);
1152
+ }
1153
+ const validatedTreeCache = new Map();
1154
+ function computeSkillTreeFingerprint(skillsRoot) {
1155
+ // mtime-only fingerprint over SKILL*.md files: enough to bust the
1156
+ // cache on a source-tree edit between constructions without paying
1157
+ // the cost of a full content hash. Tests that mutate files within
1158
+ // the same millisecond should call SkillsCompiler.invalidateValidator()
1159
+ // — but in practice the millisecond resolution suffices.
1160
+ const parts = [];
1161
+ for (const slug of listBuiltinSlugs(skillsRoot).sort()) {
1162
+ const skillDir = resolveBuiltinSkillDir(skillsRoot, slug);
1163
+ let entries;
1164
+ try {
1165
+ entries = readdirSync(skillDir, { withFileTypes: true });
1166
+ }
1167
+ catch {
1168
+ continue;
1169
+ }
1170
+ for (const e of entries) {
1171
+ if (!e.isFile())
1172
+ continue;
1173
+ const name = e.name;
1174
+ if (!name.startsWith("SKILL") || !name.endsWith(".md"))
1175
+ continue;
1176
+ try {
1177
+ const stat = statSync(join(skillDir, name));
1178
+ parts.push(`${slug}/${name}:${stat.mtimeMs}:${stat.size}`);
1179
+ }
1180
+ catch { /* ignore */ }
1181
+ }
1182
+ }
1183
+ return parts.join("|");
1184
+ }
1185
+ /**
1186
+ * Return the backend-specific dotfile namespace name for a given backend's
1187
+ * skill directory, **without** the trailing `skills` segment — callers
1188
+ * join `skills` themselves. Returns `null` only for Claude (which is
1189
+ * dispatched through `materializeClaudeSession` and writes
1190
+ * `<sessionDir>/.claude/skills/` directly).
1191
+ *
1192
+ * docs/design/appendices/skills-unification.md Phase 1 — every non-Claude backend now writes
1193
+ * to its own brand-aligned namespace:
1194
+ * - `codex` → `.codex`
1195
+ * - `gemini` → `.gemini`
1196
+ * - `opencode` → `.opencode` (V2 path (c); flipped from prior `.claude/`
1197
+ * redundancy-avoiding alias).
848
1198
  */
849
1199
  export function cliSkillsDirName(backendId) {
850
1200
  switch (backendId) {
851
1201
  case "codex": return ".codex";
852
1202
  case "gemini": return ".gemini";
1203
+ case "opencode": return ".opencode";
853
1204
  default: return null;
854
1205
  }
855
1206
  }
1207
+ /**
1208
+ * Return the CLI instruction-file name for a given backend. Codex and
1209
+ * OpenCode both auto-discover `AGENTS.md` from cwd; Gemini reads
1210
+ * `GEMINI.md`. Throws for `claude` — the Claude SDK consumes a per-cwd
1211
+ * `CLAUDE.md` written by `materializeClaudeSession`, not an instruction
1212
+ * file from this helper.
1213
+ *
1214
+ * Single helper so the choice is consistent between the wide
1215
+ * `materializeCliSession` and the slim `materializeFetchWindowCliSession`
1216
+ * paths (docs/design/appendices/fetch-window-cost-reduction.md §4.5.7).
1217
+ */
1218
+ export function cliInstructionFileName(backendId) {
1219
+ switch (backendId) {
1220
+ case "codex":
1221
+ case "opencode":
1222
+ return "AGENTS.md";
1223
+ case "gemini":
1224
+ return "GEMINI.md";
1225
+ }
1226
+ }
856
1227
  /**
857
1228
  * Session instruction files the live-overwrite path (design §15.6.1 /
858
1229
  * §15.9) walks when the owner PATCHes `character` mid-session. Each file
@@ -888,8 +1259,27 @@ const CHARACTER_INSTRUCTION_FILES = [
888
1259
  */
889
1260
  export function rewriteCharacterBlock(workdir, character) {
890
1261
  const summary = { rewritten: 0, skipped: 0, failed: 0 };
891
- for (const name of CHARACTER_INSTRUCTION_FILES) {
892
- const target = join(workdir, name);
1262
+ const targets = CHARACTER_INSTRUCTION_FILES.map((name) => join(workdir, name));
1263
+ // docs/design/appendices/opencode-backend.md §6.5 opencode also carries the character
1264
+ // block inside `.opencode/agent/<slug>.md` (the per-process persona
1265
+ // body). Walk the dir so a mid-session character PATCH lands on every
1266
+ // active opencode agent file (typically one per workdir). Defensive
1267
+ // existence check below — a non-opencode workdir simply has no
1268
+ // `.opencode/agent/` dir and contributes zero rewrites.
1269
+ const opencodeAgentDir = join(workdir, ".opencode", "agent");
1270
+ if (existsSync(opencodeAgentDir)) {
1271
+ try {
1272
+ for (const entry of readdirSync(opencodeAgentDir, { withFileTypes: true })) {
1273
+ if (entry.isFile() && entry.name.endsWith(".md")) {
1274
+ targets.push(join(opencodeAgentDir, entry.name));
1275
+ }
1276
+ }
1277
+ }
1278
+ catch (err) {
1279
+ logger.warn({ err, opencodeAgentDir }, "rewriteCharacterBlock failed to enumerate opencode agent dir");
1280
+ }
1281
+ }
1282
+ for (const target of targets) {
893
1283
  if (!existsSync(target)) {
894
1284
  summary.skipped++;
895
1285
  continue;
@@ -919,7 +1309,7 @@ export function rewriteCharacterBlock(workdir, character) {
919
1309
  return summary;
920
1310
  }
921
1311
  function renderCliInstructionFile(params) {
922
- const toolName = params.backendId === "codex" ? "AGENTS.md" : "GEMINI.md";
1312
+ const toolName = cliInstructionFileName(params.backendId);
923
1313
  const parts = [
924
1314
  `# ${APP_NAME} ${toolName}`,
925
1315
  "",
@@ -964,22 +1354,40 @@ function renderCliInstructionFile(params) {
964
1354
  // For Gemini / Claude the section is informational; the position is
965
1355
  // kept consistent so the rendered file shape is uniform.
966
1356
  parts.push(renderDaemonApiUsageSection(params.backendId !== "codex"), "");
967
- parts.push("## Runtime profile", "", params.profileContent.trim(), "", "## Skills", "");
968
- if (params.skillSlugs.length === 0) {
969
- parts.push("No process-scoped built-in skills were selected for this turn.");
1357
+ // docs/design/appendices/skills-unification.md Phase 1 §R2 preamble + `<skill-index>`
1358
+ // sit after Character (already emitted above) and **before** the
1359
+ // Runtime profile (which carries the integration routing table
1360
+ // substitution). Codex / Gemini only — `skillPreamble` and
1361
+ // `skillIndexBlock` are `null` for OpenCode (R3) so the section is
1362
+ // suppressed entirely and the `## Skills` slug manifest below holds.
1363
+ if (params.skillPreamble) {
1364
+ parts.push(params.skillPreamble.trim(), "");
970
1365
  }
971
- else {
972
- for (const slug of params.skillSlugs) {
973
- const content = params.skillContents[slug];
974
- if (content) {
975
- parts.push(`### ${slug}`, "", content.trim(), "");
976
- }
977
- else {
978
- parts.push(`### ${slug}`, "", `See \`skills/${slug}/SKILL.md\` for details.`, "");
1366
+ if (params.skillIndexBlock) {
1367
+ parts.push(params.skillIndexBlock, "");
1368
+ }
1369
+ parts.push("## Runtime profile", "", params.profileContent.trim(), "");
1370
+ // docs/design/appendices/skills-unification.md Phase 1 §R3 — the `## Skills` slug manifest
1371
+ // only fires for OpenCode (no `<skill-index>` block; cwd auto-discovery
1372
+ // already enumerates the skills, but the manifest pins the per-turn
1373
+ // active set so the agent doesn't grab unrelated user skills). Codex /
1374
+ // Gemini suppress this section since their `<skill-index>` above already
1375
+ // serves as the canonical listing — duplicating it here would risk the
1376
+ // agent mistaking the manifest for the authoritative path source.
1377
+ if (!params.skillIndexBlock) {
1378
+ parts.push("## Skills", "");
1379
+ if (params.skillSlugs.length === 0) {
1380
+ parts.push("No process-scoped built-in skills were selected for this turn.", "");
1381
+ }
1382
+ else {
1383
+ parts.push("Active built-in skills for this turn (cwd auto-discovery loads them):", "");
1384
+ for (const slug of params.skillSlugs) {
1385
+ parts.push(`- \`${slug}\``);
979
1386
  }
1387
+ parts.push("");
980
1388
  }
1389
+ parts.push("User-authored skills may also be discovered from the same directory.");
981
1390
  }
982
- parts.push("", "User-authored skills may also exist under `skills/<name>/SKILL.md`.");
983
1391
  return parts.join("\n");
984
1392
  }
985
1393
  function renderDaemonApiUsageSection(readSensitiveAvailable) {
@@ -993,7 +1401,7 @@ function renderDaemonApiUsageSection(readSensitiveAvailable) {
993
1401
  lines.push("- The wrapper auto-attaches session auth for read-sensitive endpoints.");
994
1402
  }
995
1403
  else {
996
- lines.push("", "### Read-sensitive endpoints are UNAVAILABLE on this backend", "", "Codex sessions do not receive the read-sensitive daemon token. The", "wrapper still prepends headers it can supply, but the daemon answers", "personal-data reads with `401 Unauthorized` regardless. Endpoints", "below are affected; the skill bodies in `## Skills` describe them", "as if they were available — treat the section as a contract you", "cannot satisfy on this backend.", "", "- Context vault: `GET /api/context/*`, `GET /api/context/list/*`", "- Mail (multi-provider): `GET /api/mail/*` (read), search, providers", "- Calendar (direct mode): `GET /api/calendar/*`", "- Notion (direct mode): `GET /api/notion/{query,search,pages}`", "- Obsidian: `GET /api/obsidian/*`", "- Observations: `GET /api/observations`", "- Reading list / receipts / travel bookings", "", "If a skill body directs you at one of these reads, stop and tell", "the user the task needs a different backend (Claude or Gemini).", "Do not hammer the endpoint — the 401 is permanent for this", "session, not transient. Writes and autonomous-tier endpoints", "stay reachable; the gate is read-sensitive scope only.");
1404
+ lines.push("", "### Read-sensitive endpoints are UNAVAILABLE on this backend", "", "Codex sessions do not receive the read-sensitive daemon token. The", "wrapper still prepends headers it can supply, but the daemon answers", "personal-data reads with `401 Unauthorized` regardless. Endpoints", "below are affected; the per-skill `SKILL.md` files under", "`.codex/skills/<name>/` listed in `<skill-index>` describe them as if", "they were available — treat their `curl /api/*` examples as a", "contract you cannot satisfy on this backend.", "", "- Context vault: `GET /api/context/*`, `GET /api/context/list/*`", "- Mail (multi-provider): `GET /api/mail/*` (read), search, providers", "- Calendar (direct mode): `GET /api/calendar/*`", "- Notion (direct mode): `GET /api/notion/{query,search,pages}`", "- Obsidian: `GET /api/obsidian/*`", "- Observations: `GET /api/observations`", "- Reading list / receipts / travel bookings", "", "If a skill body directs you at one of these reads, stop and tell", "the user the task needs a different backend (Claude or Gemini).", "Do not hammer the endpoint — the 401 is permanent for this", "session, not transient. Writes and autonomous-tier endpoints", "stay reachable; the gate is read-sensitive scope only.");
997
1405
  }
998
1406
  return lines.join("\n");
999
1407
  }
@@ -1022,53 +1430,283 @@ function stripFrontmatter(content) {
1022
1430
  return content.slice(endIdx + 4).replace(/^\n+/, "");
1023
1431
  }
1024
1432
  /**
1025
- * Adapt a SKILL.md for CLI backends (Codex / Gemini): retain only `name`,
1026
- * `description`, and `when_to_use` frontmatter fields, stripping
1027
- * Claude-specific fields like `allowed-tools`. The body content is
1028
- * preserved unchanged.
1029
- *
1030
- * `when_to_use` is the secondary trigger-shape clarification documented
1031
- * in `SKILLS-PHASE-2-PLAN.md` §3.2 / §5; the Claude Agent SDK reads it
1032
- * verbatim from `q.when_to_use` (verified against
1033
- * `claude-agent-sdk@0.2.98/cli.js`). Preserving it on the CLI side keeps
1034
- * the per-backend skill frontmatter aligned even though Codex / Gemini
1035
- * do not currently consume the field — drift would surface as a missing
1036
- * activation hint when they eventually do.
1037
- *
1038
- * Assumes `name`, `description`, and `when_to_use` are each single-line
1039
- * YAML scalars (no `|` / `>` block forms). A multi-line `when_to_use:`
1040
- * is matched only by its first line — the `.+` regex stops at the
1041
- * newline — but since YAML block scalars start with the line that
1042
- * contains only `|` or `>`, the captured value would be the empty
1043
- * indicator and the inlined value would be useless. Phase 2 v1 keeps
1044
- * this conservative: callers must use single-line scalars (NG5).
1433
+ * docs/design/appendices/skills-unification.md Phase 1 parse the `name` and `description`
1434
+ * single-line YAML scalars out of a SKILL.md frontmatter block. Returns
1435
+ * `{ name: null, description: null }` when no frontmatter is present or
1436
+ * neither key is set. Multi-line block scalars (`description: |` /
1437
+ * `description: >`) are rejected at the regex level — the schema enforces
1438
+ * single-line scalars across all backends (R6).
1045
1439
  */
1046
- export function adaptSkillForCli(content) {
1440
+ export function parseSkillFrontmatter(content) {
1047
1441
  if (!content.startsWith("---"))
1048
- return content;
1442
+ return { name: null, description: null };
1049
1443
  const endIdx = content.indexOf("\n---", 3);
1050
1444
  if (endIdx < 0)
1051
- return content;
1052
- const frontmatter = content.slice(4, endIdx);
1053
- const body = content.slice(endIdx + 4);
1054
- const nameMatch = frontmatter.match(/^name:\s*(.+)$/m);
1055
- const descMatch = frontmatter.match(/^description:\s*(.+)$/m);
1056
- const whenMatch = frontmatter.match(/^when_to_use:\s*(.+)$/m);
1057
- // Reject multi-line block scalars (`when_to_use: |` / `when_to_use: >`):
1058
- // their first-line capture would just be the indicator. Falling through
1059
- // to "no when_to_use" matches the documented contract (§3.4.2 #9).
1060
- const whenIsBlockScalar = whenMatch !== null && /^[|>][-+]?\s*$/.test(whenMatch[1].trim());
1061
- const parts = ["---"];
1062
- if (nameMatch)
1063
- parts.push(`name: ${nameMatch[1].trim()}`);
1064
- if (descMatch)
1065
- parts.push(`description: ${descMatch[1].trim()}`);
1066
- if (whenMatch && !whenIsBlockScalar) {
1067
- parts.push(`when_to_use: ${whenMatch[1].trim()}`);
1445
+ return { name: null, description: null };
1446
+ const fm = content.slice(4, endIdx);
1447
+ const nameMatch = fm.match(/^name:\s*(.+)$/m);
1448
+ const descMatch = fm.match(/^description:\s*(.+)$/m);
1449
+ return {
1450
+ name: nameMatch ? nameMatch[1].trim() : null,
1451
+ description: descMatch ? descMatch[1].trim() : null,
1452
+ };
1453
+ }
1454
+ /**
1455
+ * docs/design/appendices/skills-unification.md Phase 1 §R5 — hard upper bound on a
1456
+ * SKILL.md `description` scalar. Enforced at SkillsCompiler construction
1457
+ * for built-in skills (refuses to boot on violation) and at
1458
+ * `PUT /api/skills/<slug>` for user-authored skills (HTTP 400). Sized to
1459
+ * fit the model's selection decision without pinning enough prose to
1460
+ * encode body content.
1461
+ */
1462
+ export const SKILL_DESCRIPTION_MAX_LENGTH = 280;
1463
+ /**
1464
+ * docs/design/appendices/skills-unification.md Phase 1 §"Codex read-sensitive banner
1465
+ * inheritance" — endpoints flagged `RiskTier.ReadSensitive` by
1466
+ * `safety/risk-classifier.ts` that a Codex session cannot satisfy (no
1467
+ * read-sensitive token). Any SKILL.md whose body references one of these
1468
+ * prefixes triggers a one-line banner prepend on the Codex copy. Listed
1469
+ * literally (not derived from `API_RISK` at module-load time) so the
1470
+ * core/skills-compiler module stays independent of safety/risk-classifier
1471
+ * — a circular import would invert the bootstrap order.
1472
+ *
1473
+ * Drift guard: `skills-compiler.test.ts` pins this list against the
1474
+ * RiskTier.ReadSensitive GET-prefix set in `risk-classifier.ts` so a new
1475
+ * read-sensitive endpoint added to API_RISK surfaces here at test time
1476
+ * instead of as silent 401 retries in a future Codex session.
1477
+ *
1478
+ * Exported for the drift-guard regression test only — production code
1479
+ * MUST use {@link skillBodyTouchesReadSensitive} to keep the
1480
+ * "literal prefix" decision encapsulated.
1481
+ */
1482
+ export const READ_SENSITIVE_API_PREFIXES = [
1483
+ "/api/apple-calendar",
1484
+ "/api/books",
1485
+ "/api/calendar",
1486
+ "/api/context",
1487
+ "/api/entities",
1488
+ "/api/mail",
1489
+ "/api/mcp/servers",
1490
+ "/api/notion",
1491
+ "/api/observations",
1492
+ "/api/obsidian",
1493
+ "/api/receipts",
1494
+ "/api/travel-bookings",
1495
+ ];
1496
+ function skillBodyTouchesReadSensitive(skillBody) {
1497
+ return READ_SENSITIVE_API_PREFIXES.some((prefix) => skillBody.includes(prefix));
1498
+ }
1499
+ const CODEX_READ_SENSITIVE_BANNER_HEADER = "<!-- codex-read-sensitive-banner -->";
1500
+ const CODEX_READ_SENSITIVE_BANNER = [
1501
+ CODEX_READ_SENSITIVE_BANNER_HEADER,
1502
+ "> NOTE (Codex session): Some endpoints in this skill are read-sensitive and",
1503
+ "> return 401 here. See `## Read-sensitive endpoints are UNAVAILABLE` in",
1504
+ "> AGENTS.md before invoking. Do not retry on 401 — stop and notify the user.",
1505
+ "",
1506
+ ].join("\n");
1507
+ /**
1508
+ * docs/design/appendices/skills-unification.md Phase 1 §"Codex read-sensitive banner
1509
+ * inheritance" — prepend the 3-line caveat banner to a Codex skill body
1510
+ * whose contents reference any read-sensitive `/api/*` endpoint. The
1511
+ * banner sits immediately after the YAML frontmatter (so the frontmatter
1512
+ * parser on the agent side still picks up `name`/`description`/
1513
+ * `allowed-tools` first) and is idempotent — re-running on an already-
1514
+ * banner-bearing file is a no-op (the HTML-comment sentinel lets us
1515
+ * detect prior insertion without false positives from user prose).
1516
+ *
1517
+ * No-op when:
1518
+ * - The skill body references zero read-sensitive endpoints.
1519
+ * - The banner is already present (sentinel hit).
1520
+ */
1521
+ function prependCodexReadSensitiveBanner(skillMdPath) {
1522
+ if (!existsSync(skillMdPath))
1523
+ return;
1524
+ const content = readFileSync(skillMdPath, "utf-8");
1525
+ if (!skillBodyTouchesReadSensitive(content))
1526
+ return;
1527
+ if (content.includes(CODEX_READ_SENSITIVE_BANNER_HEADER))
1528
+ return;
1529
+ if (!content.startsWith("---")) {
1530
+ writeFileSync(skillMdPath, CODEX_READ_SENSITIVE_BANNER + content, "utf-8");
1531
+ return;
1532
+ }
1533
+ const fmCloseIdx = content.indexOf("\n---", 3);
1534
+ if (fmCloseIdx < 0) {
1535
+ writeFileSync(skillMdPath, CODEX_READ_SENSITIVE_BANNER + content, "utf-8");
1536
+ return;
1068
1537
  }
1069
- parts.push("---");
1070
- return parts.join("\n") + body;
1538
+ const afterFm = fmCloseIdx + 4; // include `\n---`
1539
+ // Skip a single trailing newline after `---` so the banner sits on its
1540
+ // own line cleanly. If no newline follows, we still emit one before the
1541
+ // banner so the prose split is unambiguous.
1542
+ const head = content.slice(0, afterFm);
1543
+ const tail = content.slice(afterFm).replace(/^\n+/, "");
1544
+ writeFileSync(skillMdPath, `${head}\n\n${CODEX_READ_SENSITIVE_BANNER}${tail ? `\n${tail}` : ""}`, "utf-8");
1071
1545
  }
1546
+ /**
1547
+ * docs/design/appendices/skills-unification.md Phase 1 §"Skill preamble" — load the static
1548
+ * preamble shipped at
1549
+ * `agent-assets/system-prompts/skill-index-instruction.md`. The preamble
1550
+ * is constant per backend (Codex / Gemini) and explains the on-demand
1551
+ * skill-load protocol. Returns a built-in minimal fallback when the asset
1552
+ * is missing so tests that don't seed the system-prompts dir still
1553
+ * produce deterministic output.
1554
+ */
1555
+ function loadSkillIndexPreamble(workspaceDir) {
1556
+ const path = join(workspaceDir, "agent-assets", "system-prompts", "skill-index-instruction.md");
1557
+ if (existsSync(path)) {
1558
+ return readFileSync(path, "utf-8").trim();
1559
+ }
1560
+ return [
1561
+ "## Skills",
1562
+ "",
1563
+ "Skills are materialised on disk under the per-backend dotfile",
1564
+ "directory. When your task matches an entry in `<skill-index>` below,",
1565
+ "`Read` its `SKILL.md` and follow the contents.",
1566
+ ].join("\n");
1567
+ }
1568
+ /**
1569
+ * docs/design/appendices/skills-unification.md Phase 1 §"`<skill-index>` block" — render
1570
+ * the per-slug index from the **materialised** SKILL.md frontmatter on
1571
+ * disk. Walking the destination dir (instead of the source manifest)
1572
+ * keeps the index in sync with what the agent will actually find when
1573
+ * it reads:
1574
+ *
1575
+ * - Same-backend native MCP slugs whose variant resolved to `null` are
1576
+ * correctly omitted (no SKILL.md was written).
1577
+ * - User-authored slugs synced AFTER `writeSkillsDir` (via
1578
+ * `syncAllUserSkills` from the workdir layer) appear automatically
1579
+ * when this is called from the post-sync refresh helper.
1580
+ * - Frontmatter that has gone through curation / mode filter / deny
1581
+ * pass / read-sensitive banner reflects the post-pipeline state.
1582
+ *
1583
+ * The block is emitted with a fixed XML-style envelope so tests can pin
1584
+ * its placement and the splicer in `refreshSkillIndexBlock` can locate
1585
+ * it for in-place rewrites between turns.
1586
+ *
1587
+ * `destSkillsRootRelative` is the on-disk path the agent should Read
1588
+ * (`.codex/skills` or `.gemini/skills`); it gets embedded in the header
1589
+ * sentence verbatim. Built-ins and user-authored slugs are not
1590
+ * distinguished here — see R4.
1591
+ */
1592
+ /**
1593
+ * docs/design/appendices/skills-unification.md Phase 1 — splice sentinels.
1594
+ *
1595
+ * The visible `<skill-index>` / `</skill-index>` XML-style tags are the
1596
+ * agent-facing contract; they MUST stay in the rendered output for the
1597
+ * preamble's protocol to make sense. But using them as the splicer's
1598
+ * region markers is fragile — any profile body, skill body, or user
1599
+ * prose that quotes the tag verbatim would be misidentified as the
1600
+ * splice region and silently corrupted on `refreshSkillIndexBlock`.
1601
+ *
1602
+ * The sentinels below are unique HTML comments emitted immediately
1603
+ * outside the visible tags. The splicer keys on them instead, so even
1604
+ * a profile that quotes `<skill-index>` cannot collide with the splice
1605
+ * region. Comments render as low-signal tokens to the model and add
1606
+ * ~50 bytes per session — negligible against the ~3 KB block.
1607
+ */
1608
+ const SKILL_INDEX_START_SENTINEL = "<!-- skill-index:start -->";
1609
+ const SKILL_INDEX_END_SENTINEL = "<!-- skill-index:end -->";
1610
+ export function renderSkillIndexBlock(destSkillsRootAbs, destSkillsRootRelative) {
1611
+ const lines = [
1612
+ SKILL_INDEX_START_SENTINEL,
1613
+ "<skill-index>",
1614
+ `The following skills are materialized at \`${destSkillsRootRelative}/<name>/SKILL.md\`.`,
1615
+ "When your task matches a skill's `description`, `Read` the `SKILL.md`",
1616
+ "to load its guidance and follow it. Skill bodies are NOT inlined in",
1617
+ "this prompt — read them on demand. Multiple skills may be loaded in",
1618
+ "one turn.",
1619
+ "",
1620
+ ];
1621
+ let entryCount = 0;
1622
+ if (existsSync(destSkillsRootAbs)) {
1623
+ const slugs = readdirSync(destSkillsRootAbs, { withFileTypes: true })
1624
+ .filter((e) => e.isDirectory())
1625
+ .map((e) => e.name)
1626
+ .sort((a, b) => a.localeCompare(b));
1627
+ for (const slug of slugs) {
1628
+ const skillMdPath = join(destSkillsRootAbs, slug, "SKILL.md");
1629
+ if (!existsSync(skillMdPath))
1630
+ continue;
1631
+ const fm = parseSkillFrontmatter(readFileSync(skillMdPath, "utf-8"));
1632
+ if (!fm.name || !fm.description)
1633
+ continue;
1634
+ lines.push(`- name: ${fm.name}`);
1635
+ lines.push(` description: ${fm.description}`);
1636
+ entryCount++;
1637
+ }
1638
+ }
1639
+ if (entryCount === 0) {
1640
+ lines.push("(No skills materialized this turn — proceed with the runtime profile only.)");
1641
+ }
1642
+ lines.push("</skill-index>", SKILL_INDEX_END_SENTINEL);
1643
+ return lines.join("\n");
1644
+ }
1645
+ /**
1646
+ * docs/design/appendices/skills-unification.md Phase 1 — re-render the `<skill-index>` block
1647
+ * inside an existing instruction file. Called by the workdir layer AFTER
1648
+ * `syncAllUserSkills` so user-authored slugs land in the index alongside
1649
+ * the built-ins (`renderSkillIndexBlock` reads the dest dir on disk, so a
1650
+ * post-sync re-render naturally picks them up).
1651
+ *
1652
+ * No-op when:
1653
+ * - The backend is Claude (no instruction file with `<skill-index>`).
1654
+ * - The instruction file is missing (the session has not been
1655
+ * materialised yet).
1656
+ * - The instruction file carries no `<skill-index>` block (slim
1657
+ * fetch_window sessions, or future backends that opt out).
1658
+ *
1659
+ * Idempotent — re-running with the same dest contents produces an
1660
+ * identical instruction file.
1661
+ */
1662
+ export function refreshSkillIndexBlock(sessionDir, backendId) {
1663
+ // docs/design/appendices/skills-unification.md Phase 1 §R3 — OpenCode never gets a
1664
+ // `<skill-index>` block. The cwd auto-discovery loader is the source
1665
+ // of truth; emitting an index would inject a second listing the
1666
+ // runtime ignores. Also matters in fallback workdirs where codex and
1667
+ // opencode share AGENTS.md: a stray opencode refresh would clobber
1668
+ // the codex-rendered sentinels with opencode's skill listing.
1669
+ if (backendId === "claude" || backendId === "opencode")
1670
+ return;
1671
+ const cliRoot = cliSkillsDirName(backendId);
1672
+ if (cliRoot === null)
1673
+ return;
1674
+ const destSkillsRootRelative = join(cliRoot, "skills");
1675
+ const destSkillsRootAbs = join(sessionDir, destSkillsRootRelative);
1676
+ const fileName = backendId === "gemini" ? "GEMINI.md" : "AGENTS.md";
1677
+ const instructionPath = join(sessionDir, fileName);
1678
+ if (!existsSync(instructionPath))
1679
+ return;
1680
+ const current = readFileSync(instructionPath, "utf-8");
1681
+ // Splice on the HTML-comment sentinels, NOT on the visible
1682
+ // `<skill-index>` tags — the sentinels are unique enough that a
1683
+ // profile body or user-authored skill that quotes the visible tag
1684
+ // cannot collide with the splice region.
1685
+ const startIdx = current.indexOf(SKILL_INDEX_START_SENTINEL);
1686
+ const endIdx = startIdx >= 0
1687
+ ? current.indexOf(SKILL_INDEX_END_SENTINEL, startIdx + SKILL_INDEX_START_SENTINEL.length)
1688
+ : -1;
1689
+ if (startIdx < 0 || endIdx < 0)
1690
+ return; // OpenCode (no index) or slim path
1691
+ const replacement = renderSkillIndexBlock(destSkillsRootAbs, destSkillsRootRelative);
1692
+ const next = current.slice(0, startIdx) +
1693
+ replacement +
1694
+ current.slice(endIdx + SKILL_INDEX_END_SENTINEL.length);
1695
+ if (next !== current) {
1696
+ writeFileSync(instructionPath, next, "utf-8");
1697
+ }
1698
+ }
1699
+ /**
1700
+ * docs/design/appendices/skills-unification.md Phase 1 §R6 — `adaptSkillForCli` (which used
1701
+ * to retain only `name`/`description`/`when_to_use` and strip
1702
+ * `allowed-tools` from CLI-bound copies) is deleted. The source
1703
+ * SKILL.md frontmatter is byte-identical across all backends post-
1704
+ * materialisation. Codex / Gemini tolerate unknown YAML keys; OpenCode's
1705
+ * permissive frontmatter parser does too (verified against
1706
+ * `docs/design/appendices/opencode-backend.md` §5.5). The `when_to_use:` field has been
1707
+ * dropped from every built-in SKILL.md (Phase 0.1 of the sister doc) so
1708
+ * there is no per-backend fork to maintain.
1709
+ */
1072
1710
  /**
1073
1711
  * Resolve `{{> base }}` include directives in a skill/task-flow variant file.
1074
1712
  * Reads `SKILL.base.md` (or `<key>.base.md` for task flows) from `basePath`
@@ -1313,10 +1951,11 @@ function appendCliDenyBlock(content, namespacedDenied) {
1313
1951
  * own deny list.
1314
1952
  *
1315
1953
  * Hard enforcement of the same deny list for cross-backend delegated
1316
- * calls lives at the `POST /api/integrations/:key/invoke` chokepoint
1317
- * (DELEGATED-MODE-V2-DESIGN.md §4.3.2). For same-backend native MCP it
1318
- * is enforced via SDK `disallowedTools` (Claude) / admin policy
1319
- * (Gemini); see `collectSessionDeniedTools` (§4.3.3).
1954
+ * calls lives at the `POST /api/integrations/:key/exec` task-mode
1955
+ * chokepoint (DELEGATED-MODE-V2-DESIGN.md §4.3.2; the legacy `/invoke`
1956
+ * RPC was retired 2026-05-01). For same-backend native MCP it is
1957
+ * enforced via SDK `disallowedTools` (Claude) / admin policy (Gemini);
1958
+ * see `collectSessionDeniedTools` (§4.3.3).
1320
1959
  */
1321
1960
  export function applyAllDeniedToolsForSkill(content, skillSlug, backendId, integrations) {
1322
1961
  let result = content;