stitchkit 0.105.0 → 0.105.2

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 (40) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/dist/entrypoints/agent-runtime/coding-tools.js +3 -3
  3. package/dist/entrypoints/agent-runtime/sandbox.js +3 -3
  4. package/dist/entrypoints/application/directory-inbox.js +3 -3
  5. package/dist/entrypoints/cli/publish.js +4 -4
  6. package/dist/entrypoints/cli.js +3 -3
  7. package/dist/entrypoints/files/packaging.js +10 -4
  8. package/dist/entrypoints/files.js +3 -3
  9. package/dist/entrypoints/process.js +1 -1
  10. package/dist/entrypoints/server.js +3 -3
  11. package/dist/entrypoints/telegram.js +2 -2
  12. package/dist/entrypoints/tools.js +3 -3
  13. package/dist/files/native-packaging.d.ts.map +1 -1
  14. package/dist/{index-2rc6jd9n.js → index-1ptj98e0.js} +1 -1
  15. package/dist/{index-g2vfg7ak.js → index-3s86a7kf.js} +39 -11
  16. package/dist/{index-ef8gdaq0.js → index-cazts87s.js} +1 -1
  17. package/dist/{index-szybbezc.js → index-drs41arz.js} +1 -1
  18. package/dist/{index-cq59agna.js → index-j4zh647a.js} +9 -1
  19. package/dist/{index-ma963wz7.js → index-sevbwsnn.js} +2 -2
  20. package/dist/{index-wqmvtnkp.js → index-w8etpm8j.js} +1 -1
  21. package/dist/internal/atomic-staging.d.ts +2 -1
  22. package/dist/internal/atomic-staging.d.ts.map +1 -1
  23. package/dist/process/cleanup.d.ts +1 -1
  24. package/dist/process/cleanup.d.ts.map +1 -1
  25. package/dist/process/command-lifetime.d.ts +2 -1
  26. package/dist/process/command-lifetime.d.ts.map +1 -1
  27. package/dist/process/command-owner.d.ts +1 -0
  28. package/dist/process/command-owner.d.ts.map +1 -1
  29. package/dist/process/contract.d.ts +9 -2
  30. package/dist/process/contract.d.ts.map +1 -1
  31. package/dist/process/group.d.ts +4 -2
  32. package/dist/process/group.d.ts.map +1 -1
  33. package/dist/process/terminate.d.ts +3 -2
  34. package/dist/process/terminate.d.ts.map +1 -1
  35. package/llms/files-packaging.txt +2 -0
  36. package/llms/files.txt +1 -1
  37. package/llms/process.txt +49 -11
  38. package/llms-full.txt +52 -12
  39. package/llms.txt +2 -2
  40. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -15,6 +15,50 @@ additive**; the first breaking change landed in 0.10.0. Grep the file for
15
15
 
16
16
  ## [Unreleased]
17
17
 
18
+ ## [0.105.2] - 2026-10-06
19
+
20
+ ### Added
21
+
22
+ - `stitchkit/process` — `runNativeCommand` takes `onLeaderStarted({ pid })`, called once right
23
+ after the leader exists (a throw stops the command with that error), and `drainTimeoutMs`,
24
+ which bounds how long the output pipes may stay open after the leader exited: a holder that
25
+ left the group with `setsid` otherwise keeps the command waiting until `timeoutMs` or the
26
+ signal, and with the bound it ends with `COMMAND_CLEANUP`.
27
+
28
+ ### Documentation
29
+
30
+ - `stitchkit/process` — the native IO guide no longer says that `cleanupTimeoutMs` bounds the drain
31
+ after the leader exited; it bounds the wait after a stop, and `drainTimeoutMs` bounds the drain.
32
+
33
+ ## [0.105.1] - 2026-10-06
34
+
35
+ ### Added
36
+
37
+ - `stitchkit/process` — `NativeCommandResult.descendantsStopped` reports that the group still had
38
+ members after the leader exited and that `descendants: 'terminate-after-leader'` stopped them,
39
+ so a helper ended this way is visible in the result instead of only missing afterwards.
40
+ - `stitchkit/files/packaging` — `assetPath` accepts `[hash]`, replaced by the first 16 hex digits
41
+ of the addon's published SHA256, so two installed versions get different companion names
42
+ (`addons/darwin-arm64-[hash].node`); the loader requires exactly that name.
43
+
44
+ ### Fixed
45
+
46
+ - `stitchkit/files` — `sweepAtomicStaging` returns `[]` for a `directory` that does not exist yet
47
+ instead of throwing `ENOENT`; any other listing failure still throws.
48
+ - `stitchkit/process` — an option `runNativeCommand` does not know is refused by name, and the
49
+ removed `killGraceMs` names its replacement, `stop: { target: 'group', graceMs }`: a spread
50
+ object can carry a key the type never checked.
51
+
52
+ ### Documentation
53
+
54
+ - `stitchkit/process` — the 0.105.0 note that a descendant leaving the group with `setsid` is
55
+ unaffected holds only when it has left before the leader exits: `setsid helper &` and
56
+ `nohup helper &` race the leader and are stopped, `setsid -f helper` survives. The native IO
57
+ guide shows the measured forms, how a guardian or worker that holds a child until it exits
58
+ maps onto `runNativeCommand`, and why a child inheriting the terminal stays a plain spawn.
59
+ - `stitchkit/files/packaging` — calling `createNativePackaging` has to stay in the build step;
60
+ importing the leaf from a module that is also bundled is side-effect free.
61
+
18
62
  ## [0.105.0] - 2026-10-05
19
63
 
20
64
  ### ⚠️ Breaking changes
@@ -7,10 +7,10 @@ import {
7
7
  AgentCodingToolAuthorizationSchema2,
8
8
  AgentCodingToolPathAuthorizationSchema2,
9
9
  createAgentCodingTools2
10
- } from "../../index-ma963wz7.js";
10
+ } from "../../index-sevbwsnn.js";
11
11
  import"../../index-v5ee8ath.js";
12
- import"../../index-cq59agna.js";
13
- import"../../index-g2vfg7ak.js";
12
+ import"../../index-j4zh647a.js";
13
+ import"../../index-3s86a7kf.js";
14
14
  import"../../index-8ks9b85e.js";
15
15
  import"../../index-gxm9rc97.js";
16
16
  import"../../index-yvfk3y36.js";
@@ -9,9 +9,9 @@ import"../../index-r393tnfp.js";
9
9
  import"../../index-rpzewktb.js";
10
10
  import {
11
11
  createAgentCodingTools2
12
- } from "../../index-ma963wz7.js";
12
+ } from "../../index-sevbwsnn.js";
13
13
  import"../../index-v5ee8ath.js";
14
- import"../../index-cq59agna.js";
14
+ import"../../index-j4zh647a.js";
15
15
  import {
16
16
  COMMAND_CLEANUP_TIMEOUT_MS,
17
17
  NativeCommandError2,
@@ -19,7 +19,7 @@ import {
19
19
  nativeCommandOwner,
20
20
  terminateOwnedGroup,
21
21
  startNativeCommand
22
- } from "../../index-g2vfg7ak.js";
22
+ } from "../../index-3s86a7kf.js";
23
23
  import"../../index-gxm9rc97.js";
24
24
  import {
25
25
  MAX_TIMER_MS
@@ -10,7 +10,7 @@ import {
10
10
  renewEntry,
11
11
  forgetMissing
12
12
  } from "../../index-msfpyy2f.js";
13
- import"../../index-cq59agna.js";
13
+ import"../../index-j4zh647a.js";
14
14
  import {
15
15
  backoffDelay
16
16
  } from "../../index-g6a3na27.js";
@@ -19,7 +19,7 @@ import"../../index-azx12jgv.js";
19
19
  import"../../index-v5ee8ath.js";
20
20
  import {
21
21
  createFileStateStore2
22
- } from "../../index-2rc6jd9n.js";
22
+ } from "../../index-1ptj98e0.js";
23
23
  import {
24
24
  defineManagedResource2
25
25
  } from "../../index-50ejfz75.js";
@@ -37,7 +37,7 @@ import {
37
37
  } from "../../index-m616f0yz.js";
38
38
  import {
39
39
  writeAtomicFileData
40
- } from "../../index-ef8gdaq0.js";
40
+ } from "../../index-cazts87s.js";
41
41
  import {
42
42
  closeAfter,
43
43
  publishAtomicFile
@@ -1,9 +1,9 @@
1
1
  import"../../index-xqhede6x.js";
2
- import"../../index-cq59agna.js";
2
+ import"../../index-j4zh647a.js";
3
3
  import {
4
4
  ManagedFileError2,
5
5
  createManagedFileBoundary2
6
- } from "../../index-wqmvtnkp.js";
6
+ } from "../../index-w8etpm8j.js";
7
7
  import"../../index-dsnjzb62.js";
8
8
  import"../../index-azx12jgv.js";
9
9
  import"../../index-v5ee8ath.js";
@@ -20,13 +20,13 @@ import {
20
20
  gzipCliAsset,
21
21
  decodeCliAsset,
22
22
  compareCliVersions2
23
- } from "../../index-szybbezc.js";
23
+ } from "../../index-drs41arz.js";
24
24
  import {
25
25
  withExclusiveLock2
26
26
  } from "../../index-4vsby8n8.js";
27
27
  import {
28
28
  writeFileAtomic2
29
- } from "../../index-ef8gdaq0.js";
29
+ } from "../../index-cazts87s.js";
30
30
  import {
31
31
  AtomicFilePublicationError2,
32
32
  assertDirectoryDurability,
@@ -16,7 +16,7 @@ import {
16
16
  pollUntilDone2,
17
17
  createCli2
18
18
  } from "../index-ksfagmyz.js";
19
- import"../index-cq59agna.js";
19
+ import"../index-j4zh647a.js";
20
20
  import {
21
21
  AppError2
22
22
  } from "../index-j9gxbztg.js";
@@ -45,10 +45,10 @@ import {
45
45
  checkCliUpdate2,
46
46
  applyCliUpdate2,
47
47
  rollbackCliUpdate2
48
- } from "../index-szybbezc.js";
48
+ } from "../index-drs41arz.js";
49
49
  import {
50
50
  writeFileAtomicSync2
51
- } from "../index-ef8gdaq0.js";
51
+ } from "../index-cazts87s.js";
52
52
  import"../index-pz3y6b6g.js";
53
53
  import"../index-yvfk3y36.js";
54
54
  import {
@@ -65,17 +65,20 @@ var CommonOptions = {
65
65
  platform: PlatformSchema,
66
66
  entryPath: RelativePathSchema.refine((value) => !value.includes("[") && !value.includes("]"), "Expected a fixed entry path without Bun naming templates")
67
67
  };
68
+ var ASSET_HASH_TOKEN = "[hash]";
69
+ var ASSET_HASH_LENGTH = 16;
70
+ var AssetPathSchema = RelativePathSchema.refine((value) => !/[[\]]/.test(value.replaceAll(ASSET_HASH_TOKEN, "")), "Expected an addon path whose only template is [hash]");
68
71
  var SingleOptionsSchema = z2.object({
69
72
  ...CommonOptions,
70
73
  architecture: z2.string().min(1),
71
74
  delivery: z2.enum(["companion", "embedded"]),
72
- assetPath: RelativePathSchema
75
+ assetPath: AssetPathSchema
73
76
  });
74
77
  var MultipleOptionsSchema = z2.object({
75
78
  ...CommonOptions,
76
79
  architecture: z2.array(z2.string().min(1)).refine((targets) => targets.length > 0),
77
80
  delivery: z2.literal("companion"),
78
- assetPath: z2.record(z2.string().min(1), RelativePathSchema)
81
+ assetPath: z2.record(z2.string().min(1), AssetPathSchema)
79
82
  });
80
83
  var OptionsSchema = z2.union([SingleOptionsSchema, MultipleOptionsSchema]).check((ctx) => {
81
84
  const input = ctx.value;
@@ -220,13 +223,16 @@ function createNativePackaging(options) {
220
223
  const specifiers = {};
221
224
  const embedded = new Map;
222
225
  for (const architecture of architectures) {
223
- const outputPath = typeof input.assetPath === "string" ? input.assetPath : input.assetPath[architecture];
224
- if (!outputPath)
226
+ const template = typeof input.assetPath === "string" ? input.assetPath : input.assetPath[architecture];
227
+ if (!template)
225
228
  throw new Error("Declared architecture has no output path");
226
229
  const verified = readVerifiedAsset(root, published.assets[architecture], input.platform, architecture);
227
230
  if ("refusal" in verified)
228
231
  return verified.refusal;
229
232
  const { sourcePath, bytes, size, sha256 } = verified;
233
+ const outputPath = template.replaceAll(ASSET_HASH_TOKEN, sha256.slice(0, ASSET_HASH_LENGTH));
234
+ if (assets.some((asset) => asset.outputPath === outputPath))
235
+ throw new Error("Addons must have distinct output paths");
230
236
  if (input.delivery === "embedded")
231
237
  embedded.set(sourcePath, new Uint8Array(bytes));
232
238
  const outputSpecifier = relative(dirname(input.entryPath), outputPath).split("\\").join("/");
@@ -6,11 +6,11 @@ import {
6
6
  stagingPath,
7
7
  isAtomicStagingName2,
8
8
  sweepAtomicStaging2
9
- } from "../index-cq59agna.js";
9
+ } from "../index-j4zh647a.js";
10
10
  import {
11
11
  ManagedFileError2,
12
12
  createManagedFileBoundary2
13
- } from "../index-wqmvtnkp.js";
13
+ } from "../index-w8etpm8j.js";
14
14
  import {
15
15
  AppError2
16
16
  } from "../index-j9gxbztg.js";
@@ -24,7 +24,7 @@ import {
24
24
  import {
25
25
  writeFileAtomic2,
26
26
  writeFileAtomicSync2
27
- } from "../index-ef8gdaq0.js";
27
+ } from "../index-cazts87s.js";
28
28
  import {
29
29
  AtomicFilePublicationError2
30
30
  } from "../index-b56nnscm.js";
@@ -7,7 +7,7 @@ import {
7
7
  import {
8
8
  NativeCommandError2,
9
9
  startNativeCommand
10
- } from "../index-g2vfg7ak.js";
10
+ } from "../index-3s86a7kf.js";
11
11
  // src/process/command.ts
12
12
  function runNativeCommand(input) {
13
13
  return startNativeCommand(input).result;
@@ -1,10 +1,10 @@
1
- import"../index-cq59agna.js";
1
+ import"../index-j4zh647a.js";
2
2
  import"../index-dsnjzb62.js";
3
3
  import"../index-azx12jgv.js";
4
4
  import"../index-v5ee8ath.js";
5
5
  import {
6
6
  createFileStateStore2
7
- } from "../index-2rc6jd9n.js";
7
+ } from "../index-1ptj98e0.js";
8
8
  import {
9
9
  AppError2,
10
10
  notFound2,
@@ -96,7 +96,7 @@ import {
96
96
  isWithinDir2,
97
97
  realPathWithinDir
98
98
  } from "../index-5cc6r990.js";
99
- import"../index-ef8gdaq0.js";
99
+ import"../index-cazts87s.js";
100
100
  import {
101
101
  DEFAULT_CORS_ALLOW_HEADERS2,
102
102
  DEFAULT_CORS_EXPOSE_HEADERS2,
@@ -8,7 +8,7 @@ import {
8
8
  TELEGRAM_SEND_FAILURE_REASONS2,
9
9
  classifyTelegramSendFailure2
10
10
  } from "../index-e05cjgtf.js";
11
- import"../index-cq59agna.js";
11
+ import"../index-j4zh647a.js";
12
12
  import {
13
13
  attemptExclusiveLock
14
14
  } from "../index-dsnjzb62.js";
@@ -23,7 +23,7 @@ import {
23
23
  } from "../index-b0kddvzw.js";
24
24
  import {
25
25
  writeFileAtomic2
26
- } from "../index-ef8gdaq0.js";
26
+ } from "../index-cazts87s.js";
27
27
  import {
28
28
  MAX_TIMER_MS,
29
29
  sleep
@@ -85,10 +85,10 @@ import {
85
85
  ManagedFilePathSchema2,
86
86
  ManagedFileRefSchema2
87
87
  } from "../index-xqhede6x.js";
88
- import"../index-cq59agna.js";
88
+ import"../index-j4zh647a.js";
89
89
  import {
90
90
  ManagedFileError2
91
- } from "../index-wqmvtnkp.js";
91
+ } from "../index-w8etpm8j.js";
92
92
  import {
93
93
  fetchGuarded,
94
94
  fetchPinnedDocument,
@@ -102,7 +102,7 @@ import {
102
102
  contractOnlyService,
103
103
  mediaTypeEssence
104
104
  } from "../index-cmzvhhtd.js";
105
- import"../index-ef8gdaq0.js";
105
+ import"../index-cazts87s.js";
106
106
  import {
107
107
  collectToolSurface
108
108
  } from "../index-pz3y6b6g.js";
@@ -1 +1 @@
1
- {"version":3,"file":"native-packaging.d.ts","sourceRoot":"","sources":["../../src/files/native-packaging.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"native-packaging.d.ts","sourceRoot":"","sources":["../../src/files/native-packaging.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,7 @@ import {
6
6
  } from "./index-m616f0yz.js";
7
7
  import {
8
8
  writeAtomicFileData
9
- } from "./index-ef8gdaq0.js";
9
+ } from "./index-cazts87s.js";
10
10
  import {
11
11
  publishAtomicFile
12
12
  } from "./index-b56nnscm.js";
@@ -27,6 +27,16 @@ var NativeCommandStopPolicySchema = z.strictObject({
27
27
  graceMs: z.number().int().nonnegative().max(MAX_COMMAND_STOP_GRACE_MS),
28
28
  killOn: z.custom((v) => v instanceof AbortSignal).optional()
29
29
  });
30
+ var REMOVED_NATIVE_COMMAND_OPTIONS = {
31
+ killGraceMs: "stop: { target: 'group', graceMs } (removed in 0.105.0)"
32
+ };
33
+ function unknownOptionMessage(keys) {
34
+ return keys.map((key) => {
35
+ const name = String(key);
36
+ const replacement = Object.hasOwn(REMOVED_NATIVE_COMMAND_OPTIONS, name) ? REMOVED_NATIVE_COMMAND_OPTIONS[name] : undefined;
37
+ return replacement === undefined ? `Unknown runNativeCommand option ${name}` : `Unknown runNativeCommand option ${name}; use ${replacement}`;
38
+ }).join("; ");
39
+ }
30
40
  var NativeCommandOptionsSchema = z.strictObject({
31
41
  executable: z.string().min(1),
32
42
  args: z.array(z.string()).default([]),
@@ -41,6 +51,8 @@ var NativeCommandOptionsSchema = z.strictObject({
41
51
  maxStdinBytes: z.number().int().positive().default(1024 * 1024),
42
52
  onOutput: z.custom((v) => typeof v === "function").optional(),
43
53
  onLeaderSettled: z.custom((v) => typeof v === "function").optional(),
54
+ onLeaderStarted: z.custom((v) => typeof v === "function").optional(),
55
+ drainTimeoutMs: z.number().int().positive().max(MAX_TIMER_MS).optional(),
44
56
  stop: NativeCommandStopPolicySchema.default({
45
57
  target: "group",
46
58
  signal: "SIGTERM",
@@ -48,6 +60,8 @@ var NativeCommandOptionsSchema = z.strictObject({
48
60
  }),
49
61
  descendants: z.enum(["terminate-after-leader", "leave"]).default("terminate-after-leader"),
50
62
  cleanupTimeoutMs: z.number().int().positive().max(30000).default(COMMAND_CLEANUP_TIMEOUT_MS)
63
+ }, {
64
+ error: (issue) => issue.code === "unrecognized_keys" ? unknownOptionMessage(issue.keys) : undefined
51
65
  }).check((ctx) => {
52
66
  const input = ctx.value;
53
67
  if (!input.signal && input.timeoutMs === undefined)
@@ -72,6 +86,7 @@ var NativeCommandOptionsSchema = z.strictObject({
72
86
  var NativeCommandResultSchema = z.object({
73
87
  exitCode: z.number().int().nullable(),
74
88
  signal: z.string().nullable(),
89
+ descendantsStopped: z.boolean(),
75
90
  stdout: z.instanceof(Uint8Array),
76
91
  stderr: z.instanceof(Uint8Array)
77
92
  });
@@ -158,12 +173,10 @@ async function signalUntilSettled(pid, signal, deadline) {
158
173
  async function stopCommandGroup(stop) {
159
174
  const { pid, policy } = stop;
160
175
  const deadline = performance.now() + policy.graceMs + stop.cleanupTimeoutMs;
161
- if (stop.force || policy.killOn?.aborted) {
162
- await signalUntilSettled(pid, "SIGKILL", deadline);
163
- return;
164
- }
176
+ if (stop.force || policy.killOn?.aborted)
177
+ return signalUntilSettled(pid, "SIGKILL", deadline);
165
178
  if (!await signalUntilSettled(pid, policy.signal, deadline))
166
- return;
179
+ return false;
167
180
  const until = performance.now() + policy.graceMs;
168
181
  let interval = 10;
169
182
  let present = exists(pid);
@@ -176,14 +189,17 @@ async function stopCommandGroup(stop) {
176
189
  }
177
190
  if (present)
178
191
  await signalUntilSettled(pid, "SIGKILL", deadline);
192
+ return true;
179
193
  }
180
194
  async function stopCommandLeader(stop) {
181
195
  const { pid, policy, leader } = stop;
182
196
  const deadline = performance.now() + policy.graceMs + stop.cleanupTimeoutMs;
183
197
  const running = () => leader.exitCode === null && leader.signalCode === null;
198
+ let signalled = false;
184
199
  if (!stop.force && !policy.killOn?.aborted && pid !== undefined && running()) {
185
200
  try {
186
201
  process.kill(pid, policy.signal);
202
+ signalled = true;
187
203
  } catch (error) {
188
204
  if (!isErrno(error, "ESRCH"))
189
205
  throw error;
@@ -198,7 +214,7 @@ async function stopCommandLeader(stop) {
198
214
  policy.killOn?.removeEventListener("abort", end);
199
215
  grace.abort();
200
216
  }
201
- await signalUntilSettled(pid, "SIGKILL", deadline);
217
+ return await signalUntilSettled(pid, "SIGKILL", deadline) || signalled;
202
218
  }
203
219
  function commandCleanupError(cause) {
204
220
  return new NativeCommandError2("COMMAND_CLEANUP", "Command cleanup did not complete", {
@@ -616,8 +632,11 @@ function signalCommandChild(child, input) {
616
632
  return input.policy.target === "leader" ? stopCommandLeader({ ...stop, leader: child, leaderExit: input.leaderExit }) : stopCommandGroup(stop);
617
633
  }
618
634
  return Promise.resolve().then(() => {
619
- if (child.exitCode === null && child.signalCode === null && !child.kill("SIGKILL"))
635
+ if (child.exitCode !== null || child.signalCode !== null)
636
+ return false;
637
+ if (!child.kill("SIGKILL"))
620
638
  throw new Error("Command leader termination was refused");
639
+ return true;
621
640
  });
622
641
  }
623
642
  async function terminateOwnedGroup(child, closed, cleanupTimeoutMs) {
@@ -677,7 +696,7 @@ function startNativeCommand(input, onSpawn, driver) {
677
696
  });
678
697
  const signalOwned = (force = driver?.force) => {
679
698
  if (!acquired)
680
- return Promise.resolve();
699
+ return Promise.resolve(false);
681
700
  return signalCommandChild(acquired.child, {
682
701
  group: driver?.group !== false,
683
702
  policy: options.stop,
@@ -731,7 +750,7 @@ function startNativeCommand(input, onSpawn, driver) {
731
750
  const stderr = [];
732
751
  let total = 0;
733
752
  const { stdout: output, stderr: errorOutput, leader, closed } = launched;
734
- const cancelCloseDeadline = createLeaderCloseDeadline(leader, driver?.closeTimeoutMs, controller);
753
+ const cancelCloseDeadline = createLeaderCloseDeadline(leader, driver?.closeTimeoutMs ?? options.drainTimeoutMs, controller);
735
754
  const drain = async (stream, channel, captured) => {
736
755
  for await (const chunk of stream) {
737
756
  if (controller.signal.aborted)
@@ -757,6 +776,7 @@ function startNativeCommand(input, onSpawn, driver) {
757
776
  }
758
777
  }
759
778
  };
779
+ let descendantsStopped = false;
760
780
  const settleLeader = async (event) => {
761
781
  await settle(event);
762
782
  if (controller.signal.aborted)
@@ -764,7 +784,7 @@ function startNativeCommand(input, onSpawn, driver) {
764
784
  if (options.descendants !== "terminate-after-leader" || event.kind !== "exit")
765
785
  return;
766
786
  try {
767
- await signalOwned();
787
+ descendantsStopped = await signalOwned();
768
788
  } catch (cause) {
769
789
  throw commandCleanupError(cause);
770
790
  }
@@ -772,6 +792,9 @@ function startNativeCommand(input, onSpawn, driver) {
772
792
  const run = (async () => {
773
793
  try {
774
794
  launched.start();
795
+ const pid = acquired?.child.pid;
796
+ if (pid !== undefined)
797
+ options.onLeaderStarted?.({ pid });
775
798
  const drains = Promise.all([
776
799
  drain(output, "stdout", stdout),
777
800
  drain(errorOutput, "stderr", stderr)
@@ -780,7 +803,12 @@ function startNativeCommand(input, onSpawn, driver) {
780
803
  const status = await raceAbort(closed, controller.signal);
781
804
  if (spawnFailure !== undefined)
782
805
  throw spawnFailure;
783
- return { ...status, stdout: Buffer.concat(stdout), stderr: Buffer.concat(stderr) };
806
+ return {
807
+ ...status,
808
+ descendantsStopped,
809
+ stdout: Buffer.concat(stdout),
810
+ stderr: Buffer.concat(stderr)
811
+ };
784
812
  } catch (error) {
785
813
  controller.abort(error);
786
814
  await cleanupNativeCommand({
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  stagingPath
3
- } from "./index-cq59agna.js";
3
+ } from "./index-j4zh647a.js";
4
4
  import {
5
5
  closeAfter,
6
6
  closeAfterSync,
@@ -11,7 +11,7 @@ import {
11
11
  } from "./index-b0kddvzw.js";
12
12
  import {
13
13
  writeFileAtomicSync2
14
- } from "./index-ef8gdaq0.js";
14
+ } from "./index-cazts87s.js";
15
15
  import {
16
16
  assertPositiveSafeInteger
17
17
  } from "./index-0s4xebbg.js";
@@ -29,7 +29,15 @@ async function sweepAtomicStaging2(options) {
29
29
  signal?.throwIfAborted();
30
30
  const cutoff = Date.now() - olderThanMs;
31
31
  const removed = [];
32
- for (const name of await readdir(directory)) {
32
+ let names;
33
+ try {
34
+ names = await readdir(directory);
35
+ } catch (error) {
36
+ if (isMissing(error))
37
+ return removed;
38
+ throw error;
39
+ }
40
+ for (const name of names) {
33
41
  signal?.throwIfAborted();
34
42
  if (!isAtomicStagingName2(name))
35
43
  continue;
@@ -7,12 +7,12 @@ import {
7
7
  } from "./index-v5ee8ath.js";
8
8
  import {
9
9
  stagingName
10
- } from "./index-cq59agna.js";
10
+ } from "./index-j4zh647a.js";
11
11
  import {
12
12
  NativeCommandError2,
13
13
  CommandStopped,
14
14
  startNativeCommand
15
- } from "./index-g2vfg7ak.js";
15
+ } from "./index-3s86a7kf.js";
16
16
  import {
17
17
  probeAgentProcessSandboxOutcome,
18
18
  missingSandboxRestrictions2,
@@ -15,7 +15,7 @@ import {
15
15
  import {
16
16
  writeAllBytes,
17
17
  writeAtomicFileStaged
18
- } from "./index-ef8gdaq0.js";
18
+ } from "./index-cazts87s.js";
19
19
  import {
20
20
  AtomicFilePublicationError2
21
21
  } from "./index-b56nnscm.js";
@@ -40,7 +40,8 @@ export interface SweepAtomicStagingOptions {
40
40
  * Remove the abandoned staging files of atomic writes from one directory and return their
41
41
  * names. Only regular files matching {@link isAtomicStagingName} and older than `olderThanMs`
42
42
  * are removed; a symlink, a directory or any other entry is left alone, and nothing is
43
- * followed or recursed into.
43
+ * followed or recursed into. A `directory` that does not exist holds nothing to sweep and
44
+ * yields `[]`; any other listing failure (a file in its place, a denied read) throws.
44
45
  */
45
46
  export declare function sweepAtomicStaging(options: SweepAtomicStagingOptions): Promise<string[]>;
46
47
  //# sourceMappingURL=atomic-staging.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"atomic-staging.d.ts","sourceRoot":"","sources":["../../src/internal/atomic-staging.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAaH,mGAAmG;AACnG,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,4FAA4F;AAC5F,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,6CAA6C;AAC7C,MAAM,WAAW,yBAAyB;IACxC,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAQD;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,MAAM,EAAE,CAAC,CAsBnB"}
1
+ {"version":3,"file":"atomic-staging.d.ts","sourceRoot":"","sources":["../../src/internal/atomic-staging.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAaH,mGAAmG;AACnG,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,4FAA4F;AAC5F,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,6CAA6C;AAC7C,MAAM,WAAW,yBAAyB;IACxC,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAQD;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,MAAM,EAAE,CAAC,CA6BnB"}
@@ -11,7 +11,7 @@ export declare function cleanupNativeCommand(input: {
11
11
  transport?: NativeCommandTransport;
12
12
  settle: (event: NativeCommandSettlement) => Promise<void>;
13
13
  event?: NativeCommandSettlement;
14
- signal: () => Promise<void>;
14
+ signal: () => Promise<unknown>;
15
15
  timeoutMs: number;
16
16
  }): Promise<void>;
17
17
  //# sourceMappingURL=cleanup.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/process/cleanup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE1D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAE1D;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,EAAE;IAChD,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,sBAAsB,CAAC;IACnC,MAAM,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,KAAK,CAAC,EAAE,uBAAuB,CAAC;IAChC,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BhB"}
1
+ {"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/process/cleanup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE1D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAE1D;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,EAAE;IAChD,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,sBAAsB,CAAC;IACnC,MAAM,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,KAAK,CAAC,EAAE,uBAAuB,CAAC;IAChC,MAAM,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BhB"}
@@ -8,12 +8,13 @@ export declare function createCommandLifetime(input: {
8
8
  result: Promise<NativeCommandResult>;
9
9
  controller: AbortController;
10
10
  finished: () => boolean;
11
- signal: () => Promise<void>;
11
+ signal: () => Promise<unknown>;
12
12
  cleanupTimeoutMs: number;
13
13
  }): {
14
14
  result: Promise<{
15
15
  exitCode: number | null;
16
16
  signal: string | null;
17
+ descendantsStopped: boolean;
17
18
  stdout: Uint8Array<ArrayBuffer>;
18
19
  stderr: Uint8Array<ArrayBuffer>;
19
20
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"command-lifetime.d.ts","sourceRoot":"","sources":["../../src/process/command-lifetime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAG1E,gFAAgF;AAChF,qBAAa,cAAe,SAAQ,YAAY;IAC9C,cAEC;CACF;AAED,yFAAyF;AACzF,wBAAgB,qBAAqB,CAAC,KAAK,EAAE;IAC3C,MAAM,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACrC,UAAU,EAAE,eAAe,CAAC;IAC5B,QAAQ,EAAE,MAAM,OAAO,CAAC;IACxB,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;CAC1B;IAKG,MAAM;;;;;;IACA,SAAS;IAoBT,IAAI;EAKb"}
1
+ {"version":3,"file":"command-lifetime.d.ts","sourceRoot":"","sources":["../../src/process/command-lifetime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAG1E,gFAAgF;AAChF,qBAAa,cAAe,SAAQ,YAAY;IAC9C,cAEC;CACF;AAED,yFAAyF;AACzF,wBAAgB,qBAAqB,CAAC,KAAK,EAAE;IAC3C,MAAM,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACrC,UAAU,EAAE,eAAe,CAAC;IAC5B,QAAQ,EAAE,MAAM,OAAO,CAAC;IACxB,MAAM,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;CAC1B;IAKG,MAAM;;;;;;;IACA,SAAS;IAoBT,IAAI;EAKb"}
@@ -6,6 +6,7 @@ export declare function startNativeCommand(input: NativeCommandOptions, onSpawn?
6
6
  result: Promise<{
7
7
  exitCode: number | null;
8
8
  signal: string | null;
9
+ descendantsStopped: boolean;
9
10
  stdout: Uint8Array<ArrayBuffer>;
10
11
  stderr: Uint8Array<ArrayBuffer>;
11
12
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"command-owner.d.ts","sourceRoot":"","sources":["../../src/process/command-owner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AAIzE,OAAO,EAEL,KAAK,oBAAoB,EAI1B,MAAM,YAAY,CAAC;AAEpB,OAAO,EAEL,KAAK,yBAAyB,EAG/B,MAAM,UAAU,CAAC;AAMlB,wFAAwF;AACxF,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,oBAAoB,EAC3B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,8BAA8B,KAAK,IAAI,EACzD,MAAM,CAAC,EAAE,yBAAyB;;;;;;;;;EAyLnC"}
1
+ {"version":3,"file":"command-owner.d.ts","sourceRoot":"","sources":["../../src/process/command-owner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AAIzE,OAAO,EAEL,KAAK,oBAAoB,EAI1B,MAAM,YAAY,CAAC;AAEpB,OAAO,EAEL,KAAK,yBAAyB,EAG/B,MAAM,UAAU,CAAC;AAMlB,wFAAwF;AACxF,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,oBAAoB,EAC3B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,8BAA8B,KAAK,IAAI,EACzD,MAAM,CAAC,EAAE,yBAAyB;;;;;;;;;;EAiMnC"}
@@ -58,6 +58,12 @@ export declare const NativeCommandOptionsSchema: z.ZodObject<{
58
58
  maxStdinBytes: z.ZodDefault<z.ZodNumber>;
59
59
  onOutput: z.ZodOptional<z.ZodCustom<(bytes: Uint8Array, channel: 'stdout' | 'stderr', signal: AbortSignal) => void | Promise<void>, (bytes: Uint8Array, channel: 'stdout' | 'stderr', signal: AbortSignal) => void | Promise<void>>>;
60
60
  onLeaderSettled: z.ZodOptional<z.ZodCustom<(event: NativeCommandSettlement, signal: AbortSignal) => void | Promise<void>, (event: NativeCommandSettlement, signal: AbortSignal) => void | Promise<void>>>;
61
+ onLeaderStarted: z.ZodOptional<z.ZodCustom<(event: {
62
+ pid: number;
63
+ }) => void, (event: {
64
+ pid: number;
65
+ }) => void>>;
66
+ drainTimeoutMs: z.ZodOptional<z.ZodNumber>;
61
67
  stop: z.ZodDefault<z.ZodObject<{
62
68
  target: z.ZodEnum<{
63
69
  group: "group";
@@ -89,12 +95,13 @@ export type ParsedNativeCommandOptions = z.output<typeof NativeCommandOptionsSch
89
95
  declare const NativeCommandResultSchema: z.ZodObject<{
90
96
  exitCode: z.ZodNullable<z.ZodNumber>;
91
97
  signal: z.ZodNullable<z.ZodString>;
98
+ descendantsStopped: z.ZodBoolean;
92
99
  stdout: z.ZodInstanceOf<Uint8Array<ArrayBuffer>>;
93
100
  stderr: z.ZodInstanceOf<Uint8Array<ArrayBuffer>>;
94
101
  }, z.core.$strip>;
95
102
  /**
96
- * Exit code, signal and captured stdout and stderr bytes of a finished command; the buffers
97
- * stay empty unless `capture` was set.
103
+ * Exit code, signal, whether descendants were stopped after the leader exited, and captured
104
+ * stdout and stderr bytes of a finished command; the buffers stay empty unless `capture` was set.
98
105
  */
99
106
  export type NativeCommandResult = z.infer<typeof NativeCommandResultSchema>;
100
107
  declare const NativeCommandLimitReasonSchema: z.ZodEnum<{
@@ -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;;;;;;;2BAOjC,CAAC;AACH;;;GAGG;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;;;;GAIG;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;AAE3F,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;gDAoBtB,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;;;;;;;;;;;;;;;;;;;;;;kBAuCvF,CAAC;AACL;;;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;;;;;iBAK7B,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;;;;;;;2BAOjC,CAAC;AACH;;;GAGG;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;;;;GAIG;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;AAqB3F,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;;;;;;;;;;;;;;;;;;;;;;;;;kBAgD5C,CAAC;AACL;;;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"}
@@ -23,8 +23,9 @@ export interface CommandGroupStop {
23
23
  * A group still visible after the grace (including members holding a pipe after
24
24
  * the leader exited, or Darwin zombies awaiting the reaper) is killed. The probe
25
25
  * backs off to 250 ms, so a grace of an hour costs a few thousand probes, not millions.
26
+ * Resolves `true` when the group still had a member to receive the first signal.
26
27
  */
27
- export declare function stopCommandGroup(stop: CommandGroupStop): Promise<void>;
28
+ export declare function stopCommandGroup(stop: CommandGroupStop): Promise<boolean>;
28
29
  /** The leader of a stop with `target: 'leader'`: its exit state and the promise of its exit. */
29
30
  export interface CommandLeader {
30
31
  readonly pid?: number;
@@ -38,11 +39,12 @@ export interface CommandLeader {
38
39
  * The leader's exit ends the grace at once: the rest of the group are processes the leader
39
40
  * left behind, and nothing in them was asked to cooperate. A leader that has already
40
41
  * exited is not signalled again, because its pid may be reused once it was reaped.
42
+ * Resolves `true` when the leader or a member of its group received a signal.
41
43
  */
42
44
  export declare function stopCommandLeader(stop: CommandGroupStop & {
43
45
  leader: CommandLeader;
44
46
  leaderExit: Promise<unknown>;
45
- }): Promise<void>;
47
+ }): Promise<boolean>;
46
48
  export declare function commandCleanupError(cause: unknown): NativeCommandError;
47
49
  export declare function waitForCommandClose<T>(closed: Promise<T>, timeoutMs: number): Promise<T>;
48
50
  //# sourceMappingURL=group.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"group.d.ts","sourceRoot":"","sources":["../../src/process/group.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,KAAK,6BAA6B,EAAE,MAAM,YAAY,CAAC;AAEpF,+FAA+F;AAC/F,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO;IAYpE,MAAM;IACN,MAAM;EAIT;AAeD,gGAAgG;AAChG,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CASpF;AAmCD,sGAAsG;AACtG,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,6BAA6B,CAAC;IAC/C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB5E;AAED,gGAAgG;AAChG,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,gBAAgB,GAAG;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,GAC/E,OAAO,CAAC,IAAI,CAAC,CAoBf;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,CAItE;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAMxF"}
1
+ {"version":3,"file":"group.d.ts","sourceRoot":"","sources":["../../src/process/group.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,KAAK,6BAA6B,EAAE,MAAM,YAAY,CAAC;AAEpF,+FAA+F;AAC/F,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO;IAYpE,MAAM;IACN,MAAM;EAIT;AAeD,gGAAgG;AAChG,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CASpF;AAmCD,sGAAsG;AACtG,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,6BAA6B,CAAC;IAC/C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAmB/E;AAED,gGAAgG;AAChG,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,gBAAgB,GAAG;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,GAC/E,OAAO,CAAC,OAAO,CAAC,CAsBlB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,CAItE;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAMxF"}
@@ -7,7 +7,8 @@ interface SignalableChild extends CommandLeader {
7
7
  /**
8
8
  * Deliver the stop signals to `child` by its stop policy. A child this package spawned as a
9
9
  * group leader is stopped as a group (`target: 'group'`) or leader first (`'leader'`); any
10
- * other child is only a leader, killed while it still runs.
10
+ * other child is only a leader, killed while it still runs. Resolves `true` when a signal
11
+ * reached a process.
11
12
  */
12
13
  export declare function signalCommandChild(child: SignalableChild, input: {
13
14
  group: boolean;
@@ -16,7 +17,7 @@ export declare function signalCommandChild(child: SignalableChild, input: {
16
17
  leaderExit: Promise<unknown>;
17
18
  cleanupTimeoutMs: number;
18
19
  force: boolean;
19
- }): Promise<void>;
20
+ }): Promise<boolean>;
20
21
  interface ClosableChild extends SignalableChild {
21
22
  readonly stdin: {
22
23
  destroy(): unknown;
@@ -1 +1 @@
1
- {"version":3,"file":"terminate.d.ts","sourceRoot":"","sources":["../../src/process/terminate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,EACL,KAAK,aAAa,EAKnB,MAAM,SAAS,CAAC;AAGjB,mFAAmF;AACnF,UAAU,eAAgB,SAAQ,aAAa;IAC7C,IAAI,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;CAClC;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,eAAe,EACtB,KAAK,EAAE;IACL,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,6BAA6B,CAAC;IACtC,mFAAmF;IACnF,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,OAAO,CAAC;CAChB,GACA,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED,UAAU,aAAc,SAAQ,eAAe;IAC7C,QAAQ,CAAC,KAAK,EAAE;QAAE,OAAO,IAAI,OAAO,CAAA;KAAE,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE;QAAE,OAAO,IAAI,OAAO,CAAA;KAAE,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE;QAAE,OAAO,IAAI,OAAO,CAAA;KAAE,CAAC;CACzC;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,EACxB,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,IAAI,CAAC,CAcf"}
1
+ {"version":3,"file":"terminate.d.ts","sourceRoot":"","sources":["../../src/process/terminate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,EACL,KAAK,aAAa,EAKnB,MAAM,SAAS,CAAC;AAGjB,mFAAmF;AACnF,UAAU,eAAgB,SAAQ,aAAa;IAC7C,IAAI,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;CAClC;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,eAAe,EACtB,KAAK,EAAE;IACL,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,6BAA6B,CAAC;IACtC,mFAAmF;IACnF,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,OAAO,CAAC;CAChB,GACA,OAAO,CAAC,OAAO,CAAC,CAiBlB;AAED,UAAU,aAAc,SAAQ,eAAe;IAC7C,QAAQ,CAAC,KAAK,EAAE;QAAE,OAAO,IAAI,OAAO,CAAA;KAAE,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE;QAAE,OAAO,IAAI,OAAO,CAAA;KAAE,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE;QAAE,OAAO,IAAI,OAAO,CAAA;KAAE,CAAC;CACzC;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,EACxB,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,IAAI,CAAC,CAcf"}
@@ -20,6 +20,8 @@ It resolves the installed package's target/version, reads each selected addon on
20
20
  against the `size` and `sha256` published in the package's `native-assets.json` (`formatVersion: 2`,
21
21
  written when Stitchkit is built). Call it once per build and reuse the result.
22
22
  `platform`, `architecture`, `delivery`, `entryPath` and `assetPath` are explicit public inputs;
23
+ `assetPath` accepts one template, `[hash]`, replaced by the first 16 hex digits of the addon's
24
+ published SHA256;
23
25
  `platform` is the closed set `'darwin'`, and another name is a type error and a schema refusal.
24
26
  The result is `ready` with verified assets and a structural Bun plugin, or `unsupported` /
25
27
  `missing` / `mismatch` with the safe code `NATIVE_TARGET_UNSUPPORTED`, `NATIVE_ASSET_MISSING` or
package/llms/files.txt CHANGED
@@ -31,7 +31,7 @@ available from `stitchkit/contract`.
31
31
  | `ManagedFileInspectionInput` / `ManagedFileInspection` | _type_ | inspector prefix/name/declared media/signal input and validated metadata-only result |
32
32
  | `writeFileAtomic` / `writeFileAtomicSync` / `WriteFileAtomicOptions` | function / _type_ | replace a file atomically: a random staging name created exclusively (never through a planted link), the mode set on the descriptor before the file is visible (default `0o600`, not masked by the umask), `fsync`, rename; a failure leaves the target and no staging file. The asynchronous form keeps the event loop running. A process killed before publication leaves its staging file; sweeping it is the caller's job |
33
33
  | `isAtomicStagingName` | function | true for a staging file name of an atomic write of this library (`.stitchkit-<24 lowercase hex>.tmp`, also used by the managed writer and the chunk spool); the form is a stable contract, and changing it is a breaking change ([ADR 0242](../decisions/0242-atomic-staging-name-is-a-public-contract.md)) |
34
- | `sweepAtomicStaging` / `SweepAtomicStagingOptions` | function / _type_ | remove abandoned staging files from one `directory`: only regular files matching `isAtomicStagingName` and older than the required `olderThanMs`, never following a symlink or entering a subdirectory; stops on `signal`; returns the removed names |
34
+ | `sweepAtomicStaging` / `SweepAtomicStagingOptions` | function / _type_ | remove abandoned staging files from one `directory`: only regular files matching `isAtomicStagingName` and older than the required `olderThanMs`, never following a symlink or entering a subdirectory; stops on `signal`; returns the removed names, `[]` for a `directory` that does not exist |
35
35
  | `withExclusiveLock` / `ExclusiveLockOptions` / `ExclusiveLock` / `ExclusiveLockOwner` | function / _type_ | run work under an exclusive lock between processes — a file recording its owner (pid, host, machine identity, time and nullable kernel process identity); waits up to `timeoutMs` (default 10 s) and stops on `signal`; a dead owner on this machine is taken over, a live, slow or foreign one never is; the lock is published with its owner already recorded (temporary file plus hard link), so a stalled holder is never displaced; a legacy empty lock file is taken by age only when `ownerlessGraceMs` is a number (default `null`: never; an abandoned empty reclaim guard is taken after 5 000 ms unless a value is set); exact `mode` is independent of umask; shared readers need a common group and traversable directories |
36
36
  | `ExclusiveLockError` | class | `LOCK_TIMEOUT` naming the resource and its holder, or `LOCK_ABORTED` with the signal's reason |
37
37
  | `createChunkSpool` | function | the server half of a chunked upload: parts on disk under `owner` + client-minted `uploadId`, each with a size+sha256 receipt; idempotent `open` and `put`, the first writer of a part wins across processes, `assemble` in order once every part is in, `sweep` of untouched uploads — [guide](../guide/client.md#chunked-uploads) |
package/llms/process.txt CHANGED
@@ -68,7 +68,8 @@ The bytes are staged beside the target under `.stitchkit-<24 lowercase hex>.tmp`
68
68
  `writeFileAtomic`, `writeFileAtomicSync`, the managed writer and the chunk spool. A process killed
69
69
  between the staging and the publication (SIGKILL, OOM, power loss) leaves that file behind, and no
70
70
  later write removes it: a random name alone cannot tell an abandoned write from one in flight.
71
- Removing it is the caller's responsibility:
71
+ Removing it is the caller's responsibility. A directory that does not exist yet has nothing to
72
+ sweep and yields `[]`; a file standing where the directory should be, or a denied listing, throws:
72
73
 
73
74
  ```ts
74
75
  import { isAtomicStagingName, sweepAtomicStaging } from 'stitchkit/files'
@@ -197,7 +198,7 @@ permanent refusal is kept in the cause. The close of every owned pipe and the le
197
198
  observed separately, including the absence of a shared `child.close` during teardown. The caller or
198
199
  sink cause is kept; a cleanup failure is a `NativeCommandError` with `COMMAND_CLEANUP` and an
199
200
  `AggregateError` cause. Even an exited parent does not exclude a helper that holds a pipe. Windows
200
- refuses with `COMMAND_UNAVAILABLE`; a descendant that leaves the group on its own with `setsid` is
201
+ refuses with `COMMAND_UNAVAILABLE`; a descendant that has left the group on its own with `setsid` is
201
202
  outside this capability. This is one-shot execution, not a PTY, a supervisor or a daemon host.
202
203
 
203
204
  ### Stopping a command: the `stop` policy
@@ -252,13 +253,28 @@ successfully:
252
253
 
253
254
  | `descendants` | After the leader exits |
254
255
  |---|---|
255
- | `'terminate-after-leader'` (the default) | The group is stopped right after `onLeaderSettled` returns and before the pipes drain: with `target: 'group'` by the same signal, grace, KILL sequence as cancellation; with `target: 'leader'` by KILL at once, since the leader has already exited. Descendants that left the group with `setsid` stay out of reach. |
256
+ | `'terminate-after-leader'` (the default) | The group is stopped right after `onLeaderSettled` returns and before the pipes drain: with `target: 'group'` by the same signal, grace, KILL sequence as cancellation; with `target: 'leader'` by KILL at once, since the leader has already exited. A descendant that had already left the group with `setsid` when the leader exited stays out of reach. |
256
257
  | `'leave'` | Nothing. A helper started with its stdio detached keeps running. One that inherited stdout or stderr keeps the pipes open, and the command then waits for it until its deadline or abort. |
257
258
 
258
259
  Omitting the option means `'terminate-after-leader'`: a command does not leak the helpers it
259
- started. A real daemon detaches into its own session (`setsid`, as `daemon(3)` does), is no member
260
- of the group and is unaffected. Declare `'leave'` only for a helper that has to outlive the
261
- command while staying in its group:
260
+ started. The result's `descendantsStopped` is `true` when the group still had members after the
261
+ leader exited and they were stopped, so a helper that was ended this way is visible to the caller
262
+ rather than only missing afterwards; under `'leave'` it is always `false`.
263
+
264
+ A real daemon detaches into its own session (`setsid`, as `daemon(3)` does), is no member of the
265
+ group and is unaffected, provided it has left the group **before the leader exits**. Leaving is
266
+ the daemon's own system call, and the group is stopped as soon as the leader's exit is observed,
267
+ so a helper started in the background races the leader:
268
+
269
+ | launched by the leader as | after the leader exits |
270
+ |---|---|
271
+ | `setsid -f helper` (returns once the new session exists) | survives |
272
+ | `setsid helper &`, `(setsid helper &)`, `nohup helper &` | stopped: the leader usually exits before the background job has left the group |
273
+ | any of these under `descendants: 'leave'` | survives |
274
+
275
+ Start a daemon so that the session exists before the leader returns (`setsid -f`, or the
276
+ daemon's own double fork followed by the leader waiting for it), or declare `'leave'`. Declare
277
+ `'leave'` only for a helper that has to outlive the command while staying in its group:
262
278
 
263
279
  ```ts
264
280
  await runNativeCommand({
@@ -279,7 +295,21 @@ regular-file read becomes `files.read`; JSON and schema parsing, receipt conflic
279
295
  and application locks stay with the application. A spawn, drain, capture and cancellation wrapper
280
296
  becomes `runNativeCommand`; shell policy, command admission, logging, redaction, the bytes-to-text
281
297
  decoder and the operator sink stay with the application. Long signal-only commands stay streaming;
282
- bounded tar or capture commands get their own explicit limits. Importing one leaf does not make
298
+ bounded tar or capture commands get their own explicit limits.
299
+
300
+ A child the caller holds until it exits is the same call. A guardian that forwards its own SIGTERM
301
+ passes an abort signal and `stop: { target: 'leader', signal: 'SIGTERM', graceMs }`. It records the
302
+ pid in `onLeaderStarted({ pid })`, which runs once right after the leader exists (a throw stops the
303
+ command with that error), reads the exit code and signal in `onLeaderSettled` before the pipes
304
+ drain, and reads stderr through `onOutput` or `capture` with `maxOutputBytes`. `drainTimeoutMs`
305
+ bounds how long the output pipes may stay open after the leader exited: a holder that left the
306
+ group with `setsid` keeps them open, and without the option the command waits for it until
307
+ `timeoutMs` or the signal; with it the command ends with `COMMAND_CLEANUP` (a holder inside the
308
+ group is already stopped by `descendants`). A worker whose whole group must stop on abort is the
309
+ default `target: 'group'`. A child that inherits the caller's terminal is outside this
310
+ capability: every command runs in a group of its own, and a background group that reads the
311
+ terminal is stopped by the kernel (`SIGTTIN`), so an interactive re-execution stays a plain
312
+ spawn in the caller's group. Importing one leaf does not make
283
313
  installing the whole npm package smaller; choose a dependency after measuring packed size and its
284
314
  dependency closure.
285
315
 
@@ -407,7 +437,11 @@ package was built. A ready asset carries those verified `bytes` with the publish
407
437
  `sha256`; its Bun-compatible plugin integrates the same bytes with the same lazy native loader.
408
438
  Each call reads and hashes the selected addons, so call it once per build and reuse the result.
409
439
  The leaf is evolving. It requires no optional peer or Bun ambient declarations for Node imports.
410
- It must run unbundled from its installed package, never from an application's runtime artifact.
440
+ Calling it must happen in a process that runs it from its installed package: it locates the
441
+ package's `native-assets.json` beside its own file and throws `Native packaging must run from its
442
+ installed Stitchkit package` anywhere else, such as inside an application's runtime artifact.
443
+ Importing the leaf is side-effect free (it loads no addon and reads no file), so a module that
444
+ both builds and is bundled may import it; only the call has to stay in the build step.
411
445
 
412
446
  ```ts
413
447
  import { createNativePackaging } from 'stitchkit/files/packaging'
@@ -434,7 +468,11 @@ for (const asset of native.assets) {
434
468
  ```
435
469
 
436
470
  `entryPath` and `assetPath` are relative paths inside the application's output root, without
437
- absolute paths, traversal or overlapping file/directory paths. `entryPath` is fixed, without
471
+ absolute paths, traversal or overlapping file/directory paths. `assetPath` may contain `[hash]`,
472
+ which becomes the first 16 hex digits of that addon's published SHA256: the digest is known before
473
+ the build, so `addons/darwin-arm64-[hash].node` gives two installed versions of the package
474
+ different companion names, and the loader requires exactly that name. It is the only template an
475
+ addon path accepts. `entryPath` is fixed, without
438
476
  Bun naming templates such as `[dir]` or `[name]`. Companion JS builds require one entry, no splitting,
439
477
  and `naming.entry` exactly matching `entryPath`; the plugin rejects a mismatching layout.
440
478
  Choose any application layout; the framework does not prescribe an app directory or installer.
@@ -536,9 +574,9 @@ Native POSIX Bun/Node one-shot command execution. See [native IO](../guide/nativ
536
574
  | Export | Kind | Purpose |
537
575
  |---|---|---|
538
576
  | `runNativeCommand` | function | caller-lifetime streaming or explicitly bounded binary capture |
539
- | `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'`) |
577
+ | `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'`); `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 |
540
578
  | `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 }` |
541
- | `NativeCommandResult` | type | observed nullable exit code/signal and captured stdout/stderr bytes |
579
+ | `NativeCommandResult` | type | observed nullable exit code/signal, `descendantsStopped` (members left in the group after the leader exited were stopped) and captured stdout/stderr bytes |
542
580
  | `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 |
543
581
 
544
582
  | `NativeCommandSettlement` | type | observed leader `exit` or terminal `error`, 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 |
package/llms-full.txt CHANGED
@@ -8210,7 +8210,8 @@ The bytes are staged beside the target under `.stitchkit-<24 lowercase hex>.tmp`
8210
8210
  `writeFileAtomic`, `writeFileAtomicSync`, the managed writer and the chunk spool. A process killed
8211
8211
  between the staging and the publication (SIGKILL, OOM, power loss) leaves that file behind, and no
8212
8212
  later write removes it: a random name alone cannot tell an abandoned write from one in flight.
8213
- Removing it is the caller's responsibility:
8213
+ Removing it is the caller's responsibility. A directory that does not exist yet has nothing to
8214
+ sweep and yields `[]`; a file standing where the directory should be, or a denied listing, throws:
8214
8215
 
8215
8216
  ```ts
8216
8217
  import { isAtomicStagingName, sweepAtomicStaging } from 'stitchkit/files'
@@ -8339,7 +8340,7 @@ permanent refusal is kept in the cause. The close of every owned pipe and the le
8339
8340
  observed separately, including the absence of a shared `child.close` during teardown. The caller or
8340
8341
  sink cause is kept; a cleanup failure is a `NativeCommandError` with `COMMAND_CLEANUP` and an
8341
8342
  `AggregateError` cause. Even an exited parent does not exclude a helper that holds a pipe. Windows
8342
- refuses with `COMMAND_UNAVAILABLE`; a descendant that leaves the group on its own with `setsid` is
8343
+ refuses with `COMMAND_UNAVAILABLE`; a descendant that has left the group on its own with `setsid` is
8343
8344
  outside this capability. This is one-shot execution, not a PTY, a supervisor or a daemon host.
8344
8345
 
8345
8346
  ### Stopping a command: the `stop` policy
@@ -8394,13 +8395,28 @@ successfully:
8394
8395
 
8395
8396
  | `descendants` | After the leader exits |
8396
8397
  |---|---|
8397
- | `'terminate-after-leader'` (the default) | The group is stopped right after `onLeaderSettled` returns and before the pipes drain: with `target: 'group'` by the same signal, grace, KILL sequence as cancellation; with `target: 'leader'` by KILL at once, since the leader has already exited. Descendants that left the group with `setsid` stay out of reach. |
8398
+ | `'terminate-after-leader'` (the default) | The group is stopped right after `onLeaderSettled` returns and before the pipes drain: with `target: 'group'` by the same signal, grace, KILL sequence as cancellation; with `target: 'leader'` by KILL at once, since the leader has already exited. A descendant that had already left the group with `setsid` when the leader exited stays out of reach. |
8398
8399
  | `'leave'` | Nothing. A helper started with its stdio detached keeps running. One that inherited stdout or stderr keeps the pipes open, and the command then waits for it until its deadline or abort. |
8399
8400
 
8400
8401
  Omitting the option means `'terminate-after-leader'`: a command does not leak the helpers it
8401
- started. A real daemon detaches into its own session (`setsid`, as `daemon(3)` does), is no member
8402
- of the group and is unaffected. Declare `'leave'` only for a helper that has to outlive the
8403
- command while staying in its group:
8402
+ started. The result's `descendantsStopped` is `true` when the group still had members after the
8403
+ leader exited and they were stopped, so a helper that was ended this way is visible to the caller
8404
+ rather than only missing afterwards; under `'leave'` it is always `false`.
8405
+
8406
+ A real daemon detaches into its own session (`setsid`, as `daemon(3)` does), is no member of the
8407
+ group and is unaffected, provided it has left the group **before the leader exits**. Leaving is
8408
+ the daemon's own system call, and the group is stopped as soon as the leader's exit is observed,
8409
+ so a helper started in the background races the leader:
8410
+
8411
+ | launched by the leader as | after the leader exits |
8412
+ |---|---|
8413
+ | `setsid -f helper` (returns once the new session exists) | survives |
8414
+ | `setsid helper &`, `(setsid helper &)`, `nohup helper &` | stopped: the leader usually exits before the background job has left the group |
8415
+ | any of these under `descendants: 'leave'` | survives |
8416
+
8417
+ Start a daemon so that the session exists before the leader returns (`setsid -f`, or the
8418
+ daemon's own double fork followed by the leader waiting for it), or declare `'leave'`. Declare
8419
+ `'leave'` only for a helper that has to outlive the command while staying in its group:
8404
8420
 
8405
8421
  ```ts
8406
8422
  await runNativeCommand({
@@ -8421,7 +8437,21 @@ regular-file read becomes `files.read`; JSON and schema parsing, receipt conflic
8421
8437
  and application locks stay with the application. A spawn, drain, capture and cancellation wrapper
8422
8438
  becomes `runNativeCommand`; shell policy, command admission, logging, redaction, the bytes-to-text
8423
8439
  decoder and the operator sink stay with the application. Long signal-only commands stay streaming;
8424
- bounded tar or capture commands get their own explicit limits. Importing one leaf does not make
8440
+ bounded tar or capture commands get their own explicit limits.
8441
+
8442
+ A child the caller holds until it exits is the same call. A guardian that forwards its own SIGTERM
8443
+ passes an abort signal and `stop: { target: 'leader', signal: 'SIGTERM', graceMs }`. It records the
8444
+ pid in `onLeaderStarted({ pid })`, which runs once right after the leader exists (a throw stops the
8445
+ command with that error), reads the exit code and signal in `onLeaderSettled` before the pipes
8446
+ drain, and reads stderr through `onOutput` or `capture` with `maxOutputBytes`. `drainTimeoutMs`
8447
+ bounds how long the output pipes may stay open after the leader exited: a holder that left the
8448
+ group with `setsid` keeps them open, and without the option the command waits for it until
8449
+ `timeoutMs` or the signal; with it the command ends with `COMMAND_CLEANUP` (a holder inside the
8450
+ group is already stopped by `descendants`). A worker whose whole group must stop on abort is the
8451
+ default `target: 'group'`. A child that inherits the caller's terminal is outside this
8452
+ capability: every command runs in a group of its own, and a background group that reads the
8453
+ terminal is stopped by the kernel (`SIGTTIN`), so an interactive re-execution stays a plain
8454
+ spawn in the caller's group. Importing one leaf does not make
8425
8455
  installing the whole npm package smaller; choose a dependency after measuring packed size and its
8426
8456
  dependency closure.
8427
8457
 
@@ -8549,7 +8579,11 @@ package was built. A ready asset carries those verified `bytes` with the publish
8549
8579
  `sha256`; its Bun-compatible plugin integrates the same bytes with the same lazy native loader.
8550
8580
  Each call reads and hashes the selected addons, so call it once per build and reuse the result.
8551
8581
  The leaf is evolving. It requires no optional peer or Bun ambient declarations for Node imports.
8552
- It must run unbundled from its installed package, never from an application's runtime artifact.
8582
+ Calling it must happen in a process that runs it from its installed package: it locates the
8583
+ package's `native-assets.json` beside its own file and throws `Native packaging must run from its
8584
+ installed Stitchkit package` anywhere else, such as inside an application's runtime artifact.
8585
+ Importing the leaf is side-effect free (it loads no addon and reads no file), so a module that
8586
+ both builds and is bundled may import it; only the call has to stay in the build step.
8553
8587
 
8554
8588
  ```ts
8555
8589
  import { createNativePackaging } from 'stitchkit/files/packaging'
@@ -8576,7 +8610,11 @@ for (const asset of native.assets) {
8576
8610
  ```
8577
8611
 
8578
8612
  `entryPath` and `assetPath` are relative paths inside the application's output root, without
8579
- absolute paths, traversal or overlapping file/directory paths. `entryPath` is fixed, without
8613
+ absolute paths, traversal or overlapping file/directory paths. `assetPath` may contain `[hash]`,
8614
+ which becomes the first 16 hex digits of that addon's published SHA256: the digest is known before
8615
+ the build, so `addons/darwin-arm64-[hash].node` gives two installed versions of the package
8616
+ different companion names, and the loader requires exactly that name. It is the only template an
8617
+ addon path accepts. `entryPath` is fixed, without
8580
8618
  Bun naming templates such as `[dir]` or `[name]`. Companion JS builds require one entry, no splitting,
8581
8619
  and `naming.entry` exactly matching `entryPath`; the plugin rejects a mismatching layout.
8582
8620
  Choose any application layout; the framework does not prescribe an app directory or installer.
@@ -22039,7 +22077,7 @@ available from `stitchkit/contract`.
22039
22077
  | `ManagedFileInspectionInput` / `ManagedFileInspection` | _type_ | inspector prefix/name/declared media/signal input and validated metadata-only result |
22040
22078
  | `writeFileAtomic` / `writeFileAtomicSync` / `WriteFileAtomicOptions` | function / _type_ | replace a file atomically: a random staging name created exclusively (never through a planted link), the mode set on the descriptor before the file is visible (default `0o600`, not masked by the umask), `fsync`, rename; a failure leaves the target and no staging file. The asynchronous form keeps the event loop running. A process killed before publication leaves its staging file; sweeping it is the caller's job |
22041
22079
  | `isAtomicStagingName` | function | true for a staging file name of an atomic write of this library (`.stitchkit-<24 lowercase hex>.tmp`, also used by the managed writer and the chunk spool); the form is a stable contract, and changing it is a breaking change ([ADR 0242](../decisions/0242-atomic-staging-name-is-a-public-contract.md)) |
22042
- | `sweepAtomicStaging` / `SweepAtomicStagingOptions` | function / _type_ | remove abandoned staging files from one `directory`: only regular files matching `isAtomicStagingName` and older than the required `olderThanMs`, never following a symlink or entering a subdirectory; stops on `signal`; returns the removed names |
22080
+ | `sweepAtomicStaging` / `SweepAtomicStagingOptions` | function / _type_ | remove abandoned staging files from one `directory`: only regular files matching `isAtomicStagingName` and older than the required `olderThanMs`, never following a symlink or entering a subdirectory; stops on `signal`; returns the removed names, `[]` for a `directory` that does not exist |
22043
22081
  | `withExclusiveLock` / `ExclusiveLockOptions` / `ExclusiveLock` / `ExclusiveLockOwner` | function / _type_ | run work under an exclusive lock between processes — a file recording its owner (pid, host, machine identity, time and nullable kernel process identity); waits up to `timeoutMs` (default 10 s) and stops on `signal`; a dead owner on this machine is taken over, a live, slow or foreign one never is; the lock is published with its owner already recorded (temporary file plus hard link), so a stalled holder is never displaced; a legacy empty lock file is taken by age only when `ownerlessGraceMs` is a number (default `null`: never; an abandoned empty reclaim guard is taken after 5 000 ms unless a value is set); exact `mode` is independent of umask; shared readers need a common group and traversable directories |
22044
22082
  | `ExclusiveLockError` | class | `LOCK_TIMEOUT` naming the resource and its holder, or `LOCK_ABORTED` with the signal's reason |
22045
22083
  | `createChunkSpool` | function | the server half of a chunked upload: parts on disk under `owner` + client-minted `uploadId`, each with a size+sha256 receipt; idempotent `open` and `put`, the first writer of a part wins across processes, `assemble` in order once every part is in, `sweep` of untouched uploads — [guide](../guide/client.md#chunked-uploads) |
@@ -22608,9 +22646,9 @@ Native POSIX Bun/Node one-shot command execution. See [native IO](../guide/nativ
22608
22646
  | Export | Kind | Purpose |
22609
22647
  |---|---|---|
22610
22648
  | `runNativeCommand` | function | caller-lifetime streaming or explicitly bounded binary capture |
22611
- | `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'`) |
22649
+ | `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'`); `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 |
22612
22650
  | `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 }` |
22613
- | `NativeCommandResult` | type | observed nullable exit code/signal and captured stdout/stderr bytes |
22651
+ | `NativeCommandResult` | type | observed nullable exit code/signal, `descendantsStopped` (members left in the group after the leader exited were stopped) and captured stdout/stderr bytes |
22614
22652
  | `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 |
22615
22653
 
22616
22654
  | `NativeCommandSettlement` | type | observed leader `exit` or terminal `error`, 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 |
@@ -22626,6 +22664,8 @@ It resolves the installed package's target/version, reads each selected addon on
22626
22664
  against the `size` and `sha256` published in the package's `native-assets.json` (`formatVersion: 2`,
22627
22665
  written when Stitchkit is built). Call it once per build and reuse the result.
22628
22666
  `platform`, `architecture`, `delivery`, `entryPath` and `assetPath` are explicit public inputs;
22667
+ `assetPath` accepts one template, `[hash]`, replaced by the first 16 hex digits of the addon's
22668
+ published SHA256;
22629
22669
  `platform` is the closed set `'darwin'`, and another name is a type error and a schema refusal.
22630
22670
  The result is `ready` with verified assets and a structural Bun plugin, or `unsupported` /
22631
22671
  `missing` / `mismatch` with the safe code `NATIVE_TARGET_UNSUPPORTED`, `NATIVE_ASSET_MISSING` or
package/llms.txt CHANGED
@@ -56,8 +56,8 @@ 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) 32.8 KB
60
- - **stitchkit/files/packaging**: [llms/files-packaging.txt](llms/files-packaging.txt) 2.7 KB
59
+ - **stitchkit/process**: [llms/process.txt](llms/process.txt) 36.2 KB
60
+ - **stitchkit/files/packaging**: [llms/files-packaging.txt](llms/files-packaging.txt) 2.8 KB
61
61
 
62
62
  ## Upgrading slices
63
63
  - **Upgrading — how to move across versions**: [llms/upgrading.txt](llms/upgrading.txt) 10.3 KB
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.105.0",
3
+ "version": "0.105.2",
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",