stitchkit 0.110.5 → 0.111.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 (100) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/agent-runtime/branch-observations.d.ts +16 -16
  3. package/dist/agent-runtime/sandbox-broker.d.ts.map +1 -1
  4. package/dist/browser/stream.d.ts +3 -2
  5. package/dist/browser/stream.d.ts.map +1 -1
  6. package/dist/contract/runtime-context.d.ts +3 -1
  7. package/dist/contract/runtime-context.d.ts.map +1 -1
  8. package/dist/entrypoints/agent-runtime/coding-tools.js +2 -2
  9. package/dist/entrypoints/agent-runtime/sandbox.js +15 -29
  10. package/dist/entrypoints/agent-runtime/sqlite/bun.js +4 -4
  11. package/dist/entrypoints/agent-runtime/sqlite/node.js +4 -4
  12. package/dist/entrypoints/agent-runtime/testing.js +4 -4
  13. package/dist/entrypoints/agent-runtime.js +4 -4
  14. package/dist/entrypoints/bin/upgrade-cli.d.ts.map +1 -1
  15. package/dist/entrypoints/bin/upgrade-cli.js +123 -29
  16. package/dist/entrypoints/cli/publish.js +1 -1
  17. package/dist/entrypoints/cli.js +2 -2
  18. package/dist/entrypoints/http.d.ts +2 -0
  19. package/dist/entrypoints/http.d.ts.map +1 -1
  20. package/dist/entrypoints/http.js +5 -1
  21. package/dist/entrypoints/index.d.ts +1 -0
  22. package/dist/entrypoints/index.d.ts.map +1 -1
  23. package/dist/entrypoints/index.js +5 -1
  24. package/dist/entrypoints/node.d.ts +1 -0
  25. package/dist/entrypoints/node.d.ts.map +1 -1
  26. package/dist/entrypoints/node.js +3 -1
  27. package/dist/entrypoints/observability.js +24 -9
  28. package/dist/entrypoints/process.js +1 -1
  29. package/dist/entrypoints/remote.js +1 -1
  30. package/dist/entrypoints/server.d.ts +2 -0
  31. package/dist/entrypoints/server.d.ts.map +1 -1
  32. package/dist/entrypoints/server.js +79 -6
  33. package/dist/entrypoints/telegram.js +3 -3
  34. package/dist/entrypoints/testing.js +1 -1
  35. package/dist/entrypoints/tools/connections.js +16 -31
  36. package/dist/entrypoints/tools.js +39 -7
  37. package/dist/{index-mpg1t7nv.js → index-0z3kfphz.js} +1 -1
  38. package/dist/{index-jk44mbqb.js → index-1y0arq4z.js} +3 -57
  39. package/dist/{index-5pbtbce0.js → index-7c957abz.js} +1 -1
  40. package/dist/{index-e1sjcjfy.js → index-7r4knwf8.js} +94 -23
  41. package/dist/index-cjbn98zt.js +68 -0
  42. package/dist/{index-bm180f2d.js → index-ey15wx6j.js} +1 -1
  43. package/dist/{index-s0xbnpfh.js → index-kdnfe0sr.js} +1 -1
  44. package/dist/{index-s6d8zsha.js → index-krng2a5j.js} +64 -110
  45. package/dist/{index-9ket8wzx.js → index-mnk5vgdr.js} +1 -1
  46. package/dist/index-qndsr7f0.js +55 -0
  47. package/dist/{index-n7hrpngg.js → index-syzngt7v.js} +1 -1
  48. package/dist/{index-3h0ztg0z.js → index-t65erk4z.js} +5 -21
  49. package/dist/internal/bounded-body.d.ts +44 -0
  50. package/dist/internal/bounded-body.d.ts.map +1 -0
  51. package/dist/internal/bounded-lines.d.ts +1 -2
  52. package/dist/internal/bounded-lines.d.ts.map +1 -1
  53. package/dist/internal/secure-fetch.d.ts.map +1 -1
  54. package/dist/internal/stream-chunks.d.ts +13 -0
  55. package/dist/internal/stream-chunks.d.ts.map +1 -0
  56. package/dist/internal/upgrade-affects.d.ts +5 -0
  57. package/dist/internal/upgrade-affects.d.ts.map +1 -1
  58. package/dist/internal/upgrade-plan.d.ts +18 -3
  59. package/dist/internal/upgrade-plan.d.ts.map +1 -1
  60. package/dist/internal/upgrade-usage.d.ts +21 -5
  61. package/dist/internal/upgrade-usage.d.ts.map +1 -1
  62. package/dist/observability/audit.d.ts +10 -0
  63. package/dist/observability/audit.d.ts.map +1 -1
  64. package/dist/observability/event.d.ts +5 -0
  65. package/dist/observability/event.d.ts.map +1 -1
  66. package/dist/process/group-diagnostics.d.ts +20 -0
  67. package/dist/process/group-diagnostics.d.ts.map +1 -0
  68. package/dist/process/group-settlement.d.ts +1 -1
  69. package/dist/process/group-settlement.d.ts.map +1 -1
  70. package/dist/process/group.d.ts.map +1 -1
  71. package/dist/server/bun.d.ts +9 -0
  72. package/dist/server/bun.d.ts.map +1 -1
  73. package/dist/server/multipart.d.ts.map +1 -1
  74. package/dist/server/oauth/endpoints.d.ts.map +1 -1
  75. package/dist/server/oauth/provider.d.ts +5 -0
  76. package/dist/server/oauth/provider.d.ts.map +1 -1
  77. package/dist/server/proxy-origin.d.ts +12 -0
  78. package/dist/server/proxy-origin.d.ts.map +1 -0
  79. package/dist/server/raw.d.ts +6 -3
  80. package/dist/server/raw.d.ts.map +1 -1
  81. package/dist/server/request-body.d.ts.map +1 -1
  82. package/dist/server/request-completion.d.ts.map +1 -1
  83. package/dist/server/request-ingress.d.ts +31 -0
  84. package/dist/server/request-ingress.d.ts.map +1 -0
  85. package/dist/server/unix-client-body.d.ts.map +1 -1
  86. package/dist/tools/connections/limits.d.ts.map +1 -1
  87. package/llms/http.txt +3 -0
  88. package/llms/observability.txt +19 -2
  89. package/llms/server.2.txt +135 -0
  90. package/llms/server.5.txt +3 -1
  91. package/llms/server.txt +97 -131
  92. package/llms/stitchkit.2.txt +28 -0
  93. package/llms/stitchkit.txt +3 -3
  94. package/llms/tools.3.txt +1 -1
  95. package/llms/tools.txt +4 -0
  96. package/llms/{upgrading-0.101.0-0.110.0.txt → upgrading-0.101.0-0.111.0.txt} +29 -3
  97. package/llms/upgrading.txt +8 -2
  98. package/llms-full.txt +192 -8
  99. package/llms.txt +6 -6
  100. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -15,6 +15,45 @@ additive**; the first breaking change landed in 0.10.0. Grep the file for
15
15
 
16
16
  ## [Unreleased]
17
17
 
18
+ ## [0.111.0] - 2026-10-17
19
+
20
+ ### ⚠️ Breaking changes
21
+
22
+ **Who must act:** applications whose raw routes call `parseBody` on JSON larger than 1 MiB, and applications whose OAuth clients send `/register` or `/token` bodies larger than 64 KiB. Everyone else changes nothing.
23
+
24
+ - `stitchkit/server` — **`parseBody` reads at most 1 MiB by default** and returns `null` for a larger body, where it used to read any size into memory. An unbounded read of a raw route's body is a hole in the bounded-everything rule (I10), and `maxJsonBodyBytes` never covered raw routes. Before: `await parseBody(req, Schema)` parsed a body of any size; after: pass the limit your route needs, `await parseBody(req, Schema, { maxBytes: 8 * 1024 * 1024 })`. → ADR 0262
25
+ **Affects:** `stitchkit/server` parseBody
26
+ - `stitchkit/tools` — **`mountOAuthProvider` reads at most 64 KiB of a `/token` or `/register` body** and answers `413` with `invalid_request` for a larger one, where it used to read any size. Before: no limit; after: the default is 64 KiB and `mountOAuthProvider({ ..., maxRequestBodyBytes: 256 * 1024 })` raises it. → ADR 0262
27
+ **Affects:** `stitchkit/tools` mountOAuthProvider
28
+
29
+ ### Added
30
+
31
+ - `stitchkit/observability`: `request.payloadMaxBytes` sets how much of a request body the audit row reads with `includePayload` (default: the handler's `maxJsonBodyBytes`, or 1 MiB), and an event whose body was larger carries `payloadTruncated: true` beside its `null` payload.
32
+ - `stitchkit/tools`: `mountOAuthProvider({ maxRequestBodyBytes })` sets the most bytes `/token` and `/register` read of a request body (default 64 KiB).
33
+ - `stitchkit`, `stitchkit/http`: `readBoundedBody(source, { maxBytes, signal?, limitError, abortError? })` reads a `ReadableStream<Uint8Array>`, an async byte iterable or a `null` body into bytes without reading past `maxBytes` plus one chunk. The source is cancelled when the limit is crossed and when the signal aborts, an abort is honoured before the first read and while a read never settles, and the caller picks both errors. A consuming project no longer needs its own copy; the request-text, unix-client, connection-response, capped-download and sandbox-gateway readers of the framework now run on the same chunk loop. → ADR 0262
34
+ - `stitchkit/server`, `stitchkit/node`: `defineRequestIngress<T>(name)` returns a typed key whose `attach(request, value)` is called by the code that builds a `Request` (a local socket ingress, a relay) and whose `from(ctx)` an endpoint, `authorize`, `beforeHandle` or `onError` reads. A header, `clone()` and `new Request(request)` carry nothing; a request from another ingress has no value. `ctx.req` is documented, and tested on every HTTP context, as the very `Request` the handler received. → ADR 0261
35
+ - `stitchkit upgrade` prints a second section, **Fixes that touch this project**, with the same verdicts as breaking items for every fix of the range that names what it touches (`fixes` and `fixesWithoutAffects` in `--json`); `release:check` requires the `**Affects:**` line on a Fixed item that leads with a public entrypoint, from the release after 0.110.6. → ADR 0263
36
+
37
+ ### Fixed
38
+
39
+ - `stitchkit/server`, `stitchkit/node`: a `createUnixClientTransport` request that is aborted while its body is being read rejects with the abort reason at once instead of waiting for the next chunk of a stalled source, and cancels the body when it crosses the request size limit.
40
+ **Affects:** `stitchkit/server`, `stitchkit/node` createUnixClientTransport
41
+ - `stitchkit/server`: with `observability.includePayload`, the audit row reads the cloned request body up to `payloadMaxBytes` (by default the handler's `maxJsonBodyBytes`, or 1 MiB; an endpoint's own `maxJsonBodyBytes` is not known when the body is cloned, so set `payloadMaxBytes` for endpoints that accept more) and cancels that branch there; before, the clone branch of the body stream drained the whole body into memory even when the handler's own branch was cut at `maxJsonBodyBytes`.
42
+ **Affects:** `stitchkit/server` createServer(observability.includePayload)
43
+
44
+ ## [0.110.6] - 2026-10-15
45
+
46
+ ### Added
47
+
48
+ - `stitchkit/server`: `createServer({ proxyOrigin: { trustedPeer } })` restores the external HTTP/HTTPS scheme from a single trusted ingress before fetch composition and routing. It validates the real TCP peer and one `X-Forwarded-Proto`, rejects competing URL headers, preserves wire Host/ports and native cancellation, peer lookup and WebSocket upgrade. `trustProxy` remains client-IP-only. The server surface grows by one configuration type, `ProxyOriginConfig`, owned by this entrypoint so the trust decision is explicit and independently testable (I8, I9, I12).
49
+
50
+ ### Fixed
51
+
52
+ - `stitchkit/process`: bounded process-group settlement observations remain readable through nested cleanup errors in Node CI, including up to 16 actual states, the group id, sample count and elapsed time. Observation failures retain their original cause. Cleanup deadlines and the definition of a live process are unchanged; these diagnostics do not claim to repair a historical native termination failure.
53
+ **Affects:** `stitchkit/process` runNativeCommand
54
+ - `stitchkit/process`: stopping a process group repeats `SIGKILL` for members still confirmed alive within the original cleanup deadline. Fresh kernel absence ends further signals; dead-only, invalid and failed process observations never trigger a blind re-signal.
55
+ **Affects:** `stitchkit/process` runNativeCommand
56
+
18
57
  ## [0.110.5] - 2026-10-15
19
58
 
20
59
  ### Added
@@ -52,6 +91,7 @@ additive**; the first breaking change landed in 0.10.0. Grep the file for
52
91
  ### Fixed
53
92
 
54
93
  - Process-group cleanup accepts a fresh kernel absence after SIGKILL instead of relying only on a potentially stale process-table snapshot. Permission refusals and unknown/exiting states still require proof; the same cleanup deadline applies and failures retain their last observed states.
94
+ **Affects:** `stitchkit/process` runNativeCommand
55
95
  - A synchronously throwing injected Socket.IO peer loader now reaches `onConnectError`, clears connection intent and allows the next `connect()` to retry, just like an asynchronously rejected loader.
56
96
 
57
97
  ## [0.110.0] - 2026-10-14
@@ -66,6 +106,7 @@ additive**; the first breaking change landed in 0.10.0. Grep the file for
66
106
  ### Fixed
67
107
 
68
108
  - A fast owner-loss guard exit no longer overtakes a buffered start handshake or discards captured output while the handshake is in flight. The control stream determines whether the handshake was missing, and output readers attach before waiting for it. Native lifetime qualification checks descendant death within its cleanup window before asserting stable output.
109
+ **Affects:** `stitchkit/process` runNativeCommand(ownerLoss: 'terminate')
69
110
 
70
111
  ### Added
71
112
 
@@ -79,6 +120,7 @@ additive**; the first breaking change landed in 0.10.0. Grep the file for
79
120
  timer on a loaded host. The grace wait and the Darwin permission retry read the clock once for both
80
121
  the decision to wait and the length of the wait, so Node no longer prints `TimeoutNegativeWarning`
81
122
  to the application's stderr when the deadline passes between two reads.
123
+ **Affects:** `stitchkit/process` runNativeCommand
82
124
 
83
125
  ## [0.109.3] - 2026-10-13
84
126
 
@@ -206,6 +248,7 @@ scripts relied on spelling-based conversion of dotted values.
206
248
  `Command deadline exceeded`. Under Bun a command is now launched through `Bun.spawn`, presented to the
207
249
  command owner with the same events, streams, group ownership and failure reporting; Node still uses
208
250
  `node:child_process`. The deadline, stop policy and process-group cleanup are unchanged.
251
+ **Affects:** `stitchkit/process` runNativeCommand
209
252
 
210
253
  ## [0.108.0] - 2026-10-06
211
254
 
@@ -25,20 +25,8 @@ export declare function branchObservation(ids: BranchIdentities, kind: string, r
25
25
  delayMs?: number | undefined;
26
26
  reason?: string | undefined;
27
27
  } | {
28
- effectName: string;
29
- phase: "intent";
30
- runId: string;
31
- id?: string | undefined;
32
- } | {
33
- effectName: string;
34
- phase: "accepted";
28
+ stepName: string;
35
29
  encoded: string;
36
- via: "reconcile" | "run";
37
- runId: string;
38
- id?: string | undefined;
39
- } | {
40
- effectName: string;
41
- phase: "uncertain";
42
30
  runId: string;
43
31
  id?: string | undefined;
44
32
  } | {
@@ -53,15 +41,27 @@ export declare function branchObservation(ids: BranchIdentities, kind: string, r
53
41
  id: string;
54
42
  runId: string;
55
43
  } | {
56
- stepName: string;
44
+ event: string;
45
+ id: string;
57
46
  encoded: string;
58
47
  runId: string;
48
+ } | {
49
+ effectName: string;
50
+ phase: "intent";
51
+ runId: string;
59
52
  id?: string | undefined;
60
53
  } | {
61
- event: string;
62
- id: string;
54
+ effectName: string;
55
+ phase: "accepted";
63
56
  encoded: string;
57
+ via: "reconcile" | "run";
58
+ runId: string;
59
+ id?: string | undefined;
60
+ } | {
61
+ effectName: string;
62
+ phase: "uncertain";
64
63
  runId: string;
64
+ id?: string | undefined;
65
65
  } | {
66
66
  bytes: number;
67
67
  sha256?: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox-broker.d.ts","sourceRoot":"","sources":["../../src/agent-runtime/sandbox-broker.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE7E,6FAA6F;AAC7F,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,oBAAoB,EACrC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI;;;GA4HlC"}
1
+ {"version":3,"file":"sandbox-broker.d.ts","sourceRoot":"","sources":["../../src/agent-runtime/sandbox-broker.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgB,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE7E,6FAA6F;AAC7F,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,oBAAoB,EACrC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI;;;GA4GlC"}
@@ -1,6 +1,7 @@
1
1
  import type { StreamFinalLinePolicy } from '../contract/define.js';
2
- import { type StreamByteSource } from '../internal/bounded-lines.js';
3
- export { DEFAULT_STREAM_LINE_BYTES, type StreamByteSource, StreamLineLimitError, StreamTruncatedLineError, } from '../internal/bounded-lines.js';
2
+ import type { StreamByteSource } from '../internal/stream-chunks.js';
3
+ export { DEFAULT_STREAM_LINE_BYTES, StreamLineLimitError, StreamTruncatedLineError, } from '../internal/bounded-lines.js';
4
+ export type { StreamByteSource } from '../internal/stream-chunks.js';
4
5
  /** Options for `parseNDJSON` and `createNDJSONDecoder`. */
5
6
  export interface ParseNDJSONOptions {
6
7
  /** Maximum bytes retained for one line; past it, `StreamLineLimitError`. Default 1 MiB. */
@@ -1 +1 @@
1
- {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/browser/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,yBAAyB,EACzB,KAAK,gBAAgB,EACrB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AAEnC,2DAA2D;AAC3D,MAAM,WAAW,kBAAkB;IACjC,2FAA2F;IAC3F,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACnD;;;OAGG;IACH,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAClC,4FAA4F;IAC5F,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAiBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAuB,WAAW,CAAC,CAAC,EAClC,MAAM,EAAE,gBAAgB,EACxB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,cAAc,CAAC,CAAC,CAAC,CA4BnB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,CAAC,EAAE,CAAC;IAC7B,GAAG,IAAI,CAAC,EAAE,CAAC;CACZ;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EACnC,OAAO,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,GAC3C,aAAa,CAAC,CAAC,CAAC,CAkClB;AAED,8BAA8B;AAC9B,MAAM,WAAW,eAAe;IAC9B,+FAA+F;IAC/F,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACnD,4FAA4F;IAC5F,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAuB,QAAQ,CAAC,CAAC,EAC/B,MAAM,EAAE,gBAAgB,EACxB,OAAO,CAAC,EAAE,eAAe,GACxB,cAAc,CAAC,CAAC,CAAC,CA6BnB"}
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/browser/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAMhE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,OAAO,EACL,yBAAyB,EACzB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,2DAA2D;AAC3D,MAAM,WAAW,kBAAkB;IACjC,2FAA2F;IAC3F,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACnD;;;OAGG;IACH,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAClC,4FAA4F;IAC5F,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAiBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAuB,WAAW,CAAC,CAAC,EAClC,MAAM,EAAE,gBAAgB,EACxB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,cAAc,CAAC,CAAC,CAAC,CA4BnB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,CAAC,EAAE,CAAC;IAC7B,GAAG,IAAI,CAAC,EAAE,CAAC;CACZ;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EACnC,OAAO,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,GAC3C,aAAa,CAAC,CAAC,CAAC,CAkClB;AAED,8BAA8B;AAC9B,MAAM,WAAW,eAAe;IAC9B,+FAA+F;IAC/F,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACnD,4FAA4F;IAC5F,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAuB,QAAQ,CAAC,CAAC,EAC/B,MAAM,EAAE,gBAAgB,EACxB,OAAO,CAAC,EAAE,eAAe,GACxB,cAAc,CAAC,CAAC,CAAC,CA6BnB"}
@@ -81,7 +81,9 @@ export interface RuntimeContext {
81
81
  * validation failure). Absent on the non-HTTP transports (MCP / agent / CLI /
82
82
  * a bring-your-own lane), which carry no `Request`, so they are optional and a
83
83
  * reader narrows them. Web Fetch types only — the core stays Fetch-clean
84
- * (→ ADR 0013).
84
+ * (→ ADR 0013). On every HTTP context it is the very `Request` the handler of
85
+ * the core received, never a copy: a `RequestIngress` key attached by the code
86
+ * that built that request reads its value through this identity.
85
87
  */
86
88
  req?: Request;
87
89
  url?: URL;
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-context.d.ts","sourceRoot":"","sources":["../../src/contract/runtime-context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtime-context.d.ts","sourceRoot":"","sources":["../../src/contract/runtime-context.ts"],"names":[],"mappings":"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"}
@@ -6,10 +6,10 @@ import {
6
6
  AgentCodingToolAuthorizationSchema2,
7
7
  AgentCodingToolPathAuthorizationSchema2,
8
8
  createAgentCodingTools2
9
- } from "../../index-bm180f2d.js";
9
+ } from "../../index-ey15wx6j.js";
10
10
  import"../../index-2kbysk9s.js";
11
11
  import"../../index-84bf5spd.js";
12
- import"../../index-e1sjcjfy.js";
12
+ import"../../index-7r4knwf8.js";
13
13
  import"../../index-zrtrjkbf.js";
14
14
  import"../../index-636mggad.js";
15
15
  export {
@@ -3,7 +3,7 @@ import {
3
3
  missingSandboxRestrictions2,
4
4
  codingRefusal,
5
5
  createAgentCodingTools2
6
- } from "../../index-bm180f2d.js";
6
+ } from "../../index-ey15wx6j.js";
7
7
  import"../../index-ct75c3at.js";
8
8
  import"../../index-q6crhe1n.js";
9
9
  import"../../index-fynr93w4.js";
@@ -17,8 +17,11 @@ import {
17
17
  nativeCommandOwner,
18
18
  terminateOwnedGroup,
19
19
  startNativeCommand
20
- } from "../../index-e1sjcjfy.js";
20
+ } from "../../index-7r4knwf8.js";
21
21
  import"../../index-zrtrjkbf.js";
22
+ import {
23
+ readBoundedBody2
24
+ } from "../../index-qndsr7f0.js";
22
25
  import {
23
26
  MAX_TIMER_MS
24
27
  } from "../../index-eemvahkc.js";
@@ -108,15 +111,10 @@ async function createSandboxBroker(socketPath, getPolicy, onError) {
108
111
  req.on("aborted", abort);
109
112
  res.on("close", abort);
110
113
  try {
111
- const chunks = [];
112
- let size = 0;
113
- for await (const chunk of req) {
114
- const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
115
- size += bytes.byteLength;
116
- if (size > maxBytes)
117
- throw new SandboxError("SANDBOX_LIMIT", "Sandbox request limit exceeded");
118
- chunks.push(bytes);
119
- }
114
+ const requestBody = await readBoundedBody2(req, {
115
+ maxBytes,
116
+ limitError: () => new SandboxError("SANDBOX_LIMIT", "Sandbox request limit exceeded")
117
+ });
120
118
  const target = new URL(req.url, rule.origin);
121
119
  if (target.origin !== new URL(rule.origin).origin)
122
120
  throw new SandboxError("SANDBOX_NETWORK_DENIED", "Sandbox network denied");
@@ -133,31 +131,19 @@ async function createSandboxBroker(socketPath, getPolicy, onError) {
133
131
  headers,
134
132
  redirect: "manual",
135
133
  signal: controller.signal,
136
- ...size > 0 && { body: Buffer.concat(chunks) }
134
+ ...requestBody.byteLength > 0 && { body: requestBody }
137
135
  });
138
136
  if (response.status >= 300 && response.status < 400) {
139
137
  await response.body?.cancel();
140
138
  throw new SandboxError("SANDBOX_NETWORK_DENIED", "Sandbox redirects are denied");
141
139
  }
142
- const reader = response.body?.getReader();
143
- const output = [];
144
- size = 0;
145
- try {
146
- while (reader) {
147
- const next = await reader.read();
148
- if (next.done)
149
- break;
150
- size += next.value.byteLength;
151
- if (size > maxBytes)
152
- throw new SandboxError("SANDBOX_LIMIT", "Sandbox response limit exceeded");
153
- output.push(next.value);
154
- }
155
- } finally {
156
- await reader?.cancel();
157
- }
140
+ const output = await readBoundedBody2(response.body, {
141
+ maxBytes,
142
+ limitError: () => new SandboxError("SANDBOX_LIMIT", "Sandbox response limit exceeded")
143
+ });
158
144
  const type = response.headers.get("content-type");
159
145
  res.writeHead(response.status, type ? { "content-type": type } : {});
160
- res.end(Buffer.concat(output));
146
+ res.end(output);
161
147
  } catch (cause) {
162
148
  try {
163
149
  onError(cause);
@@ -1,20 +1,20 @@
1
1
  import"../../../index-jna0ejsa.js";
2
- import"../../../index-mpg1t7nv.js";
2
+ import"../../../index-0z3kfphz.js";
3
3
  import"../../../index-8kzct1d6.js";
4
4
  import {
5
5
  initializeAgentRuntimeSqlite2,
6
6
  createSqliteAgentRuntimeStore2
7
- } from "../../../index-5pbtbce0.js";
7
+ } from "../../../index-7c957abz.js";
8
8
  import"../../../index-kqnd6a85.js";
9
9
  import"../../../index-5w6t91ze.js";
10
- import"../../../index-bm180f2d.js";
10
+ import"../../../index-ey15wx6j.js";
11
11
  import"../../../index-ct75c3at.js";
12
12
  import"../../../index-q6crhe1n.js";
13
13
  import"../../../index-fynr93w4.js";
14
14
  import"../../../index-2kbysk9s.js";
15
15
  import"../../../index-84bf5spd.js";
16
+ import"../../../index-7r4knwf8.js";
16
17
  import"../../../index-snef22zr.js";
17
- import"../../../index-e1sjcjfy.js";
18
18
  import"../../../index-zrtrjkbf.js";
19
19
  import"../../../index-636mggad.js";
20
20
 
@@ -1,20 +1,20 @@
1
1
  import"../../../index-jna0ejsa.js";
2
- import"../../../index-mpg1t7nv.js";
2
+ import"../../../index-0z3kfphz.js";
3
3
  import"../../../index-8kzct1d6.js";
4
4
  import {
5
5
  initializeAgentRuntimeSqlite2,
6
6
  createSqliteAgentRuntimeStore2
7
- } from "../../../index-5pbtbce0.js";
7
+ } from "../../../index-7c957abz.js";
8
8
  import"../../../index-kqnd6a85.js";
9
9
  import"../../../index-5w6t91ze.js";
10
- import"../../../index-bm180f2d.js";
10
+ import"../../../index-ey15wx6j.js";
11
11
  import"../../../index-ct75c3at.js";
12
12
  import"../../../index-q6crhe1n.js";
13
13
  import"../../../index-fynr93w4.js";
14
14
  import"../../../index-2kbysk9s.js";
15
15
  import"../../../index-84bf5spd.js";
16
+ import"../../../index-7r4knwf8.js";
16
17
  import"../../../index-snef22zr.js";
17
- import"../../../index-e1sjcjfy.js";
18
18
  import"../../../index-zrtrjkbf.js";
19
19
  import"../../../index-636mggad.js";
20
20
 
@@ -10,18 +10,18 @@ import {
10
10
  advanceToolChronology
11
11
  } from "../../index-jna0ejsa.js";
12
12
  import"../../index-5w6t91ze.js";
13
- import"../../index-bm180f2d.js";
14
- import"../../index-mpg1t7nv.js";
13
+ import"../../index-ey15wx6j.js";
14
+ import"../../index-0z3kfphz.js";
15
15
  import"../../index-ct75c3at.js";
16
16
  import"../../index-q6crhe1n.js";
17
17
  import"../../index-fynr93w4.js";
18
18
  import"../../index-2kbysk9s.js";
19
19
  import"../../index-84bf5spd.js";
20
+ import"../../index-7r4knwf8.js";
20
21
  import"../../index-snef22zr.js";
21
22
  import {
22
23
  createMemoryAgentRuntimeStore2
23
- } from "../../index-9ket8wzx.js";
24
- import"../../index-e1sjcjfy.js";
24
+ } from "../../index-mnk5vgdr.js";
25
25
  import"../../index-zrtrjkbf.js";
26
26
  import {
27
27
  assertPositiveSafeInteger
@@ -5,7 +5,7 @@ import {
5
5
  missingSandboxRestrictions2,
6
6
  recordAgentSandboxProbe2,
7
7
  refuseUnknownSpillReference
8
- } from "../index-bm180f2d.js";
8
+ } from "../index-ey15wx6j.js";
9
9
  import {
10
10
  AgentRecordIdSchema2,
11
11
  AgentRecordVersionSchema2,
@@ -58,7 +58,7 @@ import {
58
58
  AgentHistoryMutationSchema2,
59
59
  ACTIVE_AGENT_RUN_STATES2,
60
60
  createAgentRuntimeStore2
61
- } from "../index-mpg1t7nv.js";
61
+ } from "../index-0z3kfphz.js";
62
62
  import {
63
63
  AgentStoreEventKindSchema2,
64
64
  AgentStoreEventEnvelopeSchema2,
@@ -188,13 +188,13 @@ import {
188
188
  import"../index-56yx8dxp.js";
189
189
  import"../index-2kbysk9s.js";
190
190
  import"../index-84bf5spd.js";
191
+ import"../index-7r4knwf8.js";
191
192
  import {
192
193
  createMemoryAgentRuntimeStore2
193
- } from "../index-9ket8wzx.js";
194
+ } from "../index-mnk5vgdr.js";
194
195
  import {
195
196
  createAgentRuntimeEventSink2
196
197
  } from "../index-616xh7f2.js";
197
- import"../index-e1sjcjfy.js";
198
198
  import"../index-zrtrjkbf.js";
199
199
  import {
200
200
  MAX_TIMER_MS
@@ -1 +1 @@
1
- {"version":3,"file":"upgrade-cli.d.ts","sourceRoot":"","sources":["../../../src/entrypoints/bin/upgrade-cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,KAAK,MAAM,EAA2C,MAAM,SAAS,CAAC;AAI/E,OAAO,EACL,KAAK,aAAa,EAKnB,MAAM,8BAA8B,CAAC;AA4BtC,mGAAmG;AACnG,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;CAChC;AAED,yFAAyF;AACzF,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAWD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,EAAE,GAAE,eAGH,GACA;IAAE,OAAO,EAAE,aAAa,EAAE,CAAC;IAAC,SAAS,EAAE,SAAS,EAAE,CAAA;CAAE,CAiCtD;AAoCD,MAAM,WAAW,gBAAgB;IAC/B,+BAA+B;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,gBAAgB,CA+DvE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CASrF"}
1
+ {"version":3,"file":"upgrade-cli.d.ts","sourceRoot":"","sources":["../../../src/entrypoints/bin/upgrade-cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,KAAK,MAAM,EAA2C,MAAM,SAAS,CAAC;AAI/E,OAAO,EACL,KAAK,aAAa,EAOnB,MAAM,8BAA8B,CAAC;AA8BtC,mGAAmG;AACnG,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;CAChC;AAED,yFAAyF;AACzF,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAWD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,EAAE,GAAE,eAGH,GACA;IAAE,OAAO,EAAE,aAAa,EAAE,CAAC;IAAC,SAAS,EAAE,SAAS,EAAE,CAAA;CAAE,CAiCtD;AAoCD,MAAM,WAAW,gBAAgB;IAC/B,+BAA+B;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,gBAAgB,CA8EvE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CASrF"}
@@ -47,6 +47,31 @@ function breakingItems(section) {
47
47
  flush();
48
48
  return items;
49
49
  }
50
+ function fixedSectionItems(releaseBody) {
51
+ const items = [];
52
+ let section;
53
+ let fenced = false;
54
+ const flush = () => {
55
+ if (section)
56
+ items.push(...breakingItems(section.join(`
57
+ `)));
58
+ section = undefined;
59
+ };
60
+ for (const line of releaseBody.split(`
61
+ `)) {
62
+ if (FENCE.test(line))
63
+ fenced = !fenced;
64
+ if (!fenced && /^### /.test(line)) {
65
+ flush();
66
+ if (/^### Fixed\b/.test(line))
67
+ section = [];
68
+ continue;
69
+ }
70
+ section?.push(line);
71
+ }
72
+ flush();
73
+ return items;
74
+ }
50
75
  function affectsLineOf(itemMarkdown) {
51
76
  let fenced = false;
52
77
  const lines = [];
@@ -127,13 +152,13 @@ function parseAffectsLine(line) {
127
152
  // src/internal/upgrade-plan.ts
128
153
  var BREAKING_HEADING = /^### \s*⚠️?\s*Breaking changes[^\n]*$/m;
129
154
  var NOT_DECLARED = "Not declared in this legacy changelog section.";
130
- function leadingEntrypoints(item) {
155
+ function leadingEntrypoints(item, accept = () => true) {
131
156
  let rest = item.replace(/^[-*+] /, "").replace(/^\*\*/, "");
132
157
  const names = [];
133
158
  for (;; ) {
134
- const match = /^`(stitchkit(?:\/[a-z0-9][a-z0-9-]*)*)`/.exec(rest);
159
+ const match = /^`(stitchkit(?:-[a-z0-9-]+)?(?:\/[a-z0-9][a-z0-9-]*)*)`/.exec(rest);
135
160
  const name = match?.[1];
136
- if (!match || name === undefined)
161
+ if (!match || name === undefined || !accept(name))
137
162
  break;
138
163
  names.push(name);
139
164
  rest = rest.slice(match[0].length);
@@ -157,18 +182,32 @@ function itemAudience(item) {
157
182
  const who = /\*\*Who must act:\*\*\s*(.*?)(?=\s+See \[|\s+→|\s+\*\*Affects:\*\*|$)/.exec(flat)?.[1];
158
183
  return who?.trim() || undefined;
159
184
  }
185
+ function upgradeItem(version, item, title = itemTitle) {
186
+ const line = affectsLineOf(item);
187
+ return {
188
+ version,
189
+ entrypoints: leadingEntrypoints(item),
190
+ title: title(item.replace(/^[ \t]*\*\*Affects:\*\*.*$/gm, "").trimEnd()),
191
+ affects: line === undefined ? undefined : parseAffectsLine(line),
192
+ markdown: item
193
+ };
194
+ }
195
+ function fixTitle(item) {
196
+ const flat = item.replace(/\s+/g, " ").replace(/^[-*+] /, "").trim();
197
+ const prefix = /^(?:`stitchkit[^`]*`(?:, and |, | and | \+ )?)+\s*[:—-]?\s*/.exec(flat);
198
+ const text = flat.slice(prefix?.[0].length ?? 0).replace(/\*\*/g, "");
199
+ const sentence = /^(.*?[.!?])(?:\s|$)/.exec(text)?.[1] ?? text;
200
+ const trimmed = sentence.replace(/[.:]$/, "");
201
+ return trimmed.length > 100 ? `${trimmed.slice(0, 99)}…` : trimmed;
202
+ }
203
+ function fixedItem(version, item) {
204
+ return upgradeItem(version, item, fixTitle);
205
+ }
160
206
  function sectionItems(version, markdown, sectionAudience) {
161
- return breakingItems(markdown).map(({ markdown: item }) => {
162
- const line = affectsLineOf(item);
163
- return {
164
- version,
165
- entrypoints: leadingEntrypoints(item),
166
- title: itemTitle(item),
167
- affects: line === undefined ? undefined : parseAffectsLine(line),
168
- whoMustAct: itemAudience(item) ?? sectionAudience,
169
- markdown: item
170
- };
171
- });
207
+ return breakingItems(markdown).map(({ markdown: item }) => ({
208
+ ...upgradeItem(version, item),
209
+ whoMustAct: itemAudience(item) ?? sectionAudience
210
+ }));
172
211
  }
173
212
  function semverParts(version) {
174
213
  const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(version);
@@ -190,14 +229,14 @@ function compareSemver(left, right) {
190
229
  }
191
230
  return 0;
192
231
  }
193
- function planUpgrade(changelog, from, to) {
232
+ function releasesInRange(changelog, from, to) {
194
233
  semverParts(from);
195
234
  semverParts(to);
196
235
  if (compareSemver(from, to) >= 0) {
197
236
  throw new Error(`Upgrade range must increase: ${from} → ${to}`);
198
237
  }
199
238
  const releases = [...changelog.matchAll(/^## \[(\d+\.\d+\.\d+)\].*$/gm)];
200
- const changes = [];
239
+ const found = [];
201
240
  for (const [index, release] of releases.entries()) {
202
241
  const version = release[1];
203
242
  if (version === undefined)
@@ -206,7 +245,13 @@ function planUpgrade(changelog, from, to) {
206
245
  continue;
207
246
  const bodyStart = (release.index ?? 0) + release[0].length;
208
247
  const bodyEnd = releases[index + 1]?.index ?? changelog.length;
209
- const body = changelog.slice(bodyStart, bodyEnd);
248
+ found.push({ version, body: changelog.slice(bodyStart, bodyEnd) });
249
+ }
250
+ return found;
251
+ }
252
+ function planUpgrade(changelog, from, to) {
253
+ const changes = [];
254
+ for (const { version, body } of releasesInRange(changelog, from, to)) {
210
255
  const breakingHeader = BREAKING_HEADING.exec(body);
211
256
  if (!breakingHeader)
212
257
  continue;
@@ -225,6 +270,17 @@ function planUpgrade(changelog, from, to) {
225
270
  }
226
271
  return changes.sort((left, right) => compareSemver(left.version, right.version));
227
272
  }
273
+ function fixedItems(version, body) {
274
+ return fixedSectionItems(body).map(({ markdown }) => fixedItem(version, markdown));
275
+ }
276
+ function planFixes(changelog, from, to) {
277
+ const releases = releasesInRange(changelog, from, to).sort((left, right) => compareSemver(left.version, right.version));
278
+ const all = releases.flatMap(({ version, body }) => fixedItems(version, body));
279
+ return {
280
+ declared: all.filter((item) => item.affects !== undefined),
281
+ withoutAffects: all.filter((item) => item.affects === undefined).length
282
+ };
283
+ }
228
284
  function renderUpgradePlan(changes, from, to) {
229
285
  const header = `# Stitchkit upgrade ${from} → ${to}`;
230
286
  if (changes.length === 0)
@@ -411,10 +467,8 @@ var VERDICT_TEXT = {
411
467
  behavioural: "behavioural — check by hand",
412
468
  "not-declared": "not declared — check by hand"
413
469
  };
414
- function renderUpgradeVerdicts(verdicts) {
415
- if (verdicts.length === 0)
416
- return "";
417
- const lines = ["## Does it touch this project?", ""];
470
+ function renderVerdictLines(verdicts) {
471
+ const lines = [];
418
472
  for (const { item, verdict } of verdicts) {
419
473
  const where = item.entrypoints.length > 0 ? ` ${item.entrypoints.map((name) => `\`${name}\``).join(", ")}` : "";
420
474
  lines.push(`- **${item.version}**${where} — ${item.title}: **${VERDICT_TEXT[verdict.kind]}**`);
@@ -425,23 +479,47 @@ function renderUpgradeVerdicts(verdicts) {
425
479
  for (const file of verdict.files)
426
480
  lines.push(` - ${file}`);
427
481
  }
482
+ return lines;
483
+ }
484
+ function renderUpgradeVerdicts(verdicts) {
485
+ if (verdicts.length === 0)
486
+ return "";
487
+ return `${["## Does it touch this project?", "", ...renderVerdictLines(verdicts)].join(`
488
+ `)}
489
+ `;
490
+ }
491
+ function renderUpgradeFixes(verdicts, withoutAffects) {
492
+ if (verdicts.length === 0 && withoutAffects === 0)
493
+ return "";
494
+ const lines = ["## Fixes that touch this project", ""];
495
+ lines.push(...renderVerdictLines(verdicts));
496
+ if (verdicts.length === 0)
497
+ lines.push("No fix of this range names what it touches.");
498
+ if (withoutAffects > 0)
499
+ lines.push("", `${withoutAffects} more fix${withoutAffects === 1 ? "" : "es"} in this range carry no machine line and are not judged here.`);
428
500
  return `${lines.join(`
429
501
  `)}
430
502
  `;
431
503
  }
432
504
  function upgradeVerdictsJson(verdicts) {
433
- return verdicts.map(({ item, verdict }) => ({
505
+ return verdicts.map((entry) => verdictJson(entry, entry.item.whoMustAct));
506
+ }
507
+ function upgradeFixesJson(verdicts) {
508
+ return verdicts.map((entry) => verdictJson(entry));
509
+ }
510
+ function verdictJson({ item, verdict }, whoMustAct) {
511
+ return {
434
512
  version: item.version,
435
513
  entrypoints: item.entrypoints,
436
514
  title: item.title,
437
- whoMustAct: item.whoMustAct,
515
+ ...whoMustAct !== undefined && { whoMustAct },
438
516
  affects: item.affects ?? null,
439
517
  verdict: verdict.kind,
440
518
  ...verdict.kind === "affects" && { uses: verdict.uses },
441
519
  ...(verdict.kind === "behavioural" || verdict.kind === "not-declared") && {
442
520
  files: verdict.files
443
521
  }
444
- }));
522
+ };
445
523
  }
446
524
 
447
525
  // src/entrypoints/bin/upgrade-cli.ts
@@ -455,11 +533,13 @@ Options
455
533
  --to <version> target version (default: the version of this package)
456
534
  --cwd <dir> project to read the installed version and imports from (default: .)
457
535
  --changelog <path> changelog to plan from (default: the one in this package)
458
- --json print the breaking items and their verdicts as JSON
536
+ --json print the breaking items, the fixes and their verdicts as JSON
459
537
 
460
538
  Each breaking item is matched against what the project imports from stitchkit:
461
539
  "affects this project" (with file:line), "not used here", "behavioural — check
462
540
  by hand" or, for an item written before machine lines, "not declared — check by hand".
541
+ The fixes of the range that name what they touch get the same verdicts in a
542
+ second section; a fix that carries no such line is only counted.
463
543
  `;
464
544
  var SKIPPED_DIRECTORIES = new Set(["node_modules", ".git", ".next", ".turbo", ".cache"]);
465
545
  var OUTPUT_DIRECTORIES = new Set(["dist", "build", "out", "coverage"]);
@@ -555,7 +635,7 @@ ${USAGE}`, code: 1 };
555
635
  const json = argv.includes("--json");
556
636
  if (from === to) {
557
637
  return json ? {
558
- output: `${JSON.stringify({ from, to, items: [], unscanned: [] }, null, 2)}
638
+ output: `${JSON.stringify({ from, to, items: [], fixes: [], fixesWithoutAffects: 0, unscanned: [] }, null, 2)}
559
639
  `,
560
640
  code: 0
561
641
  } : { output: `Already on ${to}. Nothing to upgrade.
@@ -569,14 +649,28 @@ ${USAGE}`, code: 1 };
569
649
  throw new Error(`Cannot read the changelog at ${changelogPath}`);
570
650
  }
571
651
  const plan = planUpgrade(changelog, from, to);
652
+ const fixes = planFixes(changelog, from, to);
572
653
  const { sources, unscanned } = projectSources(cwd);
573
- const verdicts = upgradeVerdicts(plan.flatMap((change) => change.items), scanStitchkitImports(sources));
654
+ const imports = scanStitchkitImports(sources);
655
+ const verdicts = upgradeVerdicts(plan.flatMap((change) => change.items), imports);
656
+ const fixVerdicts = upgradeVerdicts(fixes.declared, imports);
574
657
  if (json) {
575
- const document = { from, to, items: upgradeVerdictsJson(verdicts), unscanned };
658
+ const document = {
659
+ from,
660
+ to,
661
+ items: upgradeVerdictsJson(verdicts),
662
+ fixes: upgradeFixesJson(fixVerdicts),
663
+ fixesWithoutAffects: fixes.withoutAffects,
664
+ unscanned
665
+ };
576
666
  return { output: `${JSON.stringify(document, null, 2)}
577
667
  `, code: 0 };
578
668
  }
579
- const usage = renderUpgradeVerdicts(verdicts);
669
+ const usage = [
670
+ renderUpgradeVerdicts(verdicts),
671
+ renderUpgradeFixes(fixVerdicts, fixes.withoutAffects)
672
+ ].filter(Boolean).join(`
673
+ `);
580
674
  const skipped = unscanned.length === 0 ? "" : `
581
675
  ## Not scanned
582
676