stitchkit 0.104.2 → 0.105.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 (429) hide show
  1. package/CHANGELOG.md +372 -13
  2. package/darwin-native.cjs +4 -2
  3. package/dist/agent-runtime/browser-control-contract.d.ts +32 -2
  4. package/dist/agent-runtime/browser-control-contract.d.ts.map +1 -1
  5. package/dist/agent-runtime/browser-controller.d.ts +21 -3
  6. package/dist/agent-runtime/browser-controller.d.ts.map +1 -1
  7. package/dist/agent-runtime/coding-shell-process.d.ts.map +1 -1
  8. package/dist/agent-runtime/coding-tool-refusals.d.ts +1 -0
  9. package/dist/agent-runtime/coding-tool-refusals.d.ts.map +1 -1
  10. package/dist/agent-runtime/coding-tool-shell.d.ts.map +1 -1
  11. package/dist/agent-runtime/compaction.d.ts.map +1 -1
  12. package/dist/agent-runtime/contained-write.d.ts.map +1 -1
  13. package/dist/agent-runtime/control-schema.d.ts +48 -1
  14. package/dist/agent-runtime/control-schema.d.ts.map +1 -1
  15. package/dist/agent-runtime/deferred-tool-search.d.ts +3 -2
  16. package/dist/agent-runtime/deferred-tool-search.d.ts.map +1 -1
  17. package/dist/agent-runtime/harness-control.d.ts.map +1 -1
  18. package/dist/agent-runtime/harness-realtime.d.ts +34 -4
  19. package/dist/agent-runtime/harness-realtime.d.ts.map +1 -1
  20. package/dist/agent-runtime/runtime-recovery.d.ts.map +1 -1
  21. package/dist/agent-runtime/runtime-state.d.ts.map +1 -1
  22. package/dist/agent-runtime/sandbox-contract.d.ts.map +1 -1
  23. package/dist/agent-runtime/sandbox-process-owner.d.ts +9 -1
  24. package/dist/agent-runtime/sandbox-process-owner.d.ts.map +1 -1
  25. package/dist/agent-runtime/sandbox.d.ts +32 -1
  26. package/dist/agent-runtime/sandbox.d.ts.map +1 -1
  27. package/dist/agent-runtime/schedule-records.d.ts.map +1 -1
  28. package/dist/agent-runtime/schedules.d.ts.map +1 -1
  29. package/dist/agent-runtime/store-events.d.ts +9 -4
  30. package/dist/agent-runtime/store-events.d.ts.map +1 -1
  31. package/dist/agent-runtime/testing.d.ts.map +1 -1
  32. package/dist/application/diagnostic-journal-contract.d.ts +50 -0
  33. package/dist/application/diagnostic-journal-contract.d.ts.map +1 -1
  34. package/dist/application/diagnostic-journal-generations.d.ts +24 -0
  35. package/dist/application/diagnostic-journal-generations.d.ts.map +1 -0
  36. package/dist/application/diagnostic-journal-manager.d.ts.map +1 -1
  37. package/dist/application/diagnostic-journal-open.d.ts +10 -0
  38. package/dist/application/diagnostic-journal-open.d.ts.map +1 -0
  39. package/dist/application/diagnostic-journal-quarantine.d.ts +28 -0
  40. package/dist/application/diagnostic-journal-quarantine.d.ts.map +1 -0
  41. package/dist/application/diagnostic-journal-read-contract.d.ts +73 -3
  42. package/dist/application/diagnostic-journal-read-contract.d.ts.map +1 -1
  43. package/dist/application/diagnostic-journal-reader.d.ts +17 -2
  44. package/dist/application/diagnostic-journal-reader.d.ts.map +1 -1
  45. package/dist/application/diagnostic-journal-recovery.d.ts +18 -2
  46. package/dist/application/diagnostic-journal-recovery.d.ts.map +1 -1
  47. package/dist/application/diagnostic-journal-storage.d.ts +6 -2
  48. package/dist/application/diagnostic-journal-storage.d.ts.map +1 -1
  49. package/dist/application/diagnostic-journal-tail.d.ts +12 -0
  50. package/dist/application/diagnostic-journal-tail.d.ts.map +1 -0
  51. package/dist/application/diagnostic-journal.d.ts +3 -0
  52. package/dist/application/diagnostic-journal.d.ts.map +1 -1
  53. package/dist/application/directory-inbox-accept.d.ts +3 -3
  54. package/dist/application/directory-inbox-accept.d.ts.map +1 -1
  55. package/dist/application/directory-inbox-contract.d.ts +38 -10
  56. package/dist/application/directory-inbox-contract.d.ts.map +1 -1
  57. package/dist/application/directory-inbox-delivery.d.ts +3 -3
  58. package/dist/application/directory-inbox-delivery.d.ts.map +1 -1
  59. package/dist/application/directory-inbox-files.d.ts +17 -2
  60. package/dist/application/directory-inbox-files.d.ts.map +1 -1
  61. package/dist/application/directory-inbox-state.d.ts +1 -1
  62. package/dist/application/directory-inbox-state.d.ts.map +1 -1
  63. package/dist/application/directory-inbox.d.ts +1 -1
  64. package/dist/application/directory-inbox.d.ts.map +1 -1
  65. package/dist/application/file-state-store.d.ts +21 -1
  66. package/dist/application/file-state-store.d.ts.map +1 -1
  67. package/dist/application/grammy.d.ts.map +1 -1
  68. package/dist/application/kernel-contract.d.ts.map +1 -1
  69. package/dist/application/revision-signal.d.ts.map +1 -1
  70. package/dist/application/state-store.d.ts +3 -0
  71. package/dist/application/state-store.d.ts.map +1 -1
  72. package/dist/browser/api-error.d.ts +38 -0
  73. package/dist/browser/api-error.d.ts.map +1 -0
  74. package/dist/browser/chunked-upload.d.ts.map +1 -1
  75. package/dist/browser/client-executors.d.ts.map +1 -1
  76. package/dist/browser/client-url.d.ts.map +1 -1
  77. package/dist/browser/contract-stream.d.ts.map +1 -1
  78. package/dist/browser/http.d.ts +0 -25
  79. package/dist/browser/http.d.ts.map +1 -1
  80. package/dist/browser/resumable.d.ts.map +1 -1
  81. package/dist/contract/define-validation.d.ts +0 -1
  82. package/dist/contract/define-validation.d.ts.map +1 -1
  83. package/dist/contract/define.d.ts.map +1 -1
  84. package/dist/contract/errors-factory.d.ts.map +1 -1
  85. package/dist/contract/errors.d.ts +15 -18
  86. package/dist/contract/errors.d.ts.map +1 -1
  87. package/dist/contract/normalize.d.ts.map +1 -1
  88. package/dist/durability/effect.d.ts.map +1 -1
  89. package/dist/durability/scheduler.d.ts.map +1 -1
  90. package/dist/entrypoints/agent-runtime/browser.js +29 -18
  91. package/dist/entrypoints/agent-runtime/coding-tools.js +8 -7
  92. package/dist/entrypoints/agent-runtime/harness.js +15 -14
  93. package/dist/entrypoints/agent-runtime/realtime.d.ts +1 -1
  94. package/dist/entrypoints/agent-runtime/realtime.d.ts.map +1 -1
  95. package/dist/entrypoints/agent-runtime/realtime.js +119 -54
  96. package/dist/entrypoints/agent-runtime/sandbox.js +23 -17
  97. package/dist/entrypoints/agent-runtime/sqlite/bun.js +4 -3
  98. package/dist/entrypoints/agent-runtime/sqlite/node.js +4 -3
  99. package/dist/entrypoints/agent-runtime/testing.js +8 -6
  100. package/dist/entrypoints/agent-runtime.js +37 -38
  101. package/dist/entrypoints/application/diagnostic-journal.js +305 -111
  102. package/dist/entrypoints/application/directory-inbox.js +174 -77
  103. package/dist/entrypoints/application/grammy.js +5 -2
  104. package/dist/entrypoints/application/opentelemetry.js +2 -2
  105. package/dist/entrypoints/application.d.ts +2 -2
  106. package/dist/entrypoints/application.d.ts.map +1 -1
  107. package/dist/entrypoints/application.js +17 -8
  108. package/dist/entrypoints/cli/publish.d.ts +16 -0
  109. package/dist/entrypoints/cli/publish.d.ts.map +1 -0
  110. package/dist/entrypoints/cli/publish.js +527 -0
  111. package/dist/entrypoints/cli.d.ts +1 -2
  112. package/dist/entrypoints/cli.d.ts.map +1 -1
  113. package/dist/entrypoints/cli.js +59 -966
  114. package/dist/entrypoints/contract.js +3 -3
  115. package/dist/entrypoints/files/packaging.js +153 -64
  116. package/dist/entrypoints/files.d.ts +1 -0
  117. package/dist/entrypoints/files.d.ts.map +1 -1
  118. package/dist/entrypoints/files.js +17 -10
  119. package/dist/entrypoints/index.d.ts +2 -1
  120. package/dist/entrypoints/index.d.ts.map +1 -1
  121. package/dist/entrypoints/index.js +31 -60
  122. package/dist/entrypoints/node.js +8 -8
  123. package/dist/entrypoints/observability.js +3 -3
  124. package/dist/entrypoints/primitives.js +67 -83
  125. package/dist/entrypoints/process.d.ts +1 -1
  126. package/dist/entrypoints/process.d.ts.map +1 -1
  127. package/dist/entrypoints/process.js +2 -2
  128. package/dist/entrypoints/react.js +4 -2
  129. package/dist/entrypoints/remote.js +37 -13
  130. package/dist/entrypoints/server.js +18 -16
  131. package/dist/entrypoints/telegram/screens.js +5 -3
  132. package/dist/entrypoints/telegram.js +31 -46
  133. package/dist/entrypoints/testing.d.ts +1 -1
  134. package/dist/entrypoints/testing.d.ts.map +1 -1
  135. package/dist/entrypoints/testing.js +444 -448
  136. package/dist/entrypoints/tools/connections.js +268 -105
  137. package/dist/entrypoints/tools/contract.js +2 -2
  138. package/dist/entrypoints/tools/invoker.js +8 -7
  139. package/dist/entrypoints/tools/mcp.d.ts +2 -2
  140. package/dist/entrypoints/tools/mcp.d.ts.map +1 -1
  141. package/dist/entrypoints/tools/mcp.js +10 -9
  142. package/dist/entrypoints/tools.d.ts +0 -1
  143. package/dist/entrypoints/tools.d.ts.map +1 -1
  144. package/dist/entrypoints/tools.js +118 -53
  145. package/dist/entrypoints/tracking.js +2 -3
  146. package/dist/files/boundary.d.ts +2 -2
  147. package/dist/files/boundary.d.ts.map +1 -1
  148. package/dist/files/chunk-spool.d.ts.map +1 -1
  149. package/dist/files/file-io.d.ts +2 -2
  150. package/dist/files/file-io.d.ts.map +1 -1
  151. package/dist/files/native-packaging-layout.d.ts +50 -4
  152. package/dist/files/native-packaging-layout.d.ts.map +1 -1
  153. package/dist/files/native-packaging.d.ts +78 -17
  154. package/dist/files/native-packaging.d.ts.map +1 -1
  155. package/dist/{index-r5hsgkz5.js → index-0gs4ymfj.js} +6 -3
  156. package/dist/{index-zax7resm.js → index-0gxvns6s.js} +1 -13
  157. package/dist/index-0s4xebbg.js +8 -0
  158. package/dist/{index-r4r70zmh.js → index-12zsej7b.js} +5 -2
  159. package/dist/{index-kemm0ej5.js → index-1pwwan01.js} +65 -22
  160. package/dist/{index-vgkbcnkc.js → index-299sm5tr.js} +1 -1
  161. package/dist/{index-2vnh05w4.js → index-2k91mewf.js} +31 -74
  162. package/dist/{index-269zqj8m.js → index-2rc6jd9n.js} +28 -12
  163. package/dist/{index-wh0ecvyk.js → index-37asdw3a.js} +1 -1
  164. package/dist/index-3h0ztg0z.js +285 -0
  165. package/dist/{index-g95fk660.js → index-4vsby8n8.js} +8 -15
  166. package/dist/index-556g5hsh.js +17 -0
  167. package/dist/{index-adhgd4pe.js → index-5p55xreg.js} +2 -2
  168. package/dist/index-5w6t91ze.js +47 -0
  169. package/dist/{index-9pw0a51a.js → index-6yxhe58g.js} +40 -7
  170. package/dist/{index-6d9xaxw1.js → index-8ks9b85e.js} +33 -5
  171. package/dist/{index-bhb950qs.js → index-916yh4e2.js} +25 -12
  172. package/dist/index-9tqbxv5p.js +44 -0
  173. package/dist/{index-5csmzesf.js → index-azx12jgv.js} +4 -3
  174. package/dist/{index-mbnnw3f2.js → index-b0kddvzw.js} +15 -5
  175. package/dist/{index-n5yqxd3d.js → index-b0w7rbpt.js} +23 -2
  176. package/dist/index-b56nnscm.js +132 -0
  177. package/dist/{index-0ndk4555.js → index-c0hffcmj.js} +2 -2
  178. package/dist/{index-pptyv13k.js → index-c17xcx4k.js} +42 -6
  179. package/dist/{index-g2j7pnak.js → index-cmzvhhtd.js} +5 -2
  180. package/dist/index-cq59agna.js +51 -0
  181. package/dist/{index-ssmd41kh.js → index-d2h99n7d.js} +1 -1
  182. package/dist/{index-z94wht4y.js → index-dky0dcmf.js} +34 -5
  183. package/dist/{index-za6j7nwy.js → index-dsnjzb62.js} +104 -51
  184. package/dist/index-eemvahkc.js +21 -0
  185. package/dist/index-ef8gdaq0.js +105 -0
  186. package/dist/{index-fa4wg312.js → index-f199nfq5.js} +10 -6
  187. package/dist/{index-ck71tbcf.js → index-fsw1ybf3.js} +11 -15
  188. package/dist/{index-f330qqyg.js → index-g2vfg7ak.js} +217 -63
  189. package/dist/{index-fk18k56k.js → index-gr5g3xfw.js} +11 -18
  190. package/dist/{index-jn9g8xdt.js → index-hjvje0pf.js} +6 -4
  191. package/dist/{index-x928baz2.js → index-j9gxbztg.js} +18 -14
  192. package/dist/index-kfjkb396.js +37 -0
  193. package/dist/{index-6drst9sg.js → index-ksfagmyz.js} +45 -345
  194. package/dist/index-m616f0yz.js +120 -0
  195. package/dist/{index-fm1c1a08.js → index-m6w6jtda.js} +40 -21
  196. package/dist/{index-ptn0g0gj.js → index-ma963wz7.js} +21 -20
  197. package/dist/{index-bakgedh8.js → index-msfpyy2f.js} +2 -4
  198. package/dist/{index-ywppsaby.js → index-n1nszyk0.js} +23 -34
  199. package/dist/{index-v14qqmys.js → index-n4689krb.js} +1 -1
  200. package/dist/{index-a0zzh8ak.js → index-pz3y6b6g.js} +3 -3
  201. package/dist/{index-43p08g7t.js → index-pzb63z66.js} +12 -8
  202. package/dist/{index-h97tqqp1.js → index-qaet40b2.js} +5 -3
  203. package/dist/{index-t1sr4aks.js → index-qaqbdm7s.js} +52 -6
  204. package/dist/{index-77nxk6ay.js → index-r393tnfp.js} +16 -10
  205. package/dist/{index-kb8styz3.js → index-rpzewktb.js} +15 -5
  206. package/dist/{index-27a2pj09.js → index-sj28htvf.js} +1 -1
  207. package/dist/index-szybbezc.js +455 -0
  208. package/dist/{index-2hyavjjj.js → index-wbhdzxar.js} +3 -3
  209. package/dist/{index-4e0ah203.js → index-wdy68sh6.js} +47 -24
  210. package/dist/{index-hbd32c6a.js → index-wqmvtnkp.js} +38 -89
  211. package/dist/{index-hp9d77wk.js → index-x7w1z6pf.js} +15 -4
  212. package/dist/{index-20yvtn9a.js → index-yt7gyg5x.js} +1 -1
  213. package/dist/{index-cvda079a.js → index-yvfk3y36.js} +12 -2
  214. package/dist/{index-5z6jn897.js → index-z23rfxhj.js} +1 -1
  215. package/dist/internal/abort-race.d.ts +8 -2
  216. package/dist/internal/abort-race.d.ts.map +1 -1
  217. package/dist/internal/atomic-file.d.ts +55 -9
  218. package/dist/internal/atomic-file.d.ts.map +1 -1
  219. package/dist/internal/atomic-publication.d.ts +39 -4
  220. package/dist/internal/atomic-publication.d.ts.map +1 -1
  221. package/dist/internal/atomic-staging.d.ts +46 -0
  222. package/dist/internal/atomic-staging.d.ts.map +1 -0
  223. package/dist/internal/bounded-file-read.d.ts +19 -11
  224. package/dist/internal/bounded-file-read.d.ts.map +1 -1
  225. package/dist/internal/bounded-lines.d.ts.map +1 -1
  226. package/dist/internal/close-after.d.ts +11 -0
  227. package/dist/internal/close-after.d.ts.map +1 -0
  228. package/dist/internal/deadline.d.ts +10 -0
  229. package/dist/internal/deadline.d.ts.map +1 -1
  230. package/dist/internal/exclusive-lock-read.d.ts +10 -12
  231. package/dist/internal/exclusive-lock-read.d.ts.map +1 -1
  232. package/dist/internal/exclusive-lock.d.ts +2 -2
  233. package/dist/internal/exclusive-lock.d.ts.map +1 -1
  234. package/dist/internal/file-observation.d.ts +14 -0
  235. package/dist/internal/file-observation.d.ts.map +1 -0
  236. package/dist/internal/json-data.d.ts +22 -5
  237. package/dist/internal/json-data.d.ts.map +1 -1
  238. package/dist/internal/positive-integer.d.ts +9 -0
  239. package/dist/internal/positive-integer.d.ts.map +1 -0
  240. package/dist/internal/process-instance.d.ts +35 -5
  241. package/dist/internal/process-instance.d.ts.map +1 -1
  242. package/dist/internal/secure-fetch.d.ts.map +1 -1
  243. package/dist/internal/timers.d.ts +11 -0
  244. package/dist/internal/timers.d.ts.map +1 -0
  245. package/dist/internal/with-exclusive-lock.d.ts +5 -4
  246. package/dist/internal/with-exclusive-lock.d.ts.map +1 -1
  247. package/dist/observability/bounded-sink.d.ts.map +1 -1
  248. package/dist/primitives/canonical-json.d.ts +23 -2
  249. package/dist/primitives/canonical-json.d.ts.map +1 -1
  250. package/dist/primitives/delivery.d.ts.map +1 -1
  251. package/dist/primitives/index.d.ts +1 -1
  252. package/dist/primitives/index.d.ts.map +1 -1
  253. package/dist/primitives/money.d.ts.map +1 -1
  254. package/dist/process/cleanup.d.ts +6 -1
  255. package/dist/process/cleanup.d.ts.map +1 -1
  256. package/dist/process/command-lifetime.d.ts +4 -0
  257. package/dist/process/command-lifetime.d.ts.map +1 -1
  258. package/dist/process/command-owner.d.ts.map +1 -1
  259. package/dist/process/command.d.ts +4 -0
  260. package/dist/process/command.d.ts.map +1 -1
  261. package/dist/process/contract.d.ts +67 -2
  262. package/dist/process/contract.d.ts.map +1 -1
  263. package/dist/process/group.d.ts +40 -3
  264. package/dist/process/group.d.ts.map +1 -1
  265. package/dist/process/launch.d.ts +12 -1
  266. package/dist/process/launch.d.ts.map +1 -1
  267. package/dist/process/terminate.d.ts +39 -0
  268. package/dist/process/terminate.d.ts.map +1 -0
  269. package/dist/react/query-client.d.ts.map +1 -1
  270. package/dist/realtime/rejection.d.ts.map +1 -1
  271. package/dist/server/contract-stream.d.ts.map +1 -1
  272. package/dist/server/handler-state.d.ts.map +1 -1
  273. package/dist/server/implement.d.ts.map +1 -1
  274. package/dist/server/request-body.d.ts +0 -1
  275. package/dist/server/request-body.d.ts.map +1 -1
  276. package/dist/server/unix-client.d.ts.map +1 -1
  277. package/dist/telegram/broadcast-delivery.d.ts.map +1 -1
  278. package/dist/telegram/broadcast-failure.d.ts +10 -2
  279. package/dist/telegram/broadcast-failure.d.ts.map +1 -1
  280. package/dist/telegram/operator-channel.d.ts.map +1 -1
  281. package/dist/telegram/screens/outcome.d.ts.map +1 -1
  282. package/dist/testing/surface-conformance.d.ts +1 -1
  283. package/dist/testing/surface-conformance.d.ts.map +1 -1
  284. package/dist/testing/surface-manifest.d.ts +0 -6
  285. package/dist/testing/surface-manifest.d.ts.map +1 -1
  286. package/dist/tools/agent.d.ts +1 -1
  287. package/dist/tools/agent.d.ts.map +1 -1
  288. package/dist/tools/cli/args.d.ts +1 -1
  289. package/dist/tools/cli/args.d.ts.map +1 -1
  290. package/dist/tools/cli/help.d.ts.map +1 -1
  291. package/dist/tools/cli/invoke.d.ts +2 -2
  292. package/dist/tools/cli/invoke.d.ts.map +1 -1
  293. package/dist/tools/cli/profile.d.ts.map +1 -1
  294. package/dist/tools/cli/publication-assets.d.ts.map +1 -1
  295. package/dist/tools/cli/publication-contract.d.ts +8 -0
  296. package/dist/tools/cli/publication-contract.d.ts.map +1 -1
  297. package/dist/tools/cli/publication-control.d.ts.map +1 -1
  298. package/dist/tools/cli/publication-storage.d.ts +23 -2
  299. package/dist/tools/cli/publication-storage.d.ts.map +1 -1
  300. package/dist/tools/cli/publication.d.ts +8 -1
  301. package/dist/tools/cli/publication.d.ts.map +1 -1
  302. package/dist/tools/connections/errors.d.ts +18 -6
  303. package/dist/tools/connections/errors.d.ts.map +1 -1
  304. package/dist/tools/connections/limits.d.ts +8 -2
  305. package/dist/tools/connections/limits.d.ts.map +1 -1
  306. package/dist/tools/connections/mcp-client.d.ts.map +1 -1
  307. package/dist/tools/connections/mcp-envelope.d.ts.map +1 -1
  308. package/dist/tools/connections/openapi.d.ts.map +1 -1
  309. package/dist/tools/connections/schema-budget.d.ts +1 -1
  310. package/dist/tools/connections/schema-budget.d.ts.map +1 -1
  311. package/dist/tools/connections/sse-session.d.ts.map +1 -1
  312. package/dist/tools/execute-args.d.ts.map +1 -1
  313. package/dist/tools/execute-result.d.ts.map +1 -1
  314. package/dist/tools/internal/surface-projector.d.ts +17 -3
  315. package/dist/tools/internal/surface-projector.d.ts.map +1 -1
  316. package/dist/tools/internal/tool-error-projection.d.ts +16 -0
  317. package/dist/tools/internal/tool-error-projection.d.ts.map +1 -0
  318. package/dist/tools/internal/tool-view.d.ts.map +1 -1
  319. package/dist/tools/invoker.d.ts.map +1 -1
  320. package/dist/tools/list-names.d.ts +3 -2
  321. package/dist/tools/list-names.d.ts.map +1 -1
  322. package/dist/tools/manifest.d.ts +3 -2
  323. package/dist/tools/manifest.d.ts.map +1 -1
  324. package/dist/tools/mcp/handler.d.ts +7 -0
  325. package/dist/tools/mcp/handler.d.ts.map +1 -1
  326. package/dist/tools/mcp/mount.d.ts +18 -2
  327. package/dist/tools/mcp/mount.d.ts.map +1 -1
  328. package/dist/tools/mcp/prepare.d.ts +3 -3
  329. package/dist/tools/mcp/prepare.d.ts.map +1 -1
  330. package/dist/tools/mcp/register.d.ts.map +1 -1
  331. package/dist/tools/mcp/runtime-tools.d.ts.map +1 -1
  332. package/dist/tools/mcp/stdio-signals.d.ts +14 -0
  333. package/dist/tools/mcp/stdio-signals.d.ts.map +1 -1
  334. package/dist/tools/mcp/stdio.d.ts +7 -0
  335. package/dist/tools/mcp/stdio.d.ts.map +1 -1
  336. package/dist/tools/operations/async-operation-runtime-tools.d.ts.map +1 -1
  337. package/dist/tools/operations/async-operation-runtime-types.d.ts +3 -3
  338. package/dist/tools/operations/async-operation-runtime-types.d.ts.map +1 -1
  339. package/dist/tools/operations/define-wait-tool.d.ts +1 -1
  340. package/dist/tools/operations/define-wait-tool.d.ts.map +1 -1
  341. package/dist/tools/operations/wait-core.d.ts +0 -6
  342. package/dist/tools/operations/wait-core.d.ts.map +1 -1
  343. package/dist/tools/registry.d.ts +1 -1
  344. package/dist/tools/registry.d.ts.map +1 -1
  345. package/dist/tools/remote.d.ts +1 -1
  346. package/dist/tools/remote.d.ts.map +1 -1
  347. package/dist/tools/{runtime-tool-execution.d.ts → runtime-tool-declaration.d.ts} +32 -9
  348. package/dist/tools/runtime-tool-declaration.d.ts.map +1 -0
  349. package/dist/tools/runtime-tool-mcp.d.ts +6 -15
  350. package/dist/tools/runtime-tool-mcp.d.ts.map +1 -1
  351. package/dist/tools/runtime-tool.d.ts +14 -12
  352. package/dist/tools/runtime-tool.d.ts.map +1 -1
  353. package/dist/tools/schema/coerce.d.ts +4 -0
  354. package/dist/tools/schema/coerce.d.ts.map +1 -1
  355. package/dist/tools/schema/flatten-join.d.ts.map +1 -1
  356. package/dist/tools/surface.d.ts +7 -11
  357. package/dist/tools/surface.d.ts.map +1 -1
  358. package/dist/tools/transfer/define-download-tool.d.ts +1 -1
  359. package/dist/tools/transfer/define-download-tool.d.ts.map +1 -1
  360. package/dist/tools/transfer/define-upload-tool.d.ts +1 -1
  361. package/dist/tools/transfer/define-upload-tool.d.ts.map +1 -1
  362. package/dist/tools/transfer/define-view-file-tool.d.ts +1 -1
  363. package/dist/tools/transfer/define-view-file-tool.d.ts.map +1 -1
  364. package/dist/tools/transfer/managed-file-error.d.ts.map +1 -1
  365. package/dist/tools/transfer/view-file-contract.d.ts.map +1 -1
  366. package/dist/tools/transfer/view-file.d.ts +1 -1
  367. package/dist/tools/transfer/view-file.d.ts.map +1 -1
  368. package/dist/tools/transports.d.ts +3 -2
  369. package/dist/tools/transports.d.ts.map +1 -1
  370. package/llms/agent-runtime-browser.txt +10 -4
  371. package/llms/agent-runtime-harness.txt +32 -31
  372. package/llms/agent-runtime-react.txt +1 -1
  373. package/llms/agent-runtime-realtime.txt +14 -5
  374. package/llms/agent-runtime-sandbox.txt +3 -11
  375. package/llms/agent-runtime.3.txt +2 -2
  376. package/llms/agent-runtime.txt +0 -9
  377. package/llms/application.2.txt +3 -12
  378. package/llms/application.3.txt +7 -4
  379. package/llms/application.txt +44 -15
  380. package/llms/cli-publish.txt +29 -0
  381. package/llms/cli.2.txt +9 -11
  382. package/llms/cli.txt +26 -14
  383. package/llms/declaration.txt +0 -9
  384. package/llms/files-packaging.txt +16 -8
  385. package/llms/files.txt +4 -2
  386. package/llms/geo.txt +0 -9
  387. package/llms/live.txt +4 -13
  388. package/llms/observability.txt +31 -5
  389. package/llms/primitives.txt +38 -20
  390. package/llms/process.txt +287 -157
  391. package/llms/react-keyboard.txt +0 -9
  392. package/llms/react.txt +0 -18
  393. package/llms/server.4.txt +1 -1
  394. package/llms/server.5.txt +1 -1
  395. package/llms/server.txt +1 -1
  396. package/llms/stitchkit.txt +6 -7
  397. package/llms/telegram-screens.txt +2 -2
  398. package/llms/testing.txt +0 -1
  399. package/llms/tools-mcp.txt +2 -3
  400. package/llms/tools.2.txt +12 -0
  401. package/llms/tools.3.txt +5 -6
  402. package/llms/tools.txt +6 -4
  403. package/llms/upgrading-0.37.0-0.50.0.txt +947 -0
  404. package/llms/{upgrading-0.44.0-0.61.0.txt → upgrading-0.53.0-0.67.0.txt} +576 -506
  405. package/llms/{upgrading-0.62.0-0.80.0.txt → upgrading-0.68.0-0.94.0.txt} +562 -576
  406. package/llms/{upgrading-0.81.0-0.104.0.txt → upgrading-0.95.0-0.105.0.txt} +452 -567
  407. package/llms/upgrading.txt +4 -4
  408. package/llms-full.txt +1029 -409
  409. package/llms.txt +24 -24
  410. package/native-assets.json +11 -3
  411. package/package.json +6 -6
  412. package/dist/agent-runtime/harness-tools.d.ts +0 -11
  413. package/dist/agent-runtime/harness-tools.d.ts.map +0 -1
  414. package/dist/entrypoints/agent-runtime/harness-tools.d.ts +0 -2
  415. package/dist/entrypoints/agent-runtime/harness-tools.d.ts.map +0 -1
  416. package/dist/entrypoints/agent-runtime/harness-tools.js +0 -32
  417. package/dist/index-1a6jtnd9.js +0 -88
  418. package/dist/index-8a9ksm91.js +0 -95
  419. package/dist/index-a3wma1hk.js +0 -48
  420. package/dist/index-jd470k6q.js +0 -109
  421. package/dist/index-n1dqr7gf.js +0 -20
  422. package/dist/index-nggfa2yn.js +0 -34
  423. package/dist/index-s4evrmp5.js +0 -98
  424. package/dist/index-ze1eph1k.js +0 -20
  425. package/dist/tools/connections/error-projection.d.ts +0 -4
  426. package/dist/tools/connections/error-projection.d.ts.map +0 -1
  427. package/dist/tools/runtime-tool-execution.d.ts.map +0 -1
  428. package/llms/agent-runtime-harness-tools.txt +0 -25
  429. package/llms/upgrading-0.37.0-0.44.0.txt +0 -444
@@ -1,14 +1,421 @@
1
- # Upgrading 0.81.0 → 0.104.0 — stitchkit docs slice
1
+ # Upgrading 0.95.0 → 0.105.0 — stitchkit docs slice
2
2
 
3
3
  > Generated from the `docs/` tree by `bun run gen:llms`. The index of all slices is
4
4
  > `llms.txt` in this package.
5
5
 
6
- Contains: Guide: Upgrading, 0.81.0 → 0.104.0 (docs/guide/upgrading.md)
6
+ Contains: Guide: Upgrading, 0.95.0 → 0.105.0 (docs/guide/upgrading.md)
7
7
 
8
8
  ==============================================================================
9
- # Guide: Upgrading, 0.81.0 → 0.104.0 (docs/guide/upgrading.md)
9
+ # Guide: Upgrading, 0.95.0 → 0.105.0 (docs/guide/upgrading.md)
10
10
  ==============================================================================
11
11
 
12
+ ## Released migration: 0.105.0
13
+
14
+ ### CLI publication has its own entrypoint
15
+
16
+ **Who must act:** code that imports `publishCli`, `CliPublicationOptions`, `CliPublicationPhase` or
17
+ `CliPublicationResult` from `stitchkit/cli`. Everything else in `stitchkit/cli` — `createCli`, the
18
+ manifest schemas, signatures, `renderCliInstaller` and the updater — is unchanged.
19
+
20
+ `publishCli` is release infrastructure, so it now ships from the evolving entrypoint
21
+ `stitchkit/cli/publish` instead of the stable `stitchkit/cli`
22
+ ([ADR 0245](../decisions/0245-cli-publication-is-an-evolving-leaf.md)). Its options, result and
23
+ behaviour are the same.
24
+
25
+ 1. Move the publication names to the new specifier; keep every other CLI import where it is:
26
+
27
+ ```ts
28
+ // before
29
+ import { publishCli, type CliPublicationOptions, verifyCliManifest } from 'stitchkit/cli'
30
+ // after
31
+ import { verifyCliManifest } from 'stitchkit/cli'
32
+ import { publishCli, type CliPublicationOptions } from 'stitchkit/cli/publish'
33
+ ```
34
+
35
+ Search pattern: `\b(publishCli|CliPublication(Options|Phase|Result))\b` in files that import
36
+ from `'stitchkit/cli'`.
37
+ 2. Type-check: an import left on `stitchkit/cli` fails with "has no exported member".
38
+ 3. `stitchkit/cli/publish` is evolving: read its breaking entries in each minor you upgrade across.
39
+
40
+ ### a command stops by its `stop` policy
41
+
42
+ **Who must act:** callers of `runNativeCommand` (`stitchkit/process`) that pass `killGraceMs`.
43
+ Callers that omit it need no change: the default stop is the same TERM to the group, 100 ms, KILL.
44
+
45
+ 1. Replace `killGraceMs: N` with a group stop of the same grace:
46
+
47
+ ```ts
48
+ // before
49
+ await runNativeCommand({ executable, args, signal, killGraceMs: 500 })
50
+ // after
51
+ await runNativeCommand({ executable, args, signal, stop: { target: 'group', graceMs: 500 } })
52
+ ```
53
+
54
+ Search pattern: `killGraceMs:\s*(\d[\d_]*)` → `stop: { target: 'group', graceMs: $1 }`.
55
+ 2. If your own wrapper signals only the leader and waits a long grace (cooperative cancellation),
56
+ replace it with `stop: { target: 'leader', signal: 'SIGINT', graceMs }` (up to one hour). Pass
57
+ `killOn` with your shutdown signal so an application that stops sooner kills the group first.
58
+ 3. The result of a stopped command rejects once the group is gone, up to `graceMs` plus
59
+ `cleanupTimeoutMs` after the abort; size your caller deadlines on that sum.
60
+
61
+ ### a command stops what its leader left
62
+
63
+ **Who must act:** callers of `runNativeCommand` (`stitchkit/process`) whose command starts a helper
64
+ in its own process group that must keep running after the command returns. A daemon that detaches
65
+ with `setsid` (as `daemon(3)` does) is not in the group and needs
66
+ no change.
67
+
68
+ `descendants` now defaults to `'terminate-after-leader'`
69
+ ([ADR 0246](../decisions/0246-a-command-stops-its-descendants-by-default.md)): when the leader
70
+ exits, the members it left in the group are stopped by the command's `stop` policy before the
71
+ pipes drain.
72
+
73
+ 1. Find the commands that start a background helper on purpose (a `&` in a shell script, a spawned
74
+ child the leader does not wait for) and declare `'leave'` on them:
75
+
76
+ ```ts
77
+ // before
78
+ await runNativeCommand({ executable, args, timeoutMs })
79
+ // after
80
+ await runNativeCommand({ executable, args, timeoutMs, descendants: 'leave' })
81
+ ```
82
+
83
+ 2. Remove an explicit `descendants: 'terminate-after-leader'`, or keep it: it is now the default.
84
+ 3. A command whose helper inherited stdout or stderr used to wait for that helper until its
85
+ deadline. It now completes when the leader exits; drop a workaround that killed the helper from
86
+ `onLeaderSettled`.
87
+
88
+ ### native packaging verifies published digests
89
+
90
+ **Who must act:** build scripts that call `createNativePackaging` (`stitchkit/files/packaging`) and
91
+ read `asset.sourcePath`, hash the addon themselves, switch over the refusal `state`/`code`, pass a
92
+ `platform` other than the literal `'darwin'`, or parse `node_modules/stitchkit/native-assets.json`.
93
+
94
+ The package now publishes the `size` and SHA256 of each Darwin addon, computed when Stitchkit is
95
+ built, in `native-assets.json` at `formatVersion: 2`. `createNativePackaging` reads each selected
96
+ addon once, compares it with that digest and returns the verified bytes. An installed addon that
97
+ differs refuses with `NATIVE_ASSET_DIGEST_MISMATCH`.
98
+
99
+ 1. Replace every read of `asset.sourcePath` with `asset.bytes`, and delete your own re-hash of the
100
+ addon: the result's `sha256` is the published digest and `bytes` already match it.
101
+
102
+ ```ts
103
+ // before
104
+ const bytes = readFileSync(asset.sourcePath)
105
+ if (createHash('sha256').update(bytes).digest('hex') !== asset.sha256) throw …
106
+ copyFileSync(asset.sourcePath, destination)
107
+ // after
108
+ writeFileSync(destination, asset.bytes)
109
+ ```
110
+
111
+ 2. Handle the third refusal. A `switch` over `result.state` gains `'mismatch'`
112
+ (`code: 'NATIVE_ASSET_DIGEST_MISMATCH'`); treat it as a failed build, never as a missing addon.
113
+ It carries the differing `architecture` with `expected` (published) and `actual` (installed)
114
+ `{ size, sha256 }`; log both pairs.
115
+ 3. Pass the target platform as the literal `'darwin'`. `platform` is a closed enum, so a free
116
+ string (a target name read from configuration, `process.platform`) no longer type-checks, and
117
+ another platform throws instead of returning `unsupported`. Skip packaging for non-Darwin
118
+ targets before the call:
119
+
120
+ ```ts
121
+ // before
122
+ const native = createNativePackaging({ platform: target.platform, architecture, … })
123
+ if (native.state === 'unsupported') return
124
+ // after
125
+ if (target.platform !== 'darwin') return
126
+ const native = createNativePackaging({ platform: target.platform, architecture, … })
127
+ ```
128
+
129
+ `unsupported` now means only an architecture the package has no addon for.
130
+ 4. Call `createNativePackaging` once per build and pass the result (its `assets` and `plugin`)
131
+ where it is needed. Each call reads and hashes the selected addons again.
132
+ 5. If you read `native-assets.json` directly, read `assets.<arch>.path`, `.size` and `.sha256`
133
+ instead of a bare path per architecture; an architecture with no entry is not published.
134
+
135
+ ### exclusive locks publish their owner first
136
+
137
+ **Who must act:** callers of `withExclusiveLock` (`stitchkit/files`) that rely on a lock file with no
138
+ readable owner being taken by age, and anything that puts lock files on a filesystem without hard
139
+ links. Every other caller needs no change.
140
+
141
+ A lock is now written to a private `.lock-<id>.tmp` file in the lock's directory, then hard-linked to
142
+ the lock name. The name never exists without a complete owner record, so `ownerlessGraceMs` defaults
143
+ to `null` instead of 5 000 ms: a lock file with no readable owner is never taken because of its age.
144
+
145
+ 1. If you depended on age-based reclaim of an empty lock file left by an older writer, opt in:
146
+
147
+ ```ts
148
+ // before: an empty lock older than 5 s was taken by default
149
+ await withExclusiveLock(path, run)
150
+ // after: say so; only legacy empty files need it
151
+ await withExclusiveLock(path, run, { ownerlessGraceMs: 5_000 })
152
+ ```
153
+
154
+ 2. Keep lock directories on a filesystem that supports hard links (local ext4, xfs, APFS and the
155
+ like). `link` failing with `EPERM` or `ENOTSUP` fails the acquisition.
156
+ 3. Expect a `.lock-*.tmp` sibling only after a holder was killed between writing its record and
157
+ publishing it. It is not a lock; the next reclaim in that directory removes the ones whose owner
158
+ is gone on this machine. Exclude the pattern from directory-size caps or backups if you have any.
159
+
160
+ ### one runtime-tool declaration
161
+
162
+ **Who must act:** code that names `RuntimeToolExecution`, `RuntimeToolExecutionWithOutput`,
163
+ `RuntimeMcpToolDefinition`, `RuntimeMcpToolDefinitionWithOutput` or `ToolSurfaceDefinition`; code
164
+ that annotates a definition carrying `present` as `RuntimeToolDefinitionWithOutput<I, O>` from
165
+ `stitchkit/tools`; imports of `stitchkit/agent-runtime/harness-tools`; code that compares agent
166
+ control error codes; and callers that send a JSON array as text to a string-or-array tool field.
167
+ Definitions returned by `defineRuntimeTool` / `createRuntimeToolFactory`, native CLI `commands` and
168
+ contract tools need no change.
169
+
170
+ A runtime tool now has one declaration, `RuntimeToolDefinitionWithOutput` /
171
+ `RuntimeToolDefinitionWithoutOutput`, exported with the same name from `stitchkit/cli`,
172
+ `stitchkit/tools` and `stitchkit/tools/mcp`. It carries no SDK type: the presenters are the adapter's
173
+ extension, named as the fourth type argument. `RuntimeToolDefinition` is the one registration type.
174
+
175
+ 1. Replace each removed name.
176
+
177
+ | before | after |
178
+ |---|---|
179
+ | `RuntimeToolExecutionWithOutput<I, O>` (`stitchkit/cli`) | `RuntimeToolDefinitionWithOutput<I, O>` |
180
+ | `RuntimeToolExecution` (`stitchkit/cli`) | `RuntimeToolDefinition` |
181
+ | `RuntimeMcpToolDefinitionWithOutput<I, O>` (`stitchkit/tools/mcp`) | `RuntimeToolDefinitionWithOutput<I, O, undefined, RuntimeMcpToolPresenters<z.output<O>>>` |
182
+ | `RuntimeMcpToolDefinition` (`stitchkit/tools/mcp`) | `RuntimeToolDefinition` |
183
+ | `ToolSurfaceDefinition` (`stitchkit/tools`) | `ToolSurfaceProjection<RuntimeToolDefinition>` |
184
+
185
+ 2. In `stitchkit/tools`, a type that names a definition with presenters passes the presenter type:
186
+
187
+ ```ts
188
+ // before
189
+ const tool: RuntimeToolDefinitionWithOutput<typeof input, typeof output> = defineRuntimeTool({ …, present })
190
+ // after: let defineRuntimeTool infer it, or name the presenters
191
+ const tool = defineRuntimeTool({ …, present })
192
+ const named: RuntimeToolDefinitionWithOutput<typeof input, typeof output, undefined, RuntimeToolPresenters<z.output<typeof output>>> = tool
193
+ ```
194
+
195
+ 3. An inline handler in `runtimeTools: [...]` needs no wrapper: it is typed by the parsed object.
196
+ To type `input` from the schema, construct with `defineRuntimeTool` (or
197
+ `satisfies RuntimeToolDefinitionWithOutput<typeof input, typeof output>`) before registering.
198
+
199
+ 4. Replace `createAgentHarnessTools` (`stitchkit/agent-runtime/harness-tools`) with the call it made:
200
+
201
+ ```ts
202
+ // before
203
+ tools: createAgentHarnessTools(({ context }) => ({ services: [svc], context, lifecycle: auth }))
204
+ // after
205
+ import { composeToolLifecycle, mountAgent } from 'stitchkit/tools'
206
+ tools: ({ context, toolFenceLifecycle }) =>
207
+ mountAgent([svc], { context, lifecycle: composeToolLifecycle(auth, toolFenceLifecycle) })
208
+ ```
209
+
210
+ 5. Agent control codes: `ACCESS_DENIED` is `FORBIDDEN`, and `CONNECTION_CLOSED` is returned for a closed
211
+ connection. `AgentControlErrorCode` lists every code. `authorize` now runs once per request; after you
212
+ withdraw someone's access, call `binding.revoke(conversationId, matches?)` so an open stream is
213
+ re-authorized and ends with an `access-denied` delivery.
214
+
215
+ 6. A string-or-array field that receives `'["a","b"]'` now fails with `VALIDATION_ERROR` ("`paths` is a
216
+ list written as text"). Send the array itself. A string that is not a list the array member accepts
217
+ (`[preview].png`) is still one plain string.
218
+
219
+ ### flattened unions keep declaration order
220
+
221
+ **Who must act:** consumers that use `flattenUnionInput: true` and keep snapshot tests, golden
222
+ files or provider prompt caches of flattened tool schemas.
223
+
224
+ A flattened union now lists its properties, enum values and branch labels in the order they first
225
+ appear across the variants, not alphabetically. Declaration order often encodes priority, so the
226
+ model now reads the order you wrote. Alternatives of different kinds (`anyOf`) keep their
227
+ canonical order, independent of variant order.
228
+
229
+ 1. Regenerate every snapshot or golden file of a flattened tool listing (`buildToolManifest`,
230
+ `listToolNames`, MCP `tools/list`, Agent tool schemas) and review the diff: only ordering moves.
231
+ 2. Expect one provider prompt-cache miss per flattened tool after the upgrade.
232
+ 3. To keep an order you prefer, declare the variants and fields in that order.
233
+
234
+ ### connection limits are validated
235
+
236
+ **Who must act:** callers that pass `timeoutMs` or `maxResponseBytes` to a connection and relied
237
+ on an invalid value silently becoming the default.
238
+
239
+ `stitchkit/tools/connections` throws a `RangeError` when `timeoutMs` is not a positive integer
240
+ within timer range (at most 2 147 483 647) or `maxResponseBytes` is not a positive safe integer.
241
+ Before 0.104.0 a value of 0, a negative number, a fraction or an out-of-range number fell back to
242
+ the default without a message.
243
+
244
+ ```ts
245
+ // Before: { timeoutMs: 0 } meant "use the default" by accident.
246
+ // After: omit the option to take the default, or pass a real limit.
247
+ { timeoutMs: 30_000 }
248
+ ```
249
+
250
+ ### one canonical JSON serializer
251
+
252
+ **Who must act:** tests that call `serializeSurfaceValue` from `stitchkit/testing`, and code that
253
+ puts a value nested deeper than 100 levels into agent store events, archives or projections
254
+ through `canonicalAgentJson`.
255
+
256
+ `canonicalJson` from `stitchkit/primitives` is the package's one canonical serializer. It
257
+ admits dense arrays, plain objects, strings, booleans, `null` and finite numbers; an `undefined`
258
+ object member is omitted. It refuses everything else with a `CanonicalJsonError`, a `TypeError`
259
+ whose `reason` says why: `'depth'`, `'nodes'` and `'bytes'` are the limits you set, while
260
+ `'cycle'`, `'negative-zero'` and `'not-json'` say the value is not JSON data.
261
+
262
+ `serializeSurfaceValue` is removed. It produced the same bytes without limits:
263
+
264
+ ```ts
265
+ // Before
266
+ import { serializeSurfaceValue } from 'stitchkit/testing'
267
+ const text = serializeSurfaceValue(manifest)
268
+ // After: the limits default to 100 levels, 100 000 nodes and 1 MiB; raise them for a large manifest
269
+ import { canonicalJson } from 'stitchkit/primitives'
270
+ const text = canonicalJson(manifest, { maxBytes: 16 * 1024 * 1024 })
271
+ ```
272
+
273
+ `canonicalAgentJson` in `stitchkit/agent-runtime` is `canonicalJson` with the node and byte
274
+ limits at their maximum. A value both accepted has the same bytes as before, so stored digests
275
+ and archives still match: like `z.json()` before it, the store hashes `-0` as `0` and drops an
276
+ own `__proto__` member (the public `canonicalJson` refuses `-0` and keeps `__proto__`). What
277
+ changed is the refusal table: an `undefined` object member used to fail and is now omitted, and
278
+ a value nested deeper than 100 levels is now refused.
279
+
280
+ ```ts
281
+ // Before: canonicalAgentJson({ a: undefined }) threw a ZodError
282
+ // After: canonicalAgentJson({ a: undefined }) === '{}'
283
+ // canonicalAgentJson(nestedBeyond100Levels) throws CanonicalJsonError (reason 'depth')
284
+ ```
285
+
286
+ ### directory inbox entries
287
+
288
+ **Who must act:** producers that drop hard links into an inbox directory, and callers that pass
289
+ `accept` the output of a transforming schema.
290
+
291
+ A file dropped into the inbox directory with more than one link is set aside as `invalid`
292
+ (detail `managed file has multiple links`). Another name can still rewrite such a file after it
293
+ was validated, so it is never trusted. Write each entry as its own regular file: a temporary
294
+ name in the same directory, then a rename onto `<name>.json`.
295
+
296
+ `accept` takes the schema's input type, stores that input as given and parses it with the
297
+ schema on delivery. A schema without a transform has the same input and output type and needs
298
+ no change. With a transform, pass the input:
299
+
300
+ ```ts
301
+ const schema = z.object({ amount: z.string().transform(Number) })
302
+ // Before: accept({ source, key, entry: { amount: 42 } }) // typed as the output; `z.string()` refused it
303
+ // After: accept({ source, key, entry: { amount: '42' } }) // delivered as { amount: 42 }
304
+ ```
305
+
306
+ A name that is already in `rejected/` no longer stops the pass: identical bytes are the entry
307
+ already set aside, different bytes are kept as `rejected/<name>.<16 hex digits>`.
308
+
309
+ ### journal startup scan
310
+
311
+ **Who must act:** operators that read `status.recovery` right after `createDiagnosticJournal` to
312
+ find damaged rows in the middle of a file.
313
+
314
+ Opening a journal reads only the last line of the active file and of every retained
315
+ generation (`startupScan: 'tails'`, the default). A crash tears the end of a file, so a torn tail
316
+ is still reported and still rotated away, and opening no longer parses and validates every
317
+ line of every generation. It still reads each file once in large blocks to count lines, so the time
318
+ grows with the bytes retained, at read speed. Pass `startupScan: 'full'` to read and validate every line as before:
319
+
320
+ ```ts
321
+ // Before: every open parsed every line of every generation.
322
+ // After: the same full scan, on request.
323
+ const journal = await createDiagnosticJournal({ path, eventSchema, limits, startupScan: 'full' })
324
+ ```
325
+
326
+ ### journal startup quarantine
327
+
328
+ **Who must act:** operators of a journal that is a source of truth and must not start over
329
+ damaged retained files; code that constructs `DiagnosticJournalRecoveryError` or reads its
330
+ `recovery`; protocols that embed `DiagnosticJournalRecoveryStatusSchema`, and their readers.
331
+ A diagnostic journal needs no change.
332
+
333
+ Opening a journal no longer refuses to start over a torn active file with `maxFiles: 1`, a
334
+ generation name that is not a regular file or a retained file it cannot read. It renames the file
335
+ to `<file>.quarantined-<epoch>` beside the journal, starts, and lists the move in
336
+ `getStatus().recovery.quarantined`. Quarantined files are outside retention and never deleted;
337
+ every later open lists them again, without a `reason`, until you remove them.
338
+
339
+ 1. A journal whose damage must stop the process declares the old behaviour:
340
+
341
+ ```ts
342
+ // Before: refusing was the only behaviour.
343
+ await createDiagnosticJournal({ path, eventSchema, limits })
344
+ // After:
345
+ await createDiagnosticJournal({ path, eventSchema, limits, onStartupRefusal: 'fail' })
346
+ ```
347
+
348
+ 2. Branch on the refusal's `reason` instead of its message or error class. Every startup refusal
349
+ about retained evidence is a `DiagnosticJournalRecoveryError`, including the former plain
350
+ `Error` for a non-file generation and the raw `EACCES` for an unreadable one (now in `cause`):
351
+
352
+ ```ts
353
+ // Before: catch (error) { if (error instanceof DiagnosticJournalRecoveryError) use(error.recovery) }
354
+ // After:
355
+ catch (error) {
356
+ if (error instanceof DiagnosticJournalRecoveryError && error.reason === 'torn-without-retention-slot') use(error.recovery)
357
+ }
358
+ ```
359
+
360
+ `recovery` is present only for `torn-without-retention-slot`. The constructor takes one
361
+ options object: `new DiagnosticJournalRecoveryError({ reason, file, recovery?, cause? })`.
362
+
363
+ 3. A protocol that embeds `DiagnosticJournalRecoveryStatusSchema` carries the new optional
364
+ `quarantined` array (at most 32 entries, `reason` optional) and `quarantinedUnlisted` count.
365
+ The schema is `.strict()`: upgrade every reader that parses it with its own copy before a
366
+ writer on this version sends a status with either field, or bump your protocol version.
367
+
368
+ ### error constructors take named options
369
+
370
+ **Who must act:** code that constructs an `AppError` or an `ApiError` with anything beyond its
371
+ code, and classes that extend `AppError` and call `super(code, message, status, …)`. Code that
372
+ only throws the `notFound`, `badRequest`, `unauthorized`, `forbidden`, `conflict` and
373
+ `rateLimited` helpers, or only reads `code`, `status`, `details`, `hint`, `traceId`,
374
+ `retryable` and `cause` from a caught error, needs no change.
375
+
376
+ `AppError` (`stitchkit/contract`, `stitchkit/server`, `stitchkit/node`) and `ApiError`
377
+ (`stitchkit`) keep the code as the one positional argument. Every other value is a named
378
+ option, so a call site reads without the signature open. `new AppError(code)` and
379
+ `new ApiError(code)` are unchanged. The compiler finds every old call: a string or number
380
+ in the second position is a type error.
381
+
382
+ 1. `AppError`: move `message`, `status`, `details`, `hint`, `traceId` and `retryable` into one
383
+ object after the code. `status` defaults to 500 and `message` to the code.
384
+
385
+ ```ts
386
+ // before
387
+ throw new AppError('CONFLICT', 'Selection is stale', 409, { revision: 7 })
388
+ throw new AppError('BUSY', 'Try later', 503, undefined, undefined, undefined, true)
389
+ // after
390
+ throw new AppError('CONFLICT', { message: 'Selection is stale', status: 409, details: { revision: 7 } })
391
+ throw new AppError('BUSY', { message: 'Try later', status: 503, retryable: true })
392
+ ```
393
+
394
+ 2. A subclass passes the same object to `super`:
395
+
396
+ ```ts
397
+ // before
398
+ super('FEATURE_LOCKED', 'locked', 403)
399
+ // after
400
+ super('FEATURE_LOCKED', { message: 'locked', status: 403 })
401
+ ```
402
+
403
+ 3. `ApiError`: the old order was `code, status, details, message, hint, traceId, errorOptions,
404
+ retryable`. Name each value; `status` defaults to 0 and the former `ErrorOptions` argument
405
+ is now the `cause` option.
406
+
407
+ ```ts
408
+ // before
409
+ new ApiError('RATE_LIMITED', 429, undefined, 'slow down', 'wait', 'trace-1', { cause }, true)
410
+ new ApiError('VALIDATION_ERROR', 0, { issues }, 'bad input')
411
+ // after
412
+ new ApiError('RATE_LIMITED', { status: 429, message: 'slow down', hint: 'wait', traceId: 'trace-1', retryable: true, cause })
413
+ new ApiError('VALIDATION_ERROR', { status: 0, details: { issues }, message: 'bad input' })
414
+ ```
415
+
416
+ 4. Both classes accept the standard `cause`, which `error.cause` returns; omit the option to
417
+ leave the property absent.
418
+
12
419
  ## Released migration: 0.104.0
13
420
 
14
421
  JS bundles carrying Darwin native capabilities also need the
@@ -134,10 +541,20 @@ that work actually completes.
134
541
 
135
542
  ### Darwin native assets in JS distributions
136
543
 
137
- **Who must act:** Bun JS builds using `--outfile`, copying only `outputs[0]`, custom
138
- single-file/archive packagers and installers delivering native process/files capabilities.
139
- First affected publication: **0.103.13**. It shipped as a patch; its changed delivery graph
140
- requires this migration despite unchanged API signatures.
544
+ **Who must act:** Bun builds that import `stitchkit/server`, `stitchkit/files` or
545
+ `stitchkit/process` (Linux-only server apps included) and use `--outfile`, copy only
546
+ `outputs[0]`, or package a single file; custom single-file/archive packagers and installers
547
+ delivering native process/files capabilities.
548
+ First affected publication: **0.103.13**, through **0.104.2**. It shipped as a patch; its
549
+ changed delivery graph requires this migration despite unchanged API signatures.
550
+
551
+ In those versions every Bun bundle that reaches the lock or process-identity code,
552
+ `stitchkit/server` included, carries both Darwin `.node` addons as extra outputs on every
553
+ operating system. `bun build --outfile` then fails with
554
+ `cannot write multiple output files without an output directory`, and `--outdir` writes the
555
+ addons next to a Linux artifact. Releases after 0.104.2 resolve the default loader at run time,
556
+ so these bundles are one JS file with no `.node` output again. The static loader exists only
557
+ in a build that uses the `stitchkit/files/packaging` plugin.
141
558
 
142
559
  ```sh
143
560
  # Before: one JS file was assumed to be the entire distribution.
@@ -154,12 +571,39 @@ Custom output layout uses the evolving build-only packaging contract in the
154
571
 
155
572
  Three deliveries have different rules: an ordinary npm install retains the package's
156
573
  native assets; a JS distribution must ship its complete output graph; a Bun compiled
157
- executable embeds the matching addon and may still use `--outfile`.
574
+ executable embeds the matching addon and may still use `--outfile`. In 0.103.13–0.104.2 a plain
575
+ `bun build` carries the addon without a plugin; later releases carry it only when the build
576
+ uses `createNativePackaging` (`delivery: 'companion'` for JS, `'embedded'` for a compiled
577
+ executable).
158
578
  The [native IO guide](native-io.md#libraries-with-a-zod-only-runtime) is the canonical recipe.
159
579
  Check the resulting artifact offline outside the build tree and `node_modules`, including
160
580
  process identity, live-owner lock refusal, dead-owner recovery and contained IO.
161
581
  A missing or corrupt addon remains `unavailable`, never evidence that an owner died.
162
582
 
583
+ ### CLI: repeated options are refused
584
+
585
+ **Who must act:** wrappers, aliases and scripts that append `--json`, `--profile X` or an
586
+ application global to arguments the user may already have given, and anything that passes the
587
+ same global twice.
588
+ First affected publication: **0.103.13**. It shipped as a patch; the change in grammar needs
589
+ this migration.
590
+
591
+ A repeated option that is not an array field is an argument error:
592
+ `--json --json` and `--profile a --profile b` fail with `--json was passed 2 times`. Before
593
+ 0.103.13 the last value won, for framework globals, application globals and repeated
594
+ `kind: 'other'` fields alike. Array fields, and untyped passthrough fields that keep their
595
+ raw-list grammar, still repeat.
596
+
597
+ ```sh
598
+ # Before: a wrapper appended its default and the last value won.
599
+ mytool deploy --profile staging "$@" --profile production
600
+ # After: build the argument list once, so each option appears once.
601
+ mytool deploy --profile "${PROFILE:-production}" "$@"
602
+ ```
603
+
604
+ Dotted leaves such as `--filter.name` follow the same rule as their parent field. Declare a
605
+ field as an array when repetition is meant.
606
+
163
607
  ## Released migration: 0.103.0
164
608
 
165
609
  ### Diagnostic journal startup preserves torn evidence and inspects archives
@@ -493,562 +937,3 @@ version loads unchanged — the new `unavailableAt` reads as `null`.
493
937
  drains; without it downtime is counted from the recorded stop. Call
494
938
  `recordReady()` when the run serves; a run stopped without it now ends
495
939
  `startup-failed`, not `clean`.
496
-
497
- ## Released migration: 0.94.0
498
-
499
- One breaking minor that consolidates: tool options move into one group, and
500
- names that were exported from two entrypoints keep only their owner. Every step
501
- is an edit a type checker or `defineContract` points at; the few behaviour
502
- changes that need no edit are under Changed and Fixed in the changelog.
503
-
504
- 1. **Move endpoint tool options into `tool`.** **Who must act:** every project
505
- with an endpoint that sets `toolName`, `ui`, `annotations` or `mcp`. Run the
506
- codemod from a checkout of this repository, then typecheck:
507
-
508
- ```bash
509
- bun packages/core/scripts/codemod-tool-group.ts --check path/to/your/src # list
510
- bun packages/core/scripts/codemod-tool-group.ts path/to/your/src # rewrite
511
- ```
512
-
513
- ```ts
514
- // before
515
- { method: 'GET', path: '/', desc: 'List', toolName: 'user_list', mcp: { inputRequired } }
516
- // after
517
- { method: 'GET', path: '/', desc: 'List', tool: { name: 'user_list', mcp: { inputRequired } } }
518
- ```
519
-
520
- The codemod leaves two kinds of endpoint for a person and prints where: one
521
- built with a spread (`{ ...base, toolName }`), and one exposed on HTTP only,
522
- whose tool options never reached a tool — delete them there. Anything left
523
- over fails at startup, by name — a key moved into the group under its old
524
- name (`tool: { toolName }`) included:
525
-
526
- ```text
527
- Contract "users": endpoint "list" sets `toolName` — tool options live in `tool` since 0.94.0: use tool.name
528
- ```
529
-
530
- `expose` does not move. `MethodDef` — what hooks and runtime tools see — keeps
531
- `toolName`, `ui`, `annotations` and `mcp` at the top level, so hook code does
532
- not change. A tool view is declared only with `withToolView`, which now puts
533
- it in `tool.view`.
534
-
535
- 2. **Change imports of moved names.** **Who must act:** projects importing any
536
- of these; the compiler lists every site.
537
-
538
- | Name | From | To |
539
- |---|---|---|
540
- | `RuntimeToolTransport`, `ToolSurfaceTransport`, `ToolInvokerTransport` | `stitchkit/tools`, `stitchkit/tools/invoker`, `stitchkit/tools/connections` | `ToolTransport` from `stitchkit/contract` |
541
- | `createCli`, `defineCliCommand`, `CliConfig`, `CliSurfaceSource`, `CliPresentationPolicyConfig`, `CliWaitConfig`, `ExitCodeMap`, `CliCommand*` | `stitchkit/tools` | `stitchkit/cli` |
542
- | `parseSSE`, `ParseSSEOptions` | `stitchkit/server` | `stitchkit` |
543
- | `runAgentStoreConformance`, `AgentStoreConformance*`, `createAgentRace*`, `AgentRace*` | `stitchkit/testing` | `stitchkit/agent-runtime/testing` |
544
- | `createLocalStepDurability`, `LocalStepDurability`, `LocalStepDurabilityOptions`, `StepDurabilityLedger` | `stitchkit/agent-runtime` | `stitchkit/tools` |
545
-
546
- 3. **Regenerate a surface snapshot only if it reports drift.** **Who must act:**
547
- a project whose committed snapshot has an object with integer-like keys
548
- (`"9"`, `"10"`) — they are now sorted like every other key. Every other
549
- snapshot, CLI manifest signature and agent-store archive is byte-identical.
550
-
551
- ## Released migration: 0.93.0
552
-
553
- 1. **Regenerate every committed surface snapshot, once.** `manifestVersion` is
554
- `3` and each operation row gained `mcp` — the rounds it declares before it
555
- runs. Most rows get `null`, so the first diff is large and mechanical.
556
- **Who must act:** anyone with a committed snapshot. A snapshot on the older
557
- version is refused by name rather than failing a schema literal:
558
-
559
- ```text
560
- Surface snapshot is manifestVersion 2; this build writes 3. Regenerate it
561
- and review the diff — the format changed, so the first regeneration is
562
- expected to be large.
563
- ```
564
-
565
- ```ts
566
- // before — a declared round left no trace, so declaring or removing one
567
- // passed review invisibly
568
- manifest.operations[0]
569
- // after
570
- manifest.operations[0].mcp
571
- // null | { inputRequired: [{ key, message, schema }] }
572
- // | { inputRequired: 'resolved-per-call' }
573
- ```
574
-
575
- A project that kept its own test for "declared `inputRequired` implies a
576
- configured state key" can drop it: the snapshot holds that link now.
577
-
578
- 2. **Nothing else to do.** Native commands that declare `output` became
579
- invokable in process; a name that answered `NOT_FOUND` from
580
- `createCliInvoker` in 0.92.0 may now resolve. If an application relied on
581
- native commands being unreachable there, stop passing them to the invoker.
582
-
583
- ## Released migration: 0.92.0
584
-
585
- 1. **`RequestEvent.method`, `path` and `statusCode` are optional.** Work that did
586
- not arrive over a transport now records their **absence** instead of inventing
587
- values — a background loop used to write `method: 'AGENT'`, which is not a
588
- verb. **Who must act:** anyone whose `RequestEventSinkConfig.write` puts these
589
- into NOT NULL columns, or whose filter reads `event.method`.
590
-
591
- ```ts
592
- // before
593
- write: (event) => db.audit.create({ data: { method: event.method, path: event.path, status: event.statusCode } })
594
- // after — a job has none of the three; `kind` says which kind of row it is
595
- write: (event) => db.audit.create({ data: {
596
- kind: event.kind,
597
- name: event.name ?? null,
598
- method: event.method ?? null,
599
- path: event.path ?? null,
600
- status: event.statusCode ?? null,
601
- } })
602
- ```
603
-
604
- A filter written as `event.method !== 'GET'` keeps jobs (`undefined !== 'GET'`),
605
- which is usually what you want. To exclude them deliberately:
606
- `event.kind === 'request' && event.method !== 'GET'`.
607
-
608
- 2. **`applyCliUpdate` needs the manifest when given a trust root.** The signature
609
- covers the manifest and every asset digest together, so an asset alone cannot
610
- be verified. **Who must act:** only callers adopting signature verification;
611
- the unsigned call is unchanged.
612
-
613
- ```ts
614
- // before
615
- await applyCliUpdate({ asset })
616
- // after
617
- await applyCliUpdate({ asset, manifest: check.manifest, trust })
618
- ```
619
-
620
- 3. **An MCP continuation minted before this release is refused once.** The signed
621
- round state now carries a fingerprint of the question plan, checked on every
622
- round, so a plan that moved between rounds is a refusal rather than a
623
- different question asked under the previous one's key. A conversation already
624
- in flight at deploy time has no fingerprint and gets
625
- `INVALID_REQUEST_STATE`; the host re-asks and the second attempt succeeds.
626
- **Who must act:** nobody — but expect a small number of these in the minutes
627
- after a deploy, and do not read them as tampering.
628
-
629
- ## Released migration: 0.91.0
630
-
631
- 1. `STITCH_ERROR_STATUS` gained `NOT_IMPLEMENTED` (501). An **exhaustive** error
632
- vocabulary must name it — without the row `defineErrors({ mapping: { exhaustive:
633
- true } })` stops compiling and then throws at startup. Nothing else in this
634
- release requires action.
635
-
636
- ```ts
637
- // before
638
- map: { …, WAIT_TIMEOUT: 'timeout' }
639
- // after
640
- map: { …, NOT_IMPLEMENTED: 'not_implemented', WAIT_TIMEOUT: 'timeout' }
641
- ```
642
-
643
- The code is thrown only by the new dev-only `onMissingHandler: 'stub'` policy;
644
- a vocabulary that is not exhaustive is unaffected.
645
-
646
- ## Released migration: 0.90.0
647
-
648
- 1. `stitchkit.watch.value` is a discriminated union on `kind` — `full`, `delta`,
649
- `unchanged` — and every frame carries `fingerprint`. **Both ends must come from
650
- the same major.** A client older than this release reads a `delta` frame as a
651
- value of `undefined`, silently; upgrade the hub and the pages that talk to it
652
- together, or set `deltaMemoryBytes: 0` on the hub until they are.
653
-
654
- Applications using `createWatchClient` need no code change: it rebuilds the
655
- value and hands the listener the whole answer as before. Code that reads
656
- `WatchValueFrame.value` directly — a hand-written subscriber, a test double —
657
- narrows on `kind` first.
658
-
659
- ```ts
660
- // before: frame.value
661
- // after:
662
- if (frame.kind === 'full') hold(frame.value);
663
- else if (frame.kind === 'delta') hold(applyWatchDelta(held, frame.delta));
664
- // 'unchanged' leaves what you hold standing
665
- ```
666
-
667
- 2. `AttachedWatcher.open` takes an optional third argument, `have`. A custom
668
- server binding that forwards `stitchkit.watch.open` should pass the payload's
669
- `have` through; omitting it costs a whole value on every reconnection and is
670
- otherwise harmless.
671
-
672
- ## Released migration: 0.89.0
673
-
674
- 1. Custom `AgentRuntimeStore` adapters implement `seedConversationInput`; custom
675
- `AgentRuntimeStoreDriver` adapters implement `seeds.load` and `seeds.create` together
676
- with atomic, ordered history insertion. Use the maintained Prisma example and run
677
- `runAgentStoreConformance` against the adapter. Built-in memory and SQLite
678
- stores already implement the contract; SQLite migrates to schema version 3.
679
- 2. OpenRouter usage normalization consumes each completed SDK step's `usage`, including
680
- `raw`, rather than aggregate usage. Missing counters stay `unavailable`.
681
-
682
- ```ts
683
- // before: normalizeOpenRouterUsage(await result.usage, metadata)
684
- // after:
685
- for (const step of await result.steps) {
686
- const usage = normalizeOpenRouterUsage(step.usage, step.providerMetadata);
687
- // Persist the step's measured usage with its provenance.
688
- }
689
- ```
690
-
691
- 3. Durable step bodies return lossless JSON. Convert dates explicitly, reject invalid
692
- numbers upstream, and return `null` after an effect-only operation.
693
-
694
- ```ts
695
- await context.step('send', async () => {
696
- await sendIdempotently();
697
- return null;
698
- });
699
- ```
700
-
701
- First execution, replay and concurrent callers receive detached values. Persistence
702
- does not make external effects transactional; the host retains idempotency and recovery.
703
-
704
-
705
- How to move a consuming project from one stitchkit version to another — including
706
- across many versions at once (a project frozen on an old version, then jumped
707
- forward). The process is mechanical: stitchkit marks every breaking change in one
708
- place and one format, so you can recover the full migration from the version diff.
709
-
710
- ## Released migration: 0.88.0
711
-
712
- Two mechanical edits, and only if your project builds these values rather than only reading them.
713
-
714
- A completed step event now carries the provider's response identity, and the field is required:
715
-
716
- ```ts
717
- // before
718
- { type: 'step-finished', step: 0, usage }
719
-
720
- // after
721
- { type: 'step-finished', step: 0, usage, response: { id: generationId } }
722
- ```
723
-
724
- Every event the runtime emits already has it, so a sink that only reads them needs no change. A
725
- fixture, a test double or a pipeline that re-validates events persisted by an earlier version does:
726
- give the older records a response identity, or keep parsing them with the schema they were written
727
- under.
728
-
729
- If you implement the whole `AgentRuntime` interface — usually a mock — add the new method:
730
-
731
- ```ts
732
- // before
733
- const fake: AgentRuntime = { submit, interrupt, recover, close }
734
-
735
- // after
736
- const fake: AgentRuntime = { submit, interrupt, abandon, recover, close }
737
- ```
738
-
739
- No data migration is involved, and nothing in the store changes shape.
740
-
741
- ## Released migration: 0.87.0
742
-
743
- Only if your project implements `AgentConversationReader` itself. A message page
744
- now names which of its messages compaction removed:
745
-
746
- ```ts
747
- // before
748
- return { items, ...(nextCursor && { nextCursor }) }
749
-
750
- // after
751
- return { items, compacted: [], ...(nextCursor && { nextCursor }) }
752
- ```
753
-
754
- An empty array is the honest answer for a reader that pages only the active
755
- history; it is what the SQLite reader returns unless the caller asks for
756
- `includeCompacted`. Calling the reader needs no change, and no data migration is
757
- involved.
758
-
759
- ## Released migration: 0.86.0
760
-
761
- Only if you branch on `AgentTerminalReason` or show it to a person. Three
762
- failures that used to arrive as `provider_failure` now arrive as themselves:
763
-
764
- ```ts
765
- // before
766
- if (run.terminalReason === 'provider_failure') showOutage()
767
-
768
- // after
769
- switch (run.terminalReason) {
770
- case 'provider_failure':
771
- showOutage()
772
- break
773
- case 'storage_conflict':
774
- // Another writer took this run's revision, or the store refused the write.
775
- retryOrReport()
776
- break
777
- case 'output_rejected':
778
- // Your own `protocol.acceptTerminal` refused the finished message.
779
- reportRejectedAnswer()
780
- break
781
- case 'runtime_failure':
782
- // The runtime, or a check the SDK ran on what it was handed, failed
783
- // before the provider was reached.
784
- reportInternal()
785
- break
786
- }
787
- ```
788
-
789
- A run that never reached the provider can no longer report `provider_failure`,
790
- so an alert keyed on that value stops firing for causes that were never the
791
- provider's.
792
-
793
- If you implement `AgentRuntimeStore` directly, add the event-ledger surface:
794
-
795
- ```ts
796
- const store: AgentRuntimeStore = {
797
- // existing normalized operations
798
- appendEvent,
799
- readEvents,
800
- exportConversation,
801
- importConversation,
802
- }
803
- ```
804
-
805
- If you implement an `AgentRuntimeStoreDriver` (Prisma, Postgres, any external
806
- database), the ledger is yours to keep: `events` is a required member, and it
807
- needs a table.
808
-
809
- ```ts
810
- // before
811
- const driver: AgentRuntimeStoreDriver<Tx> = { transaction, head, runs, admissions, history, scanRecoverable }
812
-
813
- // after
814
- const driver: AgentRuntimeStoreDriver<Tx> = {
815
- transaction, head, runs, admissions, history, scanRecoverable,
816
- events: {
817
- // One row per event; `seq` is per conversation, starts at 1, and is
818
- // assigned inside the caller's transaction so concurrent appends cannot
819
- // share or skip a number.
820
- append: async (tx, draft) => {
821
- // Two transactions that both read max(seq) and both insert max + 1
822
- // collide on the primary key; under SERIALIZABLE the snapshot predates
823
- // any lock you take here. Treat a unique violation on this table as a
824
- // serialization conflict and re-run the whole transaction — see
825
- // `runTransaction` in examples/agent-store-prisma/adapter.ts.
826
- const seq = (await tx.event.aggregate({ _max: { seq: true }, where: { conversationId: draft.conversationId } }))._max.seq ?? 0
827
- await tx.event.create({ data: { ...draft, seq: seq + 1, payload: JSON.stringify(draft.payload) } })
828
- return { ...draft, seq: seq + 1 }
829
- },
830
- // Ordered by `seq`, bounded by `fromSeq`/`toSeq`/`limit`; `nextSeq` when
831
- // more remain.
832
- list: async (tx, input) => { /* see examples/agent-store-prisma/adapter.ts */ },
833
- },
834
- }
835
- ```
836
-
837
- The table carries `eventId` (unique), `conversationId`, `seq`, `schemaVersion`,
838
- `kind`, `occurredAt`, `ignorable` and `payload`. `runAgentStoreConformance`
839
- from `stitchkit/testing` now exercises it — contiguous `seq` under twenty
840
- concurrent appends, bounded reads, the `ignorable` flag, a byte-stable export
841
- — so run it against your driver before deploying. Expect one more insert per
842
- run operation (`runtime/transition`) and one per model step
843
- (`provider/request`) on the hot path; there is no opt-out.
844
-
845
- If you operate a built-in SQLite store file:
846
-
847
- 1. Back the file up. The first open by 0.86.0 migrates it to schema 2 in one
848
- transaction and there is no way back: a 0.85.x package refuses a migrated
849
- file with `Unsupported Stitchkit agent-runtime SQLite schema version 2`.
850
- 2. Check the build for FTS5 before deploying:
851
-
852
- ```sql
853
- SELECT sqlite_compileoption_used('ENABLE_FTS5');
854
- ```
855
-
856
- A build without it is refused at open with `requires FTS5 support`. On the
857
- machine this was verified, Bun 1.3 `bun:sqlite` and Node 24.18 `node:sqlite`
858
- both carry it; verify your own build rather than assuming — the table of
859
- supported runtimes says Node ≥ 22.5, and FTS5 there is not verified here.
860
- 3. Know what the migration wrote. Each existing conversation becomes one
861
- `runtime/baseline` event at `seq 1`, dated when the migration ran, with
862
- `asOf` inside the payload naming the last message it describes. Event
863
- search and projections address that conversation's pre-migration history as
864
- one snapshot at `seq 1`; event-level precision begins with the first event
865
- after the migration.
866
-
867
- If you subscribe to `AgentRuntimeEvent` and switch over `event.type`
868
- exhaustively, add the transient `attempt-reset` case — drop the run's
869
- transient text — or the reducer stops compiling; a reducer that ignores it
870
- keeps a failed attempt's partial text on screen.
871
-
872
- New in this release, not a migration: child runs cascade only when the manager
873
- is given to the runtime —
874
- `createAgentRuntime({ ...config, children: createSqliteAgentChildManager({ sqlite, spawn }) })`
875
- — and the SQLite companions take the store handle (`{ sqlite }`), whose
876
- `database` and `transaction` they share.
877
-
878
- ## Released migration: 0.85.0
879
-
880
- Only if you implement `AgentRuntimeStore` directly. Add the new durable
881
- operation mutation beside the existing run mutations:
882
-
883
- ```ts
884
- // before
885
- const store: AgentRuntimeStore = {
886
- checkpointRunAssistant,
887
- commitRunTerminal,
888
- // ...
889
- }
890
-
891
- // after
892
- const store: AgentRuntimeStore = {
893
- checkpointRunAssistant,
894
- recordRunOperation,
895
- commitRunTerminal,
896
- // ...
897
- }
898
- ```
899
-
900
- It must atomically replace `AgentRun.lastOperation`, increment the run revision
901
- and conversation snapshot version, and enforce the supplied owner, fencing
902
- token and expected revision. Adapters built with `createAgentRuntimeStore`
903
- already receive the reference implementation; no driver method is added.
904
-
905
- ## Released migration: 0.84.0
906
-
907
- Only if you call `createAgentCodingTools`.
908
-
909
- ```bash
910
- rg -n "createAgentCodingTools"
911
- ```
912
-
913
- **1. Backslashes are refused.** If anything in your system hands the tools a Windows-style path,
914
- it now gets `FORBIDDEN`. Convert to `/` at the boundary:
915
-
916
- ```ts
917
- // before: read_file({ path: 'src\\index.ts' }) // reached openat as two segments
918
- // after: read_file({ path: 'src/index.ts' })
919
- ```
920
-
921
- This is the half that matters most: until now a backslash bypassed your **required**
922
- `authorize({ operation, path })` callback, not just `authorizePath`. A rule denying
923
- `credentials/token.txt` refused that spelling and served — and overwrote — the same file spelled
924
- `credentials\token.txt`. If your policy denies specific files, re-read your audit logs for
925
- backslash spellings.
926
-
927
- **2. Denying a directory now denies everything under it — and a policy must admit every directory
928
- on the way to a file**, the way POSIX needs `+x` on each directory in a path.
929
-
930
- If your policy is a DENY-list, it now does what it read as:
931
-
932
- ```ts
933
- authorizePath: ({ path }) => path !== 'credentials'
934
- // before: hid `credentials` from glob, served `credentials/token.txt` to read_file
935
- // after: refuses `credentials/token.txt`, `credentials/nested/deep.txt` and writes under it
936
- ```
937
-
938
- If you relied on the old behaviour — a directory hidden from discovery but readable directly — you
939
- were relying on a defect, and the two halves of one callback disagreeing. Name the paths you
940
- actually want reachable instead.
941
-
942
- If your policy is an ALLOW-list, widen it to the directories it leads through, or nothing under
943
- them is reachable:
944
-
945
- ```ts
946
- // before: allowed src/index.ts, because only the leaf was ever asked
947
- authorizePath: ({ path }) => path.startsWith('src/')
948
- // after: `src` itself is asked first and refused, so the file is refused too
949
- authorizePath: ({ path }) => path === 'src' || path.startsWith('src/')
950
- ```
951
-
952
- The workspace root is not asked about — it is the boundary the tools already own.
953
-
954
- **3. The policy is called more often.** A path of depth N costs N+1 calls (`.`, then each ancestor,
955
- then the leaf), outermost first, stopping at the first refusal. A policy that logs or meters will
956
- see a different sequence, and will no longer see the leaf once an ancestor has refused.
957
-
958
- ## Released migration: 0.83.0
959
-
960
- Two things, both mechanical, and only if you touch an observability sink.
961
-
962
- ```bash
963
- rg -n "createObservability|createApplicationEventSink|createApplicationSnapshotSink|createAgentRuntimeEventSink|createAgentObservability"
964
- ```
965
-
966
- **1. `flush()` returns `Promise<boolean>`.** `await sink.flush()` needs no
967
- change. Only a declared type does:
968
-
969
- ```ts
970
- // before
971
- const flushAudit: () => Promise<void> = observability.flush
972
- // after
973
- const flushAudit: () => Promise<boolean> = observability.flush
974
- ```
975
-
976
- **2. `ObservabilityDrainReport` carries `drained`.** The framework builds it, so
977
- reading code is unchanged. A hand-built report — a test double, or one persisted
978
- and re-parsed through `ObservabilityDrainReportSchema` — needs the field:
979
-
980
- ```ts
981
- // before
982
- { request, tools, total, durationMs }
983
- // after
984
- { request, tools, total, durationMs, drained: true }
985
- ```
986
-
987
- Then take the thing this release exists for. Every drain now accepts
988
- `{ timeoutMs?, signal? }`, so a shutdown can give the audit drain the same
989
- deadline it gives every other step:
990
-
991
- ```ts
992
- const report = await observability.close({ timeoutMs: 5_000 })
993
- if (!report.drained) {
994
- logger.warn('audit drain incomplete', {
995
- unwritten: report.total.received - report.total.filtered - report.total.completed,
996
- })
997
- }
998
- ```
999
-
1000
- The bound ends the **waiting**, not the writes: a sink's `write` is handed no
1001
- cancellation, so an outstanding one keeps running against whatever you close
1002
- next. Racing `close()` against your own timer looks equivalent and is not — it
1003
- discards the report along with the wait.
1004
-
1005
- ## Released migration: 0.82.0
1006
-
1007
- One thing, and only if you mount MCP or agent tools from a `createTrackingContract` contract.
1008
-
1009
- ```bash
1010
- rg -n "createTrackingContract"
1011
- ```
1012
-
1013
- The event ingest (`track`, `POST /events`) is now `expose: ['HTTP']`, which is
1014
- what its sibling `bootstrap` always declared. Before, it declared nothing — and
1015
- an endpoint with no `expose` is a tool on MCP and AGENT by default, so the
1016
- mounted surface carried a `track_<prefix>` tool. Since this contract is built
1017
- inside the framework, an application that had made every tool opt-in for the
1018
- endpoints *it* authors could not have opted this one out.
1019
-
1020
- **If you pin a tool-surface digest or count**, it moves by one; re-record it.
1021
- **If you assert on tool names**, `track_<prefix>` is gone. **If nothing in your
1022
- project mounts tools from this contract**, there is nothing to do — the HTTP
1023
- routes, the client and the schemas are unchanged.
1024
-
1025
- Un-declaring the tool was never the intent, so there is no option to keep it. If
1026
- an agent in your system genuinely needs to record something, give it your own
1027
- endpoint with your own schema: the browser ingest trusts a client-minted event
1028
- id and a visit lease, and an agent holds neither.
1029
-
1030
- ## Released migration: 0.81.0
1031
-
1032
- **Path literals own string params.**
1033
-
1034
- An endpoint whose path contains `:id` or a terminal `*rest` no longer needs a
1035
- duplicate `params: z.object({ …string() })` declaration. Remove schemas that do
1036
- nothing beyond repeating path names:
1037
-
1038
- ```ts
1039
- // before
1040
- { path: '/projects/:projectId/*filePath',
1041
- params: z.object({ projectId: z.string(), filePath: z.string() }) }
1042
-
1043
- // after
1044
- { path: '/projects/:projectId/*filePath' }
1045
- ```
1046
-
1047
- Keep an explicit schema when it validates or coerces. It must cover every name
1048
- in the path — an explicit schema that misses one now fails at `defineContract`
1049
- with the path and the missing field named. Client calls and handler contexts
1050
- infer the string fields from the literal, so a call that omitted one becomes a
1051
- compile error instead of building a URL with an unresolved segment. Measured
1052
- across three consuming applications before release (373 endpoints with path
1053
- segments), no explicit schema missed a field: the migration is deleting
1054
- schemas that only repeated the path, or nothing.