stitchkit 0.103.12 → 0.104.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 (225) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/darwin-native.cjs +12 -0
  3. package/darwin-native.d.cts +2 -0
  4. package/dist/agent-runtime/store-conformance-lifecycle.d.ts +10 -10
  5. package/dist/application/directory-inbox-accept.d.ts +13 -0
  6. package/dist/application/directory-inbox-accept.d.ts.map +1 -0
  7. package/dist/application/directory-inbox-contract.d.ts +42 -5
  8. package/dist/application/directory-inbox-contract.d.ts.map +1 -1
  9. package/dist/application/directory-inbox-delivery.d.ts +14 -0
  10. package/dist/application/directory-inbox-delivery.d.ts.map +1 -0
  11. package/dist/application/directory-inbox-files.d.ts +28 -0
  12. package/dist/application/directory-inbox-files.d.ts.map +1 -0
  13. package/dist/application/directory-inbox-state.d.ts +14 -0
  14. package/dist/application/directory-inbox-state.d.ts.map +1 -0
  15. package/dist/application/directory-inbox.d.ts +2 -1
  16. package/dist/application/directory-inbox.d.ts.map +1 -1
  17. package/dist/application/file-state-store.d.ts +2 -8
  18. package/dist/application/file-state-store.d.ts.map +1 -1
  19. package/dist/application/state-store.d.ts +6 -1
  20. package/dist/application/state-store.d.ts.map +1 -1
  21. package/dist/browser/client-arguments.d.ts +4 -0
  22. package/dist/browser/client-arguments.d.ts.map +1 -0
  23. package/dist/browser/client-executors.d.ts.map +1 -1
  24. package/dist/browser/client.d.ts.map +1 -1
  25. package/dist/browser/contract-stream.d.ts.map +1 -1
  26. package/dist/browser/http.d.ts +2 -1
  27. package/dist/browser/http.d.ts.map +1 -1
  28. package/dist/browser/native-fetch.d.ts +8 -0
  29. package/dist/browser/native-fetch.d.ts.map +1 -0
  30. package/dist/contract/errors.d.ts +16 -12
  31. package/dist/contract/errors.d.ts.map +1 -1
  32. package/dist/contract/normalize.d.ts +5 -1
  33. package/dist/contract/normalize.d.ts.map +1 -1
  34. package/dist/contract/stream.d.ts +1 -0
  35. package/dist/contract/stream.d.ts.map +1 -1
  36. package/dist/entrypoints/agent-runtime/browser.js +3 -3
  37. package/dist/entrypoints/agent-runtime/coding-tools.js +8 -6
  38. package/dist/entrypoints/agent-runtime/harness-tools.js +8 -8
  39. package/dist/entrypoints/agent-runtime/harness.js +12 -11
  40. package/dist/entrypoints/agent-runtime/realtime.js +3 -3
  41. package/dist/entrypoints/agent-runtime/sandbox.js +8 -6
  42. package/dist/entrypoints/agent-runtime.js +13 -13
  43. package/dist/entrypoints/application/diagnostic-journal.js +3 -2
  44. package/dist/entrypoints/application/directory-inbox.js +424 -119
  45. package/dist/entrypoints/application/grammy.js +1 -1
  46. package/dist/entrypoints/application.d.ts +2 -2
  47. package/dist/entrypoints/application.d.ts.map +1 -1
  48. package/dist/entrypoints/application.js +7 -3
  49. package/dist/entrypoints/cli.d.ts +2 -0
  50. package/dist/entrypoints/cli.d.ts.map +1 -1
  51. package/dist/entrypoints/cli.js +757 -136
  52. package/dist/entrypoints/contract.js +3 -3
  53. package/dist/entrypoints/files.js +11 -107
  54. package/dist/entrypoints/index.js +7 -7
  55. package/dist/entrypoints/node.js +8 -8
  56. package/dist/entrypoints/observability.js +2 -2
  57. package/dist/entrypoints/process.js +2 -1
  58. package/dist/entrypoints/react.js +1 -1
  59. package/dist/entrypoints/remote.js +19 -6
  60. package/dist/entrypoints/server.d.ts +1 -1
  61. package/dist/entrypoints/server.d.ts.map +1 -1
  62. package/dist/entrypoints/server.js +20 -14
  63. package/dist/entrypoints/telegram.d.ts +1 -0
  64. package/dist/entrypoints/telegram.d.ts.map +1 -1
  65. package/dist/entrypoints/telegram.js +214 -98
  66. package/dist/entrypoints/testing.js +7 -7
  67. package/dist/entrypoints/tools/connections.d.ts +2 -2
  68. package/dist/entrypoints/tools/connections.d.ts.map +1 -1
  69. package/dist/entrypoints/tools/connections.js +427 -294
  70. package/dist/entrypoints/tools/invoker.js +6 -6
  71. package/dist/entrypoints/tools/mcp.d.ts +12 -0
  72. package/dist/entrypoints/tools/mcp.d.ts.map +1 -0
  73. package/dist/entrypoints/tools/mcp.js +45 -0
  74. package/dist/entrypoints/tools.d.ts +1 -0
  75. package/dist/entrypoints/tools.d.ts.map +1 -1
  76. package/dist/entrypoints/tools.js +82 -1147
  77. package/dist/entrypoints/tracking.js +1 -1
  78. package/dist/files/boundary.d.ts +2 -8
  79. package/dist/files/boundary.d.ts.map +1 -1
  80. package/dist/files/file-io.d.ts +0 -5
  81. package/dist/files/file-io.d.ts.map +1 -1
  82. package/dist/files/read.d.ts +2 -2
  83. package/dist/files/read.d.ts.map +1 -1
  84. package/dist/index-1a6jtnd9.js +88 -0
  85. package/dist/{index-fyphpknh.js → index-22rhg58f.js} +1 -1
  86. package/dist/index-269zqj8m.js +77 -0
  87. package/dist/{index-r34mvse1.js → index-27a2pj09.js} +1 -1
  88. package/dist/{index-r956rndn.js → index-2hyavjjj.js} +3 -3
  89. package/dist/{index-m2xqkv55.js → index-2vnh05w4.js} +83 -14
  90. package/dist/{index-pw99k9h5.js → index-43p08g7t.js} +1 -1
  91. package/dist/{index-xwq9j1sf.js → index-4e0ah203.js} +9 -7
  92. package/dist/{index-nybn2err.js → index-5csmzesf.js} +1 -1
  93. package/dist/{index-qapzv4p5.js → index-5z6jn897.js} +1 -1
  94. package/dist/{index-ahvsksw5.js → index-6d9xaxw1.js} +1 -1
  95. package/dist/{index-ahtnte39.js → index-6drst9sg.js} +46 -35
  96. package/dist/{index-x87j7csh.js → index-77nxk6ay.js} +2 -2
  97. package/dist/{index-dnn9z96q.js → index-a0zzh8ak.js} +3 -3
  98. package/dist/{index-kmpzj1cq.js → index-a3wma1hk.js} +1 -1
  99. package/dist/{index-j8aw2c0e.js → index-bakgedh8.js} +35 -7
  100. package/dist/index-bhb950qs.js +1145 -0
  101. package/dist/{index-tgzhq07n.js → index-cvda079a.js} +1 -1
  102. package/dist/{index-n2gre124.js → index-fa4wg312.js} +4 -4
  103. package/dist/{index-zp4jpkp0.js → index-fk18k56k.js} +2 -2
  104. package/dist/{index-afjvjyck.js → index-g2j7pnak.js} +2 -134
  105. package/dist/index-g95fk660.js +116 -0
  106. package/dist/{index-ej331hah.js → index-gxm9rc97.js} +1 -1
  107. package/dist/{index-r5c4fedv.js → index-h2fhjqy7.js} +2 -1
  108. package/dist/{index-sybedc8b.js → index-hbd32c6a.js} +23 -94
  109. package/dist/index-jd470k6q.js +109 -0
  110. package/dist/{index-b2bz0kdm.js → index-kb8styz3.js} +4 -3
  111. package/dist/{index-0c419yx7.js → index-kemm0ej5.js} +12 -9
  112. package/dist/{index-806d5phm.js → index-ptn0g0gj.js} +7 -7
  113. package/dist/{index-w575evhq.js → index-r4r70zmh.js} +1 -1
  114. package/dist/{index-12m2v2a9.js → index-s4evrmp5.js} +1 -1
  115. package/dist/{index-1khy8y7n.js → index-t1sr4aks.js} +3 -3
  116. package/dist/index-v5ee8ath.js +88 -0
  117. package/dist/{index-45tdvqa3.js → index-wh0ecvyk.js} +1 -1
  118. package/dist/{index-n53mswt3.js → index-x928baz2.js} +8 -1
  119. package/dist/index-yk4g8805.js +133 -0
  120. package/dist/{index-ygkka6zn.js → index-ywppsaby.js} +28 -5
  121. package/dist/{index-xvdd2rbb.js → index-za6j7nwy.js} +19 -5
  122. package/dist/internal/bounded-file-read.d.ts +41 -0
  123. package/dist/internal/bounded-file-read.d.ts.map +1 -0
  124. package/dist/internal/darwin-binding-error.d.ts +24 -0
  125. package/dist/internal/darwin-binding-error.d.ts.map +1 -0
  126. package/dist/internal/darwin-binding.d.ts.map +1 -1
  127. package/dist/internal/exclusive-lock.d.ts +2 -0
  128. package/dist/internal/exclusive-lock.d.ts.map +1 -1
  129. package/dist/internal/with-exclusive-lock.d.ts +4 -2
  130. package/dist/internal/with-exclusive-lock.d.ts.map +1 -1
  131. package/dist/telegram/broadcast-delivery.d.ts +23 -0
  132. package/dist/telegram/broadcast-delivery.d.ts.map +1 -0
  133. package/dist/telegram/broadcast-failure.d.ts +22 -0
  134. package/dist/telegram/broadcast-failure.d.ts.map +1 -0
  135. package/dist/telegram/broadcast-state.d.ts +6 -3
  136. package/dist/telegram/broadcast-state.d.ts.map +1 -1
  137. package/dist/telegram/broadcast.d.ts +10 -5
  138. package/dist/telegram/broadcast.d.ts.map +1 -1
  139. package/dist/tools/cli/args-fields.d.ts +2 -0
  140. package/dist/tools/cli/args-fields.d.ts.map +1 -1
  141. package/dist/tools/cli/args.d.ts.map +1 -1
  142. package/dist/tools/cli/format.d.ts.map +1 -1
  143. package/dist/tools/cli/invoke.d.ts +2 -2
  144. package/dist/tools/cli/invoke.d.ts.map +1 -1
  145. package/dist/tools/cli/publication-assets.d.ts +10 -0
  146. package/dist/tools/cli/publication-assets.d.ts.map +1 -0
  147. package/dist/tools/cli/publication-contract.d.ts +75 -0
  148. package/dist/tools/cli/publication-contract.d.ts.map +1 -0
  149. package/dist/tools/cli/publication-control.d.ts +4 -0
  150. package/dist/tools/cli/publication-control.d.ts.map +1 -0
  151. package/dist/tools/cli/publication-storage.d.ts +32 -0
  152. package/dist/tools/cli/publication-storage.d.ts.map +1 -0
  153. package/dist/tools/cli/publication.d.ts +35 -0
  154. package/dist/tools/cli/publication.d.ts.map +1 -0
  155. package/dist/tools/cli/update.d.ts.map +1 -1
  156. package/dist/tools/connections/define.d.ts.map +1 -1
  157. package/dist/tools/connections/error-projection.d.ts +4 -0
  158. package/dist/tools/connections/error-projection.d.ts.map +1 -0
  159. package/dist/tools/connections/errors.d.ts +24 -8
  160. package/dist/tools/connections/errors.d.ts.map +1 -1
  161. package/dist/tools/connections/limits.d.ts +11 -31
  162. package/dist/tools/connections/limits.d.ts.map +1 -1
  163. package/dist/tools/connections/mcp-client.d.ts +6 -4
  164. package/dist/tools/connections/mcp-client.d.ts.map +1 -1
  165. package/dist/tools/connections/mcp.d.ts.map +1 -1
  166. package/dist/tools/connections/openapi.d.ts.map +1 -1
  167. package/dist/tools/connections/operation-limits.d.ts +25 -0
  168. package/dist/tools/connections/operation-limits.d.ts.map +1 -0
  169. package/dist/tools/connections/sse-frames.d.ts +11 -2
  170. package/dist/tools/connections/sse-frames.d.ts.map +1 -1
  171. package/dist/tools/connections/sse-session.d.ts +15 -2
  172. package/dist/tools/connections/sse-session.d.ts.map +1 -1
  173. package/dist/tools/connections/types.d.ts +19 -1
  174. package/dist/tools/connections/types.d.ts.map +1 -1
  175. package/dist/tools/execute-result.d.ts.map +1 -1
  176. package/dist/tools/execute.d.ts.map +1 -1
  177. package/dist/tools/internal/observe-hook.d.ts +3 -0
  178. package/dist/tools/internal/observe-hook.d.ts.map +1 -0
  179. package/dist/tools/internal/surface-projector.d.ts +2 -1
  180. package/dist/tools/internal/surface-projector.d.ts.map +1 -1
  181. package/dist/tools/mcp/mount.d.ts +2 -2
  182. package/dist/tools/mcp/mount.d.ts.map +1 -1
  183. package/dist/tools/mcp/prepare.d.ts +4 -5
  184. package/dist/tools/mcp/prepare.d.ts.map +1 -1
  185. package/dist/tools/mcp/register.d.ts +4 -1
  186. package/dist/tools/mcp/register.d.ts.map +1 -1
  187. package/dist/tools/mcp/runtime-tools.d.ts.map +1 -1
  188. package/dist/tools/remote.d.ts.map +1 -1
  189. package/dist/tools/runtime-tool-execution.d.ts +65 -0
  190. package/dist/tools/runtime-tool-execution.d.ts.map +1 -0
  191. package/dist/tools/runtime-tool-mcp.d.ts +27 -0
  192. package/dist/tools/runtime-tool-mcp.d.ts.map +1 -0
  193. package/dist/tools/runtime-tool.d.ts +9 -60
  194. package/dist/tools/runtime-tool.d.ts.map +1 -1
  195. package/dist/tools/surface.d.ts +12 -14
  196. package/dist/tools/surface.d.ts.map +1 -1
  197. package/llms/application.2.txt +221 -44
  198. package/llms/application.3.txt +3 -1
  199. package/llms/application.txt +1 -1
  200. package/llms/cli.2.txt +144 -1
  201. package/llms/cli.txt +133 -104
  202. package/llms/contract.txt +1 -1
  203. package/llms/process.txt +34 -5
  204. package/llms/server.4.txt +4 -1
  205. package/llms/server.5.txt +1 -0
  206. package/llms/stitchkit.2.txt +14 -0
  207. package/llms/stitchkit.txt +5 -4
  208. package/llms/telegram.txt +64 -2
  209. package/llms/tools-connections.txt +3 -0
  210. package/llms/tools-mcp.txt +29 -0
  211. package/llms/tools.2.txt +59 -0
  212. package/llms/tools.3.txt +1 -0
  213. package/llms/tools.txt +11 -52
  214. package/llms/upgrading-0.37.0-0.44.0.txt +444 -0
  215. package/llms/{upgrading-0.44.0-0.60.0.txt → upgrading-0.44.0-0.61.0.txt} +140 -271
  216. package/llms/{upgrading-0.61.0-0.74.0.txt → upgrading-0.62.0-0.79.0.txt} +171 -140
  217. package/llms/{upgrading-0.75.0-0.103.0.txt → upgrading-0.80.0-0.104.0.txt} +120 -171
  218. package/llms/upgrading.txt +4 -4
  219. package/llms-full.txt +677 -64
  220. package/llms.txt +13 -12
  221. package/package.json +10 -1
  222. package/dist/index-d4pa2bgs.js +0 -42
  223. package/dist/index-wykebpn9.js +0 -221
  224. package/llms/upgrading-0.37.0.txt +0 -176
  225. package/dist/{index-69nvze1q.js → index-pptyv13k.js} +3 -3
@@ -1,14 +1,182 @@
1
- # Upgrading 0.61.0 → 0.74.0 — stitchkit docs slice
1
+ # Upgrading 0.62.0 → 0.79.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.61.0 → 0.74.0 (docs/guide/upgrading.md)
6
+ Contains: Guide: Upgrading, 0.62.0 → 0.79.0 (docs/guide/upgrading.md)
7
7
 
8
8
  ==============================================================================
9
- # Guide: Upgrading, 0.61.0 → 0.74.0 (docs/guide/upgrading.md)
9
+ # Guide: Upgrading, 0.62.0 → 0.79.0 (docs/guide/upgrading.md)
10
10
  ==============================================================================
11
11
 
12
+ ## Released migration: 0.79.0
13
+
14
+ One thing, and only if you assert on the whole snapshot.
15
+
16
+ ```bash
17
+ rg -n "getSnapshot\(\)|projectApplicationStatus|status\(\)" --glob '*.test.ts' --glob '*.spec.ts'
18
+ ```
19
+
20
+ `ApplicationSnapshot` and `ApplicationStatusProjection` each gained a
21
+ `restarting` field — ids in the snapshot, a count in the projection. A reader
22
+ that names the fields it wants is unaffected. A test that compares the whole
23
+ object with `toEqual` fails until it adds the field:
24
+
25
+ ```ts
26
+ // before
27
+ expect(body).toEqual({ id, lifecycle: 'ready', /* … */ resources: { total: 1, ready: 1, degraded: 0, failed: 0 } })
28
+ // after
29
+ expect(body).toEqual({ id, lifecycle: 'ready', /* … */ resources: { total: 1, ready: 1, degraded: 0, failed: 0 }, restarting: 0 })
30
+ ```
31
+
32
+ It is zero except while a restart is running, and then it names the subtree being
33
+ replaced. That is the point: a snapshot taken mid-restart used to be
34
+ indistinguishable from a resource that had failed on its own, so a dashboard read
35
+ a planned replacement as an outage.
36
+
37
+ **If you watch a hub across a restart**, nothing to change, but the behaviour is
38
+ different and better: closing a hub now tells its subscribers `unavailable` /
39
+ `source-unavailable` instead of dropping them, so a page stops showing a value
40
+ that will never update again.
41
+
42
+ **If you need a tool contract in a browser**, `stitchkit/tools/contract` now
43
+ carries the async-operation helpers, its schemas and the view-file input/output
44
+ without the runtime. `stitchkit/tools` still exports all of them.
45
+
46
+ ## Released migration: 0.78.0
47
+
48
+ Two mechanical edits. Find them both:
49
+
50
+ ```bash
51
+ rg -n "createDecisionPipeline|createDiagnosticJournal" --glob '*.ts' --glob '*.tsx'
52
+ ```
53
+
54
+ **1. `createDecisionPipeline` takes a deadline.**
55
+
56
+ ```ts
57
+ // before
58
+ createDecisionPipeline([policyA, policyB])
59
+ // after
60
+ createDecisionPipeline([policyA, policyB], { policyTimeoutMs: 2_000 })
61
+ ```
62
+
63
+ Pick a number your slowest policy comfortably beats. There is no default on
64
+ purpose: a policy that never settles hangs every caller of the operation it
65
+ guards, and the framework has no basis for choosing that number for you.
66
+
67
+ Past the deadline — and on a throw, and on a non-decision — the pipeline raises
68
+ `DecisionPolicyError` naming the policy, with the trace so far. If you already
69
+ catch that for a bad return value, you now catch two more cases with it.
70
+
71
+ **2. `createDiagnosticJournal` moved.**
72
+
73
+ ```ts
74
+ // before
75
+ import { createDiagnosticJournal } from 'stitchkit/application'
76
+ // after
77
+ import { createDiagnosticJournal } from 'stitchkit/application/diagnostic-journal'
78
+ ```
79
+
80
+ Only the factory moved. `DiagnosticJournalConfig`, every
81
+ `DiagnosticJournal*Schema` and `readDiagnosticJournalLockDiagnosis` stay where
82
+ they were.
83
+
84
+ **If you restart resources**, nothing to change — but three things that did not
85
+ work now do: a managed schedule can be restarted, a restarted keyspace accepts
86
+ writes again, and a restarted managed server is actually shut down at exit. If
87
+ you pass `managedServerResource` a server *instance*, a restart is now refused
88
+ by name; pass a factory (`server: (context) => …`) to restart it.
89
+
90
+ ## Released migration: 0.77.0
91
+
92
+ Two type renames, and only if you named them. Nothing runtime moved.
93
+
94
+ ```bash
95
+ rg -n "EventDecision|EventUndecided" --glob '*.ts' --glob '*.tsx'
96
+ ```
97
+
98
+ ```ts
99
+ // before
100
+ import type { EventDecision, EventUndecided } from 'stitchkit/live'
101
+ // after
102
+ import type { PolicyDecision, UndecidedOutcome } from 'stitchkit/live'
103
+ ```
104
+
105
+ The shapes are identical — `{ outcome: 'allow' } | { outcome: 'deny', reason } | { outcome: 'defer' }`
106
+ and `'allow' | 'deny'`. If you only ever *return* decisions from listeners and never named the
107
+ type, the search above finds nothing and there is nothing to do.
108
+
109
+ They were renamed because `createDecisionPipeline` (new in this release) votes with exactly the
110
+ same three outcomes, and two identical types under two names is the thing that makes a search for
111
+ either one return half the truth.
112
+
113
+ ## Released migration: 0.76.0
114
+
115
+ One change, and only if you hand `createWatchClient` a transport you wrote yourself.
116
+
117
+ ```bash
118
+ rg -n "createWatchClient" --glob '*.ts'
119
+ ```
120
+
121
+ If the `transport:` you pass is a bound realtime client — `bindRealtimeClient(...)` or
122
+ `createRealtimeClient(...)` — there is nothing to do: it already carries
123
+ `onConnectionChange`. If it is an object you assembled, add the fourth member:
124
+
125
+ ```ts
126
+ onConnectionChange(listener: (connected: boolean, reason?: string) => void): () => void
127
+ ```
128
+
129
+ It is required because the client recovers through it: on a drop it publishes
130
+ `unavailable` to subscribers and forgets what was opened, and on a fresh
131
+ connection it re-opens every key that still has a listener. Without it a watch
132
+ stays "open" on the client after a server restart while the hub remembers
133
+ nothing, and the face stops updating without saying so.
134
+
135
+ ## Released migration: 0.75.0
136
+
137
+ Two mechanical renames and one option that has to move. Nothing about a passing
138
+ request changes.
139
+
140
+ ### 1. A route group's `onRequest`
141
+
142
+ ```bash
143
+ rg -n "hooks:\s*\{[^}]*onRequest" --glob '*.ts'
144
+ ```
145
+
146
+ Any match **inside a `groups: [...]` entry** must move. The hook was accepted and
147
+ never dispatched, so the behaviour you have today is "no hook"; the fix is to
148
+ decide which one you meant:
149
+
150
+ ```ts
151
+ // refuse before dispatch, for the whole server
152
+ createServer({ groups, hooks: { onRequest: gate } });
153
+
154
+ // gate this group once the endpoint is known
155
+ groups: [{ pathPrefix: '/admin', services, hooks: { authorize: gate } }]
156
+ ```
157
+
158
+ A group that still declares `onRequest` fails at startup with that message.
159
+
160
+ ### 2. The SQLite boundary type
161
+
162
+ ```bash
163
+ rg -l "AgentRuntimeSqlite(Database|Statement|Value)" | xargs sed -i \
164
+ -e 's/AgentRuntimeSqliteDatabase/SqliteDatabase/g' \
165
+ -e 's/AgentRuntimeSqliteStatement/SqliteStatement/g' \
166
+ -e 's/AgentRuntimeSqliteValue/SqliteValue/g'
167
+ ```
168
+
169
+ Type-only: the same three methods, the same structural compatibility with
170
+ `bun:sqlite` and a `node:sqlite` wrapper, imported from the same entrypoints.
171
+ `initializeAgentRuntimeSqlite` keeps its name — it really is the agent runtime's
172
+ schema.
173
+
174
+ ### 3. Nothing else
175
+
176
+ `stitchkit/live`, the watch hub, the keyspace and the trust fence are all
177
+ additive. Adopt them when you want them; the guide is
178
+ [Live data](./live.md).
179
+
12
180
  ## Released migration: 0.74.0
13
181
 
14
182
  One change, and it only reaches you if you catch a refusal the **client** raised — one it made while
@@ -957,140 +1125,3 @@ exhaustively on any of those enums, add the arm** — that is the part of this
957
1125
  release that can break a build rather than a behaviour. The record itself is
958
1126
  kept: it is excluded from the projection, not deleted, so an operator can still
959
1127
  see what was thrown away.
960
-
961
- ## Released migration: 0.61.0
962
-
963
- Three behaviour changes between versions. None moves an export — the surface is
964
- strictly additive — and all three change what a running system does, which is
965
- what this heading is for.
966
-
967
- ### A failed `start()` now drains before it rejects
968
-
969
- The rollback of a failed startup used to close every resource with a zero
970
- budget: it returned almost at once, by severing requests the server had already
971
- accepted. It now spends the application's shutdown budget, so a request already
972
- in flight is answered rather than killed.
973
-
974
- **What to check.** Nothing, if a failed startup has nothing in flight — the
975
- rollback still returns immediately. The case to think about is a request that
976
- never finishes: a hung upstream, a client ignoring a close frame, a streaming
977
- subscription. Under the default 30s grace and 5s force, a `start()` that used to
978
- reject in milliseconds can now take 35 seconds to reject.
979
-
980
- If a fast failure matters more than draining — a supervisor waiting to restart,
981
- a boot check in CI — declare a smaller budget. The same field is the default for
982
- `shutdown()` with no options, so this is one decision, not two:
983
-
984
- ```ts
985
- // before
986
- createApplication({ id: 'app', resources })
987
-
988
- // after
989
- createApplication({
990
- id: 'app',
991
- resources,
992
- shutdown: { gracePeriodMs: 5_000, forceTimeoutMs: 1_000 },
993
- })
994
- ```
995
-
996
- The budget is a real bound: a `close` that never returns is abandoned when it
997
- runs out and reported as a `close` failure, and the startup error remains the
998
- `cause` of the `AggregateError` `start()` rejects with. → ADR 0107
999
-
1000
- ### A refused realtime frame now answers its sender
1001
-
1002
- A frame that fails the receiver's `args` schema used to be dropped where it
1003
- landed. If the event carries an acknowledgement, the receiver now answers it
1004
- with a reserved envelope and the sender's `request()` rejects at once with
1005
- `RealtimeRequestRejectedError`. → ADR 0106
1006
-
1007
- **What to check before you upgrade one half of a distributed pair.** Look at the
1008
- `ack` schemas on the OLDER peer:
1009
-
1010
- ```ts
1011
- // safe: a contract-first acknowledgement refuses the envelope, so the older
1012
- // peer raises RealtimeRequestInvalidAcknowledgementError at once instead of
1013
- // waiting out its deadline. Different error, still an error, and sooner.
1014
- ack: z.object({ stored: z.boolean() })
1015
-
1016
- // NOT safe: a schema that validates nothing accepts the refusal AS A VALUE.
1017
- // The older peer reads a refusal as a successful acknowledgement — silently.
1018
- ack: z.unknown()
1019
- ack: z.looseObject({})
1020
- ```
1021
-
1022
- If any acknowledgement on the older side is permissive, tighten it before the
1023
- rollout, or upgrade both halves together.
1024
-
1025
- Also: the receiver now invokes the peer's raw acknowledgement callback for a
1026
- refused frame, including when the peer is a plain Socket.IO client. That
1027
- callback previously could not run on a refused frame and now can.
1028
-
1029
- `RealtimeRejectedEvent['reason']` gained `'rejected-by-peer'`. If you `switch`
1030
- over it exhaustively with an `assertNever` default, that stops compiling — add
1031
- the case.
1032
-
1033
- ### Two smaller behaviour changes, easy to miss
1034
-
1035
- **`streamSSE`'s `cancel` no longer awaits the generator.** Teardown is now
1036
- unordered relative to request completion. If your generator releases a resource
1037
- in `return()`/`finally` — a temp file, a pooled connection — and anything
1038
- downstream assumed that had finished by the time the response settled, it no
1039
- longer has. Release in the generator's own `finally` and do not depend on the
1040
- ordering.
1041
-
1042
- **A `socket.io-client` peer that cannot load no longer kills the process.** With
1043
- `onConnectError` configured, the failure is delivered there with
1044
- `terminal: true` instead of crashing. If your handler logs and moves on, you now
1045
- have a live process whose client will never connect, where a supervisor used to
1046
- restart it. Treat `terminal: true` as fatal if that is what you want.
1047
-
1048
- ### `reportHealth` inside `start` is no longer discarded
1049
-
1050
- Becoming ready assigned `healthy` unconditionally, throwing away whatever a
1051
- resource reported during `start`. It is now kept, and only a resource that
1052
- reported nothing is assumed healthy.
1053
-
1054
- **How to find what this touches:** grep your `start` bodies for **every**
1055
- `reportHealth` call, not only the ones reporting `degraded`. The old
1056
- unconditional assignment was also a repair — a resource that reported
1057
- `'unhealthy'` early in `start` and never corrected itself was quietly fixed up
1058
- on the way to ready.
1059
-
1060
- Two cases, and they need opposite fixes.
1061
-
1062
- **1. A resource that is genuinely expected to start degraded** — up, but still
1063
- dialling something external. `required` defaults to **`true`**, and readiness
1064
- requires every required resource to be healthy, so such a resource now refuses
1065
- the whole startup where before its report vanished. That is the invariant
1066
- working as intended; what changed is that it can be reached. Say what it is:
1067
-
1068
- ```ts
1069
- // before: started, and its report was discarded
1070
- defineManagedResource({ id: 'dialling', start: ({ reportHealth }) => reportHealth('degraded') })
1071
-
1072
- // after: says what it is, and does not gate the application
1073
- defineManagedResource({ id: 'dialling', required: false, start: ({ reportHealth }) => reportHealth('degraded') })
1074
- ```
1075
-
1076
- **2. A resource that reported `'unhealthy'` early and became healthy later** —
1077
- a pessimistic report before a connection settled. Here `required: false` is the
1078
- **wrong** fix: it would hide a real failure. Report the recovery instead:
1079
-
1080
- ```ts
1081
- start: async ({ reportHealth }) => {
1082
- reportHealth('unhealthy')
1083
- await connect()
1084
- reportHealth('healthy') // ← previously unnecessary; now it is the fix
1085
- }
1086
- ```
1087
-
1088
- **Also check your health endpoint.** An **optional** resource reporting
1089
- non-healthy during `start` now moves the application aggregate to `degraded`,
1090
- where before it stayed `healthy`. A readiness probe that maps `degraded` to a
1091
- non-200 will flip on upgrade — and a supervisor that restarts on that will loop.
1092
-
1093
- The refusals now say which of the two happened: a resource that was never
1094
- healthy is told it "is not healthy" and pointed at `required: false`; one that
1095
- was healthy and stopped is told it "lost readiness" and pointed at
1096
- `onResourceFailure`.
@@ -1,14 +1,131 @@
1
- # Upgrading 0.75.0 → 0.103.0 — stitchkit docs slice
1
+ # Upgrading 0.80.0 → 0.104.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.75.0 → 0.103.0 (docs/guide/upgrading.md)
6
+ Contains: Guide: Upgrading, 0.80.0 → 0.104.0 (docs/guide/upgrading.md)
7
7
 
8
8
  ==============================================================================
9
- # Guide: Upgrading, 0.75.0 → 0.103.0 (docs/guide/upgrading.md)
9
+ # Guide: Upgrading, 0.80.0 → 0.104.0 (docs/guide/upgrading.md)
10
10
  ==============================================================================
11
11
 
12
+ ## Released migration: 0.104.0
13
+
14
+ ### CLI runtime-tool construction
15
+
16
+ **Who must act:** callers writing a schema-dependent handler or MCP/AI `present` directly
17
+ inside an annotated `CliConfig.runtimeTools` or `CliInvokerConfig.runtimeTools` object.
18
+ Native `commands` and values returned by `defineRuntimeTool` / `createRuntimeToolFactory`
19
+ remain valid. Execution, auth, validation and the invocation result envelope keep their behavior.
20
+
21
+ Construct a CLI-only managed definition with the neutral schema-aware type before registration:
22
+
23
+ ```ts
24
+ import type { CliInvokerConfig, RuntimeToolExecutionWithOutput } from 'stitchkit/cli'
25
+ import { z } from 'zod'
26
+
27
+ const input = z.object({ text: z.string() })
28
+ const output = z.object({ size: z.number() })
29
+ // Before: handler receives the heterogeneous registry context.
30
+ const config: CliInvokerConfig = {
31
+ name: 'app',
32
+ runtimeTools: [{
33
+ name: 'measure', description: 'Measure text',
34
+ identity: { serviceName: 'text', action: 'measure', method: 'POST' },
35
+ transports: ['CLI'], input, output,
36
+ handler: ({ input }) => ({ size: String(input.text).length }),
37
+ }],
38
+ }
39
+ // After: handler input and output derive from the construction schemas.
40
+ const measure = {
41
+ name: 'measure', description: 'Measure text',
42
+ identity: { serviceName: 'text', action: 'measure', method: 'POST' },
43
+ transports: ['CLI'], input, output,
44
+ handler: ({ input }) => ({ size: input.text.length }),
45
+ } satisfies RuntimeToolExecutionWithOutput<typeof input, typeof output>
46
+ const nextConfig: CliInvokerConfig = { name: 'app', runtimeTools: [measure] }
47
+ ```
48
+
49
+ For a shared MCP/AI tool, construct the definition with `defineRuntimeTool` from
50
+ `stitchkit/tools`, including its typed SDK `present` callbacks, then pass the returned value
51
+ to `runtimeTools`. Install the corresponding SDK peers for that integration. A CLI-only
52
+ consumer needs `stitchkit`, `zod` and its ordinary Node type tooling.
53
+
54
+ `RuntimeToolExecution` names the heterogeneous registration contract. Call a registered
55
+ operation through `createCli` or `createCliInvoker`; its erased handler input is `never`
56
+ because the managed runner owns schema validation before execution. For a managed void
57
+ definition, use `RuntimeToolDefinitionWithoutOutput<typeof input>`.
58
+
59
+ ### MCP construction, state stores and delivery
60
+
61
+ **Who must act:** schema-dependent runtime tool literals written directly inside MCP mount
62
+ configuration, MCP presenters returning malformed content or metadata, custom `StateStore`
63
+ implementations, file-store consumers using retired lock
64
+ options, broadcast consumers reading `halt` or retrying unknown send outcomes, and consumers
65
+ that validate HTTP error envelopes with a closed schema. Applications collecting raw tool
66
+ causes from `console.error` must configure an internal tool hook sink.
67
+
68
+ MCP-only code can import the existing server factories from `stitchkit/tools/mcp` and
69
+ construct its schema-aware tool before heterogeneous registration:
70
+
71
+ ```ts
72
+ import { buildMcpServer, type RuntimeMcpToolDefinitionWithOutput } from 'stitchkit/tools/mcp'
73
+ import { z } from 'zod'
74
+ const input = z.object({ value: z.number() })
75
+ const output = z.object({ doubled: z.number() })
76
+ // Before: runtimeTools: [{ input, output, handler, present }]
77
+ const double = {
78
+ name: 'double', description: 'Double a number',
79
+ identity: { serviceName: 'numbers', action: 'double', method: 'POST' },
80
+ input, output,
81
+ handler: ({ input }) => ({ doubled: input.value * 2 }),
82
+ present: { mcp: ({ doubled }) => ({ content: [{ type: 'text', text: String(doubled) }] }) },
83
+ } satisfies RuntimeMcpToolDefinitionWithOutput<typeof input, typeof output>
84
+ const server = buildMcpServer({ serverInfo: { name: 'numbers', version: '1' }, services: [], runtimeTools: [double] })
85
+ ```
86
+
87
+ Full MCP/AI integrations keep `defineRuntimeTool` from `stitchkit/tools`; those typed values
88
+ remain accepted by the MCP leaf and CLI. The leaf requires the MCP SDK and Zod, with no AI peer.
89
+
90
+ `RuntimeMcpPresentation` preserves the official SDK's required `content` and typed `_meta`
91
+ fields. A presenter returning `{}` must return `{ content: [] }`; text blocks require string
92
+ text, and metadata must be an object. `structuredContent` and `isError` remain framework-owned.
93
+ This restores SDK checks that an indexed mapped type previously erased.
94
+
95
+ Unexpected tool causes remain in `hooks.onToolError` and the `error` field of
96
+ `hooks.afterToolCall`. Protocol stderr carries safe errors. MCP resolver failures use those
97
+ same observers without executing the handler or its lifecycle again. HTTP's default
98
+ unexpected-error logging retains its behavior.
99
+
100
+ A custom state adapter's `update` must invoke `transition(current, context)` while it still
101
+ owns the serialized transaction. `context.assertHeld()` checks the actual transaction or lock
102
+ generation and refuses after completion, rollback or ownership loss. A no-op guard cannot
103
+ satisfy this contract. Existing transition callbacks may keep one parameter. For the owning
104
+ file adapter, replace `{ staleLockMs, retryMs, lockTimeoutMs }` with `{ lockTimeoutMs }`:
105
+ the remaining budget controls acquisition waiting, never expiry of a live transaction.
106
+ Unknown legacy PID locks and historical temporary files are preserved; recover them only
107
+ after independently proving their owner is gone.
108
+
109
+ Broadcast consumers change `report.halt.reason` checks to the closed `halt.kind` union:
110
+ `retry-after`, `transient`, `permanent` or `ambiguous`. A custom MTProto adapter can classify
111
+ an acknowledged flood refusal as `{ kind: 'retry-after', retryAfterMs: wait }`; the exact
112
+ provider wait is respected. A wait over `maxRetryDelayMs` halts with the recipient pending.
113
+ Unknown write outcome becomes `uncertain`; restarting the same broadcast does not send it
114
+ again. A retry classification must certify that the attempt did not apply the external effect.
115
+
116
+ HTTP errors gain optional boolean `error.retryable`; framed contract streams use the same
117
+ field. Update closed consumer schemas before producers declaring it. `false` on 502 and
118
+ `true` on 409 remain explicit recommendations through the remote tool path. An absent field
119
+ retains prior status-derived defaults; the field does not change the HTTP client's retry policy.
120
+ The existing seventh `ApiError` constructor argument remains `ErrorOptions`; retryability is
121
+ the new eighth argument.
122
+
123
+ Caller cancellation now reaches `implementRemote`'s existing HTTP call. Applications bind
124
+ signals to `createCli` / `createCliInvoker` and cooperative handlers observe `ctx.signal`.
125
+ `REQUEST_ABORTED` is nonretryable and exits 130. A disconnected caller does not prove that
126
+ an origin ignoring cancellation or an external provider stopped; keep resource leases until
127
+ that work actually completes.
128
+
12
129
  ## Released migration: 0.103.0
13
130
 
14
131
  ### Diagnostic journal startup preserves torn evidence and inspects archives
@@ -947,171 +1064,3 @@ this is overloads and not one normalised key.
947
1064
  **If you compile with `skipLibCheck: false`**, this is also the release that
948
1065
  makes `stitchkit/tools/contract` compile at all: it carried five `TS2344`
949
1066
  errors, one per phase, from the same conditional spread.
950
-
951
- ## Released migration: 0.79.0
952
-
953
- One thing, and only if you assert on the whole snapshot.
954
-
955
- ```bash
956
- rg -n "getSnapshot\(\)|projectApplicationStatus|status\(\)" --glob '*.test.ts' --glob '*.spec.ts'
957
- ```
958
-
959
- `ApplicationSnapshot` and `ApplicationStatusProjection` each gained a
960
- `restarting` field — ids in the snapshot, a count in the projection. A reader
961
- that names the fields it wants is unaffected. A test that compares the whole
962
- object with `toEqual` fails until it adds the field:
963
-
964
- ```ts
965
- // before
966
- expect(body).toEqual({ id, lifecycle: 'ready', /* … */ resources: { total: 1, ready: 1, degraded: 0, failed: 0 } })
967
- // after
968
- expect(body).toEqual({ id, lifecycle: 'ready', /* … */ resources: { total: 1, ready: 1, degraded: 0, failed: 0 }, restarting: 0 })
969
- ```
970
-
971
- It is zero except while a restart is running, and then it names the subtree being
972
- replaced. That is the point: a snapshot taken mid-restart used to be
973
- indistinguishable from a resource that had failed on its own, so a dashboard read
974
- a planned replacement as an outage.
975
-
976
- **If you watch a hub across a restart**, nothing to change, but the behaviour is
977
- different and better: closing a hub now tells its subscribers `unavailable` /
978
- `source-unavailable` instead of dropping them, so a page stops showing a value
979
- that will never update again.
980
-
981
- **If you need a tool contract in a browser**, `stitchkit/tools/contract` now
982
- carries the async-operation helpers, its schemas and the view-file input/output
983
- without the runtime. `stitchkit/tools` still exports all of them.
984
-
985
- ## Released migration: 0.78.0
986
-
987
- Two mechanical edits. Find them both:
988
-
989
- ```bash
990
- rg -n "createDecisionPipeline|createDiagnosticJournal" --glob '*.ts' --glob '*.tsx'
991
- ```
992
-
993
- **1. `createDecisionPipeline` takes a deadline.**
994
-
995
- ```ts
996
- // before
997
- createDecisionPipeline([policyA, policyB])
998
- // after
999
- createDecisionPipeline([policyA, policyB], { policyTimeoutMs: 2_000 })
1000
- ```
1001
-
1002
- Pick a number your slowest policy comfortably beats. There is no default on
1003
- purpose: a policy that never settles hangs every caller of the operation it
1004
- guards, and the framework has no basis for choosing that number for you.
1005
-
1006
- Past the deadline — and on a throw, and on a non-decision — the pipeline raises
1007
- `DecisionPolicyError` naming the policy, with the trace so far. If you already
1008
- catch that for a bad return value, you now catch two more cases with it.
1009
-
1010
- **2. `createDiagnosticJournal` moved.**
1011
-
1012
- ```ts
1013
- // before
1014
- import { createDiagnosticJournal } from 'stitchkit/application'
1015
- // after
1016
- import { createDiagnosticJournal } from 'stitchkit/application/diagnostic-journal'
1017
- ```
1018
-
1019
- Only the factory moved. `DiagnosticJournalConfig`, every
1020
- `DiagnosticJournal*Schema` and `readDiagnosticJournalLockDiagnosis` stay where
1021
- they were.
1022
-
1023
- **If you restart resources**, nothing to change — but three things that did not
1024
- work now do: a managed schedule can be restarted, a restarted keyspace accepts
1025
- writes again, and a restarted managed server is actually shut down at exit. If
1026
- you pass `managedServerResource` a server *instance*, a restart is now refused
1027
- by name; pass a factory (`server: (context) => …`) to restart it.
1028
-
1029
- ## Released migration: 0.77.0
1030
-
1031
- Two type renames, and only if you named them. Nothing runtime moved.
1032
-
1033
- ```bash
1034
- rg -n "EventDecision|EventUndecided" --glob '*.ts' --glob '*.tsx'
1035
- ```
1036
-
1037
- ```ts
1038
- // before
1039
- import type { EventDecision, EventUndecided } from 'stitchkit/live'
1040
- // after
1041
- import type { PolicyDecision, UndecidedOutcome } from 'stitchkit/live'
1042
- ```
1043
-
1044
- The shapes are identical — `{ outcome: 'allow' } | { outcome: 'deny', reason } | { outcome: 'defer' }`
1045
- and `'allow' | 'deny'`. If you only ever *return* decisions from listeners and never named the
1046
- type, the search above finds nothing and there is nothing to do.
1047
-
1048
- They were renamed because `createDecisionPipeline` (new in this release) votes with exactly the
1049
- same three outcomes, and two identical types under two names is the thing that makes a search for
1050
- either one return half the truth.
1051
-
1052
- ## Released migration: 0.76.0
1053
-
1054
- One change, and only if you hand `createWatchClient` a transport you wrote yourself.
1055
-
1056
- ```bash
1057
- rg -n "createWatchClient" --glob '*.ts'
1058
- ```
1059
-
1060
- If the `transport:` you pass is a bound realtime client — `bindRealtimeClient(...)` or
1061
- `createRealtimeClient(...)` — there is nothing to do: it already carries
1062
- `onConnectionChange`. If it is an object you assembled, add the fourth member:
1063
-
1064
- ```ts
1065
- onConnectionChange(listener: (connected: boolean, reason?: string) => void): () => void
1066
- ```
1067
-
1068
- It is required because the client recovers through it: on a drop it publishes
1069
- `unavailable` to subscribers and forgets what was opened, and on a fresh
1070
- connection it re-opens every key that still has a listener. Without it a watch
1071
- stays "open" on the client after a server restart while the hub remembers
1072
- nothing, and the face stops updating without saying so.
1073
-
1074
- ## Released migration: 0.75.0
1075
-
1076
- Two mechanical renames and one option that has to move. Nothing about a passing
1077
- request changes.
1078
-
1079
- ### 1. A route group's `onRequest`
1080
-
1081
- ```bash
1082
- rg -n "hooks:\s*\{[^}]*onRequest" --glob '*.ts'
1083
- ```
1084
-
1085
- Any match **inside a `groups: [...]` entry** must move. The hook was accepted and
1086
- never dispatched, so the behaviour you have today is "no hook"; the fix is to
1087
- decide which one you meant:
1088
-
1089
- ```ts
1090
- // refuse before dispatch, for the whole server
1091
- createServer({ groups, hooks: { onRequest: gate } });
1092
-
1093
- // gate this group once the endpoint is known
1094
- groups: [{ pathPrefix: '/admin', services, hooks: { authorize: gate } }]
1095
- ```
1096
-
1097
- A group that still declares `onRequest` fails at startup with that message.
1098
-
1099
- ### 2. The SQLite boundary type
1100
-
1101
- ```bash
1102
- rg -l "AgentRuntimeSqlite(Database|Statement|Value)" | xargs sed -i \
1103
- -e 's/AgentRuntimeSqliteDatabase/SqliteDatabase/g' \
1104
- -e 's/AgentRuntimeSqliteStatement/SqliteStatement/g' \
1105
- -e 's/AgentRuntimeSqliteValue/SqliteValue/g'
1106
- ```
1107
-
1108
- Type-only: the same three methods, the same structural compatibility with
1109
- `bun:sqlite` and a `node:sqlite` wrapper, imported from the same entrypoints.
1110
- `initializeAgentRuntimeSqlite` keeps its name — it really is the agent runtime's
1111
- schema.
1112
-
1113
- ### 3. Nothing else
1114
-
1115
- `stitchkit/live`, the watch hub, the keyspace and the trust fence are all
1116
- additive. Adopt them when you want them; the guide is
1117
- [Live data](./live.md).
@@ -11,10 +11,10 @@ Contains: Guide: Upgrading, general (docs/guide/upgrading.md)
11
11
 
12
12
  Load this slice, then every range slice between your installed version and the target:
13
13
 
14
- - 0.75.0 → 0.103.0: `llms/upgrading-0.75.0-0.103.0.txt`
15
- - 0.61.0 → 0.74.0: `llms/upgrading-0.61.0-0.74.0.txt`
16
- - 0.44.0 → 0.60.0: `llms/upgrading-0.44.0-0.60.0.txt`
17
- - 0.37.0 → 0.37.0: `llms/upgrading-0.37.0.txt`
14
+ - 0.80.0 → 0.104.0: `llms/upgrading-0.80.0-0.104.0.txt`
15
+ - 0.62.0 → 0.79.0: `llms/upgrading-0.62.0-0.79.0.txt`
16
+ - 0.44.0 → 0.61.0: `llms/upgrading-0.44.0-0.61.0.txt`
17
+ - 0.37.0 → 0.44.0: `llms/upgrading-0.37.0-0.44.0.txt`
18
18
 
19
19
  # Upgrading stitchkit
20
20