stitchkit 0.106.0 → 0.106.1

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.
package/CHANGELOG.md CHANGED
@@ -15,6 +15,19 @@ additive**; the first breaking change landed in 0.10.0. Grep the file for
15
15
 
16
16
  ## [Unreleased]
17
17
 
18
+ ## [0.106.1] - 2026-10-06
19
+
20
+ ### Documentation
21
+
22
+ - `stitchkit/process` — the native IO guide no longer says `setsid -f helper` returns once the new
23
+ session exists: it forks and returns at once, its child calls `setsid()` a moment later, and a
24
+ leader that exits immediately still caught it in the group in 13 of 300 launches under load. The
25
+ deterministic form is a leader that waits until the helper has reported, after its own
26
+ `setsid()`, that it left.
27
+ - `stitchkit/process` — `NativeCommandError` names both causes of `COMMAND_CLEANUP`: handles left
28
+ open past `cleanupTimeoutMs` after a stop, and output pipes left open past `drainTimeoutMs` after
29
+ the leader exited. The error's `cause` holds the failure of the bound that tripped.
30
+
18
31
  ## [0.106.0] - 2026-10-06
19
32
 
20
33
  ### ⚠️ Breaking changes
@@ -183,8 +183,10 @@ declare const NativeCommandLimitReasonSchema: z.ZodEnum<{
183
183
  }>;
184
184
  /**
185
185
  * Thrown by `runNativeCommand`; `code` is `COMMAND_LIMIT` (see `reason`),
186
- * `COMMAND_UNAVAILABLE` (could not start) or `COMMAND_CLEANUP` (handles stayed open past
187
- * `cleanupTimeoutMs`).
186
+ * `COMMAND_UNAVAILABLE` (could not start) or `COMMAND_CLEANUP` (the command's resources were not
187
+ * proven closed): handles stayed open past `cleanupTimeoutMs` after a stop, or the output pipes
188
+ * stayed open past `drainTimeoutMs` after the leader exited. `cause` holds the failure of the
189
+ * bound that tripped.
188
190
  */
189
191
  export declare class NativeCommandError extends Error {
190
192
  readonly code: 'COMMAND_LIMIT' | 'COMMAND_UNAVAILABLE' | 'COMMAND_CLEANUP';
@@ -1 +1 @@
1
- {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../src/process/contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,QAAA,MAAM,6BAA6B;;;;;;;;;;;;2BAajC,CAAC;AACH;;;;;;GAMG;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEpF;;GAEG;AACH,eAAO,MAAM,0BAA0B,OAAO,CAAC;AAE/C,gGAAgG;AAChG,eAAO,MAAM,yBAAyB,UAAY,CAAC;AAEnD,QAAA,MAAM,6BAA6B;;;;;;;;;;;;;;;kBAOjC,CAAC;AACH;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AACpF,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAiC3F,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;gDAqBpB,UAAU,WACR,QAAQ,GAAG,QAAQ,UACpB,WAAW,KAChB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;uDAKX,uBAAuB,UAAU,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;uDAMrE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmF3C,CAAC;AACN;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAC9E,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,0BAA0B,CAAC,CAAC;AACrF,QAAA,MAAM,yBAAyB;;;;;;iBAU7B,CAAC;AACH;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E,QAAA,MAAM,8BAA8B;;;EAAwC,CAAC;AAE7E;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;aAezB,IAAI,EAAE,eAAe,GAAG,qBAAqB,GAAG,iBAAiB;IAdnF,2GAA2G;IAC3G,SAAgB,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,GAAG,SAAS,CAAC;IAEnF,YACE,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,YAAY,GAAG;QAAE,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAA;KAAE,EACpF;IACF,YACE,IAAI,EAAE,eAAe,GAAG,qBAAqB,GAAG,iBAAiB,EACjE,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,YAAY,GAAG;QAAE,MAAM,CAAC,EAAE,KAAK,CAAA;KAAE,EAC3C;CAgBH"}
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../src/process/contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,QAAA,MAAM,6BAA6B;;;;;;;;;;;;2BAajC,CAAC;AACH;;;;;;GAMG;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEpF;;GAEG;AACH,eAAO,MAAM,0BAA0B,OAAO,CAAC;AAE/C,gGAAgG;AAChG,eAAO,MAAM,yBAAyB,UAAY,CAAC;AAEnD,QAAA,MAAM,6BAA6B;;;;;;;;;;;;;;;kBAOjC,CAAC;AACH;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AACpF,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAiC3F,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;gDAqBpB,UAAU,WACR,QAAQ,GAAG,QAAQ,UACpB,WAAW,KAChB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;uDAKX,uBAAuB,UAAU,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;uDAMrE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmF3C,CAAC;AACN;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAC9E,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,0BAA0B,CAAC,CAAC;AACrF,QAAA,MAAM,yBAAyB;;;;;;iBAU7B,CAAC;AACH;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E,QAAA,MAAM,8BAA8B;;;EAAwC,CAAC;AAE7E;;;;;;GAMG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;aAezB,IAAI,EAAE,eAAe,GAAG,qBAAqB,GAAG,iBAAiB;IAdnF,2GAA2G;IAC3G,SAAgB,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,GAAG,SAAS,CAAC;IAEnF,YACE,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,YAAY,GAAG;QAAE,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAA;KAAE,EACpF;IACF,YACE,IAAI,EAAE,eAAe,GAAG,qBAAqB,GAAG,iBAAiB,EACjE,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,YAAY,GAAG;QAAE,MAAM,CAAC,EAAE,KAAK,CAAA;KAAE,EAC3C;CAgBH"}
package/llms/process.txt CHANGED
@@ -270,13 +270,15 @@ so a helper started in the background races the leader:
270
270
 
271
271
  | launched by the leader as | after the leader exits |
272
272
  |---|---|
273
- | `setsid -f helper` (returns once the new session exists) | survives |
273
+ | `setsid -f helper` | usually survives: `setsid -f` forks and returns at once, and the child calls `setsid()` a moment later, so a leader that exits immediately can still catch it in the group (13 of 300 launches under CPU load) |
274
274
  | `setsid helper &`, `(setsid helper &)`, `nohup helper &` | stopped: the leader usually exits before the background job has left the group |
275
+ | a launch the leader waits on until the helper reports it has left the group | survives |
275
276
  | any of these under `descendants: 'leave'` | survives |
276
277
 
277
- Start a daemon so that the session exists before the leader returns (`setsid -f`, or the
278
- daemon's own double fork followed by the leader waiting for it), or declare `'leave'`. Declare
279
- `'leave'` only for a helper that has to outlive the command while staying in its group:
278
+ Start a daemon so that the leader waits for the session to exist before it returns: the helper
279
+ writes its pid, or prints a line, only after its own `setsid()`, and the leader waits for that.
280
+ Or declare `'leave'`. Declare `'leave'` only for a helper that has to outlive the command while
281
+ staying in its group:
280
282
 
281
283
  ```ts
282
284
  await runNativeCommand({
@@ -622,7 +624,7 @@ Native POSIX Bun/Node one-shot command execution. See [native IO](../guide/nativ
622
624
  | `NativeCommandOptions` | type | executable/args, env policy, signal/deadline, bytes sink, finite cleanup limits, the `stop` policy and `descendants` (`'terminate-after-leader'`, the default: stop the group after the leader exits, or `'leave'`); `stdio` (`'pipe'`, or `'inherit'` for the caller's descriptors, refusing the pipe-only options) and `group` (`'own'`, or `'caller'`: joins the caller's process group, stops only the leader, refuses `descendants` and a group stop); `onLeaderStarted({ pid })` (once, after the leader exists), `drainTimeoutMs` (bound on the pipes staying open after the leader exited, `COMMAND_CLEANUP`); an unknown key is refused by name, a removed one (`killGraceMs`) with its replacement |
623
625
  | `NativeCommandStopPolicy` | type | how a cancelled command stops: `target` `'group'` (signal every member) or `'leader'` (signal only the leader; its exit ends the grace), `signal` (default `SIGTERM`), `graceMs` (at most one hour) before KILL to the group, and `killOn`, an `AbortSignal` that skips the grace; default `{ target: 'group', signal: 'SIGTERM', graceMs: 100 }` |
624
626
  | `NativeCommandResult` | type | observed nullable exit code/signal, `descendantsStopped` (members left in the group after the leader exited were stopped) and captured stdout/stderr bytes |
625
- | `NativeCommandError` | class | COMMAND_LIMIT with machine reason `deadline` or `output-budget`; COMMAND_UNAVAILABLE / COMMAND_CLEANUP have no limit reason. Preserves internal cause and existing constructor; caller-created limits without supplied reason remain unclassified |
627
+ | `NativeCommandError` | class | COMMAND_LIMIT with machine reason `deadline` or `output-budget`; COMMAND_UNAVAILABLE / COMMAND_CLEANUP have no limit reason; COMMAND_CLEANUP means the command's resources were not proven closed, either past `cleanupTimeoutMs` after a stop or past `drainTimeoutMs` after the leader exited, and `cause` holds that bound's failure. Preserves internal cause and existing constructor; caller-created limits without supplied reason remain unclassified |
626
628
 
627
629
  | `NativeCommandSettlement` | type | `exit` (the leader ended on its own), `stopped` (the command was stopped and the leader's exit after the stop observed: the stop's `cause` with `exitCode`/`signal`) or `error` (no exit observed), including synchronous native launch failure; `onLeaderSettled` runs once before drain, bounded by cleanupTimeoutMs, with a cancellable settlement signal; schema/pre-abort refusal creates no settlement obligation |
628
630
  | `observeProcessInstance` / `ProcessInstanceObservation` | function / type | Linux/Darwin lifetime observation; observed identity or unavailable with its original cause, never guessed absence |
package/llms-full.txt CHANGED
@@ -8412,13 +8412,15 @@ so a helper started in the background races the leader:
8412
8412
 
8413
8413
  | launched by the leader as | after the leader exits |
8414
8414
  |---|---|
8415
- | `setsid -f helper` (returns once the new session exists) | survives |
8415
+ | `setsid -f helper` | usually survives: `setsid -f` forks and returns at once, and the child calls `setsid()` a moment later, so a leader that exits immediately can still catch it in the group (13 of 300 launches under CPU load) |
8416
8416
  | `setsid helper &`, `(setsid helper &)`, `nohup helper &` | stopped: the leader usually exits before the background job has left the group |
8417
+ | a launch the leader waits on until the helper reports it has left the group | survives |
8417
8418
  | any of these under `descendants: 'leave'` | survives |
8418
8419
 
8419
- Start a daemon so that the session exists before the leader returns (`setsid -f`, or the
8420
- daemon's own double fork followed by the leader waiting for it), or declare `'leave'`. Declare
8421
- `'leave'` only for a helper that has to outlive the command while staying in its group:
8420
+ Start a daemon so that the leader waits for the session to exist before it returns: the helper
8421
+ writes its pid, or prints a line, only after its own `setsid()`, and the leader waits for that.
8422
+ Or declare `'leave'`. Declare `'leave'` only for a helper that has to outlive the command while
8423
+ staying in its group:
8422
8424
 
8423
8425
  ```ts
8424
8426
  await runNativeCommand({
@@ -22731,7 +22733,7 @@ Native POSIX Bun/Node one-shot command execution. See [native IO](../guide/nativ
22731
22733
  | `NativeCommandOptions` | type | executable/args, env policy, signal/deadline, bytes sink, finite cleanup limits, the `stop` policy and `descendants` (`'terminate-after-leader'`, the default: stop the group after the leader exits, or `'leave'`); `stdio` (`'pipe'`, or `'inherit'` for the caller's descriptors, refusing the pipe-only options) and `group` (`'own'`, or `'caller'`: joins the caller's process group, stops only the leader, refuses `descendants` and a group stop); `onLeaderStarted({ pid })` (once, after the leader exists), `drainTimeoutMs` (bound on the pipes staying open after the leader exited, `COMMAND_CLEANUP`); an unknown key is refused by name, a removed one (`killGraceMs`) with its replacement |
22732
22734
  | `NativeCommandStopPolicy` | type | how a cancelled command stops: `target` `'group'` (signal every member) or `'leader'` (signal only the leader; its exit ends the grace), `signal` (default `SIGTERM`), `graceMs` (at most one hour) before KILL to the group, and `killOn`, an `AbortSignal` that skips the grace; default `{ target: 'group', signal: 'SIGTERM', graceMs: 100 }` |
22733
22735
  | `NativeCommandResult` | type | observed nullable exit code/signal, `descendantsStopped` (members left in the group after the leader exited were stopped) and captured stdout/stderr bytes |
22734
- | `NativeCommandError` | class | COMMAND_LIMIT with machine reason `deadline` or `output-budget`; COMMAND_UNAVAILABLE / COMMAND_CLEANUP have no limit reason. Preserves internal cause and existing constructor; caller-created limits without supplied reason remain unclassified |
22736
+ | `NativeCommandError` | class | COMMAND_LIMIT with machine reason `deadline` or `output-budget`; COMMAND_UNAVAILABLE / COMMAND_CLEANUP have no limit reason; COMMAND_CLEANUP means the command's resources were not proven closed, either past `cleanupTimeoutMs` after a stop or past `drainTimeoutMs` after the leader exited, and `cause` holds that bound's failure. Preserves internal cause and existing constructor; caller-created limits without supplied reason remain unclassified |
22735
22737
 
22736
22738
  | `NativeCommandSettlement` | type | `exit` (the leader ended on its own), `stopped` (the command was stopped and the leader's exit after the stop observed: the stop's `cause` with `exitCode`/`signal`) or `error` (no exit observed), including synchronous native launch failure; `onLeaderSettled` runs once before drain, bounded by cleanupTimeoutMs, with a cancellable settlement signal; schema/pre-abort refusal creates no settlement obligation |
22737
22739
  | `observeProcessInstance` / `ProcessInstanceObservation` | function / type | Linux/Darwin lifetime observation; observed identity or unavailable with its original cause, never guessed absence |
package/llms.txt CHANGED
@@ -56,7 +56,7 @@ Load the slice for each entrypoint your code imports — `import … from 'stitc
56
56
  - **stitchkit/node**: [llms/node.txt](llms/node.txt) 3.1 KB
57
57
  - **stitchkit/agent-runtime/react**: [llms/agent-runtime-react.txt](llms/agent-runtime-react.txt) 1.0 KB
58
58
  - **stitchkit/agent-runtime/realtime**: [llms/agent-runtime-realtime.txt](llms/agent-runtime-realtime.txt) 2.6 KB
59
- - **stitchkit/process**: [llms/process.txt](llms/process.txt) 39.4 KB
59
+ - **stitchkit/process**: [llms/process.txt](llms/process.txt) 39.9 KB
60
60
  - **stitchkit/files/packaging**: [llms/files-packaging.txt](llms/files-packaging.txt) 2.8 KB
61
61
 
62
62
  ## Upgrading slices
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.106.0",
3
+ "version": "0.106.1",
4
4
  "description": "Contract-first backend framework — one defineContract() into an HTTP API, MCP tools, AI-agent tools and a typed client. Bun and Node.",
5
5
  "keywords": [
6
6
  "bun",
@@ -265,10 +265,10 @@
265
265
  "build:unlocked": "rm -rf dist && cp ../../CHANGELOG.md ./CHANGELOG.md && bun run build:js && chmod +x dist/entrypoints/bin/upgrade-cli.js && bun run build:types && bun scripts/check-browser-clean.mjs && bun scripts/check-browser-executes.mjs && bun scripts/check-env-live.mjs && bun scripts/check-public-types.mjs && bun scripts/check-durability-port-standalone.mjs && bun scripts/check-declarations-strict.mjs",
266
266
  "dev": "bun run build:entrypoints -- --watch",
267
267
  "prepack": "bun ../../scripts/sync-package-readme.ts && bun ../../scripts/gen-llms.ts && bun run build",
268
- "test": "bun test",
268
+ "test": "bun ../../scripts/test-leak-gate.ts -- bun test",
269
269
  "smoke:node": "node scripts/node-smoke.mjs",
270
270
  "smoke:next-ssr": "node scripts/next-ssr-retry-smoke.mjs",
271
- "consumer-lane": "bun scripts/consumer-lane/run.mjs",
271
+ "consumer-lane": "bun ../../scripts/test-leak-gate.ts -- bun scripts/consumer-lane/run.mjs",
272
272
  "bench:mcp-preparation": "bun scripts/benchmark-mcp-preparation.ts",
273
273
  "bench:durable-store": "bun scripts/bench-durable-store.ts",
274
274
  "build:entrypoints": "bun scripts/generate-native-assets.ts && bun scripts/build-entrypoints.mjs"