stitchkit 0.94.0 → 0.95.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 (360) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/dist/agent-runtime/coding-shell-process.d.ts.map +1 -1
  3. package/dist/agent-runtime/coding-tool-listing.d.ts.map +1 -1
  4. package/dist/agent-runtime/coding-tool-search-patch.d.ts.map +1 -1
  5. package/dist/agent-runtime/contained-darwin.d.ts +38 -0
  6. package/dist/agent-runtime/contained-darwin.d.ts.map +1 -0
  7. package/dist/agent-runtime/contained-files.d.ts +11 -26
  8. package/dist/agent-runtime/contained-files.d.ts.map +1 -1
  9. package/dist/agent-runtime/contained-scan.d.ts +21 -0
  10. package/dist/agent-runtime/contained-scan.d.ts.map +1 -0
  11. package/dist/agent-runtime/contained-write.d.ts +9 -0
  12. package/dist/agent-runtime/contained-write.d.ts.map +1 -0
  13. package/dist/agent-runtime/deferred-tool-types.d.ts +3 -2
  14. package/dist/agent-runtime/deferred-tool-types.d.ts.map +1 -1
  15. package/dist/agent-runtime/harness-control.d.ts +0 -1
  16. package/dist/agent-runtime/harness-control.d.ts.map +1 -1
  17. package/dist/agent-runtime/harness.d.ts +0 -5
  18. package/dist/agent-runtime/harness.d.ts.map +1 -1
  19. package/dist/agent-runtime/managed-tools.d.ts +3 -2
  20. package/dist/agent-runtime/managed-tools.d.ts.map +1 -1
  21. package/dist/agent-runtime/provider-origin.d.ts +7 -0
  22. package/dist/agent-runtime/provider-origin.d.ts.map +1 -1
  23. package/dist/agent-runtime/run-operation-lifecycle.d.ts.map +1 -1
  24. package/dist/agent-runtime/runtime.d.ts +1 -1
  25. package/dist/agent-runtime/runtime.d.ts.map +1 -1
  26. package/dist/agent-runtime/schedule-records.d.ts +34 -0
  27. package/dist/agent-runtime/schedule-records.d.ts.map +1 -0
  28. package/dist/agent-runtime/schedules.d.ts +34 -0
  29. package/dist/agent-runtime/schedules.d.ts.map +1 -1
  30. package/dist/agent-runtime/store-conformance-lifecycle.d.ts +434 -0
  31. package/dist/agent-runtime/store-conformance-lifecycle.d.ts.map +1 -0
  32. package/dist/agent-runtime/store-conformance-ordering.d.ts +18 -0
  33. package/dist/agent-runtime/store-conformance-ordering.d.ts.map +1 -0
  34. package/dist/agent-runtime/store-conformance-support.d.ts +130 -0
  35. package/dist/agent-runtime/store-conformance-support.d.ts.map +1 -0
  36. package/dist/agent-runtime/store-conformance-terminal.d.ts +12 -0
  37. package/dist/agent-runtime/store-conformance-terminal.d.ts.map +1 -0
  38. package/dist/agent-runtime/store-conformance.d.ts.map +1 -1
  39. package/dist/application/admission-rate.d.ts +21 -0
  40. package/dist/application/admission-rate.d.ts.map +1 -0
  41. package/dist/application/admission-run.d.ts +8 -0
  42. package/dist/application/admission-run.d.ts.map +1 -0
  43. package/dist/application/admission.d.ts.map +1 -1
  44. package/dist/application/diagnostic-journal-lock.d.ts +9 -34
  45. package/dist/application/diagnostic-journal-lock.d.ts.map +1 -1
  46. package/dist/application/diagnostic-journal-manager.d.ts.map +1 -1
  47. package/dist/application/diagnostic-journal-storage.d.ts.map +1 -1
  48. package/dist/application/kernel-resource-context.d.ts.map +1 -1
  49. package/dist/application/notification-outbox.d.ts.map +1 -1
  50. package/dist/application/process-lifecycle-transitions.d.ts +175 -0
  51. package/dist/application/process-lifecycle-transitions.d.ts.map +1 -0
  52. package/dist/application/process-lifecycle.d.ts +3 -131
  53. package/dist/application/process-lifecycle.d.ts.map +1 -1
  54. package/dist/application/schedule.d.ts +0 -1
  55. package/dist/application/schedule.d.ts.map +1 -1
  56. package/dist/application/watch-hub-core.d.ts +122 -0
  57. package/dist/application/watch-hub-core.d.ts.map +1 -0
  58. package/dist/application/watch-hub.d.ts +2 -2
  59. package/dist/application/watch-hub.d.ts.map +1 -1
  60. package/dist/browser/client-executors.d.ts +14 -0
  61. package/dist/browser/client-executors.d.ts.map +1 -0
  62. package/dist/browser/client-multipart.d.ts +1 -1
  63. package/dist/browser/client-multipart.d.ts.map +1 -1
  64. package/dist/browser/client.d.ts +3 -2
  65. package/dist/browser/client.d.ts.map +1 -1
  66. package/dist/browser/http-fetch.d.ts +22 -0
  67. package/dist/browser/http-fetch.d.ts.map +1 -0
  68. package/dist/browser/http.d.ts +1 -3
  69. package/dist/browser/http.d.ts.map +1 -1
  70. package/dist/browser/live-state-core.d.ts +63 -0
  71. package/dist/browser/live-state-core.d.ts.map +1 -0
  72. package/dist/browser/live-state.d.ts.map +1 -1
  73. package/dist/browser/realtime-client.d.ts +26 -0
  74. package/dist/browser/realtime-client.d.ts.map +1 -0
  75. package/dist/browser/socket-io-connection.d.ts +82 -0
  76. package/dist/browser/socket-io-connection.d.ts.map +1 -0
  77. package/dist/browser/socket-io-peer.d.ts +20 -0
  78. package/dist/browser/socket-io-peer.d.ts.map +1 -0
  79. package/dist/browser/socket-io-trace.d.ts +31 -0
  80. package/dist/browser/socket-io-trace.d.ts.map +1 -0
  81. package/dist/browser/socket-io.d.ts +2 -18
  82. package/dist/browser/socket-io.d.ts.map +1 -1
  83. package/dist/contract/client-types.d.ts +134 -0
  84. package/dist/contract/client-types.d.ts.map +1 -0
  85. package/dist/contract/define-validation.d.ts +30 -0
  86. package/dist/contract/define-validation.d.ts.map +1 -0
  87. package/dist/contract/define.d.ts +3 -357
  88. package/dist/contract/define.d.ts.map +1 -1
  89. package/dist/contract/runtime-context.d.ts +131 -0
  90. package/dist/contract/runtime-context.d.ts.map +1 -0
  91. package/dist/contract/tool-options.d.ts +105 -0
  92. package/dist/contract/tool-options.d.ts.map +1 -0
  93. package/dist/contract/tool-view.d.ts +15 -2
  94. package/dist/contract/tool-view.d.ts.map +1 -1
  95. package/dist/durability/contract.d.ts +83 -0
  96. package/dist/durability/contract.d.ts.map +1 -1
  97. package/dist/durability/effect.d.ts +24 -0
  98. package/dist/durability/effect.d.ts.map +1 -0
  99. package/dist/durability/engine.d.ts +2 -2
  100. package/dist/durability/engine.d.ts.map +1 -1
  101. package/dist/durability/events.d.ts +2 -0
  102. package/dist/durability/events.d.ts.map +1 -1
  103. package/dist/durability/ledger.d.ts +11 -0
  104. package/dist/durability/ledger.d.ts.map +1 -1
  105. package/dist/durability/parks.d.ts +22 -0
  106. package/dist/durability/parks.d.ts.map +1 -0
  107. package/dist/durability/scheduler.d.ts +1 -0
  108. package/dist/durability/scheduler.d.ts.map +1 -1
  109. package/dist/entrypoints/agent-runtime/coding-tools.js +4 -4
  110. package/dist/entrypoints/agent-runtime/harness.js +127 -116
  111. package/dist/entrypoints/agent-runtime/sandbox.js +4 -4
  112. package/dist/entrypoints/agent-runtime/sqlite/bun.js +3 -3
  113. package/dist/entrypoints/agent-runtime/sqlite/node.js +3 -3
  114. package/dist/entrypoints/agent-runtime/testing.js +246 -214
  115. package/dist/entrypoints/agent-runtime.js +224 -203
  116. package/dist/entrypoints/application/diagnostic-journal.js +63 -203
  117. package/dist/entrypoints/application/opentelemetry.js +1 -1
  118. package/dist/entrypoints/application.d.ts +2 -1
  119. package/dist/entrypoints/application.d.ts.map +1 -1
  120. package/dist/entrypoints/application.js +506 -380
  121. package/dist/entrypoints/cli.d.ts +4 -1
  122. package/dist/entrypoints/cli.d.ts.map +1 -1
  123. package/dist/entrypoints/cli.js +57 -35
  124. package/dist/entrypoints/contract.d.ts +5 -2
  125. package/dist/entrypoints/contract.d.ts.map +1 -1
  126. package/dist/entrypoints/contract.js +3 -2
  127. package/dist/entrypoints/files.d.ts +2 -0
  128. package/dist/entrypoints/files.d.ts.map +1 -1
  129. package/dist/entrypoints/files.js +98 -2
  130. package/dist/entrypoints/index.d.ts +4 -2
  131. package/dist/entrypoints/index.d.ts.map +1 -1
  132. package/dist/entrypoints/index.js +348 -282
  133. package/dist/entrypoints/live.js +89 -71
  134. package/dist/entrypoints/node.d.ts +2 -1
  135. package/dist/entrypoints/node.d.ts.map +1 -1
  136. package/dist/entrypoints/node.js +13 -12
  137. package/dist/entrypoints/react.js +1 -1
  138. package/dist/entrypoints/remote.js +4 -4
  139. package/dist/entrypoints/server.d.ts +4 -2
  140. package/dist/entrypoints/server.d.ts.map +1 -1
  141. package/dist/entrypoints/server.js +293 -79
  142. package/dist/entrypoints/testing.d.ts +2 -1
  143. package/dist/entrypoints/testing.d.ts.map +1 -1
  144. package/dist/entrypoints/testing.js +288 -281
  145. package/dist/entrypoints/tools/connections.js +2 -2
  146. package/dist/entrypoints/tools/invoker.js +4 -4
  147. package/dist/entrypoints/tools.d.ts +6 -3
  148. package/dist/entrypoints/tools.d.ts.map +1 -1
  149. package/dist/entrypoints/tools.js +245 -202
  150. package/dist/entrypoints/tracking.js +325 -274
  151. package/dist/files/boundary.d.ts.map +1 -1
  152. package/dist/files/file-io.d.ts +14 -0
  153. package/dist/files/file-io.d.ts.map +1 -0
  154. package/dist/index-1j8pm5t0.js +412 -0
  155. package/dist/{index-kvj7f4hq.js → index-2bxbyab0.js} +10 -2
  156. package/dist/{index-xnj9bgxe.js → index-2gxzjvyr.js} +2 -162
  157. package/dist/index-4gcnakhx.js +82 -0
  158. package/dist/{index-j05z5gn4.js → index-55hkhm67.js} +136 -119
  159. package/dist/{index-cq4qfycf.js → index-79z7m7dt.js} +227 -59
  160. package/dist/{index-r7nmqpsg.js → index-7p1f0vp2.js} +1 -1
  161. package/dist/{index-dcpdvjsc.js → index-863ea9jb.js} +4 -4
  162. package/dist/index-8p52kd5p.js +242 -0
  163. package/dist/{index-97ac4gph.js → index-8zja4pkf.js} +26 -4
  164. package/dist/{index-2qzskm8h.js → index-dce5wxcq.js} +1 -1
  165. package/dist/index-e01r054k.js +105 -0
  166. package/dist/{index-sees8yf8.js → index-ensd0r74.js} +118 -111
  167. package/dist/{index-1nd48tm9.js → index-gxrt5h6v.js} +2 -1
  168. package/dist/{index-e87kakm4.js → index-ham5sz8m.js} +112 -110
  169. package/dist/{index-kj2wbeta.js → index-het2he5g.js} +280 -196
  170. package/dist/{index-vcvkq30w.js → index-hmp4800j.js} +3 -3
  171. package/dist/{index-gyr48nzg.js → index-k30h66yd.js} +71 -151
  172. package/dist/{index-2cr1cqhn.js → index-khtgb21r.js} +2 -2
  173. package/dist/{index-x4799c19.js → index-ndddxtyx.js} +11 -11
  174. package/dist/{index-dydjcp8z.js → index-np4m8hd3.js} +38 -36
  175. package/dist/{index-p81267c2.js → index-p3vsv1fb.js} +621 -357
  176. package/dist/{index-mp5sn43f.js → index-p9e0w8hs.js} +2 -2
  177. package/dist/{index-rewkc2hj.js → index-p9sh0xx4.js} +3 -3
  178. package/dist/{index-70yj2ebz.js → index-paz6sgdp.js} +107 -103
  179. package/dist/{index-bn2cjajt.js → index-px2gm2jp.js} +26 -102
  180. package/dist/index-s812ycat.js +65 -0
  181. package/dist/{index-xsqjkha9.js → index-sp1tzwnb.js} +2 -2
  182. package/dist/{index-n6hxg8as.js → index-t9rhjr9f.js} +615 -566
  183. package/dist/{index-zeemqhqx.js → index-v260df89.js} +88 -80
  184. package/dist/{index-fdp6hdxn.js → index-w906953s.js} +5 -1
  185. package/dist/{index-mdzh02yc.js → index-wdkt63w3.js} +1 -1
  186. package/dist/{index-58k4fp34.js → index-wsm5w4ee.js} +1 -1
  187. package/dist/{index-v38qyerb.js → index-xw3s75nj.js} +1 -1
  188. package/dist/internal/atomic-file.d.ts +23 -2
  189. package/dist/internal/atomic-file.d.ts.map +1 -1
  190. package/dist/internal/exclusive-lock.d.ts +51 -0
  191. package/dist/internal/exclusive-lock.d.ts.map +1 -0
  192. package/dist/internal/process-identity.d.ts +47 -0
  193. package/dist/internal/process-identity.d.ts.map +1 -0
  194. package/dist/internal/with-exclusive-lock.d.ts +67 -0
  195. package/dist/internal/with-exclusive-lock.d.ts.map +1 -0
  196. package/dist/live/watch-client.d.ts.map +1 -1
  197. package/dist/observability/audit.d.ts +2 -2
  198. package/dist/observability/audit.d.ts.map +1 -1
  199. package/dist/observability/event.d.ts +2 -1
  200. package/dist/observability/event.d.ts.map +1 -1
  201. package/dist/primitives/export-operation.d.ts +1 -1
  202. package/dist/primitives/export-operation.d.ts.map +1 -1
  203. package/dist/realtime/registry.d.ts +0 -5
  204. package/dist/realtime/registry.d.ts.map +1 -1
  205. package/dist/server/bun.d.ts +0 -1
  206. package/dist/server/bun.d.ts.map +1 -1
  207. package/dist/server/context-contribution.d.ts +1 -1
  208. package/dist/server/context-contribution.d.ts.map +1 -1
  209. package/dist/server/context.d.ts +1 -1
  210. package/dist/server/context.d.ts.map +1 -1
  211. package/dist/server/endpoint-response.d.ts +2 -1
  212. package/dist/server/endpoint-response.d.ts.map +1 -1
  213. package/dist/server/error-dispatch.d.ts +1 -1
  214. package/dist/server/error-dispatch.d.ts.map +1 -1
  215. package/dist/server/error-hook.d.ts +1 -1
  216. package/dist/server/error-hook.d.ts.map +1 -1
  217. package/dist/server/handler-state.d.ts +1 -1
  218. package/dist/server/handler-state.d.ts.map +1 -1
  219. package/dist/server/implement-registry.d.ts +54 -0
  220. package/dist/server/implement-registry.d.ts.map +1 -0
  221. package/dist/server/implement.d.ts +9 -55
  222. package/dist/server/implement.d.ts.map +1 -1
  223. package/dist/server/middleware/auth.d.ts +1 -31
  224. package/dist/server/middleware/auth.d.ts.map +1 -1
  225. package/dist/server/middleware/jwt.d.ts +31 -0
  226. package/dist/server/middleware/jwt.d.ts.map +1 -0
  227. package/dist/server/multipart-reader.d.ts +22 -0
  228. package/dist/server/multipart-reader.d.ts.map +1 -0
  229. package/dist/server/multipart.d.ts +1 -1
  230. package/dist/server/multipart.d.ts.map +1 -1
  231. package/dist/server/oauth/cimd.d.ts +88 -0
  232. package/dist/server/oauth/cimd.d.ts.map +1 -0
  233. package/dist/server/oauth/endpoints.d.ts +39 -0
  234. package/dist/server/oauth/endpoints.d.ts.map +1 -0
  235. package/dist/server/oauth/provider.d.ts +1 -68
  236. package/dist/server/oauth/provider.d.ts.map +1 -1
  237. package/dist/server/streaming-pump.d.ts +66 -0
  238. package/dist/server/streaming-pump.d.ts.map +1 -0
  239. package/dist/server/streaming-route.d.ts +12 -5
  240. package/dist/server/streaming-route.d.ts.map +1 -1
  241. package/dist/server/types.d.ts +4 -1
  242. package/dist/server/types.d.ts.map +1 -1
  243. package/dist/server/unix-client-bun.d.ts.map +1 -1
  244. package/dist/server/unix-client-http1.d.ts +76 -0
  245. package/dist/server/unix-client-http1.d.ts.map +1 -0
  246. package/dist/server/unix-client.d.ts.map +1 -1
  247. package/dist/testing/handler-clients.d.ts +2 -1
  248. package/dist/testing/handler-clients.d.ts.map +1 -1
  249. package/dist/testing/realtime-probe.d.ts +33 -0
  250. package/dist/testing/realtime-probe.d.ts.map +1 -0
  251. package/dist/testing/surface-conformance.d.ts +0 -31
  252. package/dist/testing/surface-conformance.d.ts.map +1 -1
  253. package/dist/testing/surface-manifest-digest.d.ts +44 -0
  254. package/dist/testing/surface-manifest-digest.d.ts.map +1 -0
  255. package/dist/testing/surface-manifest.d.ts.map +1 -1
  256. package/dist/tools/agent.d.ts +1 -1
  257. package/dist/tools/agent.d.ts.map +1 -1
  258. package/dist/tools/cli/args-fields.d.ts +31 -0
  259. package/dist/tools/cli/args-fields.d.ts.map +1 -0
  260. package/dist/tools/cli/args-route.d.ts +42 -0
  261. package/dist/tools/cli/args-route.d.ts.map +1 -0
  262. package/dist/tools/cli/args-view.d.ts +32 -0
  263. package/dist/tools/cli/args-view.d.ts.map +1 -0
  264. package/dist/tools/cli/args.d.ts +2 -65
  265. package/dist/tools/cli/args.d.ts.map +1 -1
  266. package/dist/tools/cli/argument-error.d.ts +5 -0
  267. package/dist/tools/cli/argument-error.d.ts.map +1 -0
  268. package/dist/tools/cli/checkpoint.d.ts.map +1 -1
  269. package/dist/tools/cli/command.d.ts +1 -1
  270. package/dist/tools/cli/command.d.ts.map +1 -1
  271. package/dist/tools/cli/config.d.ts +1 -1
  272. package/dist/tools/cli/config.d.ts.map +1 -1
  273. package/dist/tools/cli/format.d.ts +2 -1
  274. package/dist/tools/cli/format.d.ts.map +1 -1
  275. package/dist/tools/cli/invoke.d.ts +2 -1
  276. package/dist/tools/cli/invoke.d.ts.map +1 -1
  277. package/dist/tools/cli/managed-surface.d.ts +1 -1
  278. package/dist/tools/cli/managed-surface.d.ts.map +1 -1
  279. package/dist/tools/cli/policy.d.ts +1 -1
  280. package/dist/tools/cli/policy.d.ts.map +1 -1
  281. package/dist/tools/cli/prepare.d.ts.map +1 -1
  282. package/dist/tools/cli/run-managed.d.ts.map +1 -1
  283. package/dist/tools/cli/session.d.ts +1 -1
  284. package/dist/tools/cli/session.d.ts.map +1 -1
  285. package/dist/tools/cli/update.d.ts +19 -0
  286. package/dist/tools/cli/update.d.ts.map +1 -1
  287. package/dist/tools/cli/view.d.ts +1 -1
  288. package/dist/tools/cli/view.d.ts.map +1 -1
  289. package/dist/tools/cli/wait.d.ts +1 -1
  290. package/dist/tools/cli/wait.d.ts.map +1 -1
  291. package/dist/tools/connections/runtime.d.ts +1 -1
  292. package/dist/tools/connections/runtime.d.ts.map +1 -1
  293. package/dist/tools/execute-args.d.ts +23 -0
  294. package/dist/tools/execute-args.d.ts.map +1 -0
  295. package/dist/tools/execute-hooks.d.ts +146 -0
  296. package/dist/tools/execute-hooks.d.ts.map +1 -0
  297. package/dist/tools/execute-result.d.ts +40 -0
  298. package/dist/tools/execute-result.d.ts.map +1 -0
  299. package/dist/tools/execute.d.ts +4 -193
  300. package/dist/tools/execute.d.ts.map +1 -1
  301. package/dist/tools/internal/surface-projector.d.ts +2 -1
  302. package/dist/tools/internal/surface-projector.d.ts.map +1 -1
  303. package/dist/tools/invoker.d.ts +2 -1
  304. package/dist/tools/invoker.d.ts.map +1 -1
  305. package/dist/tools/lifecycle.d.ts +1 -1
  306. package/dist/tools/lifecycle.d.ts.map +1 -1
  307. package/dist/tools/mcp/mount.d.ts +1 -1
  308. package/dist/tools/mcp/mount.d.ts.map +1 -1
  309. package/dist/tools/mcp/prepare.d.ts +2 -1
  310. package/dist/tools/mcp/prepare.d.ts.map +1 -1
  311. package/dist/tools/mcp/progress.d.ts +1 -1
  312. package/dist/tools/mcp/progress.d.ts.map +1 -1
  313. package/dist/tools/mcp/register.d.ts +3 -2
  314. package/dist/tools/mcp/register.d.ts.map +1 -1
  315. package/dist/tools/mcp/round-context.d.ts +38 -0
  316. package/dist/tools/mcp/round-context.d.ts.map +1 -0
  317. package/dist/tools/mcp/round-policy.d.ts +1 -1
  318. package/dist/tools/mcp/round-policy.d.ts.map +1 -1
  319. package/dist/tools/mcp/round.d.ts +3 -11
  320. package/dist/tools/mcp/round.d.ts.map +1 -1
  321. package/dist/tools/mcp/runtime-tools.d.ts +2 -1
  322. package/dist/tools/mcp/runtime-tools.d.ts.map +1 -1
  323. package/dist/tools/mount.d.ts +3 -1
  324. package/dist/tools/mount.d.ts.map +1 -1
  325. package/dist/tools/native-definition.d.ts +2 -1
  326. package/dist/tools/native-definition.d.ts.map +1 -1
  327. package/dist/tools/operations/async-operation-runtime-tools.d.ts +2 -1
  328. package/dist/tools/operations/async-operation-runtime-tools.d.ts.map +1 -1
  329. package/dist/tools/operations/async-operation-runtime-types.d.ts +2 -1
  330. package/dist/tools/operations/async-operation-runtime-types.d.ts.map +1 -1
  331. package/dist/tools/remote.d.ts.map +1 -1
  332. package/dist/tools/runtime-tool.d.ts +3 -1
  333. package/dist/tools/runtime-tool.d.ts.map +1 -1
  334. package/dist/tools/tool-logger.d.ts +1 -1
  335. package/dist/tools/tool-logger.d.ts.map +1 -1
  336. package/dist/tracking/client-listeners.d.ts +30 -0
  337. package/dist/tracking/client-listeners.d.ts.map +1 -0
  338. package/dist/tracking/client-visit.d.ts +61 -0
  339. package/dist/tracking/client-visit.d.ts.map +1 -0
  340. package/dist/tracking/client.d.ts +3 -2
  341. package/dist/tracking/client.d.ts.map +1 -1
  342. package/llms/application.2.txt +271 -7
  343. package/llms/application.txt +66 -289
  344. package/llms/cli.2.txt +80 -0
  345. package/llms/cli.txt +45 -74
  346. package/llms/contract.txt +3 -3
  347. package/llms/files.txt +3 -0
  348. package/llms/stitchkit.txt +3 -3
  349. package/llms/tools.2.txt +88 -279
  350. package/llms/tools.3.txt +288 -0
  351. package/llms/tools.txt +27 -65
  352. package/llms/{upgrading-0.37.0-0.50.0.txt → upgrading-0.37.0-0.53.0.txt} +25 -3
  353. package/llms/{upgrading-0.53.0-0.67.0.txt → upgrading-0.55.0-0.68.0.txt} +53 -25
  354. package/llms/{upgrading-0.68.0-0.94.0.txt → upgrading-0.69.0-0.95.0.txt} +45 -53
  355. package/llms/upgrading.txt +3 -3
  356. package/llms-full.txt +216 -43
  357. package/llms.txt +8 -8
  358. package/package.json +1 -1
  359. package/dist/index-e2z3ahw9.js +0 -325
  360. package/dist/index-mkm15s49.js +0 -394
@@ -4,8 +4,272 @@
4
4
  > `llms.txt` in this package.
5
5
 
6
6
  Parts of this slice:
7
- - `llms/application.txt`: Guide: Managed application kernel (docs/guide/application-kernel.md) · Guide: Application migration recipes (docs/guide/application-migration-recipes.md)
8
- - `llms/application.2.txt`: API reference: `stitchkit/application` (docs/api/reference.md)
7
+ - `llms/application.txt`: Guide: Managed application kernel (docs/guide/application-kernel.md)
8
+ - `llms/application.2.txt`: Guide: Application migration recipes (docs/guide/application-migration-recipes.md) · API reference: `stitchkit/application` (docs/api/reference.md)
9
+
10
+ ==============================================================================
11
+ # Guide: Application migration recipes (docs/guide/application-migration-recipes.md)
12
+ ==============================================================================
13
+
14
+ ---
15
+ title: Application migration recipes
16
+ description: Executable patterns for moving database, poller, queue and operational publishing lifecycle into the managed application kernel.
17
+ type: architecture
18
+ status: active
19
+ created: 2026-08-24
20
+ updated: 2026-08-24
21
+ ---
22
+
23
+ # Application migration recipes
24
+
25
+ These recipes are the migration companion to the
26
+ [managed application kernel](./application-kernel.md). Their canonical source is
27
+ the packed-consumer fixture
28
+ [`application-migration-recipes.ts`](../../packages/core/scripts/consumer-lane/fixtures/minimal/src/application-migration-recipes.ts):
29
+ the consumer lane installs the package tarball, typechecks that file and runs it
30
+ only through `stitchkit/application` exports.
31
+
32
+ ## Database connection
33
+
34
+ Wrap connection allocation and readiness in `start`, and make `close` safe after
35
+ partial setup. Stitchkit invokes cleanup for every attempted start, including a
36
+ start that allocates a client and then rejects.
37
+
38
+ ```ts
39
+ const database = defineManagedResource({
40
+ id: 'database',
41
+ async start({ signal, reportHealth }) {
42
+ await databaseClient.connect(signal)
43
+ await databaseClient.assertReady()
44
+ reportHealth('healthy')
45
+ },
46
+ close: () => databaseClient.close(),
47
+ })
48
+ ```
49
+
50
+ The application still owns the client, ORM configuration, transactions,
51
+ migrations and reconnect policy. The executable recipe deliberately fails after
52
+ allocation and proves one rollback close.
53
+
54
+ ## Long-running poller
55
+
56
+ Return separate readiness and completion promises. Readiness says dependants may
57
+ start; completion represents the whole background lifetime.
58
+
59
+ ```ts
60
+ const poller = defineManagedResource({
61
+ id: 'poller',
62
+ start: ({ signal }) => ({
63
+ ready: providerPoller.ready,
64
+ completion: providerPoller.run(signal),
65
+ }),
66
+ stopAdmission: () => providerPoller.stop(),
67
+ drain: () => providerPoller.completion,
68
+ close: () => providerPoller.close(),
69
+ })
70
+ ```
71
+
72
+ Completion before readiness fails startup and rolls back. Completion after
73
+ readiness removes application readiness. Provider cursor persistence, retry,
74
+ backoff and restart policy remain application/provider concerns.
75
+
76
+ ## Queue consumer
77
+
78
+ Acquire the application lease only after provider delivery/claim. If admission
79
+ is already closed, reject the delivery through the provider's own nack/requeue
80
+ primitive. Work admitted before shutdown releases its lease after ack/nack and
81
+ therefore participates in application drain.
82
+
83
+ ```ts
84
+ async function handleDelivery(delivery: Delivery) {
85
+ const lease = app.admission.acquire()
86
+ if (!lease) return delivery.nack({ requeue: true })
87
+ try {
88
+ await processClaim(delivery.claim)
89
+ await delivery.ack()
90
+ } catch (error) {
91
+ await delivery.nack({ requeue: shouldRetry(error) })
92
+ throw error
93
+ } finally {
94
+ lease.release()
95
+ }
96
+ }
97
+ ```
98
+
99
+ Stitchkit owns only process-local admission accounting and drain. Durable claims,
100
+ visibility timeouts, deduplication, idempotency and retry classification remain
101
+ in the queue/product layer.
102
+
103
+ ## Operational publisher
104
+
105
+ Project anonymous aggregate activity, then feed absolute snapshots into the
106
+ latest-value sink. A slow transport holds one write plus one replaceable latest
107
+ revision rather than an unbounded event queue.
108
+
109
+ ```ts
110
+ const publisher = createApplicationSnapshotSink({
111
+ write: (snapshot) => monitoring.publish(snapshot),
112
+ })
113
+ const activity = createActivityProjection({
114
+ id: 'generation',
115
+ stages: ['queued', 'running'],
116
+ })
117
+ const unsubscribe = activity.subscribe((snapshot) => {
118
+ publisher.publish(snapshot)
119
+ })
120
+
121
+ // cleanup boundary
122
+ unsubscribe()
123
+ publisher.publish(activity.getSnapshot())
124
+ await publisher.close()
125
+ ```
126
+
127
+ The monitoring backend, transport retry and cross-process aggregation remain
128
+ outside Stitchkit. The executable recipe blocks revision 0, coalesces
129
+ intermediate revisions, explicitly admits the final absolute snapshot after
130
+ unsubscribe and proves that `close()` flushes revision 3. Do not rely on an
131
+ asynchronous subscriber callback racing cleanup: publish `getSnapshot()` before
132
+ closing the outer sink, so any older or duplicate late delivery is rejected as
133
+ stale instead of dropping the final state.
134
+
135
+ ## Bound a handler and a local worker with one lease policy
136
+
137
+ Use a bounded admission when two entry paths consume the same finite local
138
+ capacity. Composing it with `application.admission` keeps readiness and shutdown
139
+ as the upstream gate:
140
+
141
+ ```ts
142
+ const work = createBoundedAdmission({
143
+ upstream: app.admission,
144
+ policy: {
145
+ global: { maxConcurrent: 4 },
146
+ perKey: { maxConcurrent: 1, maxKeys: 1_000 },
147
+ },
148
+ })
149
+
150
+ const fromHttp = (key: string, signal: AbortSignal) =>
151
+ work.run(key, (context) => render(context.signal), { signal, timeoutMs: 20_000 })
152
+
153
+ const fromWorker = (key: string) =>
154
+ work.run(key, (context) => reconcile(context.signal))
155
+ ```
156
+
157
+ A timeout in `fromHttp` does not free a permit while `render` remains active.
158
+ At shutdown call `work.stopAdmission()` with the other admission owners and
159
+ await `work.drain(...)`; the result reports the actual remainder.
160
+
161
+ ## Replace ad-hoc output and progress queues
162
+
163
+ Ordered output and replaceable progress are separate declarations:
164
+
165
+ ```ts
166
+ const lines = createBoundedChannel<string>({
167
+ policy: 'ordered', maxItems: 100, maxBytes: 1_000_000,
168
+ sizeOf: (line) => new TextEncoder().encode(line).byteLength,
169
+ })
170
+
171
+ const state = createBoundedChannel<{ revision: number; percent: number }>({
172
+ policy: 'latest', maxItems: 1, maxBytes: 64,
173
+ sizeOf: () => 64,
174
+ })
175
+
176
+ const lineResult = lines.offer('one durable-in-process ordering unit')
177
+ const stateResult = state.offer({ revision: 2, percent: 50 })
178
+ ```
179
+
180
+ Handle `refused` from `lines` at the protocol boundary; do not turn it into
181
+ implicit loss. A `coalesced` state result is expected latest-value behaviour,
182
+ not evidence that an ordered event was delivered. Neither channel is durable;
183
+ persist first when restart replay is required.
184
+
185
+ ## Handing a handle to the resources that depend on it
186
+
187
+ `dependsOn` carries ordering. To carry the object as well, return a `value` from
188
+ `start` and read it with `context.use(...)`. This replaces the module-local
189
+ `let handle: T | null` with the guard the graph makes unreachable.
190
+
191
+ ```ts
192
+ const database = defineManagedResource({
193
+ id: 'database',
194
+ start: async () => ({ value: await connect(env.DATABASE_URL) }),
195
+ })
196
+
197
+ const worker = defineManagedResource({
198
+ id: 'worker',
199
+ dependsOn: [database],
200
+ start(context) {
201
+ const db = context.use(database) // Connection — not Connection | null
202
+ },
203
+ })
204
+ ```
205
+
206
+ Declare the dependency with the **resource** whenever you intend to read from
207
+ it: that is the form `use` can type, and it stops the declaration and the read
208
+ from drifting. A string still expresses order on its own.
209
+
210
+ The value is published when `start` resolves and stays readable from `activate`
211
+ and from the shutdown phases. `use` refuses a resource that was not declared in
212
+ `dependsOn` — that only ever worked by luck of declaration order — and refuses a
213
+ resource that published nothing, which the compiler refuses too. The executable
214
+ recipe proves both the read and the refusal.
215
+
216
+ ## Managed HTTP server
217
+
218
+ The main resource of a web backend, and the one whose ownership rule is
219
+ counter-intuitive: give `managedServerResource` a **thunk** and it creates the
220
+ server during `start`, after its dependencies are ready. Give it an
221
+ already-listening server and it adopts that one instead.
222
+
223
+ ```ts
224
+ const http = managedServerResource({
225
+ id: 'http',
226
+ dependsOn: [database],
227
+ server: (context) => {
228
+ const db = context.use(database)
229
+ return createServer({ port: env.PORT, services: createServices(db) })
230
+ },
231
+ })
232
+
233
+ const app = createApplication({ id: 'service', resources: [database, http] })
234
+ await app.start() // the port is bound; the snapshot means it
235
+ ```
236
+
237
+ The server resource publishes its `ManagedServerHandle`, so anything that needs
238
+ the running server — a Socket.IO attachment, a URL to log, a probe — reads it
239
+ with `context.use(http)` rather than through a module-local.
240
+
241
+ The factory itself receives `ManagedResourceContext` too. It can read only the
242
+ dependencies declared on the server resource and shares the graph's startup
243
+ signal. A dependency failure prevents the factory from binding; a factory
244
+ rejection is rolled back without invoking the factory a second time.
245
+
246
+ Do not spread this resource over your own `start` to control creation order:
247
+ that shape exists only as a workaround for the version whose `start` was empty,
248
+ and `dependsOn` now expresses the order directly. The executable recipe binds a
249
+ real port, proves a request reaches it after `start()` resolves, and proves the
250
+ port is closed after `shutdown()`.
251
+
252
+ ## Deletion checklist
253
+
254
+ After the cutover, remove the old generic lifecycle path completely:
255
+
256
+ - duplicate `process.on(...)` handlers and shutdown promise caches;
257
+ - manual readiness waiters and resource close fan-out;
258
+ - raw interval handles, overlap flags and timer drain code;
259
+ - global in-flight counters and waiter sets replaced by application leases;
260
+ - progress delta queues replaced by absolute snapshot publishing.
261
+
262
+ Keep the product code that still owns durable state and policy:
263
+
264
+ - database schema, transactions and migrations;
265
+ - queue claims, ack/nack, deduplication and external-effect idempotency;
266
+ - provider cursor, retry/backoff and credentials;
267
+ - monitoring transport configuration and durable retention;
268
+ - process exit code, hard-exit and deployment/supervisor policy.
269
+
270
+ Run the old and new lifecycle paths separately during development if needed,
271
+ but do not ship both. Before cutover, verify there is exactly one signal binding,
272
+ one timer owner, one admission gate and one resource cleanup chain.
9
273
 
10
274
  ==============================================================================
11
275
  # API reference: `stitchkit/application` (docs/api/reference.md)
@@ -26,11 +290,11 @@ cutovers are covered by the executable
26
290
  | `createApplication` | function | compose a validated resource DAG into one startup, readiness, admission and shutdown state machine |
27
291
  | `StateStore` / `StateStoreUpdate` | _type_ | async atomic read/update boundary shared by durable application state machines |
28
292
  | `createProcessLifecycleLedger` / `ProcessLifecycleLedger` / `ProcessLifecycleLedgerConfig` | function / _type_ | durable bounded run history and typed fact subscription |
29
- | `LifecycleRunSchema` / `LifecycleRun` / `LifecycleStateSchema` / `LifecycleState` / `LifecycleTerminationSchema` / `LifecycleTermination` | schema / _type_ | versioned process-run state and termination vocabulary |
30
- | `PreviousExitSchema` / `PreviousExit` / `StartFact` / `ReadyFact` / `ShutdownFact` / `ProcessLifecycleFact` | schema / _type_ | first-boot, hot-reload, clean, forced, handoff and abnormal lifecycle facts |
31
- | `transitionProcessStart` / `transitionProcessReady` / `transitionProcessShutdown` | function | pure idempotent runId+pid-owned transitions |
32
- | `LifecycleTransition` / `TransitionStartInput` / `TransitionReadyInput` / `TransitionShutdownInput` / `SameVersionOverlap` | _type_ | pure transition inputs, the same-build overlap policy (`abnormal` default / `handoff`) and state+fact result |
33
- | `lifecycleLedgerResource` / `LifecycleLedgerResource` / `LifecycleLedgerResourceConfig` | function / _type_ | managed-resource adapter that records start, readiness and shutdown |
293
+ | `LifecycleRunSchema` / `LifecycleRun` / `LifecycleStateSchema` / `LifecycleState` / `LifecycleTerminationSchema` / `LifecycleTermination` | schema / _type_ | versioned process-run state — open (`active`, `draining` with `unavailableAt`) and ended (`clean`, `forced`, `startup-failed`, `hot-reload`, `abnormal`) |
294
+ | `PreviousExitSchema` / `PreviousExit` / `StartFact` / `ReadyFact` / `DrainingFact` / `ShutdownFact` / `ProcessLifecycleFact` | schema / _type_ | first-boot, hot-reload, clean, forced, startup-failed, handoff and abnormal lifecycle facts; `processGapMs` on start, `downtimeMs` (unavailable → ready) on ready |
295
+ | `transitionProcessStart` / `transitionProcessReady` / `transitionProcessDraining` / `transitionProcessShutdown` | function | pure idempotent runId+pid-owned transitions |
296
+ | `LifecycleTransition` / `TransitionStartInput` / `TransitionRunInput` / `TransitionShutdownInput` / `SameVersionOverlap` | _type_ | pure transition inputs (`TransitionRunInput` for ready and draining, extended with `forced` for shutdown), the same-build overlap policy (`abnormal` default / `handoff`) and state+fact result |
297
+ | `lifecycleLedgerResource` / `LifecycleLedgerResource` / `LifecycleLedgerResourceConfig` | function / _type_ | managed-resource adapter that records start, readiness, admission stop (draining) and shutdown |
34
298
  | `createNotificationOutbox` / `NotificationOutbox` / `NotificationOutboxConfig` | function / _type_ | bounded at-least-once queue with durable claims, leases, retries and supersede |
35
299
  | `NotificationOutboxItem` / `NotificationOutboxReceipt` / `NotificationOutboxState` / `NotificationSend` / `NotificationFailureClassification` / `DroppedNotification` / `EnqueueNotification` | _type_ | versioned queue records, stable send identity and delivery decisions |
36
300
  | `notificationOutboxStateSchema` | function | strict persisted-state schema over an application payload schema |
@@ -5,8 +5,8 @@
5
5
  > Continues in `llms/application.2.txt`.
6
6
 
7
7
  Parts of this slice:
8
- - `llms/application.txt`: Guide: Managed application kernel (docs/guide/application-kernel.md) · Guide: Application migration recipes (docs/guide/application-migration-recipes.md)
9
- - `llms/application.2.txt`: API reference: `stitchkit/application` (docs/api/reference.md)
8
+ - `llms/application.txt`: Guide: Managed application kernel (docs/guide/application-kernel.md)
9
+ - `llms/application.2.txt`: Guide: Application migration recipes (docs/guide/application-migration-recipes.md) · API reference: `stitchkit/application` (docs/api/reference.md)
10
10
 
11
11
  ==============================================================================
12
12
  # Guide: Managed application kernel (docs/guide/application-kernel.md)
@@ -208,6 +208,12 @@ answered the question, and the answer stands. (It used to be overwritten — and
208
208
  the example above hides that, because `healthy` is the same value that
209
209
  overwrote it.)
210
210
 
211
+ **Reporting the same health again is not a change.** A resource may confirm its
212
+ health on a timer; a report with the value it already reported publishes
213
+ nothing — no new revision, no `changedAt`, no subscriber call. A change of value
214
+ publishes once, as does the first report that confirms the `healthy` the kernel
215
+ assumed at readiness.
216
+
211
217
  **A resource is required unless you write `required: false`.** That default is
212
218
  what makes the next sentence bite.
213
219
 
@@ -809,39 +815,74 @@ application-owned.
809
815
  ## Durable process facts and owner notifications
810
816
 
811
817
  `createProcessLifecycleLedger` records a bounded versioned list of process runs.
812
- Start, readiness and shutdown target both `runId` and `pid`, so hot reload and
813
- PID reuse cannot close the wrong generation. A start classifies what happened to
814
- the newest run before it, and the classification is decided by three facts —
815
- whether that run recorded its own exit, whether the pid is the same, and whether
816
- the version changed:
818
+ Start, readiness, draining and shutdown target both `runId` and `pid`, so hot
819
+ reload and PID reuse cannot close the wrong generation. `lifecycleLedgerResource`
820
+ drives it from the kernel's phases: `start` records the start, `activate` the
821
+ readiness, `stopAdmission` the drain — the run's `unavailableAt`, the moment it
822
+ stops answering new work — and `close` / `force` the stop. A run that stops
823
+ without ever becoming ready (a failed startup rolls back with `close` only)
824
+ ends as `startup-failed`, not `clean`.
825
+
826
+ A start classifies what happened to the newest run before it, and the
827
+ classification is decided by four facts — whether that run recorded its own
828
+ exit, whether the pid is the same, whether the version changed and whether it
829
+ ever became ready:
817
830
 
818
831
  | newest run | same pid | version | `previousExit` | predecessor's `termination` |
819
832
  |---|---|---|---|---|
820
833
  | none | — | — | `first-boot` | — |
821
- | recorded `stoppedAt` | — | — | `clean` / `forced` / `abnormal` as recorded | unchanged |
822
- | still `active` | yes | — | `hot-reload` | `hot-reload`, closed at the new start |
823
- | still `active` | no | changed | `handoff` | stays `active`; it records its own stop later |
824
- | still `active` | no | same | `abnormal` (default) | `abnormal`, closed at the new start — an upper bound, the crash time is unknown |
834
+ | recorded `stoppedAt` | — | — | `clean` / `forced` / `startup-failed` / `abnormal` as recorded | unchanged |
835
+ | still open | yes | — | `hot-reload` | `hot-reload`, closed at the new start |
836
+ | still open | no | changed | `handoff` | stays open; it records its own stop later |
837
+ | still open, was ready | no | same | `abnormal` (default) | `abnormal`, closed at the new start — an upper bound, the crash time is unknown |
838
+ | still open, never ready | no | same | `startup-failed` (default) | `startup-failed`, closed at the new start |
839
+
840
+ Every other open run the start finds was abandoned too and is closed the same
841
+ way — two crashes in a row leave two open runs, and both are closed, not only
842
+ the newest. Open means `active` or `draining`.
825
843
 
826
844
  A version of `unknown` on either side is never a version change, so a dev build
827
845
  after a crashed release reads `abnormal`, not `handoff`. `forced` means the
828
846
  process itself acknowledged a kill; `abnormal` means a successor found it dead.
829
847
 
830
- The last row is a choice, and the default is the single-process deployment:
848
+ ### Downtime is the window nobody answered in
849
+
850
+ `ReadyFact.downtimeMs` is `readyAt` of the new run minus `unavailableAt` of the
851
+ last run that served — the predecessor's drain plus the successor's boot. A
852
+ 110 s forced drain followed by a 4 s boot is 114 s of downtime; the gap between
853
+ the two processes alone would read 4 s before and after that defect was fixed.
854
+ Runs that never became ready answered nobody, so the count passes them: after a
855
+ failed start it still opens where the last serving run stopped answering. It is
856
+ `0` when that run still answers (a handoff whose predecessor has not drained
857
+ yet) and `null` on first boot and when the end was never timed — a crash or a
858
+ hot reload records no `unavailableAt`. `unavailableSince` names the moment it is
859
+ counted from. The gap between two processes is still there, under its own
860
+ name: `StartFact.processGapMs` is the start minus the predecessor's recorded
861
+ stop.
862
+
863
+ The ledger records what the process says while it can say it. stitchkit never
864
+ calls `process.exit` (ADR 0074), so a stop is recorded on the kernel's `close`
865
+ or `force` path, both awaited. An application that exits the process on its
866
+ own before its shutdown settles loses that last write; the successor then
867
+ finds the run open and closes it as `abnormal`, keeping the `unavailableAt`
868
+ already recorded — which is why the drain moment is written first, at
869
+ `stopAdmission`, and the downtime survives a stop that was never recorded.
870
+
871
+ The `abnormal` default is a choice, and it is the single-process deployment:
831
872
  one process per build, a new pid of the same build means the old one stopped
832
- answering. Where two processes of **one** build overlap on purpose — a
833
- cluster, a zero-downtime reload of the same build — pass
834
- `sameVersionOverlap: 'handoff'` to the ledger, and the predecessor stays
835
- `active` until it records its own shutdown. The cost of that setting is
836
- symmetric: a real crash under it is reported as a handoff and the dead run
837
- stays `active` in the ledger until retention drops it. The list is kept in the
838
- order the transitions wrote it — every write goes through one atomic update,
839
- so that order is the causal one, and a successor whose clock lags its
840
- predecessor still finds it at the head; `startedAt` is data, not the sort key.
841
- Retention (`retain`, default 20) drops finished runs first and an active one —
842
- a live handoff predecessor — only when nothing finished is left. Facts are
843
- published through the ledger's own subscription and resource value;
844
- `ApplicationEventSink` remains the strict application-state stream.
873
+ answering. Where processes of **one** build overlap on purpose — a cluster, a
874
+ zero-downtime reload of the same build — pass `sameVersionOverlap: 'handoff'`
875
+ to the ledger, and every open run stays open until it records its own
876
+ shutdown. The cost of that setting is symmetric: a real crash under it is
877
+ reported as a handoff and the dead run stays open in the ledger until
878
+ retention drops it. The list is kept in the order the transitions wrote it —
879
+ every write goes through one atomic update, so that order is the causal one,
880
+ and a successor whose clock lags its predecessor still finds it at the head;
881
+ `startedAt` is data, not the sort key. Retention (`retain`, default 20) drops
882
+ finished runs first and an open one — a live handoff predecessor — only when
883
+ nothing finished is left. Facts are published through the ledger's own
884
+ subscription and resource value; `ApplicationEventSink` remains the strict
885
+ application-state stream.
845
886
 
846
887
  `createNotificationOutbox` is the transport-neutral durable delivery side. It
847
888
  persists before send, claims an item with an expiring lease, carries one stable
@@ -878,267 +919,3 @@ so a scheduler stall on a loaded host cannot pull a live lock from under its
878
919
  holder — after which the heartbeat wins and the lock is abandoned. Temporary files a crashed writer left beside the state are swept on
879
920
  the store's first update. Ledger corruption may be declared reconstructable;
880
921
  an outbox must fail closed rather than silently discard pending delivery.
881
-
882
- ==============================================================================
883
- # Guide: Application migration recipes (docs/guide/application-migration-recipes.md)
884
- ==============================================================================
885
-
886
- ---
887
- title: Application migration recipes
888
- description: Executable patterns for moving database, poller, queue and operational publishing lifecycle into the managed application kernel.
889
- type: architecture
890
- status: active
891
- created: 2026-08-24
892
- updated: 2026-08-24
893
- ---
894
-
895
- # Application migration recipes
896
-
897
- These recipes are the migration companion to the
898
- [managed application kernel](./application-kernel.md). Their canonical source is
899
- the packed-consumer fixture
900
- [`application-migration-recipes.ts`](../../packages/core/scripts/consumer-lane/fixtures/minimal/src/application-migration-recipes.ts):
901
- the consumer lane installs the package tarball, typechecks that file and runs it
902
- only through `stitchkit/application` exports.
903
-
904
- ## Database connection
905
-
906
- Wrap connection allocation and readiness in `start`, and make `close` safe after
907
- partial setup. Stitchkit invokes cleanup for every attempted start, including a
908
- start that allocates a client and then rejects.
909
-
910
- ```ts
911
- const database = defineManagedResource({
912
- id: 'database',
913
- async start({ signal, reportHealth }) {
914
- await databaseClient.connect(signal)
915
- await databaseClient.assertReady()
916
- reportHealth('healthy')
917
- },
918
- close: () => databaseClient.close(),
919
- })
920
- ```
921
-
922
- The application still owns the client, ORM configuration, transactions,
923
- migrations and reconnect policy. The executable recipe deliberately fails after
924
- allocation and proves one rollback close.
925
-
926
- ## Long-running poller
927
-
928
- Return separate readiness and completion promises. Readiness says dependants may
929
- start; completion represents the whole background lifetime.
930
-
931
- ```ts
932
- const poller = defineManagedResource({
933
- id: 'poller',
934
- start: ({ signal }) => ({
935
- ready: providerPoller.ready,
936
- completion: providerPoller.run(signal),
937
- }),
938
- stopAdmission: () => providerPoller.stop(),
939
- drain: () => providerPoller.completion,
940
- close: () => providerPoller.close(),
941
- })
942
- ```
943
-
944
- Completion before readiness fails startup and rolls back. Completion after
945
- readiness removes application readiness. Provider cursor persistence, retry,
946
- backoff and restart policy remain application/provider concerns.
947
-
948
- ## Queue consumer
949
-
950
- Acquire the application lease only after provider delivery/claim. If admission
951
- is already closed, reject the delivery through the provider's own nack/requeue
952
- primitive. Work admitted before shutdown releases its lease after ack/nack and
953
- therefore participates in application drain.
954
-
955
- ```ts
956
- async function handleDelivery(delivery: Delivery) {
957
- const lease = app.admission.acquire()
958
- if (!lease) return delivery.nack({ requeue: true })
959
- try {
960
- await processClaim(delivery.claim)
961
- await delivery.ack()
962
- } catch (error) {
963
- await delivery.nack({ requeue: shouldRetry(error) })
964
- throw error
965
- } finally {
966
- lease.release()
967
- }
968
- }
969
- ```
970
-
971
- Stitchkit owns only process-local admission accounting and drain. Durable claims,
972
- visibility timeouts, deduplication, idempotency and retry classification remain
973
- in the queue/product layer.
974
-
975
- ## Operational publisher
976
-
977
- Project anonymous aggregate activity, then feed absolute snapshots into the
978
- latest-value sink. A slow transport holds one write plus one replaceable latest
979
- revision rather than an unbounded event queue.
980
-
981
- ```ts
982
- const publisher = createApplicationSnapshotSink({
983
- write: (snapshot) => monitoring.publish(snapshot),
984
- })
985
- const activity = createActivityProjection({
986
- id: 'generation',
987
- stages: ['queued', 'running'],
988
- })
989
- const unsubscribe = activity.subscribe((snapshot) => {
990
- publisher.publish(snapshot)
991
- })
992
-
993
- // cleanup boundary
994
- unsubscribe()
995
- publisher.publish(activity.getSnapshot())
996
- await publisher.close()
997
- ```
998
-
999
- The monitoring backend, transport retry and cross-process aggregation remain
1000
- outside Stitchkit. The executable recipe blocks revision 0, coalesces
1001
- intermediate revisions, explicitly admits the final absolute snapshot after
1002
- unsubscribe and proves that `close()` flushes revision 3. Do not rely on an
1003
- asynchronous subscriber callback racing cleanup: publish `getSnapshot()` before
1004
- closing the outer sink, so any older or duplicate late delivery is rejected as
1005
- stale instead of dropping the final state.
1006
-
1007
- ## Bound a handler and a local worker with one lease policy
1008
-
1009
- Use a bounded admission when two entry paths consume the same finite local
1010
- capacity. Composing it with `application.admission` keeps readiness and shutdown
1011
- as the upstream gate:
1012
-
1013
- ```ts
1014
- const work = createBoundedAdmission({
1015
- upstream: app.admission,
1016
- policy: {
1017
- global: { maxConcurrent: 4 },
1018
- perKey: { maxConcurrent: 1, maxKeys: 1_000 },
1019
- },
1020
- })
1021
-
1022
- const fromHttp = (key: string, signal: AbortSignal) =>
1023
- work.run(key, (context) => render(context.signal), { signal, timeoutMs: 20_000 })
1024
-
1025
- const fromWorker = (key: string) =>
1026
- work.run(key, (context) => reconcile(context.signal))
1027
- ```
1028
-
1029
- A timeout in `fromHttp` does not free a permit while `render` remains active.
1030
- At shutdown call `work.stopAdmission()` with the other admission owners and
1031
- await `work.drain(...)`; the result reports the actual remainder.
1032
-
1033
- ## Replace ad-hoc output and progress queues
1034
-
1035
- Ordered output and replaceable progress are separate declarations:
1036
-
1037
- ```ts
1038
- const lines = createBoundedChannel<string>({
1039
- policy: 'ordered', maxItems: 100, maxBytes: 1_000_000,
1040
- sizeOf: (line) => new TextEncoder().encode(line).byteLength,
1041
- })
1042
-
1043
- const state = createBoundedChannel<{ revision: number; percent: number }>({
1044
- policy: 'latest', maxItems: 1, maxBytes: 64,
1045
- sizeOf: () => 64,
1046
- })
1047
-
1048
- const lineResult = lines.offer('one durable-in-process ordering unit')
1049
- const stateResult = state.offer({ revision: 2, percent: 50 })
1050
- ```
1051
-
1052
- Handle `refused` from `lines` at the protocol boundary; do not turn it into
1053
- implicit loss. A `coalesced` state result is expected latest-value behaviour,
1054
- not evidence that an ordered event was delivered. Neither channel is durable;
1055
- persist first when restart replay is required.
1056
-
1057
- ## Handing a handle to the resources that depend on it
1058
-
1059
- `dependsOn` carries ordering. To carry the object as well, return a `value` from
1060
- `start` and read it with `context.use(...)`. This replaces the module-local
1061
- `let handle: T | null` with the guard the graph makes unreachable.
1062
-
1063
- ```ts
1064
- const database = defineManagedResource({
1065
- id: 'database',
1066
- start: async () => ({ value: await connect(env.DATABASE_URL) }),
1067
- })
1068
-
1069
- const worker = defineManagedResource({
1070
- id: 'worker',
1071
- dependsOn: [database],
1072
- start(context) {
1073
- const db = context.use(database) // Connection — not Connection | null
1074
- },
1075
- })
1076
- ```
1077
-
1078
- Declare the dependency with the **resource** whenever you intend to read from
1079
- it: that is the form `use` can type, and it stops the declaration and the read
1080
- from drifting. A string still expresses order on its own.
1081
-
1082
- The value is published when `start` resolves and stays readable from `activate`
1083
- and from the shutdown phases. `use` refuses a resource that was not declared in
1084
- `dependsOn` — that only ever worked by luck of declaration order — and refuses a
1085
- resource that published nothing, which the compiler refuses too. The executable
1086
- recipe proves both the read and the refusal.
1087
-
1088
- ## Managed HTTP server
1089
-
1090
- The main resource of a web backend, and the one whose ownership rule is
1091
- counter-intuitive: give `managedServerResource` a **thunk** and it creates the
1092
- server during `start`, after its dependencies are ready. Give it an
1093
- already-listening server and it adopts that one instead.
1094
-
1095
- ```ts
1096
- const http = managedServerResource({
1097
- id: 'http',
1098
- dependsOn: [database],
1099
- server: (context) => {
1100
- const db = context.use(database)
1101
- return createServer({ port: env.PORT, services: createServices(db) })
1102
- },
1103
- })
1104
-
1105
- const app = createApplication({ id: 'service', resources: [database, http] })
1106
- await app.start() // the port is bound; the snapshot means it
1107
- ```
1108
-
1109
- The server resource publishes its `ManagedServerHandle`, so anything that needs
1110
- the running server — a Socket.IO attachment, a URL to log, a probe — reads it
1111
- with `context.use(http)` rather than through a module-local.
1112
-
1113
- The factory itself receives `ManagedResourceContext` too. It can read only the
1114
- dependencies declared on the server resource and shares the graph's startup
1115
- signal. A dependency failure prevents the factory from binding; a factory
1116
- rejection is rolled back without invoking the factory a second time.
1117
-
1118
- Do not spread this resource over your own `start` to control creation order:
1119
- that shape exists only as a workaround for the version whose `start` was empty,
1120
- and `dependsOn` now expresses the order directly. The executable recipe binds a
1121
- real port, proves a request reaches it after `start()` resolves, and proves the
1122
- port is closed after `shutdown()`.
1123
-
1124
- ## Deletion checklist
1125
-
1126
- After the cutover, remove the old generic lifecycle path completely:
1127
-
1128
- - duplicate `process.on(...)` handlers and shutdown promise caches;
1129
- - manual readiness waiters and resource close fan-out;
1130
- - raw interval handles, overlap flags and timer drain code;
1131
- - global in-flight counters and waiter sets replaced by application leases;
1132
- - progress delta queues replaced by absolute snapshot publishing.
1133
-
1134
- Keep the product code that still owns durable state and policy:
1135
-
1136
- - database schema, transactions and migrations;
1137
- - queue claims, ack/nack, deduplication and external-effect idempotency;
1138
- - provider cursor, retry/backoff and credentials;
1139
- - monitoring transport configuration and durable retention;
1140
- - process exit code, hard-exit and deployment/supervisor policy.
1141
-
1142
- Run the old and new lifecycle paths separately during development if needed,
1143
- but do not ship both. Before cutover, verify there is exactly one signal binding,
1144
- one timer owner, one admission gate and one resource cleanup chain.