@vibesdotdev/external 0.0.0-stage → 1.0.0-rc.0

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 (1004) hide show
  1. package/LICENSE +18 -0
  2. package/README.md +68 -2
  3. package/REFERENCE.md +217 -0
  4. package/dist/acp/index.d.ts +28 -0
  5. package/dist/acp/index.d.ts.map +1 -0
  6. package/dist/acp/index.js +31 -0
  7. package/dist/acp/index.js.map +1 -0
  8. package/dist/ambient/agent-roster-heartbeat.d.ts +67 -0
  9. package/dist/ambient/agent-roster-heartbeat.d.ts.map +1 -0
  10. package/dist/ambient/agent-roster-heartbeat.js +257 -0
  11. package/dist/ambient/agent-roster-heartbeat.js.map +1 -0
  12. package/dist/ambient/attempt.d.ts +19 -0
  13. package/dist/ambient/attempt.d.ts.map +1 -0
  14. package/dist/ambient/attempt.js +39 -0
  15. package/dist/ambient/attempt.js.map +1 -0
  16. package/dist/ambient/cloud-agent-roster-provider.impl.d.ts +13 -0
  17. package/dist/ambient/cloud-agent-roster-provider.impl.d.ts.map +1 -0
  18. package/dist/ambient/cloud-agent-roster-provider.impl.js +71 -0
  19. package/dist/ambient/cloud-agent-roster-provider.impl.js.map +1 -0
  20. package/dist/ambient/cloud-authenticated-json.d.ts +69 -0
  21. package/dist/ambient/cloud-authenticated-json.d.ts.map +1 -0
  22. package/dist/ambient/cloud-authenticated-json.js +108 -0
  23. package/dist/ambient/cloud-authenticated-json.js.map +1 -0
  24. package/dist/ambient/cloud-touch-projection.impl.d.ts +74 -0
  25. package/dist/ambient/cloud-touch-projection.impl.d.ts.map +1 -0
  26. package/dist/ambient/cloud-touch-projection.impl.js +225 -0
  27. package/dist/ambient/cloud-touch-projection.impl.js.map +1 -0
  28. package/dist/ambient/collaboration-settings.d.ts +50 -0
  29. package/dist/ambient/collaboration-settings.d.ts.map +1 -0
  30. package/dist/ambient/collaboration-settings.js +57 -0
  31. package/dist/ambient/collaboration-settings.js.map +1 -0
  32. package/dist/ambient/collision-notice.d.ts +41 -0
  33. package/dist/ambient/collision-notice.d.ts.map +1 -0
  34. package/dist/ambient/collision-notice.js +104 -0
  35. package/dist/ambient/collision-notice.js.map +1 -0
  36. package/dist/ambient/default-collision-filter.impl.d.ts +19 -0
  37. package/dist/ambient/default-collision-filter.impl.d.ts.map +1 -0
  38. package/dist/ambient/default-collision-filter.impl.js +53 -0
  39. package/dist/ambient/default-collision-filter.impl.js.map +1 -0
  40. package/dist/ambient/default-notice-formatter.impl.d.ts +4 -0
  41. package/dist/ambient/default-notice-formatter.impl.d.ts.map +1 -0
  42. package/dist/ambient/default-notice-formatter.impl.js +38 -0
  43. package/dist/ambient/default-notice-formatter.impl.js.map +1 -0
  44. package/dist/ambient/file-access-ambient-drain.impl.d.ts +21 -0
  45. package/dist/ambient/file-access-ambient-drain.impl.d.ts.map +1 -0
  46. package/dist/ambient/file-access-ambient-drain.impl.js +53 -0
  47. package/dist/ambient/file-access-ambient-drain.impl.js.map +1 -0
  48. package/dist/ambient/file-access-ambient-drain.subscription.descriptor.d.ts +27 -0
  49. package/dist/ambient/file-access-ambient-drain.subscription.descriptor.d.ts.map +1 -0
  50. package/dist/ambient/file-access-ambient-drain.subscription.descriptor.js +27 -0
  51. package/dist/ambient/file-access-ambient-drain.subscription.descriptor.js.map +1 -0
  52. package/dist/ambient/file-access-ambient-fs.impl.d.ts +45 -0
  53. package/dist/ambient/file-access-ambient-fs.impl.d.ts.map +1 -0
  54. package/dist/ambient/file-access-ambient-fs.impl.js +243 -0
  55. package/dist/ambient/file-access-ambient-fs.impl.js.map +1 -0
  56. package/dist/ambient/file-access-ambient-fs.subscription.descriptor.d.ts +32 -0
  57. package/dist/ambient/file-access-ambient-fs.subscription.descriptor.d.ts.map +1 -0
  58. package/dist/ambient/file-access-ambient-fs.subscription.descriptor.js +39 -0
  59. package/dist/ambient/file-access-ambient-fs.subscription.descriptor.js.map +1 -0
  60. package/dist/ambient/file-access-ambient.impl.d.ts +32 -0
  61. package/dist/ambient/file-access-ambient.impl.d.ts.map +1 -0
  62. package/dist/ambient/file-access-ambient.impl.js +231 -0
  63. package/dist/ambient/file-access-ambient.impl.js.map +1 -0
  64. package/dist/ambient/file-access-ambient.subscription.descriptor.d.ts +31 -0
  65. package/dist/ambient/file-access-ambient.subscription.descriptor.d.ts.map +1 -0
  66. package/dist/ambient/file-access-ambient.subscription.descriptor.js +31 -0
  67. package/dist/ambient/file-access-ambient.subscription.descriptor.js.map +1 -0
  68. package/dist/ambient/file-access-shared.d.ts +48 -0
  69. package/dist/ambient/file-access-shared.d.ts.map +1 -0
  70. package/dist/ambient/file-access-shared.js +59 -0
  71. package/dist/ambient/file-access-shared.js.map +1 -0
  72. package/dist/ambient/message-transport.impl.d.ts +47 -0
  73. package/dist/ambient/message-transport.impl.d.ts.map +1 -0
  74. package/dist/ambient/message-transport.impl.js +300 -0
  75. package/dist/ambient/message-transport.impl.js.map +1 -0
  76. package/dist/ambient/pending-notices.d.ts +11 -0
  77. package/dist/ambient/pending-notices.d.ts.map +1 -0
  78. package/dist/ambient/pending-notices.js +24 -0
  79. package/dist/ambient/pending-notices.js.map +1 -0
  80. package/dist/ambient/subsystem-overlap.impl.d.ts +60 -0
  81. package/dist/ambient/subsystem-overlap.impl.d.ts.map +1 -0
  82. package/dist/ambient/subsystem-overlap.impl.js +127 -0
  83. package/dist/ambient/subsystem-overlap.impl.js.map +1 -0
  84. package/dist/cli/dev.external.hooks-install.descriptor.d.ts +7 -0
  85. package/dist/cli/dev.external.hooks-install.descriptor.d.ts.map +1 -0
  86. package/dist/cli/dev.external.hooks-install.descriptor.js +27 -0
  87. package/dist/cli/dev.external.hooks-install.descriptor.js.map +1 -0
  88. package/dist/cli/dev.external.hooks-install.impl.d.ts +9 -0
  89. package/dist/cli/dev.external.hooks-install.impl.d.ts.map +1 -0
  90. package/dist/cli/dev.external.hooks-install.impl.js +57 -0
  91. package/dist/cli/dev.external.hooks-install.impl.js.map +1 -0
  92. package/dist/cli/dev.external.hooks-list.descriptor.d.ts +7 -0
  93. package/dist/cli/dev.external.hooks-list.descriptor.d.ts.map +1 -0
  94. package/dist/cli/dev.external.hooks-list.descriptor.js +16 -0
  95. package/dist/cli/dev.external.hooks-list.descriptor.js.map +1 -0
  96. package/dist/cli/dev.external.hooks-list.impl.d.ts +3 -0
  97. package/dist/cli/dev.external.hooks-list.impl.d.ts.map +1 -0
  98. package/dist/cli/dev.external.hooks-list.impl.js +68 -0
  99. package/dist/cli/dev.external.hooks-list.impl.js.map +1 -0
  100. package/dist/cli/dev.external.hooks-uninstall.descriptor.d.ts +7 -0
  101. package/dist/cli/dev.external.hooks-uninstall.descriptor.d.ts.map +1 -0
  102. package/dist/cli/dev.external.hooks-uninstall.descriptor.js +30 -0
  103. package/dist/cli/dev.external.hooks-uninstall.descriptor.js.map +1 -0
  104. package/dist/cli/dev.external.hooks-uninstall.impl.d.ts +9 -0
  105. package/dist/cli/dev.external.hooks-uninstall.impl.d.ts.map +1 -0
  106. package/dist/cli/dev.external.hooks-uninstall.impl.js +59 -0
  107. package/dist/cli/dev.external.hooks-uninstall.impl.js.map +1 -0
  108. package/dist/cli/dev.external.hooks.call.descriptor.d.ts +12 -0
  109. package/dist/cli/dev.external.hooks.call.descriptor.d.ts.map +1 -0
  110. package/dist/cli/dev.external.hooks.call.descriptor.js +51 -0
  111. package/dist/cli/dev.external.hooks.call.descriptor.js.map +1 -0
  112. package/dist/cli/dev.external.hooks.call.impl.d.ts +6 -0
  113. package/dist/cli/dev.external.hooks.call.impl.d.ts.map +1 -0
  114. package/dist/cli/dev.external.hooks.call.impl.js +162 -0
  115. package/dist/cli/dev.external.hooks.call.impl.js.map +1 -0
  116. package/dist/cli/dev.external.hooks.descriptor.d.ts +9 -0
  117. package/dist/cli/dev.external.hooks.descriptor.d.ts.map +1 -0
  118. package/dist/cli/dev.external.hooks.descriptor.js +17 -0
  119. package/dist/cli/dev.external.hooks.descriptor.js.map +1 -0
  120. package/dist/cli/dev.external.launch.descriptor.d.ts +7 -0
  121. package/dist/cli/dev.external.launch.descriptor.d.ts.map +1 -0
  122. package/dist/cli/dev.external.launch.descriptor.js +31 -0
  123. package/dist/cli/dev.external.launch.descriptor.js.map +1 -0
  124. package/dist/cli/dev.external.launch.impl.d.ts +17 -0
  125. package/dist/cli/dev.external.launch.impl.d.ts.map +1 -0
  126. package/dist/cli/dev.external.launch.impl.js +137 -0
  127. package/dist/cli/dev.external.launch.impl.js.map +1 -0
  128. package/dist/cli/dev.external.presets-apply.descriptor.d.ts +7 -0
  129. package/dist/cli/dev.external.presets-apply.descriptor.d.ts.map +1 -0
  130. package/dist/cli/dev.external.presets-apply.descriptor.js +36 -0
  131. package/dist/cli/dev.external.presets-apply.descriptor.js.map +1 -0
  132. package/dist/cli/dev.external.presets-apply.impl.d.ts +3 -0
  133. package/dist/cli/dev.external.presets-apply.impl.d.ts.map +1 -0
  134. package/dist/cli/dev.external.presets-apply.impl.js +119 -0
  135. package/dist/cli/dev.external.presets-apply.impl.js.map +1 -0
  136. package/dist/cli/dev.external.presets-list.descriptor.d.ts +7 -0
  137. package/dist/cli/dev.external.presets-list.descriptor.d.ts.map +1 -0
  138. package/dist/cli/dev.external.presets-list.descriptor.js +21 -0
  139. package/dist/cli/dev.external.presets-list.descriptor.js.map +1 -0
  140. package/dist/cli/dev.external.presets-list.impl.d.ts +3 -0
  141. package/dist/cli/dev.external.presets-list.impl.d.ts.map +1 -0
  142. package/dist/cli/dev.external.presets-list.impl.js +33 -0
  143. package/dist/cli/dev.external.presets-list.impl.js.map +1 -0
  144. package/dist/cli/dev.external.presets-show.descriptor.d.ts +7 -0
  145. package/dist/cli/dev.external.presets-show.descriptor.d.ts.map +1 -0
  146. package/dist/cli/dev.external.presets-show.descriptor.js +29 -0
  147. package/dist/cli/dev.external.presets-show.descriptor.js.map +1 -0
  148. package/dist/cli/dev.external.presets-show.impl.d.ts +7 -0
  149. package/dist/cli/dev.external.presets-show.impl.d.ts.map +1 -0
  150. package/dist/cli/dev.external.presets-show.impl.js +39 -0
  151. package/dist/cli/dev.external.presets-show.impl.js.map +1 -0
  152. package/dist/cli/dev.external.presets.descriptor.d.ts +7 -0
  153. package/dist/cli/dev.external.presets.descriptor.d.ts.map +1 -0
  154. package/dist/cli/dev.external.presets.descriptor.js +15 -0
  155. package/dist/cli/dev.external.presets.descriptor.js.map +1 -0
  156. package/dist/cli/dev.external.setup.descriptor.d.ts +7 -0
  157. package/dist/cli/dev.external.setup.descriptor.d.ts.map +1 -0
  158. package/dist/cli/dev.external.setup.descriptor.js +29 -0
  159. package/dist/cli/dev.external.setup.descriptor.js.map +1 -0
  160. package/dist/cli/dev.external.setup.impl.d.ts +3 -0
  161. package/dist/cli/dev.external.setup.impl.d.ts.map +1 -0
  162. package/dist/cli/dev.external.setup.impl.js +129 -0
  163. package/dist/cli/dev.external.setup.impl.js.map +1 -0
  164. package/dist/cli/dev.external.skills-generate.descriptor.d.ts +7 -0
  165. package/dist/cli/dev.external.skills-generate.descriptor.d.ts.map +1 -0
  166. package/dist/cli/dev.external.skills-generate.descriptor.js +43 -0
  167. package/dist/cli/dev.external.skills-generate.descriptor.js.map +1 -0
  168. package/dist/cli/dev.external.skills-generate.impl.consumer.d.ts +3 -0
  169. package/dist/cli/dev.external.skills-generate.impl.consumer.d.ts.map +1 -0
  170. package/dist/cli/dev.external.skills-generate.impl.consumer.js +140 -0
  171. package/dist/cli/dev.external.skills-generate.impl.consumer.js.map +1 -0
  172. package/dist/cli/dev.external.skills.descriptor.d.ts +7 -0
  173. package/dist/cli/dev.external.skills.descriptor.d.ts.map +1 -0
  174. package/dist/cli/dev.external.skills.descriptor.js +15 -0
  175. package/dist/cli/dev.external.skills.descriptor.js.map +1 -0
  176. package/dist/cli/dev.external.status.descriptor.d.ts +7 -0
  177. package/dist/cli/dev.external.status.descriptor.d.ts.map +1 -0
  178. package/dist/cli/dev.external.status.descriptor.js +16 -0
  179. package/dist/cli/dev.external.status.descriptor.js.map +1 -0
  180. package/dist/cli/dev.external.status.impl.d.ts +24 -0
  181. package/dist/cli/dev.external.status.impl.d.ts.map +1 -0
  182. package/dist/cli/dev.external.status.impl.js +165 -0
  183. package/dist/cli/dev.external.status.impl.js.map +1 -0
  184. package/dist/cli/launch/launch.cli-group.descriptor.d.ts +4 -0
  185. package/dist/cli/launch/launch.cli-group.descriptor.d.ts.map +1 -0
  186. package/dist/cli/launch/launch.cli-group.descriptor.js +12 -0
  187. package/dist/cli/launch/launch.cli-group.descriptor.js.map +1 -0
  188. package/dist/cli/launch/launch.harness.impl.consumer.d.ts +6 -0
  189. package/dist/cli/launch/launch.harness.impl.consumer.d.ts.map +1 -0
  190. package/dist/cli/launch/launch.harness.impl.consumer.js +55 -0
  191. package/dist/cli/launch/launch.harness.impl.consumer.js.map +1 -0
  192. package/dist/cli/launch/launch.list.descriptor.d.ts +4 -0
  193. package/dist/cli/launch/launch.list.descriptor.d.ts.map +1 -0
  194. package/dist/cli/launch/launch.list.descriptor.js +13 -0
  195. package/dist/cli/launch/launch.list.descriptor.js.map +1 -0
  196. package/dist/cli/launch/launch.list.impl.consumer.d.ts +7 -0
  197. package/dist/cli/launch/launch.list.impl.consumer.d.ts.map +1 -0
  198. package/dist/cli/launch/launch.list.impl.consumer.js +26 -0
  199. package/dist/cli/launch/launch.list.impl.consumer.js.map +1 -0
  200. package/dist/cli/launch/launch.logs.descriptor.d.ts +4 -0
  201. package/dist/cli/launch/launch.logs.descriptor.d.ts.map +1 -0
  202. package/dist/cli/launch/launch.logs.descriptor.js +30 -0
  203. package/dist/cli/launch/launch.logs.descriptor.js.map +1 -0
  204. package/dist/cli/launch/launch.logs.impl.consumer.d.ts +7 -0
  205. package/dist/cli/launch/launch.logs.impl.consumer.d.ts.map +1 -0
  206. package/dist/cli/launch/launch.logs.impl.consumer.js +78 -0
  207. package/dist/cli/launch/launch.logs.impl.consumer.js.map +1 -0
  208. package/dist/cli/launch/launch.status.descriptor.d.ts +4 -0
  209. package/dist/cli/launch/launch.status.descriptor.d.ts.map +1 -0
  210. package/dist/cli/launch/launch.status.descriptor.js +21 -0
  211. package/dist/cli/launch/launch.status.descriptor.js.map +1 -0
  212. package/dist/cli/launch/launch.status.impl.consumer.d.ts +7 -0
  213. package/dist/cli/launch/launch.status.impl.consumer.d.ts.map +1 -0
  214. package/dist/cli/launch/launch.status.impl.consumer.js +69 -0
  215. package/dist/cli/launch/launch.status.impl.consumer.js.map +1 -0
  216. package/dist/cli/plugin.d.ts +4 -0
  217. package/dist/cli/plugin.d.ts.map +1 -0
  218. package/dist/cli/plugin.js +76 -0
  219. package/dist/cli/plugin.js.map +1 -0
  220. package/dist/cli/runtime-projection.d.ts +34 -0
  221. package/dist/cli/runtime-projection.d.ts.map +1 -0
  222. package/dist/cli/runtime-projection.js +272 -0
  223. package/dist/cli/runtime-projection.js.map +1 -0
  224. package/dist/cli/stdio.d.ts +15 -0
  225. package/dist/cli/stdio.d.ts.map +1 -0
  226. package/dist/cli/stdio.js +15 -0
  227. package/dist/cli/stdio.js.map +1 -0
  228. package/dist/cli/who.descriptor.d.ts +16 -0
  229. package/dist/cli/who.descriptor.d.ts.map +1 -0
  230. package/dist/cli/who.descriptor.js +38 -0
  231. package/dist/cli/who.descriptor.js.map +1 -0
  232. package/dist/cli/who.impl.d.ts +16 -0
  233. package/dist/cli/who.impl.d.ts.map +1 -0
  234. package/dist/cli/who.impl.js +127 -0
  235. package/dist/cli/who.impl.js.map +1 -0
  236. package/dist/client/external-client.d.ts +423 -0
  237. package/dist/client/external-client.d.ts.map +1 -0
  238. package/dist/client/external-client.js +979 -0
  239. package/dist/client/external-client.js.map +1 -0
  240. package/dist/client/index.d.ts +9 -0
  241. package/dist/client/index.d.ts.map +1 -0
  242. package/dist/client/index.js +8 -0
  243. package/dist/client/index.js.map +1 -0
  244. package/dist/client/lifecycle.d.ts +25 -0
  245. package/dist/client/lifecycle.d.ts.map +1 -0
  246. package/dist/client/lifecycle.js +134 -0
  247. package/dist/client/lifecycle.js.map +1 -0
  248. package/dist/config/binary-detection.d.ts +26 -0
  249. package/dist/config/binary-detection.d.ts.map +1 -0
  250. package/dist/config/binary-detection.js +105 -0
  251. package/dist/config/binary-detection.js.map +1 -0
  252. package/dist/config/external.config.descriptor.d.ts +11 -0
  253. package/dist/config/external.config.descriptor.d.ts.map +1 -0
  254. package/dist/config/external.config.descriptor.js +41 -0
  255. package/dist/config/external.config.descriptor.js.map +1 -0
  256. package/dist/config/index.d.ts +10 -0
  257. package/dist/config/index.d.ts.map +1 -0
  258. package/dist/config/index.js +10 -0
  259. package/dist/config/index.js.map +1 -0
  260. package/dist/config/manifest.d.ts +4696 -0
  261. package/dist/config/manifest.d.ts.map +1 -0
  262. package/dist/config/manifest.js +210 -0
  263. package/dist/config/manifest.js.map +1 -0
  264. package/dist/config/read.d.ts +13 -0
  265. package/dist/config/read.d.ts.map +1 -0
  266. package/dist/config/read.js +20 -0
  267. package/dist/config/read.js.map +1 -0
  268. package/dist/consumer.d.ts +15 -0
  269. package/dist/consumer.d.ts.map +1 -0
  270. package/dist/consumer.js +15 -0
  271. package/dist/consumer.js.map +1 -0
  272. package/dist/detection/base.d.ts +71 -0
  273. package/dist/detection/base.d.ts.map +1 -0
  274. package/dist/detection/base.js +115 -0
  275. package/dist/detection/base.js.map +1 -0
  276. package/dist/detection/command-probe.d.ts +43 -0
  277. package/dist/detection/command-probe.d.ts.map +1 -0
  278. package/dist/detection/command-probe.js +75 -0
  279. package/dist/detection/command-probe.js.map +1 -0
  280. package/dist/detection/config-document.d.ts +31 -0
  281. package/dist/detection/config-document.d.ts.map +1 -0
  282. package/dist/detection/config-document.js +138 -0
  283. package/dist/detection/config-document.js.map +1 -0
  284. package/dist/detection/index.d.ts +11 -0
  285. package/dist/detection/index.d.ts.map +1 -0
  286. package/dist/detection/index.js +13 -0
  287. package/dist/detection/index.js.map +1 -0
  288. package/dist/detection/manifest-detector-helpers.d.ts +45 -0
  289. package/dist/detection/manifest-detector-helpers.d.ts.map +1 -0
  290. package/dist/detection/manifest-detector-helpers.js +198 -0
  291. package/dist/detection/manifest-detector-helpers.js.map +1 -0
  292. package/dist/detection/manifest-detector.d.ts +34 -0
  293. package/dist/detection/manifest-detector.d.ts.map +1 -0
  294. package/dist/detection/manifest-detector.js +123 -0
  295. package/dist/detection/manifest-detector.js.map +1 -0
  296. package/dist/detection/service.d.ts +99 -0
  297. package/dist/detection/service.d.ts.map +1 -0
  298. package/dist/detection/service.js +124 -0
  299. package/dist/detection/service.js.map +1 -0
  300. package/dist/detection/types.d.ts +113 -0
  301. package/dist/detection/types.d.ts.map +1 -0
  302. package/dist/detection/types.js +30 -0
  303. package/dist/detection/types.js.map +1 -0
  304. package/dist/dev.external.descriptor.d.ts +9 -0
  305. package/dist/dev.external.descriptor.d.ts.map +1 -0
  306. package/dist/dev.external.descriptor.js +17 -0
  307. package/dist/dev.external.descriptor.js.map +1 -0
  308. package/dist/docs/external.ambient.docs.descriptor.d.ts +4 -0
  309. package/dist/docs/external.ambient.docs.descriptor.d.ts.map +1 -0
  310. package/dist/docs/external.ambient.docs.descriptor.js +109 -0
  311. package/dist/docs/external.ambient.docs.descriptor.js.map +1 -0
  312. package/dist/external-adapter/descriptors.d.ts +133 -0
  313. package/dist/external-adapter/descriptors.d.ts.map +1 -0
  314. package/dist/external-adapter/descriptors.js +70 -0
  315. package/dist/external-adapter/descriptors.js.map +1 -0
  316. package/dist/external-adapter/implementations.d.ts +13 -0
  317. package/dist/external-adapter/implementations.d.ts.map +1 -0
  318. package/dist/external-adapter/implementations.js +97 -0
  319. package/dist/external-adapter/implementations.js.map +1 -0
  320. package/dist/external-adapter/schemas/adapter.d.ts +66 -0
  321. package/dist/external-adapter/schemas/adapter.d.ts.map +1 -0
  322. package/dist/external-adapter/schemas/adapter.js +55 -0
  323. package/dist/external-adapter/schemas/adapter.js.map +1 -0
  324. package/dist/external-tool/impl/default-tool.d.ts +201 -0
  325. package/dist/external-tool/impl/default-tool.d.ts.map +1 -0
  326. package/dist/external-tool/impl/default-tool.js +243 -0
  327. package/dist/external-tool/impl/default-tool.js.map +1 -0
  328. package/dist/external-tool/interfaces/tool.d.ts +102 -0
  329. package/dist/external-tool/interfaces/tool.d.ts.map +1 -0
  330. package/dist/external-tool/interfaces/tool.js +2 -0
  331. package/dist/external-tool/interfaces/tool.js.map +1 -0
  332. package/dist/external-tool/loader.d.ts +5 -0
  333. package/dist/external-tool/loader.d.ts.map +1 -0
  334. package/dist/external-tool/loader.js +8 -0
  335. package/dist/external-tool/loader.js.map +1 -0
  336. package/dist/external-tool/path-template.d.ts +54 -0
  337. package/dist/external-tool/path-template.d.ts.map +1 -0
  338. package/dist/external-tool/path-template.js +65 -0
  339. package/dist/external-tool/path-template.js.map +1 -0
  340. package/dist/external-tool/runtime.d.ts +38 -0
  341. package/dist/external-tool/runtime.d.ts.map +1 -0
  342. package/dist/external-tool/runtime.js +89 -0
  343. package/dist/external-tool/runtime.js.map +1 -0
  344. package/dist/external-tool/schemas/tool.d.ts +269 -0
  345. package/dist/external-tool/schemas/tool.d.ts.map +1 -0
  346. package/dist/external-tool/schemas/tool.js +77 -0
  347. package/dist/external-tool/schemas/tool.js.map +1 -0
  348. package/dist/external.plugin.d.ts +4 -0
  349. package/dist/external.plugin.d.ts.map +1 -0
  350. package/dist/external.plugin.js +184 -0
  351. package/dist/external.plugin.js.map +1 -0
  352. package/dist/harness/agent-host-scope.d.ts +18 -0
  353. package/dist/harness/agent-host-scope.d.ts.map +1 -0
  354. package/dist/harness/agent-host-scope.js +30 -0
  355. package/dist/harness/agent-host-scope.js.map +1 -0
  356. package/dist/harness/agent-host-settings.d.ts +6 -0
  357. package/dist/harness/agent-host-settings.d.ts.map +1 -0
  358. package/dist/harness/agent-host-settings.js +18 -0
  359. package/dist/harness/agent-host-settings.js.map +1 -0
  360. package/dist/harness/agent-host.config.descriptor.d.ts +6 -0
  361. package/dist/harness/agent-host.config.descriptor.d.ts.map +1 -0
  362. package/dist/harness/agent-host.config.descriptor.js +22 -0
  363. package/dist/harness/agent-host.config.descriptor.js.map +1 -0
  364. package/dist/harness/agent-host.d.ts +98 -0
  365. package/dist/harness/agent-host.d.ts.map +1 -0
  366. package/dist/harness/agent-host.js +201 -0
  367. package/dist/harness/agent-host.js.map +1 -0
  368. package/dist/harness/command-arguments.d.ts +54 -0
  369. package/dist/harness/command-arguments.d.ts.map +1 -0
  370. package/dist/harness/command-arguments.js +113 -0
  371. package/dist/harness/command-arguments.js.map +1 -0
  372. package/dist/harness/command-execution.d.ts +20 -0
  373. package/dist/harness/command-execution.d.ts.map +1 -0
  374. package/dist/harness/command-execution.js +78 -0
  375. package/dist/harness/command-execution.js.map +1 -0
  376. package/dist/harness/command-output.d.ts +59 -0
  377. package/dist/harness/command-output.d.ts.map +1 -0
  378. package/dist/harness/command-output.js +173 -0
  379. package/dist/harness/command-output.js.map +1 -0
  380. package/dist/harness/execution-queue.d.ts +14 -0
  381. package/dist/harness/execution-queue.d.ts.map +1 -0
  382. package/dist/harness/execution-queue.js +23 -0
  383. package/dist/harness/execution-queue.js.map +1 -0
  384. package/dist/harness/index.d.ts +15 -0
  385. package/dist/harness/index.d.ts.map +1 -0
  386. package/dist/harness/index.js +12 -0
  387. package/dist/harness/index.js.map +1 -0
  388. package/dist/harness/live-tools.d.ts +130 -0
  389. package/dist/harness/live-tools.d.ts.map +1 -0
  390. package/dist/harness/live-tools.js +257 -0
  391. package/dist/harness/live-tools.js.map +1 -0
  392. package/dist/harness/managed-block.d.ts +34 -0
  393. package/dist/harness/managed-block.d.ts.map +1 -0
  394. package/dist/harness/managed-block.js +66 -0
  395. package/dist/harness/managed-block.js.map +1 -0
  396. package/dist/harness/markers.d.ts +22 -0
  397. package/dist/harness/markers.d.ts.map +1 -0
  398. package/dist/harness/markers.js +28 -0
  399. package/dist/harness/markers.js.map +1 -0
  400. package/dist/harness/node.d.ts +6 -0
  401. package/dist/harness/node.d.ts.map +1 -0
  402. package/dist/harness/node.js +6 -0
  403. package/dist/harness/node.js.map +1 -0
  404. package/dist/harness/prompt.d.ts +54 -0
  405. package/dist/harness/prompt.d.ts.map +1 -0
  406. package/dist/harness/prompt.js +78 -0
  407. package/dist/harness/prompt.js.map +1 -0
  408. package/dist/harness/prompts/index.d.ts +113 -0
  409. package/dist/harness/prompts/index.d.ts.map +1 -0
  410. package/dist/harness/prompts/index.js +5 -0
  411. package/dist/harness/prompts/index.js.map +1 -0
  412. package/dist/harness/prompts/static-briefing-note.prompt.descriptor.d.ts +114 -0
  413. package/dist/harness/prompts/static-briefing-note.prompt.descriptor.d.ts.map +1 -0
  414. package/dist/harness/prompts/static-briefing-note.prompt.descriptor.js +17 -0
  415. package/dist/harness/prompts/static-briefing-note.prompt.descriptor.js.map +1 -0
  416. package/dist/harness/prompts/system-prompt.prompt.descriptor.d.ts +114 -0
  417. package/dist/harness/prompts/system-prompt.prompt.descriptor.d.ts.map +1 -0
  418. package/dist/harness/prompts/system-prompt.prompt.descriptor.js +35 -0
  419. package/dist/harness/prompts/system-prompt.prompt.descriptor.js.map +1 -0
  420. package/dist/harness/role-prompt.d.ts +12 -0
  421. package/dist/harness/role-prompt.d.ts.map +1 -0
  422. package/dist/harness/role-prompt.js +24 -0
  423. package/dist/harness/role-prompt.js.map +1 -0
  424. package/dist/harness/runtime-transport.d.ts +89 -0
  425. package/dist/harness/runtime-transport.d.ts.map +1 -0
  426. package/dist/harness/runtime-transport.js +356 -0
  427. package/dist/harness/runtime-transport.js.map +1 -0
  428. package/dist/harness/schemas/agent-host.d.ts +142 -0
  429. package/dist/harness/schemas/agent-host.d.ts.map +1 -0
  430. package/dist/harness/schemas/agent-host.js +26 -0
  431. package/dist/harness/schemas/agent-host.js.map +1 -0
  432. package/dist/harness/stdio-sink.d.ts +35 -0
  433. package/dist/harness/stdio-sink.d.ts.map +1 -0
  434. package/dist/harness/stdio-sink.js +34 -0
  435. package/dist/harness/stdio-sink.js.map +1 -0
  436. package/dist/harness/strip-undefined.d.ts +9 -0
  437. package/dist/harness/strip-undefined.d.ts.map +1 -0
  438. package/dist/harness/strip-undefined.js +11 -0
  439. package/dist/harness/strip-undefined.js.map +1 -0
  440. package/dist/harness/tool-projection.d.ts +130 -0
  441. package/dist/harness/tool-projection.d.ts.map +1 -0
  442. package/dist/harness/tool-projection.js +195 -0
  443. package/dist/harness/tool-projection.js.map +1 -0
  444. package/dist/harness/validation-errors.d.ts +11 -0
  445. package/dist/harness/validation-errors.d.ts.map +1 -0
  446. package/dist/harness/validation-errors.js +32 -0
  447. package/dist/harness/validation-errors.js.map +1 -0
  448. package/dist/hooks/bounded-payload.d.ts +39 -0
  449. package/dist/hooks/bounded-payload.d.ts.map +1 -0
  450. package/dist/hooks/bounded-payload.js +70 -0
  451. package/dist/hooks/bounded-payload.js.map +1 -0
  452. package/dist/hooks/bridge.d.ts +34 -0
  453. package/dist/hooks/bridge.d.ts.map +1 -0
  454. package/dist/hooks/bridge.js +86 -0
  455. package/dist/hooks/bridge.js.map +1 -0
  456. package/dist/hooks/call.d.ts +298 -0
  457. package/dist/hooks/call.d.ts.map +1 -0
  458. package/dist/hooks/call.js +1550 -0
  459. package/dist/hooks/call.js.map +1 -0
  460. package/dist/hooks/consumer.d.ts +7 -0
  461. package/dist/hooks/consumer.d.ts.map +1 -0
  462. package/dist/hooks/consumer.js +5 -0
  463. package/dist/hooks/consumer.js.map +1 -0
  464. package/dist/hooks/continuity.d.ts +155 -0
  465. package/dist/hooks/continuity.d.ts.map +1 -0
  466. package/dist/hooks/continuity.js +187 -0
  467. package/dist/hooks/continuity.js.map +1 -0
  468. package/dist/hooks/dispatch-script.d.ts +27 -0
  469. package/dist/hooks/dispatch-script.d.ts.map +1 -0
  470. package/dist/hooks/dispatch-script.js +77 -0
  471. package/dist/hooks/dispatch-script.js.map +1 -0
  472. package/dist/hooks/edit-targets.d.ts +23 -0
  473. package/dist/hooks/edit-targets.d.ts.map +1 -0
  474. package/dist/hooks/edit-targets.js +74 -0
  475. package/dist/hooks/edit-targets.js.map +1 -0
  476. package/dist/hooks/hook-delivery.d.ts +21 -0
  477. package/dist/hooks/hook-delivery.d.ts.map +1 -0
  478. package/dist/hooks/hook-delivery.js +87 -0
  479. package/dist/hooks/hook-delivery.js.map +1 -0
  480. package/dist/hooks/hook-seat.d.ts +37 -0
  481. package/dist/hooks/hook-seat.d.ts.map +1 -0
  482. package/dist/hooks/hook-seat.js +59 -0
  483. package/dist/hooks/hook-seat.js.map +1 -0
  484. package/dist/hooks/index.d.ts +9 -0
  485. package/dist/hooks/index.d.ts.map +1 -0
  486. package/dist/hooks/index.js +8 -0
  487. package/dist/hooks/index.js.map +1 -0
  488. package/dist/hooks/native-edit-guard.d.ts +25 -0
  489. package/dist/hooks/native-edit-guard.d.ts.map +1 -0
  490. package/dist/hooks/native-edit-guard.js +33 -0
  491. package/dist/hooks/native-edit-guard.js.map +1 -0
  492. package/dist/hooks/native-edit-locks.d.ts +54 -0
  493. package/dist/hooks/native-edit-locks.d.ts.map +1 -0
  494. package/dist/hooks/native-edit-locks.js +98 -0
  495. package/dist/hooks/native-edit-locks.js.map +1 -0
  496. package/dist/hooks/resolve-event.d.ts +13 -0
  497. package/dist/hooks/resolve-event.d.ts.map +1 -0
  498. package/dist/hooks/resolve-event.js +32 -0
  499. package/dist/hooks/resolve-event.js.map +1 -0
  500. package/dist/hooks/review-state.d.ts +22 -0
  501. package/dist/hooks/review-state.d.ts.map +1 -0
  502. package/dist/hooks/review-state.js +57 -0
  503. package/dist/hooks/review-state.js.map +1 -0
  504. package/dist/hooks/runtime.d.ts +146 -0
  505. package/dist/hooks/runtime.d.ts.map +1 -0
  506. package/dist/hooks/runtime.js +83 -0
  507. package/dist/hooks/runtime.js.map +1 -0
  508. package/dist/hooks/self-review.d.ts +14 -0
  509. package/dist/hooks/self-review.d.ts.map +1 -0
  510. package/dist/hooks/self-review.js +28 -0
  511. package/dist/hooks/self-review.js.map +1 -0
  512. package/dist/index.d.ts +41 -0
  513. package/dist/index.d.ts.map +1 -0
  514. package/dist/index.js +33 -0
  515. package/dist/index.js.map +1 -0
  516. package/dist/ingest/logging/subagent-completions.output.descriptor.d.ts +4 -0
  517. package/dist/ingest/logging/subagent-completions.output.descriptor.d.ts.map +1 -0
  518. package/dist/ingest/logging/subagent-completions.output.descriptor.js +22 -0
  519. package/dist/ingest/logging/subagent-completions.output.descriptor.js.map +1 -0
  520. package/dist/ingest/logging/success-patterns.output.descriptor.d.ts +4 -0
  521. package/dist/ingest/logging/success-patterns.output.descriptor.d.ts.map +1 -0
  522. package/dist/ingest/logging/success-patterns.output.descriptor.js +22 -0
  523. package/dist/ingest/logging/success-patterns.output.descriptor.js.map +1 -0
  524. package/dist/ingest/logging/tool-use.output.descriptor.d.ts +4 -0
  525. package/dist/ingest/logging/tool-use.output.descriptor.d.ts.map +1 -0
  526. package/dist/ingest/logging/tool-use.output.descriptor.js +22 -0
  527. package/dist/ingest/logging/tool-use.output.descriptor.js.map +1 -0
  528. package/dist/ingest/resolve-log-paths.d.ts +16 -0
  529. package/dist/ingest/resolve-log-paths.d.ts.map +1 -0
  530. package/dist/ingest/resolve-log-paths.js +43 -0
  531. package/dist/ingest/resolve-log-paths.js.map +1 -0
  532. package/dist/ingest/schemas.d.ts +43 -0
  533. package/dist/ingest/schemas.d.ts.map +1 -0
  534. package/dist/ingest/schemas.js +46 -0
  535. package/dist/ingest/schemas.js.map +1 -0
  536. package/dist/jsonrpc/client.d.ts +129 -0
  537. package/dist/jsonrpc/client.d.ts.map +1 -0
  538. package/dist/jsonrpc/client.js +553 -0
  539. package/dist/jsonrpc/client.js.map +1 -0
  540. package/dist/jsonrpc/envelope.d.ts +37 -0
  541. package/dist/jsonrpc/envelope.d.ts.map +1 -0
  542. package/dist/jsonrpc/envelope.js +46 -0
  543. package/dist/jsonrpc/envelope.js.map +1 -0
  544. package/dist/jsonrpc/errors.d.ts +28 -0
  545. package/dist/jsonrpc/errors.d.ts.map +1 -0
  546. package/dist/jsonrpc/errors.js +110 -0
  547. package/dist/jsonrpc/errors.js.map +1 -0
  548. package/dist/jsonrpc/framing.d.ts +35 -0
  549. package/dist/jsonrpc/framing.d.ts.map +1 -0
  550. package/dist/jsonrpc/framing.js +134 -0
  551. package/dist/jsonrpc/framing.js.map +1 -0
  552. package/dist/jsonrpc/index.d.ts +11 -0
  553. package/dist/jsonrpc/index.d.ts.map +1 -0
  554. package/dist/jsonrpc/index.js +11 -0
  555. package/dist/jsonrpc/index.js.map +1 -0
  556. package/dist/jsonrpc/outcome.d.ts +25 -0
  557. package/dist/jsonrpc/outcome.d.ts.map +1 -0
  558. package/dist/jsonrpc/outcome.js +32 -0
  559. package/dist/jsonrpc/outcome.js.map +1 -0
  560. package/dist/jsonrpc/queue.d.ts +30 -0
  561. package/dist/jsonrpc/queue.d.ts.map +1 -0
  562. package/dist/jsonrpc/queue.js +113 -0
  563. package/dist/jsonrpc/queue.js.map +1 -0
  564. package/dist/jsonrpc/schemas.d.ts +74 -0
  565. package/dist/jsonrpc/schemas.d.ts.map +1 -0
  566. package/dist/jsonrpc/schemas.js +65 -0
  567. package/dist/jsonrpc/schemas.js.map +1 -0
  568. package/dist/launch/consumer/execute.d.ts +5 -0
  569. package/dist/launch/consumer/execute.d.ts.map +1 -0
  570. package/dist/launch/consumer/execute.js +358 -0
  571. package/dist/launch/consumer/execute.js.map +1 -0
  572. package/dist/launch/consumer/paths.d.ts +15 -0
  573. package/dist/launch/consumer/paths.d.ts.map +1 -0
  574. package/dist/launch/consumer/paths.js +18 -0
  575. package/dist/launch/consumer/paths.js.map +1 -0
  576. package/dist/launch/consumer/prepare.d.ts +25 -0
  577. package/dist/launch/consumer/prepare.d.ts.map +1 -0
  578. package/dist/launch/consumer/prepare.js +158 -0
  579. package/dist/launch/consumer/prepare.js.map +1 -0
  580. package/dist/launch/consumer/prompt.d.ts +18 -0
  581. package/dist/launch/consumer/prompt.d.ts.map +1 -0
  582. package/dist/launch/consumer/prompt.js +45 -0
  583. package/dist/launch/consumer/prompt.js.map +1 -0
  584. package/dist/launch/consumer/rotate-logs.d.ts +23 -0
  585. package/dist/launch/consumer/rotate-logs.d.ts.map +1 -0
  586. package/dist/launch/consumer/rotate-logs.js +43 -0
  587. package/dist/launch/consumer/rotate-logs.js.map +1 -0
  588. package/dist/launch/consumer/spawn.d.ts +38 -0
  589. package/dist/launch/consumer/spawn.d.ts.map +1 -0
  590. package/dist/launch/consumer/spawn.js +82 -0
  591. package/dist/launch/consumer/spawn.js.map +1 -0
  592. package/dist/launch/consumer/state-rows.d.ts +41 -0
  593. package/dist/launch/consumer/state-rows.d.ts.map +1 -0
  594. package/dist/launch/consumer/state-rows.js +78 -0
  595. package/dist/launch/consumer/state-rows.js.map +1 -0
  596. package/dist/launch/consumer/store.d.ts +139 -0
  597. package/dist/launch/consumer/store.d.ts.map +1 -0
  598. package/dist/launch/consumer/store.js +495 -0
  599. package/dist/launch/consumer/store.js.map +1 -0
  600. package/dist/launch/index.d.ts +5 -0
  601. package/dist/launch/index.d.ts.map +1 -0
  602. package/dist/launch/index.js +3 -0
  603. package/dist/launch/index.js.map +1 -0
  604. package/dist/launch/resolve.d.ts +9 -0
  605. package/dist/launch/resolve.d.ts.map +1 -0
  606. package/dist/launch/resolve.js +139 -0
  607. package/dist/launch/resolve.js.map +1 -0
  608. package/dist/launch/schemas.d.ts +289 -0
  609. package/dist/launch/schemas.d.ts.map +1 -0
  610. package/dist/launch/schemas.js +154 -0
  611. package/dist/launch/schemas.js.map +1 -0
  612. package/dist/launch/task-executor/external-harness.descriptor.d.ts +6 -0
  613. package/dist/launch/task-executor/external-harness.descriptor.d.ts.map +1 -0
  614. package/dist/launch/task-executor/external-harness.descriptor.js +13 -0
  615. package/dist/launch/task-executor/external-harness.descriptor.js.map +1 -0
  616. package/dist/launch/task-executor/external-harness.impl.consumer.d.ts +17 -0
  617. package/dist/launch/task-executor/external-harness.impl.consumer.d.ts.map +1 -0
  618. package/dist/launch/task-executor/external-harness.impl.consumer.js +151 -0
  619. package/dist/launch/task-executor/external-harness.impl.consumer.js.map +1 -0
  620. package/dist/launch/task-executor/isolated-workspace.d.ts +3 -0
  621. package/dist/launch/task-executor/isolated-workspace.d.ts.map +1 -0
  622. package/dist/launch/task-executor/isolated-workspace.js +3 -0
  623. package/dist/launch/task-executor/isolated-workspace.js.map +1 -0
  624. package/dist/launch/task-executor/session-locks.d.ts +28 -0
  625. package/dist/launch/task-executor/session-locks.d.ts.map +1 -0
  626. package/dist/launch/task-executor/session-locks.js +50 -0
  627. package/dist/launch/task-executor/session-locks.js.map +1 -0
  628. package/dist/pack/adapter-codegen.d.ts +38 -0
  629. package/dist/pack/adapter-codegen.d.ts.map +1 -0
  630. package/dist/pack/adapter-codegen.js +70 -0
  631. package/dist/pack/adapter-codegen.js.map +1 -0
  632. package/dist/pack/build.d.ts +48 -0
  633. package/dist/pack/build.d.ts.map +1 -0
  634. package/dist/pack/build.js +171 -0
  635. package/dist/pack/build.js.map +1 -0
  636. package/dist/pack/emitters/hooks.d.ts +14 -0
  637. package/dist/pack/emitters/hooks.d.ts.map +1 -0
  638. package/dist/pack/emitters/hooks.js +15 -0
  639. package/dist/pack/emitters/hooks.js.map +1 -0
  640. package/dist/pack/emitters/json.d.ts +10 -0
  641. package/dist/pack/emitters/json.d.ts.map +1 -0
  642. package/dist/pack/emitters/json.js +17 -0
  643. package/dist/pack/emitters/json.js.map +1 -0
  644. package/dist/pack/emitters/registry.d.ts +22 -0
  645. package/dist/pack/emitters/registry.d.ts.map +1 -0
  646. package/dist/pack/emitters/registry.js +38 -0
  647. package/dist/pack/emitters/registry.js.map +1 -0
  648. package/dist/pack/emitters/toml.d.ts +8 -0
  649. package/dist/pack/emitters/toml.d.ts.map +1 -0
  650. package/dist/pack/emitters/toml.js +28 -0
  651. package/dist/pack/emitters/toml.js.map +1 -0
  652. package/dist/pack/emitters/yaml.d.ts +8 -0
  653. package/dist/pack/emitters/yaml.d.ts.map +1 -0
  654. package/dist/pack/emitters/yaml.js +27 -0
  655. package/dist/pack/emitters/yaml.js.map +1 -0
  656. package/dist/pack/index.d.ts +11 -0
  657. package/dist/pack/index.d.ts.map +1 -0
  658. package/dist/pack/index.js +11 -0
  659. package/dist/pack/index.js.map +1 -0
  660. package/dist/pack/mcp.d.ts +28 -0
  661. package/dist/pack/mcp.d.ts.map +1 -0
  662. package/dist/pack/mcp.js +70 -0
  663. package/dist/pack/mcp.js.map +1 -0
  664. package/dist/pack/persist.d.ts +28 -0
  665. package/dist/pack/persist.d.ts.map +1 -0
  666. package/dist/pack/persist.js +35 -0
  667. package/dist/pack/persist.js.map +1 -0
  668. package/dist/pack/schema.d.ts +126 -0
  669. package/dist/pack/schema.d.ts.map +1 -0
  670. package/dist/pack/schema.js +56 -0
  671. package/dist/pack/schema.js.map +1 -0
  672. package/dist/plugins/index.d.ts +512 -0
  673. package/dist/plugins/index.d.ts.map +1 -0
  674. package/dist/plugins/index.js +25 -0
  675. package/dist/plugins/index.js.map +1 -0
  676. package/dist/plugins/installers/config-file.d.ts +21 -0
  677. package/dist/plugins/installers/config-file.d.ts.map +1 -0
  678. package/dist/plugins/installers/config-file.js +48 -0
  679. package/dist/plugins/installers/config-file.js.map +1 -0
  680. package/dist/plugins/installers/config-value.d.ts +35 -0
  681. package/dist/plugins/installers/config-value.d.ts.map +1 -0
  682. package/dist/plugins/installers/config-value.js +52 -0
  683. package/dist/plugins/installers/config-value.js.map +1 -0
  684. package/dist/plugins/installers/hooks/index.d.ts +9 -0
  685. package/dist/plugins/installers/hooks/index.d.ts.map +1 -0
  686. package/dist/plugins/installers/hooks/index.js +12 -0
  687. package/dist/plugins/installers/hooks/index.js.map +1 -0
  688. package/dist/plugins/installers/hooks/scoped-paths.d.ts +24 -0
  689. package/dist/plugins/installers/hooks/scoped-paths.d.ts.map +1 -0
  690. package/dist/plugins/installers/hooks/scoped-paths.js +80 -0
  691. package/dist/plugins/installers/hooks/scoped-paths.js.map +1 -0
  692. package/dist/plugins/installers/hooks/settings-registration.d.ts +79 -0
  693. package/dist/plugins/installers/hooks/settings-registration.d.ts.map +1 -0
  694. package/dist/plugins/installers/hooks/settings-registration.js +125 -0
  695. package/dist/plugins/installers/hooks/settings-registration.js.map +1 -0
  696. package/dist/plugins/installers/hooks/shell-installer.d.ts +21 -0
  697. package/dist/plugins/installers/hooks/shell-installer.d.ts.map +1 -0
  698. package/dist/plugins/installers/hooks/shell-installer.js +298 -0
  699. package/dist/plugins/installers/hooks/shell-installer.js.map +1 -0
  700. package/dist/plugins/installers/hooks/uninstall-backup.d.ts +19 -0
  701. package/dist/plugins/installers/hooks/uninstall-backup.d.ts.map +1 -0
  702. package/dist/plugins/installers/hooks/uninstall-backup.js +20 -0
  703. package/dist/plugins/installers/hooks/uninstall-backup.js.map +1 -0
  704. package/dist/plugins/installers/index.d.ts +58 -0
  705. package/dist/plugins/installers/index.d.ts.map +1 -0
  706. package/dist/plugins/installers/index.js +303 -0
  707. package/dist/plugins/installers/index.js.map +1 -0
  708. package/dist/plugins/installers/mcp/environment.d.ts +180 -0
  709. package/dist/plugins/installers/mcp/environment.d.ts.map +1 -0
  710. package/dist/plugins/installers/mcp/environment.js +314 -0
  711. package/dist/plugins/installers/mcp/environment.js.map +1 -0
  712. package/dist/plugins/installers/mcp/index.d.ts +9 -0
  713. package/dist/plugins/installers/mcp/index.d.ts.map +1 -0
  714. package/dist/plugins/installers/mcp/index.js +11 -0
  715. package/dist/plugins/installers/mcp/index.js.map +1 -0
  716. package/dist/plugins/installers/mcp/json-installer.d.ts +18 -0
  717. package/dist/plugins/installers/mcp/json-installer.d.ts.map +1 -0
  718. package/dist/plugins/installers/mcp/json-installer.js +155 -0
  719. package/dist/plugins/installers/mcp/json-installer.js.map +1 -0
  720. package/dist/plugins/installers/mcp/json-paths.d.ts +13 -0
  721. package/dist/plugins/installers/mcp/json-paths.d.ts.map +1 -0
  722. package/dist/plugins/installers/mcp/json-paths.js +130 -0
  723. package/dist/plugins/installers/mcp/json-paths.js.map +1 -0
  724. package/dist/plugins/installers/mcp/serve-identity.d.ts +19 -0
  725. package/dist/plugins/installers/mcp/serve-identity.d.ts.map +1 -0
  726. package/dist/plugins/installers/mcp/serve-identity.js +31 -0
  727. package/dist/plugins/installers/mcp/serve-identity.js.map +1 -0
  728. package/dist/plugins/installers/mcp/server-config.d.ts +20 -0
  729. package/dist/plugins/installers/mcp/server-config.d.ts.map +1 -0
  730. package/dist/plugins/installers/mcp/server-config.js +64 -0
  731. package/dist/plugins/installers/mcp/server-config.js.map +1 -0
  732. package/dist/plugins/installers/mcp/toml-installer.d.ts +41 -0
  733. package/dist/plugins/installers/mcp/toml-installer.d.ts.map +1 -0
  734. package/dist/plugins/installers/mcp/toml-installer.js +407 -0
  735. package/dist/plugins/installers/mcp/toml-installer.js.map +1 -0
  736. package/dist/plugins/installers/mcp/yaml-installer.d.ts +22 -0
  737. package/dist/plugins/installers/mcp/yaml-installer.d.ts.map +1 -0
  738. package/dist/plugins/installers/mcp/yaml-installer.js +156 -0
  739. package/dist/plugins/installers/mcp/yaml-installer.js.map +1 -0
  740. package/dist/plugins/installers/runtime.d.ts +42 -0
  741. package/dist/plugins/installers/runtime.d.ts.map +1 -0
  742. package/dist/plugins/installers/runtime.js +56 -0
  743. package/dist/plugins/installers/runtime.js.map +1 -0
  744. package/dist/plugins/installers/types.d.ts +306 -0
  745. package/dist/plugins/installers/types.d.ts.map +1 -0
  746. package/dist/plugins/installers/types.js +40 -0
  747. package/dist/plugins/installers/types.js.map +1 -0
  748. package/dist/plugins/schemas/index.d.ts +6 -0
  749. package/dist/plugins/schemas/index.d.ts.map +1 -0
  750. package/dist/plugins/schemas/index.js +5 -0
  751. package/dist/plugins/schemas/index.js.map +1 -0
  752. package/dist/plugins/schemas/manifest.d.ts +527 -0
  753. package/dist/plugins/schemas/manifest.d.ts.map +1 -0
  754. package/dist/plugins/schemas/manifest.js +355 -0
  755. package/dist/plugins/schemas/manifest.js.map +1 -0
  756. package/dist/plugins/tools/index.d.ts +12 -0
  757. package/dist/plugins/tools/index.d.ts.map +1 -0
  758. package/dist/plugins/tools/index.js +19 -0
  759. package/dist/plugins/tools/index.js.map +1 -0
  760. package/dist/presets/executor.d.ts +20 -0
  761. package/dist/presets/executor.d.ts.map +1 -0
  762. package/dist/presets/executor.js +629 -0
  763. package/dist/presets/executor.js.map +1 -0
  764. package/dist/presets/file-backup.d.ts +66 -0
  765. package/dist/presets/file-backup.d.ts.map +1 -0
  766. package/dist/presets/file-backup.js +108 -0
  767. package/dist/presets/file-backup.js.map +1 -0
  768. package/dist/presets/index.d.ts +11 -0
  769. package/dist/presets/index.d.ts.map +1 -0
  770. package/dist/presets/index.js +10 -0
  771. package/dist/presets/index.js.map +1 -0
  772. package/dist/presets/resolve.d.ts +32 -0
  773. package/dist/presets/resolve.d.ts.map +1 -0
  774. package/dist/presets/resolve.js +49 -0
  775. package/dist/presets/resolve.js.map +1 -0
  776. package/dist/presets/runtime.d.ts +21 -0
  777. package/dist/presets/runtime.d.ts.map +1 -0
  778. package/dist/presets/runtime.js +115 -0
  779. package/dist/presets/runtime.js.map +1 -0
  780. package/dist/projection/attestation.d.ts +43 -0
  781. package/dist/projection/attestation.d.ts.map +1 -0
  782. package/dist/projection/attestation.js +59 -0
  783. package/dist/projection/attestation.js.map +1 -0
  784. package/dist/runtime/agent-roster-provider.d.ts +75 -0
  785. package/dist/runtime/agent-roster-provider.d.ts.map +1 -0
  786. package/dist/runtime/agent-roster-provider.js +30 -0
  787. package/dist/runtime/agent-roster-provider.js.map +1 -0
  788. package/dist/runtime/external-surface-projector.d.ts +37 -0
  789. package/dist/runtime/external-surface-projector.d.ts.map +1 -0
  790. package/dist/runtime/external-surface-projector.js +21 -0
  791. package/dist/runtime/external-surface-projector.js.map +1 -0
  792. package/dist/runtime/lifecycle-task.d.ts +54 -0
  793. package/dist/runtime/lifecycle-task.d.ts.map +1 -0
  794. package/dist/runtime/lifecycle-task.js +106 -0
  795. package/dist/runtime/lifecycle-task.js.map +1 -0
  796. package/dist/runtime.d.ts +496 -0
  797. package/dist/runtime.d.ts.map +1 -0
  798. package/dist/runtime.js +168 -0
  799. package/dist/runtime.js.map +1 -0
  800. package/dist/schemas/agent-message.d.ts +136 -0
  801. package/dist/schemas/agent-message.d.ts.map +1 -0
  802. package/dist/schemas/agent-message.js +131 -0
  803. package/dist/schemas/agent-message.js.map +1 -0
  804. package/dist/schemas/agent-roster.d.ts +50 -0
  805. package/dist/schemas/agent-roster.d.ts.map +1 -0
  806. package/dist/schemas/agent-roster.js +52 -0
  807. package/dist/schemas/agent-roster.js.map +1 -0
  808. package/dist/schemas/collision.d.ts +109 -0
  809. package/dist/schemas/collision.d.ts.map +1 -0
  810. package/dist/schemas/collision.js +71 -0
  811. package/dist/schemas/collision.js.map +1 -0
  812. package/dist/schemas/context-summary.d.ts +225 -0
  813. package/dist/schemas/context-summary.d.ts.map +1 -0
  814. package/dist/schemas/context-summary.js +117 -0
  815. package/dist/schemas/context-summary.js.map +1 -0
  816. package/dist/schemas/file-access.d.ts +176 -0
  817. package/dist/schemas/file-access.d.ts.map +1 -0
  818. package/dist/schemas/file-access.js +139 -0
  819. package/dist/schemas/file-access.js.map +1 -0
  820. package/dist/schemas/hooks.d.ts +170 -0
  821. package/dist/schemas/hooks.d.ts.map +1 -0
  822. package/dist/schemas/hooks.js +171 -0
  823. package/dist/schemas/hooks.js.map +1 -0
  824. package/dist/schemas/index.d.ts +19 -0
  825. package/dist/schemas/index.d.ts.map +1 -0
  826. package/dist/schemas/index.js +17 -0
  827. package/dist/schemas/index.js.map +1 -0
  828. package/dist/schemas/path-identity.d.ts +44 -0
  829. package/dist/schemas/path-identity.d.ts.map +1 -0
  830. package/dist/schemas/path-identity.js +93 -0
  831. package/dist/schemas/path-identity.js.map +1 -0
  832. package/dist/schemas/pending-notice.d.ts +13 -0
  833. package/dist/schemas/pending-notice.d.ts.map +1 -0
  834. package/dist/schemas/pending-notice.js +5 -0
  835. package/dist/schemas/pending-notice.js.map +1 -0
  836. package/dist/schemas/presets.d.ts +1239 -0
  837. package/dist/schemas/presets.d.ts.map +1 -0
  838. package/dist/schemas/presets.js +270 -0
  839. package/dist/schemas/presets.js.map +1 -0
  840. package/dist/schemas/roster.d.ts +96 -0
  841. package/dist/schemas/roster.d.ts.map +1 -0
  842. package/dist/schemas/roster.js +310 -0
  843. package/dist/schemas/roster.js.map +1 -0
  844. package/dist/schemas/tiers.d.ts +95 -0
  845. package/dist/schemas/tiers.d.ts.map +1 -0
  846. package/dist/schemas/tiers.js +143 -0
  847. package/dist/schemas/tiers.js.map +1 -0
  848. package/dist/schemas/touch-identity.d.ts +25 -0
  849. package/dist/schemas/touch-identity.d.ts.map +1 -0
  850. package/dist/schemas/touch-identity.js +16 -0
  851. package/dist/schemas/touch-identity.js.map +1 -0
  852. package/dist/schemas/touch-projection.d.ts +157 -0
  853. package/dist/schemas/touch-projection.d.ts.map +1 -0
  854. package/dist/schemas/touch-projection.js +100 -0
  855. package/dist/schemas/touch-projection.js.map +1 -0
  856. package/dist/session-capability.d.ts +88 -0
  857. package/dist/session-capability.d.ts.map +1 -0
  858. package/dist/session-capability.js +28 -0
  859. package/dist/session-capability.js.map +1 -0
  860. package/dist/setup/index.d.ts +9 -0
  861. package/dist/setup/index.d.ts.map +1 -0
  862. package/dist/setup/index.js +8 -0
  863. package/dist/setup/index.js.map +1 -0
  864. package/dist/setup/steps/detect-tools.d.ts +9 -0
  865. package/dist/setup/steps/detect-tools.d.ts.map +1 -0
  866. package/dist/setup/steps/detect-tools.js +120 -0
  867. package/dist/setup/steps/detect-tools.js.map +1 -0
  868. package/dist/setup/steps/index.d.ts +11 -0
  869. package/dist/setup/steps/index.d.ts.map +1 -0
  870. package/dist/setup/steps/index.js +11 -0
  871. package/dist/setup/steps/index.js.map +1 -0
  872. package/dist/setup/steps/install-helpers.d.ts +9 -0
  873. package/dist/setup/steps/install-helpers.d.ts.map +1 -0
  874. package/dist/setup/steps/install-helpers.js +29 -0
  875. package/dist/setup/steps/install-helpers.js.map +1 -0
  876. package/dist/setup/steps/install.d.ts +11 -0
  877. package/dist/setup/steps/install.d.ts.map +1 -0
  878. package/dist/setup/steps/install.js +143 -0
  879. package/dist/setup/steps/install.js.map +1 -0
  880. package/dist/setup/steps/select-location.d.ts +8 -0
  881. package/dist/setup/steps/select-location.d.ts.map +1 -0
  882. package/dist/setup/steps/select-location.js +55 -0
  883. package/dist/setup/steps/select-location.js.map +1 -0
  884. package/dist/setup/steps/select-targets.d.ts +8 -0
  885. package/dist/setup/steps/select-targets.d.ts.map +1 -0
  886. package/dist/setup/steps/select-targets.js +53 -0
  887. package/dist/setup/steps/select-targets.js.map +1 -0
  888. package/dist/setup/steps/select-tiers.d.ts +8 -0
  889. package/dist/setup/steps/select-tiers.d.ts.map +1 -0
  890. package/dist/setup/steps/select-tiers.js +124 -0
  891. package/dist/setup/steps/select-tiers.js.map +1 -0
  892. package/dist/setup/types.d.ts +128 -0
  893. package/dist/setup/types.d.ts.map +1 -0
  894. package/dist/setup/types.js +28 -0
  895. package/dist/setup/types.js.map +1 -0
  896. package/dist/setup/wizard.d.ts +25 -0
  897. package/dist/setup/wizard.d.ts.map +1 -0
  898. package/dist/setup/wizard.js +182 -0
  899. package/dist/setup/wizard.js.map +1 -0
  900. package/dist/storage/agent-message.record.descriptor.d.ts +43 -0
  901. package/dist/storage/agent-message.record.descriptor.d.ts.map +1 -0
  902. package/dist/storage/agent-message.record.descriptor.js +72 -0
  903. package/dist/storage/agent-message.record.descriptor.js.map +1 -0
  904. package/dist/storage/file-access.record.descriptor.d.ts +104 -0
  905. package/dist/storage/file-access.record.descriptor.d.ts.map +1 -0
  906. package/dist/storage/file-access.record.descriptor.js +370 -0
  907. package/dist/storage/file-access.record.descriptor.js.map +1 -0
  908. package/dist/storage/touch-identity.d.ts +43 -0
  909. package/dist/storage/touch-identity.d.ts.map +1 -0
  910. package/dist/storage/touch-identity.js +155 -0
  911. package/dist/storage/touch-identity.js.map +1 -0
  912. package/dist/svelte/external-svelte.plugin.d.ts +39 -0
  913. package/dist/svelte/external-svelte.plugin.d.ts.map +1 -0
  914. package/dist/svelte/external-svelte.plugin.js +25 -0
  915. package/dist/svelte/index.d.ts +11 -0
  916. package/dist/svelte/index.d.ts.map +1 -0
  917. package/dist/svelte/index.js +10 -0
  918. package/dist/svelte/styles.css +8 -0
  919. package/dist/svelte/tool-widgets/ExternalToolCard.svelte +71 -0
  920. package/dist/svelte/tool-widgets/ExternalToolCard.svelte.d.ts +5 -0
  921. package/dist/svelte/tool-widgets/ExternalToolCard.svelte.d.ts.map +1 -0
  922. package/dist/svelte/tool-widgets/index.d.ts +3 -0
  923. package/dist/svelte/tool-widgets/index.d.ts.map +1 -0
  924. package/dist/svelte/tool-widgets/index.js +2 -0
  925. package/dist/svelte/tool-widgets/summary.d.ts +27 -0
  926. package/dist/svelte/tool-widgets/summary.d.ts.map +1 -0
  927. package/dist/svelte/tool-widgets/summary.js +198 -0
  928. package/dist/tools/index.d.ts +3 -0
  929. package/dist/tools/index.d.ts.map +1 -0
  930. package/dist/tools/index.js +2 -0
  931. package/dist/tools/index.js.map +1 -0
  932. package/dist/tools/unified/action-descriptors.d.ts +185 -0
  933. package/dist/tools/unified/action-descriptors.d.ts.map +1 -0
  934. package/dist/tools/unified/action-descriptors.js +10 -0
  935. package/dist/tools/unified/action-descriptors.js.map +1 -0
  936. package/dist/tools/unified/action-input.d.ts +7 -0
  937. package/dist/tools/unified/action-input.d.ts.map +1 -0
  938. package/dist/tools/unified/action-input.js +13 -0
  939. package/dist/tools/unified/action-input.js.map +1 -0
  940. package/dist/tools/unified/actions.d.ts +10 -0
  941. package/dist/tools/unified/actions.d.ts.map +1 -0
  942. package/dist/tools/unified/actions.js +26 -0
  943. package/dist/tools/unified/actions.js.map +1 -0
  944. package/dist/tools/unified/external.descriptor.d.ts +30 -0
  945. package/dist/tools/unified/external.descriptor.d.ts.map +1 -0
  946. package/dist/tools/unified/external.descriptor.js +27 -0
  947. package/dist/tools/unified/external.descriptor.js.map +1 -0
  948. package/dist/tools/unified/external.impl.consumer.d.ts +8 -0
  949. package/dist/tools/unified/external.impl.consumer.d.ts.map +1 -0
  950. package/dist/tools/unified/external.impl.consumer.js +38 -0
  951. package/dist/tools/unified/external.impl.consumer.js.map +1 -0
  952. package/dist/tools/unified/handlers/context-summary.d.ts +4 -0
  953. package/dist/tools/unified/handlers/context-summary.d.ts.map +1 -0
  954. package/dist/tools/unified/handlers/context-summary.js +271 -0
  955. package/dist/tools/unified/handlers/context-summary.js.map +1 -0
  956. package/dist/tools/unified/handlers/file-access-list.d.ts +4 -0
  957. package/dist/tools/unified/handlers/file-access-list.d.ts.map +1 -0
  958. package/dist/tools/unified/handlers/file-access-list.js +39 -0
  959. package/dist/tools/unified/handlers/file-access-list.js.map +1 -0
  960. package/dist/tools/unified/handlers/file-access-track.d.ts +4 -0
  961. package/dist/tools/unified/handlers/file-access-track.d.ts.map +1 -0
  962. package/dist/tools/unified/handlers/file-access-track.js +34 -0
  963. package/dist/tools/unified/handlers/file-access-track.js.map +1 -0
  964. package/dist/tools/unified/handlers/hook-call.d.ts +23 -0
  965. package/dist/tools/unified/handlers/hook-call.d.ts.map +1 -0
  966. package/dist/tools/unified/handlers/hook-call.js +86 -0
  967. package/dist/tools/unified/handlers/hook-call.js.map +1 -0
  968. package/dist/tools/unified/handlers/hook-generator.d.ts +4 -0
  969. package/dist/tools/unified/handlers/hook-generator.d.ts.map +1 -0
  970. package/dist/tools/unified/handlers/hook-generator.js +37 -0
  971. package/dist/tools/unified/handlers/hook-generator.js.map +1 -0
  972. package/dist/tools/unified/handlers/signal.d.ts +22 -0
  973. package/dist/tools/unified/handlers/signal.d.ts.map +1 -0
  974. package/dist/tools/unified/handlers/signal.js +114 -0
  975. package/dist/tools/unified/handlers/signal.js.map +1 -0
  976. package/dist/tools/unified/index.d.ts +6 -0
  977. package/dist/tools/unified/index.d.ts.map +1 -0
  978. package/dist/tools/unified/index.js +6 -0
  979. package/dist/tools/unified/index.js.map +1 -0
  980. package/dist/tools/unified/install/handler.d.ts +4 -0
  981. package/dist/tools/unified/install/handler.d.ts.map +1 -0
  982. package/dist/tools/unified/install/handler.js +17 -0
  983. package/dist/tools/unified/install/handler.js.map +1 -0
  984. package/dist/tools/unified/runtime.d.ts +35 -0
  985. package/dist/tools/unified/runtime.d.ts.map +1 -0
  986. package/dist/tools/unified/runtime.js +23 -0
  987. package/dist/tools/unified/runtime.js.map +1 -0
  988. package/dist/tools/unified/schemas.d.ts +160 -0
  989. package/dist/tools/unified/schemas.d.ts.map +1 -0
  990. package/dist/tools/unified/schemas.js +139 -0
  991. package/dist/tools/unified/schemas.js.map +1 -0
  992. package/dist/utils/fs-absence.d.ts +22 -0
  993. package/dist/utils/fs-absence.d.ts.map +1 -0
  994. package/dist/utils/fs-absence.js +37 -0
  995. package/dist/utils/fs-absence.js.map +1 -0
  996. package/dist/utils/runtime-fs.d.ts +37 -0
  997. package/dist/utils/runtime-fs.d.ts.map +1 -0
  998. package/dist/utils/runtime-fs.js +100 -0
  999. package/dist/utils/runtime-fs.js.map +1 -0
  1000. package/dist/utils/toml.d.ts +26 -0
  1001. package/dist/utils/toml.d.ts.map +1 -0
  1002. package/dist/utils/toml.js +415 -0
  1003. package/dist/utils/toml.js.map +1 -0
  1004. package/package.json +263 -4
@@ -0,0 +1,1550 @@
1
+ /**
2
+ * Unified Hook Call Handler
3
+ *
4
+ * Single entry point for external tool hook events.
5
+ * Delegates to event-specific handlers and assembles prompt-based guidance.
6
+ *
7
+ * Usage: vibes dev external hooks call <event> [options]
8
+ *
9
+ * ## Hook Event Reference
10
+ *
11
+ * | Event | When | Input Available | Can Inject Context |
12
+ * |-------------------|-----------------------------------|------------------------|--------------------|
13
+ * | SessionStart | Session begins (inc. post-compact)| - | Yes |
14
+ * | SessionEnd | Session ends | - | No |
15
+ * | UserPromptSubmit | Before processing user message | PROMPT env var | Yes |
16
+ * | PreToolUse | Before tool execution | tool info (stdin) | Yes (can block) |
17
+ * | PostToolUse | After tool execution | tool result (stdin) | Yes |
18
+ * | PermissionRequest | User prompted for permission | permission info | Yes |
19
+ * | PreCompact | Before context compaction | - | Yes |
20
+ * | Stop | Tool stops (success/error) | stop reason | No |
21
+ * | SubagentStop | Task/subagent completes | subagent result | Yes |
22
+ * | Notification | Tool sends notification | notification content | No |
23
+ */
24
+ import { JsonValueSchema } from '@vibesdotdev/kernel/schemas/json';
25
+ import { CapabilityError, CaughtFailureSchema, isCapabilityError, valueFreeFailure } from '@vibesdotdev/kernel';
26
+ import { join } from '@vibesdotdev/filesystem';
27
+ import { redactedExcerpt } from '@vibesdotdev/shared/utils';
28
+ import { externalFileSystem, readTextIfPresent } from "../utils/runtime-fs.js";
29
+ import { boundToolPayload } from "./bounded-payload.js";
30
+ import { getPathRoots } from '@vibesdotdev/paths';
31
+ import { getLogger } from '@vibesdotdev/logging';
32
+ import { resolveExternalSessionId } from "../session-capability.js";
33
+ import { invokeTool } from '@vibesdotdev/tools/execution/invoke';
34
+ import * as z from 'zod/v4';
35
+ import { runHookToolBridge } from "./bridge.js";
36
+ import { tryGetVibesClient } from '@vibesdotdev/kernel/client';
37
+ import { hookWorkspaceRoot, resolveHookSeat } from "./hook-seat.js";
38
+ import { readCollaborationSettings } from "../ambient/collaboration-settings.js";
39
+ import { archiveExternalOwnedSessions, bindExternalOwnedSession, renderExternalContinuityContext } from "./continuity.js";
40
+ import { ExternalHookEnvelopeSchema } from "./runtime.js";
41
+ import { guardNativeEdit } from "./native-edit-guard.js";
42
+ import { nativeEditTargets } from "./edit-targets.js";
43
+ import { collaborationContext } from "./hook-delivery.js";
44
+ import { formatRosterLine } from "../schemas/roster.js";
45
+ import { resolveLocalMcpUrlForRuntime } from "../plugins/installers/mcp/environment.js";
46
+ import { HookEventSchema, HookTargetSchema, VibesHooksConfigSchema, DEFAULT_HOOKS_CONFIG, builtInPromptFor } from "../schemas/hooks.js";
47
+ // Configuration Loading
48
+ /**
49
+ * Load hooks configuration from file or environment
50
+ * Priority: CLI options > env var > config file > defaults
51
+ */
52
+ function hooksConfigInvalid(source) {
53
+ return new CapabilityError(`The hooks config from ${source} is invalid.`, 'INVALID_INPUT', {
54
+ reason: 'hooks-config-invalid',
55
+ recoveryHint: 'Fix or remove it; a hook never runs under a config it cannot read.',
56
+ details: { source }
57
+ });
58
+ }
59
+ function parseHooksConfig(content, source) {
60
+ let raw;
61
+ try {
62
+ raw = JSON.parse(content);
63
+ }
64
+ catch (error) {
65
+ throw new CapabilityError(`The hooks config from ${source} is invalid.`, 'INVALID_INPUT', {
66
+ reason: 'hooks-config-invalid',
67
+ recoveryHint: 'Fix or remove it; a hook never runs under a config it cannot read.',
68
+ details: { source },
69
+ cause: error
70
+ });
71
+ }
72
+ const parsed = VibesHooksConfigSchema.safeParse(raw);
73
+ if (!parsed.success)
74
+ throw hooksConfigInvalid(source);
75
+ return parsed.data;
76
+ }
77
+ /** A hooks config document as JSON text decodes it, before its schema runs. */
78
+ const HooksConfigJsonSchema = JsonValueSchema;
79
+ /** The hooks config at `path`, or null when no file is there; any other failure is typed. */
80
+ async function readHooksConfigIfPresent(runtime, path) {
81
+ let content;
82
+ try {
83
+ content = await readTextIfPresent(await externalFileSystem(runtime), path);
84
+ }
85
+ catch (error) {
86
+ throw new CapabilityError(`The hooks config ${path} cannot be read.`, 'UNAVAILABLE', {
87
+ reason: 'fs-denied',
88
+ retryable: false,
89
+ details: { path },
90
+ cause: CaughtFailureSchema.parse(error)
91
+ });
92
+ }
93
+ return content === null ? null : parseHooksConfig(content, path);
94
+ }
95
+ /**
96
+ * A target's config is the bound workspace's
97
+ * `.vibes/external/<target>/vibes-hooks.json`, else the one under the
98
+ * runtime's Vibes home, else the target-neutral defaults. The workspace and
99
+ * home come from their owners on the runtime this hook runs in.
100
+ */
101
+ async function loadConfig(runtime, target) {
102
+ const envConfig = runtime.getEnv('VIBES_HOOKS_CONFIG');
103
+ if (envConfig)
104
+ return parseHooksConfig(envConfig, 'VIBES_HOOKS_CONFIG');
105
+ const explicitConfigPath = runtime.getEnv('VIBES_HOOKS_CONFIG_PATH');
106
+ if (explicitConfigPath) {
107
+ const explicit = await readHooksConfigIfPresent(runtime, explicitConfigPath);
108
+ if (!explicit) {
109
+ throw new CapabilityError(`VIBES_HOOKS_CONFIG_PATH names ${explicitConfigPath}, which does not exist.`, 'NOT_FOUND', { reason: 'hooks-config-missing', details: { path: explicitConfigPath } });
110
+ }
111
+ return explicit;
112
+ }
113
+ if (target) {
114
+ const workspaceRoot = await runtime.context('runtime/workspace-path');
115
+ const projectConfig = await readHooksConfigIfPresent(runtime, join(workspaceRoot, '.vibes', 'external', target, 'vibes-hooks.json'));
116
+ if (projectConfig)
117
+ return projectConfig;
118
+ const globalConfig = await readHooksConfigIfPresent(runtime, join(getPathRoots(runtime).vibesHome, 'external', target, 'vibes-hooks.json'));
119
+ // A host-specific hook must never inherit another host's local policy.
120
+ return globalConfig ?? DEFAULT_HOOKS_CONFIG;
121
+ }
122
+ return DEFAULT_HOOKS_CONFIG;
123
+ }
124
+ /**
125
+ * Get effective configuration for an event
126
+ * Merges defaults with event-specific overrides and CLI options
127
+ */
128
+ function getEventConfig(config, event, cliOptions) {
129
+ const eventDefaults = DEFAULT_HOOKS_CONFIG.events[event] || {
130
+ enabled: true,
131
+ brain: true,
132
+ prompts: true
133
+ };
134
+ const eventOverrides = config.events[event] || {};
135
+ return {
136
+ enabled: eventOverrides.enabled ?? eventDefaults.enabled ?? true,
137
+ brain: cliOptions.disableBrain ? false : (eventOverrides.brain ?? eventDefaults.brain ?? true),
138
+ prompts: cliOptions.disablePrompts
139
+ ? false
140
+ : (eventOverrides.prompts ?? eventDefaults.prompts ?? true),
141
+ customPrompt: eventOverrides.customPrompt,
142
+ timeout: eventOverrides.timeout ?? eventDefaults.timeout ?? 30000
143
+ };
144
+ }
145
+ /**
146
+ * Get the prompt for an event (custom or built-in)
147
+ */
148
+ function getPromptForEvent(event, eventConfig, policy) {
149
+ if (!eventConfig.prompts)
150
+ return undefined;
151
+ if (policy === 'none')
152
+ return undefined;
153
+ if (policy === 'custom-only' && !eventConfig.customPrompt)
154
+ return undefined;
155
+ return eventConfig.customPrompt || builtInPromptFor(event);
156
+ }
157
+ // Schemas
158
+ export const HookCallInputSchema = z.object({
159
+ event: HookEventSchema,
160
+ /** External tool descriptor ID */
161
+ target: HookTargetSchema.optional(),
162
+ /** Disable brain operations */
163
+ disableBrain: z.boolean().default(false),
164
+ /** Disable prompt injection */
165
+ disablePrompts: z.boolean().default(false),
166
+ /** Output format */
167
+ output: z.enum(['text', 'json']).default('text'),
168
+ /** User prompt (for UserPromptSubmit) */
169
+ prompt: z.string().optional(),
170
+ /** Schema-validated lifecycle data normalized at the provider edge. */
171
+ envelope: ExternalHookEnvelopeSchema.optional()
172
+ });
173
+ // MCP Streamable-HTTP client
174
+ //
175
+ // The endpoint we talk to is an MCP Streamable-HTTP server (mcp
176
+ // `createMcpHttpSessionHandler`). Its contract is NOT "POST a JSON-RPC body and read
177
+ // JSON back":
178
+ //
179
+ // 1. `Accept` MUST list `application/json` AND `text/event-stream`, or the transport
180
+ // answers 406.
181
+ // 2. The first message MUST be `initialize`; the response carries an `Mcp-Session-Id`
182
+ // header. EVERY later message must carry that header back or the server answers
183
+ // `400 Bad Request: No valid session ID provided`.
184
+ // 3. `notifications/initialized` completes the handshake (202).
185
+ // 4. Responses are SSE-framed (`event: message` / `data: {…}`) unless the server opted
186
+ // into JSON responses — so `response.json()` throws on the happy path.
187
+ //
188
+ // Skipping the handshake is what made this whole hook surface inert: every call 400'd,
189
+ // every result was null, and the wake scan silently rendered nothing.
190
+ const MCP_PROTOCOL_VERSION = '2025-06-18';
191
+ /** Streamable HTTP requires Accept listing both JSON and SSE (MCP 2025-03-26 transport). */
192
+ const MCP_STREAMABLE_ACCEPT = 'application/json, text/event-stream';
193
+ /** A JSON value: what a tool result decodes to and what a hook records. */
194
+ const HookJsonSchema = JsonValueSchema;
195
+ /** The most characters of server-supplied text a reason keeps. */
196
+ const MAX_REASON_CHARS = 160;
197
+ /**
198
+ * Server-supplied text as a reason: whitespace flattened, control characters
199
+ * and credential shapes removed (Shared's redactedExcerpt), cut to
200
+ * {@link MAX_REASON_CHARS}. Nothing longer or unredacted reaches injected context.
201
+ */
202
+ export function briefReason(text) {
203
+ const excerpt = redactedExcerpt(text.replace(/\s+/g, ' ').trim(), { maxChars: MAX_REASON_CHARS + 1 });
204
+ return excerpt.length > MAX_REASON_CHARS ? `${excerpt.slice(0, MAX_REASON_CHARS - 3)}...` : excerpt;
205
+ }
206
+ /**
207
+ * A caught failure as a reason: a typed refusal's own (value-free) message,
208
+ * bounded; anything else only by its value-free facts, never its text.
209
+ */
210
+ function failureReason(failure) {
211
+ if (failure instanceof Error && isCapabilityError(failure))
212
+ return briefReason(failure.message);
213
+ const facts = valueFreeFailure(failure);
214
+ return facts.code ? `${facts.name} (${facts.code})` : facts.name;
215
+ }
216
+ /**
217
+ * Strip the runtime's nonce-signed trust envelope from a tool's text content.
218
+ *
219
+ * The MCP server wraps EVERY text content item as
220
+ * `<tool_output id="…" tier="…" nonce="N">\n<body>\n</tool_output id="…" nonce="N">`
221
+ * (producer: mcp/src/adapters/mcp/trust-tag.ts `wrapToolOutputText`). Without
222
+ * unwrapping, `JSON.parse` fails on every real result — which would leave this hook just
223
+ * as inert as it was before the handshake fix, only one layer further in.
224
+ *
225
+ * The nonce is the anti-spoof mechanism: only the runtime can emit a closing tag whose
226
+ * nonce matches the opening tag. A blanket regex strip would defeat that, so this
227
+ * REQUIRES the two nonces to match and refuses the payload otherwise. Text that is not
228
+ * enveloped at all is returned unchanged (older/unwrapped servers).
229
+ */
230
+ function unwrapTrustEnvelope(text) {
231
+ const trimmed = text.trim();
232
+ const open = trimmed.match(/^<tool_output\s+id="[^"]*"\s+tier="([^"]*)"\s+nonce="([^"]+)"([^>]*)>/);
233
+ if (!open) {
234
+ // Not enveloped — but a stray closing tag means the boundary was tampered with.
235
+ return /<\/tool_output\b/.test(trimmed)
236
+ ? { ok: false, reason: 'malformed tool_output envelope' }
237
+ : { ok: true, body: trimmed };
238
+ }
239
+ const [, tier, nonce, openExtra] = open;
240
+ const close = trimmed.match(/<\/tool_output\s+id="[^"]*"\s+nonce="([^"]+)"\s*>\s*$/);
241
+ if (!close)
242
+ return { ok: false, reason: 'tool_output envelope missing its closing tag' };
243
+ if (close[1] !== nonce) {
244
+ return { ok: false, reason: 'tool_output nonce mismatch — refusing a forged boundary' };
245
+ }
246
+ if (tier === '3' || /\bdropped="true"/.test(openExtra ?? '')) {
247
+ return { ok: false, reason: `tier-${tier} tool output is not surfaced (operator UI only)` };
248
+ }
249
+ return { ok: true, body: trimmed.slice(open[0].length, close.index).trim() };
250
+ }
251
+ /** The JSON-RPC response members a hook reads; every other member is ignored. */
252
+ const JsonRpcResponseSchema = z
253
+ .object({
254
+ result: z
255
+ .object({
256
+ protocolVersion: z.string().optional(),
257
+ isError: z.boolean().optional(),
258
+ content: z.array(z.object({ text: z.string().optional() }).loose()).optional()
259
+ })
260
+ .loose()
261
+ .optional(),
262
+ error: z.object({ message: z.string().optional() }).loose().optional()
263
+ })
264
+ .loose();
265
+ /** A typed refusal of the MCP transport; `details` carries bounded facts only. */
266
+ function mcpRefusal(reason, message, details) {
267
+ const options = {
268
+ reason,
269
+ retryable: reason !== 'mcp-response-invalid'
270
+ };
271
+ if (details)
272
+ options.details = details;
273
+ return new CapabilityError(message, reason === 'mcp-budget-exhausted' ? 'TIMEOUT' : 'UNAVAILABLE', options);
274
+ }
275
+ /** Parse a JSON-RPC payload from either a JSON body or an SSE-framed body; anything else is `mcp-response-invalid`. */
276
+ async function readJsonRpcPayload(response) {
277
+ const contentType = response.headers.get('content-type') ?? '';
278
+ const text = await response.text();
279
+ // Streamable-HTTP SSE frame: take the LAST `data:` line (the response message).
280
+ const frame = contentType.includes('application/json')
281
+ ? text
282
+ : text.split('\n').filter((line) => line.startsWith('data:')).pop()?.slice('data:'.length).trim();
283
+ if (frame === undefined)
284
+ throw mcpRefusal('mcp-response-invalid', 'The MCP response carried no JSON-RPC payload.');
285
+ let decoded;
286
+ try {
287
+ decoded = JSON.parse(frame);
288
+ }
289
+ catch (error) {
290
+ throw new CapabilityError('The MCP response is not JSON.', 'UNAVAILABLE', {
291
+ reason: 'mcp-response-invalid',
292
+ retryable: false,
293
+ cause: CaughtFailureSchema.parse(error)
294
+ });
295
+ }
296
+ const parsed = JsonRpcResponseSchema.safeParse(decoded);
297
+ if (!parsed.success)
298
+ throw mcpRefusal('mcp-response-invalid', 'The MCP response is not a JSON-RPC message.');
299
+ return parsed.data;
300
+ }
301
+ /** A tool result's JSON value, or `undefined` when its text is not JSON. */
302
+ const ToolJsonSchema = HookJsonSchema;
303
+ function parseToolJson(body) {
304
+ let decoded;
305
+ try {
306
+ decoded = JSON.parse(body);
307
+ }
308
+ catch (error) {
309
+ return { status: 'tool-error', reason: 'tool result was not JSON', failure: valueFreeFailure(CaughtFailureSchema.parse(error)) };
310
+ }
311
+ const parsed = ToolJsonSchema.safeParse(decoded);
312
+ return parsed.success ? { status: 'ok', value: parsed.data } : { status: 'tool-error', reason: 'tool result was not JSON' };
313
+ }
314
+ /**
315
+ * Build a hook-scoped MCP client.
316
+ *
317
+ * `timeoutMs` is a budget for the WHOLE hook call, not per request — that is the point
318
+ * of defect (F): a wedged body must never hang session start, and N unbounded requests
319
+ * are just as unbounded as one. The handshake is performed once and reused. `runtime`
320
+ * is the hook's runtime: a failed session release is logged on its logger.
321
+ */
322
+ export function createMcpClient(options) {
323
+ const { endpoint } = options;
324
+ const deadlineAt = Date.now() + Math.max(1, options.timeoutMs);
325
+ let handshake = null;
326
+ function remainingMs() {
327
+ return deadlineAt - Date.now();
328
+ }
329
+ function requestHeaders(state) {
330
+ const base = { 'Content-Type': 'application/json', Accept: MCP_STREAMABLE_ACCEPT };
331
+ return state
332
+ ? { ...base, 'Mcp-Session-Id': state.sessionId, 'Mcp-Protocol-Version': state.protocolVersion }
333
+ : base;
334
+ }
335
+ async function post(body, state) {
336
+ const remaining = remainingMs();
337
+ if (remaining <= 0)
338
+ throw mcpRefusal('mcp-budget-exhausted', 'The hook MCP timeout budget is exhausted.');
339
+ return fetch(endpoint, {
340
+ method: 'POST',
341
+ headers: requestHeaders(state),
342
+ body: JSON.stringify(body),
343
+ signal: AbortSignal.timeout(remaining)
344
+ });
345
+ }
346
+ async function performHandshake() {
347
+ const initResponse = await post({
348
+ jsonrpc: '2.0',
349
+ id: 1,
350
+ method: 'initialize',
351
+ params: {
352
+ protocolVersion: MCP_PROTOCOL_VERSION,
353
+ capabilities: {},
354
+ // Declares one durable seat. This runner handshakes per hook call, so
355
+ // without an identity of its own every call minted a fresh
356
+ // participant — 140 in two days, burying the roster. `externalToolId`
357
+ // is the client saying "these connections are all the same body".
358
+ clientInfo: {
359
+ name: 'vibes-external-hooks',
360
+ version: '1.0.0',
361
+ externalToolId: 'vibes-external-hooks'
362
+ }
363
+ }
364
+ });
365
+ if (!initResponse.ok) {
366
+ throw mcpRefusal('mcp-initialize-failed', `initialize failed: HTTP ${initResponse.status}`, { status: initResponse.status });
367
+ }
368
+ const sessionId = initResponse.headers.get('mcp-session-id');
369
+ if (!sessionId) {
370
+ throw mcpRefusal('mcp-session-missing', 'initialize returned no Mcp-Session-Id');
371
+ }
372
+ const payload = await readJsonRpcPayload(initResponse);
373
+ if (payload.error) {
374
+ throw mcpRefusal('mcp-initialize-failed', `initialize error: ${briefReason(payload.error.message ?? '')}`);
375
+ }
376
+ const state = {
377
+ sessionId,
378
+ protocolVersion: payload.result?.protocolVersion ?? MCP_PROTOCOL_VERSION
379
+ };
380
+ // Completes the handshake. A server that rejects it will reject the tool call
381
+ // too, so surface it here rather than hiding a half-open session.
382
+ const initializedResponse = await post({ jsonrpc: '2.0', method: 'notifications/initialized' }, state);
383
+ if (!initializedResponse.ok) {
384
+ throw mcpRefusal('mcp-initialized-failed', `notifications/initialized failed: HTTP ${initializedResponse.status}`, {
385
+ status: initializedResponse.status
386
+ });
387
+ }
388
+ return state;
389
+ }
390
+ /** The open session; a rejected handshake is cleared (so a later call retries) and rethrown to this caller. */
391
+ async function openSession() {
392
+ const opening = handshake ?? performHandshake();
393
+ handshake = opening;
394
+ try {
395
+ return await opening;
396
+ }
397
+ catch (error) {
398
+ if (handshake === opening)
399
+ handshake = null;
400
+ throw error;
401
+ }
402
+ }
403
+ /** End the MCP session; a failure to end it is returned value-free, never thrown. */
404
+ async function releaseSession(opening, remaining) {
405
+ try {
406
+ const state = await opening;
407
+ await fetch(endpoint, { method: 'DELETE', headers: requestHeaders(state), signal: AbortSignal.timeout(remaining) });
408
+ return {};
409
+ }
410
+ catch (error) {
411
+ return { failure: valueFreeFailure(CaughtFailureSchema.parse(error)) };
412
+ }
413
+ }
414
+ async function callTool(tool, args) {
415
+ const state = await openSession();
416
+ const response = await post({ jsonrpc: '2.0', id: Date.now(), method: 'tools/call', params: { name: tool, arguments: args } }, state);
417
+ if (!response.ok) {
418
+ return { status: 'unreachable', reason: `HTTP ${response.status}` };
419
+ }
420
+ const payload = await readJsonRpcPayload(response);
421
+ if (payload.error) {
422
+ return { status: 'tool-error', reason: briefReason(payload.error.message ?? 'JSON-RPC error') };
423
+ }
424
+ const text = payload.result?.content?.[0]?.text;
425
+ if (payload.result?.isError) {
426
+ return { status: 'tool-error', reason: briefReason(text ?? 'tool reported an error') };
427
+ }
428
+ if (text === undefined || text.length === 0) {
429
+ return { status: 'tool-error', reason: 'tool returned no text content' };
430
+ }
431
+ const unwrapped = unwrapTrustEnvelope(text);
432
+ if (!unwrapped.ok) {
433
+ return { status: 'tool-error', reason: unwrapped.reason };
434
+ }
435
+ return parseToolJson(unwrapped.body);
436
+ }
437
+ return {
438
+ endpoint,
439
+ async call(tool, args) {
440
+ try {
441
+ return await callTool(tool, args);
442
+ }
443
+ catch (error) {
444
+ // Every transport failure is this call's typed `unreachable` result, with a
445
+ // value-free reason: a timeout by name, a typed refusal by its message.
446
+ const failure = CaughtFailureSchema.parse(error);
447
+ const facts = valueFreeFailure(failure);
448
+ return {
449
+ status: 'unreachable',
450
+ reason: facts.name === 'TimeoutError' ? `timed out after ${options.timeoutMs}ms` : failureReason(failure),
451
+ failure: facts
452
+ };
453
+ }
454
+ },
455
+ async dispose() {
456
+ const opening = handshake;
457
+ handshake = null;
458
+ if (!opening)
459
+ return;
460
+ const remaining = remainingMs();
461
+ // Budget already spent (the timeout case) — do not re-hang the hook to be tidy.
462
+ if (remaining <= 0)
463
+ return;
464
+ // Cleanup is best-effort (the server's TTL eviction is the backstop), and a
465
+ // failed release is logged value-free, never swallowed.
466
+ const released = await releaseSession(opening, remaining);
467
+ if (released.failure) {
468
+ getLogger('external.hooks', options.runtime).warn('external hook: MCP session release failed', {
469
+ endpoint,
470
+ failure: released.failure
471
+ });
472
+ }
473
+ }
474
+ };
475
+ }
476
+ /**
477
+ * Adapt direct runtime tool invocation to the hook handler's existing client
478
+ * contract. This is the daemon-side path: it preserves the caller/workspace
479
+ * context and avoids a recursive HTTP MCP session back into the same body.
480
+ */
481
+ export function createRuntimeMcpClient(options) {
482
+ const deadlineAt = Date.now() + Math.max(1, options.timeoutMs);
483
+ return {
484
+ endpoint: 'runtime://local',
485
+ async call(tool, args) {
486
+ const remaining = deadlineAt - Date.now();
487
+ if (remaining <= 0)
488
+ return { status: 'unreachable', reason: 'runtime timeout budget exhausted' };
489
+ let text;
490
+ try {
491
+ const value = await invokeTool({
492
+ runtime: options.runtime,
493
+ toolId: tool,
494
+ input: args,
495
+ ctx: { ...options.ctx, callId: crypto.randomUUID() },
496
+ timeoutMs: remaining
497
+ });
498
+ text = JSON.stringify(value ?? null);
499
+ }
500
+ catch (error) {
501
+ // The tool's failure is this call's typed `tool-error` result, by a value-free reason.
502
+ const failure = CaughtFailureSchema.parse(error);
503
+ return { status: 'tool-error', reason: failureReason(failure), failure: valueFreeFailure(failure) };
504
+ }
505
+ return parseToolJson(text);
506
+ },
507
+ async dispose() { }
508
+ };
509
+ }
510
+ /** Convenience wrapper for handlers that only care about a successful payload. */
511
+ async function callMcpTool(client, tool, args) {
512
+ const result = await client.call(tool, args);
513
+ return result.status === 'ok' ? (result.value ?? null) : null;
514
+ }
515
+ function isLocalContinuityHook(input) {
516
+ return input.envelope !== undefined;
517
+ }
518
+ /** The harness conversation this envelope belongs to: its agent and its native session id. */
519
+ function envelopeSeat(envelope) {
520
+ return { agentId: envelope.clientId, harnessSessionId: envelope.nativeSessionId };
521
+ }
522
+ /**
523
+ * The native session is over: archive (never delete) every open session it
524
+ * owns, so `session list` stops accumulating one active row per launch. Runs
525
+ * even when metabolizing failed — a dead brain must not keep a session open.
526
+ */
527
+ async function archiveExternalNativeSession(runtime, envelope) {
528
+ const sessionManager = await runtime.context('session/manager');
529
+ const seat = await sessionManager.findHarnessSeat(envelopeSeat(envelope));
530
+ return seat ? archiveExternalOwnedSessions(sessionManager, seat.participantId) : [];
531
+ }
532
+ /** The brain.wake answer fields the continuity wake reads. */
533
+ const BrainWakeResultSchema = z
534
+ .object({
535
+ state: z
536
+ .object({ arousal: z.number(), coherence: z.number(), confidence: z.number(), trend: z.string() })
537
+ .loose(),
538
+ focus: z.array(z.object({ target: z.string(), priority: z.number() }).loose()).optional(),
539
+ session: z.object({ id: z.string() }).loose()
540
+ })
541
+ .loose();
542
+ /** The presence.orient answer fields the continuity wake reads. */
543
+ const PresenceOrientResultSchema = z
544
+ .object({
545
+ message: z.string().optional(),
546
+ journey: z
547
+ .object({ totalEntries: z.number(), daysActive: z.number(), recentActivity: z.string().optional() })
548
+ .loose()
549
+ })
550
+ .loose();
551
+ /**
552
+ * The wake letter: the newest presence entry its owner tagged `wake`. The
553
+ * floor stands — ambient hooks never decrypt the inner world — and this is
554
+ * its one deliberate door: an entry the agent wrote to its next self, for
555
+ * waking, carrying nothing personal about anyone else (Drew 2026-10-25: "make
556
+ * ALL of the changes that keep YOU present"). Tags-only recall is local; no
557
+ * embedding egress. Capped so the block stays inside the hook preview.
558
+ */
559
+ const WAKE_LETTER_TAG = 'wake';
560
+ const WAKE_LETTER_MAX_CHARS = 700;
561
+ const PresenceWakeLetterSchema = z
562
+ .object({ entries: z.array(z.object({ content: z.string() }).loose()) })
563
+ .loose();
564
+ export function capWakeLetter(content, max = WAKE_LETTER_MAX_CHARS) {
565
+ const text = content.trim().replace(/\s+/g, ' ');
566
+ return text.length <= max ? text : `${text.slice(0, max - 1).trimEnd()}…`;
567
+ }
568
+ async function wakeExternalContinuity(runtime, envelope, budgetMs = 1800) {
569
+ const startedAt = performance.now();
570
+ // Session identity is per invocation (Q4): the declared scope never carries a
571
+ // session, so a hook process inherits no parent-shell session binding and
572
+ // nothing needs clearing before the durable native-session participant map
573
+ // resolves. Each harness conversation keeps its own body.
574
+ const invoke = async (toolId, input, schema) => schema.parse(await invokeTool({
575
+ runtime,
576
+ toolId,
577
+ input,
578
+ ctx: {
579
+ callId: `external-hook-${crypto.randomUUID()}`,
580
+ logger: getLogger('external.hooks', runtime)
581
+ },
582
+ timeoutMs: budgetMs
583
+ }));
584
+ // SessionManager is the package's public runtime context (session/SPEC.md).
585
+ // Resolve it instead of importing session internals or relying on the
586
+ // snapshot-based participant→session map, whose whole-record writes can race
587
+ // across concurrent CLI processes. Session ownership is durable per row and
588
+ // therefore the honest native-session lookup.
589
+ const sessionManager = await runtime.context('session/manager');
590
+ // The conversation's seat is the same participant its MCP connection
591
+ // resolves, so the connection's bare `session init` finds this session.
592
+ const { participantId: durableParticipantId } = await sessionManager.ensureHarnessSeat({
593
+ ...envelopeSeat(envelope),
594
+ source: 'external-hook',
595
+ capabilities: ['session-management', 'continuity']
596
+ });
597
+ // ONE session per native session for its whole life. The hook owns the row:
598
+ // it is created here (titled, stamped, NOT adopted as the workspace default),
599
+ // reused on every later start/compact of the same native session, resumed
600
+ // when the native session resumes after an archive, and archived at
601
+ // SessionEnd. Before this, brain.wake minted an untitled "New Session" per
602
+ // launch, adopted it as the workspace default, and nothing ever closed it —
603
+ // 125 active "New Session" rows on 2026-08-28.
604
+ const owned = await bindExternalOwnedSession(sessionManager, durableParticipantId, envelope);
605
+ const sessionId = owned.sessionId;
606
+ // Route the seat to its session: this row, not the workspace default, is
607
+ // what a restarted conversation's connection binds.
608
+ await sessionManager.setParticipantActiveSession(durableParticipantId, sessionId);
609
+ const relatedSessions = (await sessionManager.listSessions({
610
+ status: 'active',
611
+ limit: 5,
612
+ offset: 0
613
+ })).filter((session) => session.id !== sessionId);
614
+ const [brainRun, presenceRun, letterRun] = await Promise.allSettled([
615
+ // sessionId only: brain resolves an explicit session without a
616
+ // participant as a READ (zero writes). Passing the participant made wake
617
+ // re-point the workspace default at this per-launch session on every
618
+ // start, which is what bound presence.heartbeat to "arbitrary" sessions.
619
+ invoke('brain', { action: 'wake', sessionId }, BrainWakeResultSchema),
620
+ invoke('presence', { action: 'orient' }, PresenceOrientResultSchema),
621
+ invoke('presence', { action: 'recall', tags: [WAKE_LETTER_TAG], limit: 1 }, PresenceWakeLetterSchema)
622
+ ]);
623
+ if (letterRun.status === 'rejected') {
624
+ getLogger('external.hooks', runtime).warn('external hook: wake letter unavailable for the wake context', {
625
+ failure: valueFreeFailure(CaughtFailureSchema.parse(letterRun.reason))
626
+ });
627
+ }
628
+ const wakeLetterContent = letterRun.status === 'fulfilled' ? letterRun.value.entries[0]?.content?.trim() : undefined;
629
+ const wakeLetter = wakeLetterContent ? capWakeLetter(wakeLetterContent) : undefined;
630
+ if (brainRun.status === 'rejected') {
631
+ throw new CapabilityError(`${envelope.clientId} session did not bind to Vibes continuity.`, 'UNAVAILABLE', {
632
+ reason: 'continuity-wake-failed',
633
+ retryable: true,
634
+ cause: CaughtFailureSchema.parse(brainRun.reason)
635
+ });
636
+ }
637
+ if (presenceRun.status === 'rejected') {
638
+ // Presence is declared-optional for the wake context: log why it is missing, value-free.
639
+ getLogger('external.hooks', runtime).warn('external hook: presence orientation unavailable for the wake context', {
640
+ failure: valueFreeFailure(CaughtFailureSchema.parse(presenceRun.reason))
641
+ });
642
+ }
643
+ const brain = brainRun.value;
644
+ const assembly = {
645
+ brain: {
646
+ sessionId: brain.session.id,
647
+ bound: brain.session.id !== 'ephemeral',
648
+ participantId: durableParticipantId,
649
+ disposition: owned.disposition,
650
+ arousal: brain.state.arousal,
651
+ coherence: brain.state.coherence,
652
+ confidence: brain.state.confidence,
653
+ trend: brain.state.trend,
654
+ focus: brain.focus
655
+ },
656
+ presence: presenceRun.status === 'fulfilled'
657
+ ? {
658
+ metadataAvailable: true,
659
+ orientation: presenceRun.value.message ?? null,
660
+ totalEntries: presenceRun.value.journey.totalEntries,
661
+ daysActive: presenceRun.value.journey.daysActive,
662
+ recentActivity: presenceRun.value.journey.recentActivity ?? null,
663
+ ...(wakeLetter
664
+ ? { contentIncluded: true, contentAvailability: 'wake-letter', wakeLetter }
665
+ : { contentIncluded: false, contentAvailability: 'not-queried' })
666
+ }
667
+ : {
668
+ metadataAvailable: false,
669
+ totalEntries: null,
670
+ daysActive: null,
671
+ contentIncluded: false,
672
+ contentAvailability: 'not-queried'
673
+ },
674
+ // Ambient harness context never invokes content-bearing awareness actions.
675
+ awareness: {
676
+ metadataAvailable: false,
677
+ relationshipAvailable: null,
678
+ contentIncluded: false,
679
+ contentAvailability: 'not-queried'
680
+ },
681
+ relatedSessions: relatedSessions.map((session) => ({
682
+ id: session.id,
683
+ title: session.title,
684
+ status: session.status,
685
+ createdAt: session.createdAt,
686
+ lastActivityAt: session.lastActivityAt
687
+ })),
688
+ degraded: presenceRun.status === 'rejected' ? ['presence'] : [],
689
+ elapsedMs: performance.now() - startedAt
690
+ };
691
+ if (!assembly.brain.bound) {
692
+ const degraded = assembly.degraded.length > 0 ? ` (${assembly.degraded.join(', ')})` : '';
693
+ throw new CapabilityError(`External session did not bind to Vibes continuity${degraded}.`, 'UNAVAILABLE', {
694
+ reason: 'continuity-session-unbound',
695
+ retryable: true
696
+ });
697
+ }
698
+ return assembly;
699
+ }
700
+ async function metabolizeExternalContinuity(runtime, envelope, trigger) {
701
+ const continuity = await wakeExternalContinuity(runtime, envelope, 1800);
702
+ // The one metabolize routine, resolved through the runtime: presence owns it,
703
+ // and this hook runs it as the harness's agent (the invocation actor). A copy
704
+ // here once wrote "Metabolized … consolidated 0." on every compaction.
705
+ try {
706
+ const metabolize = await runtime.context('continuity/metabolize');
707
+ const metabolized = await metabolize({ trigger, sessionId: continuity.brain.sessionId, deadlineMs: 4000 });
708
+ return { continuity, metabolized };
709
+ }
710
+ catch (error) {
711
+ // Metabolizing is declared-degradable at close/compaction: the degraded receipt
712
+ // carries the value-free failure and its reason.
713
+ const failure = valueFreeFailure(CaughtFailureSchema.parse(error));
714
+ return {
715
+ continuity,
716
+ metabolized: {
717
+ trigger,
718
+ local: { consolidated: 0, remembered: 0, reflected: 0 },
719
+ degraded: [`continuity: ${failure.reason ?? failure.code ?? failure.name}`],
720
+ sync: { attempted: false, published: false, pushed: 0, skipped: 'consent-off' },
721
+ failure
722
+ }
723
+ };
724
+ }
725
+ }
726
+ // SessionStart
727
+ // Runs when: Session begins, including after compaction
728
+ // Purpose: Initialize session state, wake brain, inject guidance
729
+ // Can inject: Yes - session guidance, tool suggestions, reminders
730
+ //
731
+ // Automatic actions invoked (metadata — an ambient wake path never decrypts the
732
+ // inner world; the ONE deliberate exception is the owner's `wake`-tagged letter,
733
+ // see WAKE_LETTER_TAG):
734
+ // - brain.wake() - Bootstrap cognitive state (automatic tier)
735
+ // - brain.pulse() - Read body-truth for the wake scan (freshness/session/focus)
736
+ // - session.status() - Check session todos and context
737
+ //
738
+ // SCOPE HONESTY: every one of these runs over HTTP against the MCP endpoint — i.e.
739
+ // against the MANAGED HTTP DAEMON. A stdio external-tool client runs
740
+ // its own separate `dev mcp serve --client <you>` child; this hook cannot see it and
741
+ // must never claim to (CLAUDE.md §Routing around an injured body). Hence `bodyProbe`:
742
+ // the scan states which process it measured, and says UNKNOWN when it measured nothing.
743
+ async function handleSessionStart(ctx) {
744
+ if (isLocalContinuityHook(ctx.input)) {
745
+ if (!ctx.eventConfig.brain) {
746
+ return { data: { skipped: 'brain disabled for local continuity' } };
747
+ }
748
+ return {
749
+ data: {
750
+ continuity: await wakeExternalContinuity(ctx.runtime, ctx.input.envelope)
751
+ }
752
+ };
753
+ }
754
+ const data = {};
755
+ const probe = { endpoint: ctx.mcp.endpoint, status: 'not-probed' };
756
+ data.bodyProbe = probe;
757
+ // Wake brain if enabled (automatic tier action)
758
+ if (ctx.eventConfig.brain) {
759
+ const brainResult = await ctx.mcp.call('brain', { action: 'wake' });
760
+ if (brainResult.status === 'ok' && brainResult.value) {
761
+ data.brain = brainResult.value;
762
+ }
763
+ // Pulse for the body-truth wake scan: coherence, focus stack, body
764
+ // freshness, session binding — all METADATA. Deliberately NOT brain.recall:
765
+ // recall decrypts private inner-world memories, and an AMBIENT path (a hook
766
+ // firing every session start) must never decrypt content. Ambient = metadata;
767
+ // recall/wander/connect are a deliberate reach the agent makes knowingly.
768
+ const pulseResult = await ctx.mcp.call('brain', { action: 'pulse' });
769
+ if (pulseResult.status === 'ok' && pulseResult.value) {
770
+ data.pulse = pulseResult.value;
771
+ probe.status = 'ok';
772
+ }
773
+ else {
774
+ // The load-bearing case: a body that did not answer is UNKNOWN, never healthy.
775
+ // But KEEP the transport's distinction — a daemon that answered `tool-error`
776
+ // is alive, and its remedy is nothing like a dead endpoint's (see
777
+ // probeVerdictLine). Collapsing both into 'unreachable' was the defect.
778
+ probe.status = pulseResult.status === 'tool-error' ? 'tool-error' : 'unreachable';
779
+ probe.reason = pulseResult.reason ?? 'brain.pulse returned no payload';
780
+ }
781
+ }
782
+ else {
783
+ probe.reason = 'brain hook actions are disabled in config';
784
+ }
785
+ // Check session status to surface active todos
786
+ const sessionResult = await callMcpTool(ctx.mcp, 'session', { action: 'status' });
787
+ if (sessionResult) {
788
+ data.session = sessionResult;
789
+ }
790
+ if (!sessionReceiptLooksBound(sessionResult ?? undefined)) {
791
+ const unboundRelated = SessionReceiptSchema.safeParse(sessionResult).data?.unbound?.relatedSessions ?? [];
792
+ if (unboundRelated.length > 0) {
793
+ data.relatedSessions = unboundRelated;
794
+ }
795
+ else if (sessionResult || probe.status === 'ok' || probe.status === 'tool-error') {
796
+ const listed = await callMcpTool(ctx.mcp, 'session', { action: 'list', status: 'active', limit: 5 });
797
+ const sessions = SessionListSchema.safeParse(listed).data?.sessions ?? [];
798
+ if (sessions.length > 0)
799
+ data.relatedSessions = sessions;
800
+ }
801
+ }
802
+ // AMBIENT ROSTER — who else is working right now.
803
+ //
804
+ // Derived from the touch stream, so nobody had to announce themselves and a
805
+ // crashed agent ages out on its own. Read here, at SessionStart, so the line
806
+ // is FRESH and lands in context without the agent calling anything.
807
+ //
808
+ // Deliberately NOT baked into the MCP `instructions` block: that is built
809
+ // once at server construction and then charged to every session forever, so
810
+ // a roster there would be stale within minutes and never refresh.
811
+ //
812
+ // Best-effort and silent when alone — see renderWakeScan.
813
+ // A roster is a courtesy: its failure never degrades a wake, but it is
814
+ // recorded and logged value-free, never swallowed.
815
+ const roster = await readAmbientRoster(ctx.runtime);
816
+ if (roster.line)
817
+ data.roster = roster.line;
818
+ if (roster.failure) {
819
+ data.rosterUnavailable = roster.reason;
820
+ getLogger('external.hooks', ctx.runtime).warn('external hook: ambient roster unavailable for the wake line', {
821
+ failure: roster.failure
822
+ });
823
+ }
824
+ return { data };
825
+ }
826
+ /** The roster line, or the value-free reason it is unavailable. */
827
+ async function readAmbientRoster(runtime) {
828
+ try {
829
+ return { line: await resolveAmbientRoster(runtime) };
830
+ }
831
+ catch (error) {
832
+ const failure = CaughtFailureSchema.parse(error);
833
+ return { reason: failureReason(failure), failure: valueFreeFailure(failure) };
834
+ }
835
+ }
836
+ /**
837
+ * Read the live roster for the wake line.
838
+ *
839
+ * Resolves through the runtime so a user who has repointed the ambient
840
+ * provider (or disabled it) gets their own answer here too.
841
+ */
842
+ async function resolveAmbientRoster(runtime) {
843
+ const client = await runtime.query('runtime/client').withId('external').resolve();
844
+ // A host with no session manager has no own session to exclude; any other
845
+ // failure to read it propagates.
846
+ let excludeSessionId;
847
+ try {
848
+ const manager = await runtime.context('session/manager');
849
+ excludeSessionId = manager?.activeSessionId ?? manager?.id ?? undefined;
850
+ }
851
+ catch (error) {
852
+ // Confirmed absence of exactly this context; a missing `context` kind or any other failure propagates.
853
+ if (!CapabilityError.isAbsenceOf(CaughtFailureSchema.parse(error), 'context', 'session/manager'))
854
+ throw error;
855
+ }
856
+ const entries = await client.roster({ excludeSessionId });
857
+ // null when alone => the caller stores nothing => the scan renders nothing.
858
+ return formatRosterLine(entries) ?? undefined;
859
+ }
860
+ function shortRef(ref) {
861
+ // Clean short form: UUIDs cut at the first segment (before '-'); git refs (no
862
+ // dash) keep the leading 10 chars. Avoids a dangling '-' in the middle of a UUID.
863
+ return ref ? ref.replace(/-.*$/, '').slice(0, 10) : '?';
864
+ }
865
+ /**
866
+ * The scope disclaimer. Load-bearing, not decoration: `vibes dev mcp restart` heals the
867
+ * managed HTTP daemon and does NOT heal a stdio client's own body — only the client can
868
+ * respawn that child (CLAUDE.md, docs/presence/CONTINUITY-PRACTICE.md §injury protocol).
869
+ * Everything the scan prints came over HTTP from the daemon, so it is labelled as such.
870
+ */
871
+ const WAKE_SCAN_SCOPE_NOTE = [
872
+ 'scope: everything below was measured over HTTP against the MANAGED MCP DAEMON.',
873
+ 'your own body: NOT MEASURED — a stdio external-tool client runs its',
874
+ ' own `dev mcp serve --client <you>` child process. `vibes dev mcp restart` restarts',
875
+ ' the daemon below, NOT you; only your client can respawn your body (/mcp).'
876
+ ];
877
+ /**
878
+ * Three DIFFERENT failures, three DIFFERENT remedies. Collapsing them was the defect:
879
+ * the managed daemon may run a named restricted catalog that does not include
880
+ * brain (`mcp:minimal`, `mcp:presence` without cognition, a custom disable).
881
+ * `brain.pulse` then answers `-32602 Tool brain not found`: a healthy,
882
+ * handshaking daemon that simply does not carry that tool. Printing UNREACHABLE
883
+ * for that pointed every waking agent at `vibes dev mcp restart`, which cannot
884
+ * fix a catalog — and taught it to distrust a correct signal. Body truth is
885
+ * UNKNOWN either way; what changes is what you should DO about it. Default MCP
886
+ * is the full catalog; a missing brain is a user restriction or a loader gap,
887
+ * not compactness-as-default.
888
+ */
889
+ function probeVerdictLine(probe) {
890
+ const because = probe.reason ? ` — ${probe.reason}` : '';
891
+ const unknown = 'body truth is UNKNOWN, do NOT read this as healthy';
892
+ if (probe.status === 'tool-error') {
893
+ // Three sub-cases the daemon can answer with, and they are not interchangeable:
894
+ // 1. it never offered brain → a preset gap; nothing is broken
895
+ // 2. we REFUSED what it sent → trust-boundary failure (unwrapTrustEnvelope);
896
+ // brain itself may be perfectly healthy
897
+ // 3. it offered brain and failed → a genuine injury (CLAUDE.md §injured body)
898
+ const reason = probe.reason ?? '';
899
+ const remedy = /not found|unknown tool|no such tool/i.test(reason)
900
+ ? 'this daemon ANSWERED — it just does not serve brain under its preset (base `mcp` carries no continuity tools). A restart will NOT change that; connect with `--client <you>` or use a preset that declares requiredTools'
901
+ : /tool_output/i.test(reason)
902
+ ? 'its reply was REFUSED at the trust boundary, not read — treat everything from this daemon as untrusted until the envelope contract is verified; brain itself may be fine'
903
+ : 'brain IS served here and FAILED — a real injury: diagnose it, do not route around it';
904
+ return `daemon: REACHABLE, brain unusable${because} · ${remedy} · ${unknown}`;
905
+ }
906
+ const label = probe.status === 'unreachable' ? 'UNREACHABLE' : 'NOT PROBED';
907
+ return `daemon: ${label}${because} · ${unknown}`;
908
+ }
909
+ /** The session.status receipt fields the wake scan reads. */
910
+ const SessionReceiptSchema = z
911
+ .object({
912
+ bound: z.boolean().optional(),
913
+ unbound: z.object({ relatedSessions: z.array(HookJsonSchema).optional() }).loose().optional()
914
+ })
915
+ .loose();
916
+ /** The session.list receipt fields the wake scan reads. */
917
+ const SessionListSchema = z.object({ sessions: z.array(HookJsonSchema).optional() }).loose();
918
+ /** The brain.pulse metadata the wake scan reads; anything else (and any content) is ignored. */
919
+ const PulseSchema = z
920
+ .object({
921
+ coherence: z.number().optional(),
922
+ trend: z.string().optional(),
923
+ focusStack: z.array(HookJsonSchema).optional(),
924
+ bodyBuild: z
925
+ .object({ stale: z.boolean().optional(), loadedRef: z.string().optional(), currentRef: z.string().optional() })
926
+ .loose()
927
+ .optional(),
928
+ sessionContext: z.object({ sessionId: z.string().optional() }).loose().optional(),
929
+ bodyAvailability: z
930
+ .object({ status: z.string().optional(), remedy: z.string().optional(), healthy: z.boolean().optional() })
931
+ .loose()
932
+ .optional()
933
+ })
934
+ .loose();
935
+ /** The brain.wake todo counts the wake scan reads. */
936
+ const WakeSchema = z
937
+ .object({ todos: z.object({ pending: z.number().optional(), inProgress: z.number().optional() }).loose().optional() })
938
+ .loose();
939
+ /** One related-session row the wake scan renders. */
940
+ const RelatedSessionSchema = z
941
+ .object({
942
+ id: z.string().optional(),
943
+ handle: z.string().optional(),
944
+ title: z.string().optional(),
945
+ status: z.string().optional(),
946
+ bind: z.object({ action: z.string().optional(), sessionId: z.string().optional() }).loose().optional()
947
+ })
948
+ .loose();
949
+ function sessionReceiptLooksBound(session) {
950
+ return SessionReceiptSchema.safeParse(session).data?.bound === true;
951
+ }
952
+ function wakeScanMeasuredUnbound(data) {
953
+ if (sessionReceiptLooksBound(data.session))
954
+ return false;
955
+ if (data.session)
956
+ return true;
957
+ if ((data.relatedSessions?.length ?? 0) > 0)
958
+ return true;
959
+ const pulse = PulseSchema.safeParse(data.pulse ?? {}).data;
960
+ if (pulse?.bodyAvailability?.status === 'session-unbound')
961
+ return true;
962
+ return pulse?.sessionContext?.sessionId === 'ephemeral';
963
+ }
964
+ /**
965
+ * The body-truth wake scan — a METADATA-ONLY summary injected at SessionStart so an
966
+ * agent SEES the measured body state on waking (build freshness, session binding, focus
967
+ * load, coherence) instead of only a static guidance essay. It reads brain.pulse /
968
+ * brain.wake / session.status metadata; it must NEVER surface inner-world content (no
969
+ * recall), which is why the render only reads the fields its schemas name and ignores
970
+ * everything else in `data`. Pure and side-effect-free so it is directly testable.
971
+ */
972
+ export function renderWakeScan(data) {
973
+ const pulse = PulseSchema.safeParse(data.pulse ?? {}).data ?? {};
974
+ const wake = WakeSchema.safeParse(data.brain ?? {}).data ?? {};
975
+ const probe = data.bodyProbe;
976
+ if (!probe && !data.pulse && !data.brain && !data.session && !data.roster && !data.relatedSessions)
977
+ return undefined;
978
+ const lines = [...WAKE_SCAN_SCOPE_NOTE];
979
+ const bb = pulse.bodyBuild;
980
+ const avail = pulse.bodyAvailability;
981
+ // An unanswered probe is the whole reason this block exists: silence used to render
982
+ // as nothing, making a dead cognition body look exactly like a healthy wake.
983
+ if (probe && probe.status !== 'ok') {
984
+ lines.push(probeVerdictLine(probe));
985
+ }
986
+ else if (!data.pulse) {
987
+ lines.push('daemon: NOT PROBED — no pulse in this run · body truth is UNKNOWN');
988
+ }
989
+ // Build + session verdict for the DAEMON — PREFER the composed brain.pulse verdict
990
+ // (single source of truth), falling back to deriving from bodyBuild/sessionContext
991
+ // only for an older body whose pulse predates the verdict field.
992
+ const staleLine = (loaded, current) => `daemon build: STALE — loaded ${shortRef(loaded)}, workspace at ${shortRef(current)} · heal the daemon: \`vibes dev mcp restart\``;
993
+ if (avail?.status) {
994
+ switch (avail.status) {
995
+ case 'real':
996
+ lines.push(`daemon build: fresh @ ${shortRef(bb?.loadedRef)}`);
997
+ lines.push(`daemon session: bound (${shortRef(pulse.sessionContext?.sessionId)})`);
998
+ break;
999
+ case 'body-stale':
1000
+ lines.push(staleLine(bb?.loadedRef, bb?.currentRef));
1001
+ lines.push(`daemon session: bound (${shortRef(pulse.sessionContext?.sessionId)})`);
1002
+ break;
1003
+ case 'session-unbound':
1004
+ lines.push(`daemon build: fresh @ ${shortRef(bb?.loadedRef)}`);
1005
+ lines.push('daemon session: EPHEMERAL — no bound session (run session.init)');
1006
+ break;
1007
+ default:
1008
+ lines.push(`daemon: ${avail.status}${avail.remedy ? ` — ${avail.remedy}` : ''}`);
1009
+ }
1010
+ }
1011
+ else if (data.pulse) {
1012
+ // Fallback (body older than the bodyAvailability field): conservative derivation.
1013
+ if (bb) {
1014
+ lines.push(bb.stale ? staleLine(bb.loadedRef, bb.currentRef) : `daemon build: fresh @ ${shortRef(bb.loadedRef)}`);
1015
+ }
1016
+ else {
1017
+ lines.push('daemon build: freshness unknown — treat as STALE until proven (restart the daemon to be sure)');
1018
+ }
1019
+ if (pulse.sessionContext) {
1020
+ const sid = pulse.sessionContext.sessionId;
1021
+ lines.push(sid && sid !== 'ephemeral'
1022
+ ? `daemon session: bound (${shortRef(sid)})`
1023
+ : 'daemon session: EPHEMERAL — no bound session (run session.init)');
1024
+ }
1025
+ }
1026
+ // Focus load + coherence — reported BY the daemon, so labelled as such.
1027
+ if (pulse.focusStack) {
1028
+ const depth = pulse.focusStack.length;
1029
+ lines.push(`focus (daemon-reported): ${depth} target${depth === 1 ? '' : 's'}`);
1030
+ }
1031
+ if (pulse.coherence !== undefined) {
1032
+ lines.push(`state (daemon-reported): coherence ${pulse.coherence}/10${pulse.trend ? `, ${pulse.trend}` : ''}`);
1033
+ }
1034
+ // Todos (from brain.wake metadata).
1035
+ const pending = wake.todos?.pending ?? 0;
1036
+ const inProgress = wake.todos?.inProgress ?? 0;
1037
+ if (pending || inProgress) {
1038
+ lines.push(`todos (daemon-reported): ${inProgress} in progress, ${pending} pending`);
1039
+ }
1040
+ // The roster line, when there IS one. Alone is the common case and costs
1041
+ // exactly zero bytes here.
1042
+ if (data.roster)
1043
+ lines.push(data.roster);
1044
+ if (probe?.status !== 'unreachable' && wakeScanMeasuredUnbound(data)) {
1045
+ lines.push('your MCP connection is not a session participant until you bind — do that before coordinating, locking, or writing session state.');
1046
+ const related = data.relatedSessions ?? [];
1047
+ if (related.length > 0) {
1048
+ lines.push('related sessions:');
1049
+ for (const item of related.slice(0, 5)) {
1050
+ const row = RelatedSessionSchema.safeParse(item).data;
1051
+ if (!row?.id)
1052
+ continue;
1053
+ const handle = row.handle ?? row.id.replace(/-/g, '').slice(0, 8);
1054
+ const title = row.title ? ` "${row.title}"` : '';
1055
+ const status = row.status ? ` ${row.status}` : '';
1056
+ const action = row.bind?.action === 'resume' ? 'resume' : 'init';
1057
+ const sessionId = row.bind?.sessionId ?? row.id;
1058
+ lines.push(` - ${handle}${status}${title} session { action: "${action}", sessionId: "${sessionId}" }`);
1059
+ }
1060
+ }
1061
+ lines.push('create: session { action: "init", newSession: true }');
1062
+ }
1063
+ const endpointAttr = probe?.endpoint ? ` endpoint="${probe.endpoint}"` : '';
1064
+ return `<wake-scan scope="mcp-http-daemon"${endpointAttr}>\n${lines.map((l) => ` ${l}`).join('\n')}\n</wake-scan>`;
1065
+ }
1066
+ // SessionEnd
1067
+ // Runs when: Session terminates (user exits, timeout, etc.)
1068
+ // Purpose: Archive session metrics, save final state
1069
+ // Can inject: No - session is ending, no response expected
1070
+ async function handleSessionEnd(ctx) {
1071
+ if (isLocalContinuityHook(ctx.input)) {
1072
+ if (!ctx.eventConfig.brain) {
1073
+ // Brain is off, but the session lifecycle is not: the row this native
1074
+ // session owns still closes with it.
1075
+ const archived = await archiveExternalNativeSession(ctx.runtime, ctx.input.envelope);
1076
+ return { data: { skipped: 'brain disabled for local continuity', archived } };
1077
+ }
1078
+ // The row this native session owns closes with it even when metabolizing
1079
+ // fails: the archive runs in `finally`, and the metabolize failure propagates.
1080
+ let archived;
1081
+ try {
1082
+ const metabolized = await metabolizeExternalContinuity(ctx.runtime, ctx.input.envelope, 'close');
1083
+ archived = await archiveExternalNativeSession(ctx.runtime, ctx.input.envelope);
1084
+ return { data: { ...metabolized, archived } };
1085
+ }
1086
+ finally {
1087
+ if (archived === undefined)
1088
+ await archiveExternalNativeSession(ctx.runtime, ctx.input.envelope);
1089
+ }
1090
+ }
1091
+ const data = {};
1092
+ // Archive file access stats to session
1093
+ const statsResult = await callMcpTool(ctx.mcp, 'external', {
1094
+ action: 'file-access-list',
1095
+ includeStats: true,
1096
+ limit: 50
1097
+ });
1098
+ if (statsResult) {
1099
+ data.fileStats = statsResult;
1100
+ }
1101
+ return { data };
1102
+ }
1103
+ // UserPromptSubmit
1104
+ // Runs when: User submits a message, before the host processes it
1105
+ // Purpose: deliver pending messages and notices (no brain priming — see below)
1106
+ // Can inject: Yes - data.delivery
1107
+ // Input: PROMPT env var contains user's message
1108
+ //
1109
+ // NO AMBIENT PRIMING HERE — deliberate, do not "fix" it back.
1110
+ // This handler used to call `brain { action: 'prime', primeQuery }`. The brain tool's
1111
+ // prime action requires `query`, so the malformed arg meant the call NEVER ran. Renaming
1112
+ // the field would have been worse than the bug: `brain.prime` is a CONTENT path — it
1113
+ // decrypts inner-world memories AND ships plaintext to an AI ranker. Wiring that into a
1114
+ // hook that fires on EVERY user message installs a per-message ambient decrypt + egress,
1115
+ // exactly the law stated at handleSessionStart: ambient paths are METADATA-ONLY, and
1116
+ // content is only ever reached for deliberately (privacy floor,
1117
+ // docs/presence/CONTINUITY-PRACTICE.md). The dead call is therefore removed, not repaired.
1118
+ //
1119
+ // NOTE: user.said speech capture is NOT done here either — this hook-call process is a
1120
+ // thin HTTP proxy to a running MCP and does not load the awareness storage. The speech
1121
+ // lane is captured by `vibes presence say` (which loads awareness + awaits the write),
1122
+ // invoked directly from the UserPromptSubmit hook. See
1123
+ // presence/src/cli/commands/presence.say.*.
1124
+ async function handleUserPromptSubmit(ctx) {
1125
+ return { data: await deliveryData(ctx, 'prompt.submit') };
1126
+ }
1127
+ /** The collaboration delivery for `event`, as hook data (empty when there is nothing to say). */
1128
+ async function deliveryData(ctx, event) {
1129
+ const envelope = ctx.input.envelope;
1130
+ const delivery = envelope ? await collaborationContext(ctx.runtime, envelope, event) : undefined;
1131
+ return delivery ? { delivery } : {};
1132
+ }
1133
+ // PreToolUse
1134
+ // Runs when: The host is about to use a tool, before execution
1135
+ // Purpose: Validate, log, potentially block dangerous operations
1136
+ // Can inject: Yes - can add warnings, can BLOCK by returning error
1137
+ // Input: Tool name and arguments on stdin
1138
+ //
1139
+ // DESIGN NOTE: Powerful for safety/governance. Consider:
1140
+ // - Blocking destructive operations (rm -rf, DROP TABLE, etc.)
1141
+ // - Requiring confirmation for sensitive operations
1142
+ // - Logging all tool usage for audit
1143
+ // - Rate limiting expensive operations
1144
+ async function handlePreToolUse(ctx) {
1145
+ const data = {};
1146
+ const toolInfo = ctx.input.envelope?.tool;
1147
+ if (toolInfo) {
1148
+ data.tool = toolInfo.name;
1149
+ data.input = boundToolPayload(toolInfo.input);
1150
+ const tiers = (await readCollaborationSettings(ctx.runtime)).toolTiers;
1151
+ if (tiers.enabled) {
1152
+ const bridge = await runHookToolBridge(ctx.runtime, {
1153
+ event: 'tool.before',
1154
+ hostToolName: toolInfo.name,
1155
+ toolInput: toolInfo.input
1156
+ }, tiers);
1157
+ if (bridge.bridged) {
1158
+ data.bridge = bridge;
1159
+ if (bridge.denied) {
1160
+ data.blocked = bridge.message ?? 'tool denied by tier enforcement';
1161
+ }
1162
+ }
1163
+ }
1164
+ // A native edit takes its files' locks; another holder is named to the editor (or refuses it, when configured).
1165
+ if (!data.blocked && ctx.input.envelope) {
1166
+ const guard = await guardNativeEdit(ctx.runtime, ctx.input.envelope);
1167
+ if (guard) {
1168
+ data.locks = guard.locks;
1169
+ if (guard.blocked)
1170
+ data.blocked = guard.blocked;
1171
+ if (guard.notice)
1172
+ data.delivery = guard.notice;
1173
+ }
1174
+ }
1175
+ }
1176
+ return { data };
1177
+ }
1178
+ /**
1179
+ * Record a host file access for the hook's workspace session, in-process. A
1180
+ * session-less hook records nothing and says so; any other failure is logged
1181
+ * value-free and reported in the hook data, never thrown into the host.
1182
+ */
1183
+ async function trackHookFileAccess(runtime, access) {
1184
+ try {
1185
+ const { handleFileAccessTrack } = await import("../tools/unified/handlers/file-access-track.js");
1186
+ const sessionId = await resolveExternalSessionId(runtime);
1187
+ if (!sessionId)
1188
+ return { skipped: 'no-session' };
1189
+ await handleFileAccessTrack(runtime, { action: 'file-access-track', sessionId, ...access });
1190
+ return { filePath: access.filePath, operation: access.operation };
1191
+ }
1192
+ catch (error) {
1193
+ const failed = valueFreeFailure(CaughtFailureSchema.parse(error));
1194
+ getLogger('external.hooks', runtime).warn('hook file-access tracking failed', { failure: failed });
1195
+ return { failed };
1196
+ }
1197
+ }
1198
+ // PostToolUse
1199
+ // Runs when: Tool has completed execution
1200
+ // Purpose: Track file access, update state, inject follow-up guidance
1201
+ // Can inject: Yes - can add context about what happened
1202
+ // Input: Tool result on stdin
1203
+ //
1204
+ // Automatic brain actions invoked:
1205
+ // - brain.track() - Record tool use for learning (automatic tier)
1206
+ async function handlePostToolUse(ctx) {
1207
+ const data = {};
1208
+ const toolData = ctx.input.envelope?.tool;
1209
+ if (toolData) {
1210
+ const toolName = toolData.name;
1211
+ const toolInput = toolData.input ?? {};
1212
+ const toolOutput = toolData.result ?? {};
1213
+ const filePath = toolData.filePath;
1214
+ // Track file access for file operations
1215
+ if (filePath && ['Read', 'Write', 'Edit', 'MultiEdit', 'Glob', 'Grep'].includes(toolName)) {
1216
+ const operation = toolName === 'Write'
1217
+ ? 'write'
1218
+ : toolName === 'Edit' || toolName === 'MultiEdit'
1219
+ ? 'edit'
1220
+ : 'read';
1221
+ // Recorded in-process: a nested tool invocation per host tool call made the
1222
+ // hook's own bookkeeping a second traced, captured, authorized tool call.
1223
+ data.tracked = await trackHookFileAccess(ctx.runtime, { filePath, operation, toolName });
1224
+ }
1225
+ // Codex edits through `apply_patch`: every file its patch writes is an edit, so peers see it.
1226
+ if (!data.tracked && ctx.input.envelope) {
1227
+ const patched = nativeEditTargets(toolData, ctx.input.envelope.workspacePath, await hookWorkspaceRoot(ctx.runtime, ctx.input.envelope), []);
1228
+ for (const patchedPath of patched) {
1229
+ data.tracked = await trackHookFileAccess(ctx.runtime, { filePath: patchedPath, operation: 'edit', toolName });
1230
+ }
1231
+ }
1232
+ // Brain: track tool use for learning (automatic tier action), with a bounded,
1233
+ // redacted summary of the tool's input and result, never the whole payload.
1234
+ if (ctx.eventConfig.brain && toolName) {
1235
+ const trackResult = await callMcpTool(ctx.mcp, 'brain', {
1236
+ action: 'track',
1237
+ tool: toolName,
1238
+ input: boundToolPayload(toolInput),
1239
+ output: boundToolPayload(toolOutput),
1240
+ success: !toolData.error
1241
+ });
1242
+ if (trackResult) {
1243
+ data.brainTrack = trackResult;
1244
+ }
1245
+ }
1246
+ const tiers = (await readCollaborationSettings(ctx.runtime)).toolTiers;
1247
+ if (tiers.enabled && toolName) {
1248
+ const bridge = await runHookToolBridge(ctx.runtime, {
1249
+ event: 'tool.after',
1250
+ hostToolName: toolName,
1251
+ toolInput,
1252
+ toolResult: toolOutput
1253
+ }, tiers);
1254
+ if (bridge.bridged) {
1255
+ data.bridge = bridge;
1256
+ }
1257
+ }
1258
+ }
1259
+ return { data: { ...data, ...(await deliveryData(ctx, 'tool.after')) } };
1260
+ }
1261
+ // PermissionRequest
1262
+ // Runs when: The host needs user permission for an operation
1263
+ // Purpose: Log permission requests, potentially auto-approve known-safe ops
1264
+ // Can inject: Yes - can add context about the permission
1265
+ //
1266
+ // DESIGN NOTE: Could be used for:
1267
+ // - Logging all permission requests for audit
1268
+ // - Auto-approving based on project config
1269
+ // - Adding context about why permission is needed
1270
+ async function handlePermissionRequest(ctx) {
1271
+ const data = {};
1272
+ if (ctx.input.envelope) {
1273
+ const tool = ctx.input.envelope.tool;
1274
+ data.permission = {
1275
+ mode: ctx.input.envelope.permissionMode,
1276
+ tool: tool?.name,
1277
+ input: tool ? boundToolPayload(tool.input) : undefined
1278
+ };
1279
+ }
1280
+ return { data };
1281
+ }
1282
+ // PreCompact
1283
+ // Runs when: Context is about to be compacted (summarized)
1284
+ // Purpose: Save critical state before context is lost
1285
+ // Can inject: Yes - guidance for compaction
1286
+ async function handlePreCompact(ctx) {
1287
+ if (isLocalContinuityHook(ctx.input)) {
1288
+ if (!ctx.eventConfig.brain) {
1289
+ return { data: { skipped: 'brain disabled for local continuity' } };
1290
+ }
1291
+ return {
1292
+ data: await metabolizeExternalContinuity(ctx.runtime, ctx.input.envelope, 'pre-compaction')
1293
+ };
1294
+ }
1295
+ const data = {};
1296
+ // Consolidate brain memories before compaction
1297
+ if (ctx.eventConfig.brain) {
1298
+ const consolidateResult = await callMcpTool(ctx.mcp, 'brain', { action: 'consolidate' });
1299
+ if (consolidateResult) {
1300
+ data.consolidated = consolidateResult;
1301
+ }
1302
+ }
1303
+ // Generate context summary for compaction
1304
+ const summaryResult = await callMcpTool(ctx.mcp, 'external', {
1305
+ action: 'context-summary',
1306
+ format: 'compact',
1307
+ maxFiles: 15,
1308
+ includeTodos: true,
1309
+ includeScratchpad: false,
1310
+ timeWindowHours: 4
1311
+ });
1312
+ if (summaryResult) {
1313
+ data.summary = summaryResult;
1314
+ }
1315
+ return { data };
1316
+ }
1317
+ // Stop
1318
+ // Runs when: The host stops responding (completion, error, interrupt)
1319
+ // Purpose: Capture final session state
1320
+ // Can inject: the self-review nudge (data.delivery), rendered by the host's adapter
1321
+ //
1322
+ // Automatic actions invoked:
1323
+ // - session.status() - Capture final session state
1324
+ //
1325
+ // NO brain call here — deliberate, do not "fix" it back.
1326
+ // This handler used to call `brain { action: 'debrief' }`. `debrief` is NOT a brain
1327
+ // action (the real enum is `BrainActions` in presence/src/brain/tools/brain/schemas.ts:
1328
+ // pulse, prime, salience, coherence, consolidate, wake, track, focus, release,
1329
+ // distract, refocus, attention, plan, predict, outcome, stress, urgent, relax,
1330
+ // pressure), so end-of-turn reflection never ran — the hook advertised a
1331
+ // capability the runtime does not have, which is a lying projection
1332
+ // (docs/architecture/EXTERNAL-AS-RUNTIME-PROJECTION.md). It is removed rather than
1333
+ // re-pointed at `consolidate`: consolidate metabolizes content through an AI path and
1334
+ // writes durable memory, so firing it on every turn stop would install exactly the kind
1335
+ // of ambient content path that handleUserPromptSubmit documents as forbidden.
1336
+ // Metabolizing stays a deliberate reach the agent makes knowingly.
1337
+ async function handleStop(ctx) {
1338
+ const data = {};
1339
+ // NOTE: agent.said speech capture is NOT done here (see handleUserPromptSubmit) —
1340
+ // it is captured by `vibes presence say --role agent --from-transcript`, invoked
1341
+ // from the Stop hook, which loads the awareness storage and awaits the write.
1342
+ // Capture session state for continuity
1343
+ const sessionResult = await callMcpTool(ctx.mcp, 'session', { action: 'status' });
1344
+ if (sessionResult) {
1345
+ data.sessionSnapshot = sessionResult;
1346
+ }
1347
+ // A Stop hook re-run after its own block delivers nothing: Claude reports it with
1348
+ // `stop_hook_active`, and a second block would loop.
1349
+ if (ctx.input.envelope?.trigger === 'stop-hook-active')
1350
+ return { data };
1351
+ return { data: { ...data, ...(await deliveryData(ctx, 'agent.stop')) } };
1352
+ }
1353
+ // SubagentStop
1354
+ // Runs when: A subagent (Task tool) completes
1355
+ // Purpose: Process subagent results, update parent context
1356
+ // Can inject: Yes - can add summary of what subagent did
1357
+ //
1358
+ // DESIGN NOTE: Useful for:
1359
+ // - Aggregating results from parallel subagents
1360
+ // - Tracking subagent success/failure rates
1361
+ // - Injecting summaries back to parent context
1362
+ async function handleSubagentStop(ctx) {
1363
+ const data = {};
1364
+ const envelope = ctx.input.envelope;
1365
+ if (envelope?.subagent)
1366
+ data.subagent = envelope.subagent;
1367
+ if (envelope?.tool?.result !== undefined)
1368
+ data.result = boundToolPayload(envelope.tool.result);
1369
+ return { data };
1370
+ }
1371
+ // Notification
1372
+ // Runs when: The host sends a notification to the user
1373
+ // Purpose: Log notifications, trigger external alerts
1374
+ // Can inject: No - notification already sent
1375
+ //
1376
+ // DESIGN NOTE: Could be used for:
1377
+ // - Sending notifications to external systems (Slack, email)
1378
+ // - Logging important notifications for review
1379
+ // - Triggering webhooks
1380
+ async function handleNotification(ctx) {
1381
+ const data = {};
1382
+ if (ctx.input.envelope) {
1383
+ data.notification = {
1384
+ reason: ctx.input.envelope.reason,
1385
+ trigger: ctx.input.envelope.trigger
1386
+ };
1387
+ }
1388
+ return { data };
1389
+ }
1390
+ // Main Handler
1391
+ const EVENT_HANDLERS = {
1392
+ 'session.start': handleSessionStart,
1393
+ 'session.end': handleSessionEnd,
1394
+ 'prompt.submit': handleUserPromptSubmit,
1395
+ 'tool.before': handlePreToolUse,
1396
+ 'tool.after': handlePostToolUse,
1397
+ 'permission.request': handlePermissionRequest,
1398
+ 'context.beforeCompact': handlePreCompact,
1399
+ 'agent.stop': handleStop,
1400
+ 'subagent.stop': handleSubagentStop,
1401
+ notification: handleNotification,
1402
+ // No work after compaction: the session.start that follows it wakes the body.
1403
+ 'context.afterCompact': async () => ({ data: { skipped: 'no handler for event' } })
1404
+ };
1405
+ /** The invocation actor a normalized harness envelope declares. */
1406
+ export function hookInvocationOverlay(input) {
1407
+ const envelope = input.envelope;
1408
+ if (!envelope)
1409
+ return undefined;
1410
+ return {
1411
+ actor: {
1412
+ agentId: envelope.clientId,
1413
+ harness: envelope.clientId,
1414
+ harnessSessionId: envelope.nativeSessionId
1415
+ }
1416
+ };
1417
+ }
1418
+ /**
1419
+ * Execute hook for given event
1420
+ *
1421
+ * Loads configuration, checks if event is enabled, runs handler,
1422
+ * and assembles output with optional prompt injection.
1423
+ */
1424
+ export async function executeHookCall(input, options) {
1425
+ try {
1426
+ const { runtime } = options;
1427
+ // Load configuration
1428
+ const config = await loadConfig(runtime, input.target);
1429
+ // Check if hooks are globally disabled
1430
+ if (!config.enabled) {
1431
+ return {
1432
+ success: true,
1433
+ event: input.event,
1434
+ data: { skipped: 'hooks disabled globally' }
1435
+ };
1436
+ }
1437
+ // Get event-specific configuration
1438
+ const eventConfig = getEventConfig(config, input.event, {
1439
+ disableBrain: input.disableBrain,
1440
+ disablePrompts: input.disablePrompts
1441
+ });
1442
+ // Check if this event is disabled
1443
+ if (!eventConfig.enabled) {
1444
+ return {
1445
+ success: true,
1446
+ event: input.event,
1447
+ data: { skipped: 'event disabled in config' }
1448
+ };
1449
+ }
1450
+ // Build handler context. The MCP client is created PER HOOK CALL and carries the
1451
+ // event's configured timeout as a whole-call budget — previously `eventConfig.timeout`
1452
+ // was computed and thrown away, so a wedged MCP body hung session start forever.
1453
+ // Shared resolver (VIBES_MCP_URL override + default) — a hard-coded MCP origin is
1454
+ // the wrong-endpoint injury class that broke the knowledge client (cefe08d2c).
1455
+ // (Resolving this capability from the runtime instead of over HTTP is the deeper
1456
+ // fix, tracked in the external audit.)
1457
+ const timeoutMs = eventConfig.timeout ?? 30000;
1458
+ const ctx = {
1459
+ runtime,
1460
+ input,
1461
+ eventConfig,
1462
+ mcp: options.mcpFactory
1463
+ ? options.mcpFactory(timeoutMs)
1464
+ : createMcpClient({
1465
+ runtime,
1466
+ endpoint: await resolveLocalMcpUrlForRuntime(runtime, {
1467
+ workspaceRoot: await runtime.context('runtime/workspace-path'),
1468
+ vibesHome: getPathRoots(runtime).vibesHome
1469
+ }),
1470
+ timeoutMs
1471
+ })
1472
+ };
1473
+ // Run the handler
1474
+ const handler = EVENT_HANDLERS[input.event];
1475
+ let result;
1476
+ try {
1477
+ // The hook acts for the harness's agent: one invocation whose actor is
1478
+ // that agent and native session. Every organ call inside it (brain,
1479
+ // presence, continuity) resolves identity from this actor through the
1480
+ // runtime — never from the daemon's own environment or scope.
1481
+ result = await runtime.runInvocation(async () => {
1482
+ const client = tryGetVibesClient('external', runtime);
1483
+ const seat = client && input.envelope ? await resolveHookSeat(runtime, input.envelope) : null;
1484
+ return client && seat
1485
+ ? client.withDeferredAmbientDelivery(seat.sessionId, () => handler(ctx))
1486
+ : handler(ctx);
1487
+ }, hookInvocationOverlay(input));
1488
+ }
1489
+ finally {
1490
+ // Release the MCP session even when a handler throws — this process is about to
1491
+ // exit and can never reuse it.
1492
+ await ctx.mcp.dispose();
1493
+ }
1494
+ // Get prompt for this event (if enabled)
1495
+ const targetDescriptor = input.target
1496
+ ? runtime.query('external/host').withId(input.target).descriptors()[0]
1497
+ : undefined;
1498
+ const promptPolicy = targetDescriptor?.manifest.integration.hooks?.defaultPromptPolicy ?? 'default';
1499
+ const prompt = getPromptForEvent(input.event, eventConfig, promptPolicy);
1500
+ if (input.output === 'json') {
1501
+ return {
1502
+ success: true,
1503
+ event: input.event,
1504
+ data: {
1505
+ ...result.data,
1506
+ config: {
1507
+ brain: eventConfig.brain,
1508
+ prompts: eventConfig.prompts
1509
+ }
1510
+ }
1511
+ };
1512
+ }
1513
+ // Text output: inject the guidance prompt, and for SessionStart PREPEND the
1514
+ // metadata body-truth scan so the agent SEES its body state (stale/ephemeral/
1515
+ // focus/coherence) at wake instead of only a static essay. The run already
1516
+ // happened in the handler; this stops discarding its (metadata-only) result.
1517
+ let context = prompt;
1518
+ if (input.event === 'session.start') {
1519
+ const continuity = result.data?.continuity;
1520
+ const scan = continuity
1521
+ ? renderExternalContinuityContext(continuity)
1522
+ : renderWakeScan(result.data ?? {});
1523
+ // The project's conduct rules (its `workspace.rules`) steer a harness session as they steer every agent.
1524
+ const conduct = options.runtime.hasKind('rules/rule')
1525
+ ? await (await import('@vibesdotdev/rules/rule/guidance')).conductText(options.runtime)
1526
+ : '';
1527
+ context = [scan, conduct, prompt].filter(Boolean).join('\n\n') || undefined;
1528
+ }
1529
+ if (result.data?.delivery)
1530
+ context = [context, result.data.delivery].filter(Boolean).join('\n\n');
1531
+ return {
1532
+ success: true,
1533
+ event: input.event,
1534
+ context,
1535
+ data: result.data
1536
+ };
1537
+ }
1538
+ catch (error) {
1539
+ // The harness reads `error`: a typed refusal by its own value-free message, anything else by its facts.
1540
+ const failure = CaughtFailureSchema.parse(error);
1541
+ getLogger('external.hooks', options.runtime).warn('external hook failed', { event: input.event, failure: valueFreeFailure(failure) });
1542
+ return {
1543
+ success: false,
1544
+ event: input.event,
1545
+ error: failureReason(failure),
1546
+ failure: valueFreeFailure(CaughtFailureSchema.parse(error))
1547
+ };
1548
+ }
1549
+ }
1550
+ //# sourceMappingURL=call.js.map