stitchkit 0.103.9 → 0.103.11

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 (44) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/agent-runtime/coding-shell-process.d.ts.map +1 -1
  3. package/dist/agent-runtime/sandbox-process-owner.d.ts.map +1 -1
  4. package/dist/entrypoints/agent-runtime/coding-tools.js +2 -1
  5. package/dist/entrypoints/agent-runtime/sandbox.js +28 -14
  6. package/dist/entrypoints/application/diagnostic-journal.js +2 -1
  7. package/dist/entrypoints/files.js +14 -4
  8. package/dist/entrypoints/process.d.ts +2 -1
  9. package/dist/entrypoints/process.d.ts.map +1 -1
  10. package/dist/entrypoints/process.js +9 -2
  11. package/dist/index-32jkwkdm.js +565 -0
  12. package/dist/{index-a4ajxwmb.js → index-g4jxe7ve.js} +113 -131
  13. package/dist/index-nybn2err.js +213 -0
  14. package/dist/index-ttf0y7b8.js +246 -0
  15. package/dist/internal/exclusive-lock-read.d.ts +20 -0
  16. package/dist/internal/exclusive-lock-read.d.ts.map +1 -0
  17. package/dist/internal/exclusive-lock.d.ts +3 -1
  18. package/dist/internal/exclusive-lock.d.ts.map +1 -1
  19. package/dist/internal/process-instance.d.ts +46 -9
  20. package/dist/internal/process-instance.d.ts.map +1 -1
  21. package/dist/internal/with-exclusive-lock.d.ts +4 -3
  22. package/dist/internal/with-exclusive-lock.d.ts.map +1 -1
  23. package/dist/process/command-owner.d.ts +7 -2
  24. package/dist/process/command-owner.d.ts.map +1 -1
  25. package/dist/process/contract.d.ts +22 -1
  26. package/dist/process/contract.d.ts.map +1 -1
  27. package/dist/process/group.d.ts +6 -1
  28. package/dist/process/group.d.ts.map +1 -1
  29. package/dist/process/launch.d.ts +65 -0
  30. package/dist/process/launch.d.ts.map +1 -0
  31. package/dist/process/leader-settlement.d.ts +6 -0
  32. package/dist/process/leader-settlement.d.ts.map +1 -0
  33. package/dist/process/start-failure.d.ts +7 -0
  34. package/dist/process/start-failure.d.ts.map +1 -0
  35. package/llms/agent-runtime.txt +7 -1
  36. package/llms/files.txt +1 -1
  37. package/llms/process.txt +115 -2
  38. package/llms-full.txt +123 -4
  39. package/llms.txt +3 -3
  40. package/native/darwin-arm64.node +0 -0
  41. package/native/darwin-x64.node +0 -0
  42. package/package.json +2 -2
  43. package/dist/index-7kxw1awn.js +0 -328
  44. package/dist/index-eeqmg7qm.js +0 -202
@@ -0,0 +1,246 @@
1
+ import {
2
+ machineIdentity,
3
+ ProcessInstanceSchema2,
4
+ readProcessInstance,
5
+ probeProcessOwner2
6
+ } from "./index-nybn2err.js";
7
+ import {
8
+ isRecord
9
+ } from "./index-9jfdm5tg.js";
10
+
11
+ // src/internal/exclusive-lock.ts
12
+ import { lstat, open as open2, unlink } from "node:fs/promises";
13
+ import { hostname } from "node:os";
14
+ import { z } from "zod";
15
+
16
+ // src/internal/exclusive-lock-read.ts
17
+ import { constants } from "node:fs";
18
+ import { open } from "node:fs/promises";
19
+ var OWNER_RECORD_BYTES = 16 * 1024;
20
+
21
+ class LockRecordError extends Error {
22
+ code;
23
+ name = "LockRecordError";
24
+ constructor(code, message) {
25
+ super(message);
26
+ this.code = code;
27
+ }
28
+ }
29
+ async function readLockRecord(path, openDescriptor = open, signal) {
30
+ signal?.throwIfAborted();
31
+ if (!constants.O_NOFOLLOW || !constants.O_NONBLOCK) {
32
+ throw new LockRecordError("LOCK_UNSAFE_RECORD", "Safe lock descriptor flags are unavailable");
33
+ }
34
+ const handle = await openDescriptor(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
35
+ try {
36
+ signal?.throwIfAborted();
37
+ const before = await handle.stat();
38
+ signal?.throwIfAborted();
39
+ if (!before.isFile() || before.nlink !== 1) {
40
+ throw new LockRecordError("LOCK_UNSAFE_RECORD", "Lock record must be a regular file with one link");
41
+ }
42
+ if (before.size > OWNER_RECORD_BYTES) {
43
+ throw new LockRecordError("LOCK_RECORD_TOO_LARGE", "Lock owner record exceeds its byte cap");
44
+ }
45
+ const bytes = Buffer.alloc(OWNER_RECORD_BYTES + 1);
46
+ let length = 0;
47
+ while (length < bytes.length) {
48
+ signal?.throwIfAborted();
49
+ const read = await handle.read(bytes, length, bytes.length - length, length);
50
+ if (read.bytesRead === 0)
51
+ break;
52
+ length += read.bytesRead;
53
+ }
54
+ if (length > OWNER_RECORD_BYTES) {
55
+ throw new LockRecordError("LOCK_RECORD_TOO_LARGE", "Lock owner record grew beyond its byte cap");
56
+ }
57
+ const after = await handle.stat();
58
+ signal?.throwIfAborted();
59
+ if (before.dev !== after.dev || before.ino !== after.ino || before.size !== after.size || before.mtimeMs !== after.mtimeMs || before.ctimeMs !== after.ctimeMs || before.nlink !== after.nlink || length !== after.size) {
60
+ throw new LockRecordError("LOCK_RECORD_CHANGED", "Lock owner record changed during its read");
61
+ }
62
+ return { text: bytes.subarray(0, length).toString("utf8"), info: after };
63
+ } finally {
64
+ await handle.close();
65
+ }
66
+ }
67
+
68
+ // src/internal/exclusive-lock.ts
69
+ var ExclusiveLockOwnerSchema = z.object({
70
+ pid: z.number().int().positive().max(Number.MAX_SAFE_INTEGER),
71
+ host: z.string().min(1),
72
+ acquiredAt: z.string(),
73
+ machine: z.string().min(1).optional().catch(undefined),
74
+ process: ProcessInstanceSchema2.nullable().optional().catch(null)
75
+ });
76
+ function isCode(error, code) {
77
+ return isRecord(error) && error.code === code;
78
+ }
79
+ function readOwner(text) {
80
+ let parsed;
81
+ try {
82
+ parsed = JSON.parse(text);
83
+ } catch {
84
+ return;
85
+ }
86
+ const owner = ExclusiveLockOwnerSchema.safeParse(parsed);
87
+ return owner.success ? owner.data : undefined;
88
+ }
89
+ function attribute(owner, identity) {
90
+ if (identity !== null && owner.machine !== undefined) {
91
+ return owner.machine === identity ? "this-machine" : "another-machine";
92
+ }
93
+ return owner.host === hostname() ? "this-machine" : "unattributable";
94
+ }
95
+ async function diagnose(owner, declaredIdentity) {
96
+ if (!owner)
97
+ return { attribution: "unattributable", liveness: "not-probed", owner: null };
98
+ const attribution = attribute(owner, await machineIdentity(declaredIdentity));
99
+ if (attribution !== "this-machine")
100
+ return { attribution, liveness: "not-probed", owner };
101
+ return { attribution, ...await probeProcessOwner2(owner.pid, owner.process), owner };
102
+ }
103
+ async function readLockFile(path, onFailure, signal) {
104
+ try {
105
+ const record = await readLockRecord(path, undefined, signal);
106
+ return {
107
+ owner: readOwner(record.text),
108
+ ino: record.info.ino,
109
+ dev: record.info.dev,
110
+ mtimeMs: record.info.mtimeMs
111
+ };
112
+ } catch (cause) {
113
+ if (!isCode(cause, "ENOENT"))
114
+ onFailure?.(cause);
115
+ return;
116
+ }
117
+ }
118
+ async function unlinkIfSame(path, ino, dev) {
119
+ try {
120
+ const current = await lstat(path);
121
+ if (current.ino !== ino || current.dev !== dev || !current.isFile() || current.nlink !== 1)
122
+ return;
123
+ await unlink(path);
124
+ } catch (error) {
125
+ if (!isCode(error, "ENOENT"))
126
+ throw error;
127
+ }
128
+ }
129
+ async function createOwned(path, options, reclaimed) {
130
+ const identity = await machineIdentity(options.machineIdentity);
131
+ const instance = await readProcessInstance(process.pid);
132
+ const handle = await open2(path, "wx", options.mode);
133
+ const owner = {
134
+ pid: process.pid,
135
+ process: instance,
136
+ host: hostname(),
137
+ acquiredAt: new Date().toISOString(),
138
+ ...identity !== null && { machine: identity }
139
+ };
140
+ let ino;
141
+ let dev;
142
+ try {
143
+ const info = await handle.stat();
144
+ ino = info.ino;
145
+ dev = info.dev;
146
+ await handle.chmod(options.mode);
147
+ await handle.writeFile(`${JSON.stringify(owner)}
148
+ `, "utf8");
149
+ } catch (error) {
150
+ await handle.close().catch(() => {
151
+ return;
152
+ });
153
+ if (ino !== undefined && dev !== undefined)
154
+ await unlinkIfSame(path, ino, dev).catch(() => {
155
+ return;
156
+ });
157
+ throw error;
158
+ }
159
+ const ownedInode = ino;
160
+ const ownedDevice = dev;
161
+ let released = false;
162
+ return {
163
+ path,
164
+ owner,
165
+ reclaimed,
166
+ async release() {
167
+ if (released)
168
+ return;
169
+ released = true;
170
+ try {
171
+ await handle.close();
172
+ } finally {
173
+ await unlinkIfSame(path, ownedInode, ownedDevice);
174
+ }
175
+ }
176
+ };
177
+ }
178
+ function reclaimable(state, diagnosis, graceMs) {
179
+ if (state.owner)
180
+ return diagnosis.liveness === "gone";
181
+ return typeof graceMs === "number" && Date.now() - state.mtimeMs >= graceMs;
182
+ }
183
+ async function reclaimUnderGuard(path, options) {
184
+ const guardPath = `${path}.reclaim`;
185
+ const acquired = await attemptExclusiveLock(guardPath, {
186
+ ...options,
187
+ ownerlessGraceMs: options.ownerlessGraceMs === undefined ? 5000 : options.ownerlessGraceMs
188
+ });
189
+ if (!("held" in acquired))
190
+ return;
191
+ const guard = acquired.held;
192
+ try {
193
+ let unsafe = false;
194
+ const state = await readLockFile(path, () => {
195
+ unsafe = true;
196
+ }, options.signal);
197
+ if (unsafe)
198
+ return "refused";
199
+ if (state) {
200
+ const diagnosis = await diagnose(state.owner, options.machineIdentity);
201
+ if (options.signal?.aborted)
202
+ return "refused";
203
+ if (!reclaimable(state, diagnosis, options.ownerlessGraceMs))
204
+ return "refused";
205
+ await unlinkIfSame(path, state.ino, state.dev);
206
+ }
207
+ return await createOwned(path, options, state !== undefined).catch((error) => {
208
+ if (isCode(error, "EEXIST"))
209
+ return "refused";
210
+ throw error;
211
+ });
212
+ } finally {
213
+ await guard.release().catch(() => {
214
+ return;
215
+ });
216
+ }
217
+ }
218
+ async function attemptExclusiveLock(path, options) {
219
+ try {
220
+ return { held: await createOwned(path, options, false) };
221
+ } catch (error) {
222
+ if (!isCode(error, "EEXIST"))
223
+ throw error;
224
+ if (!options.reclaim)
225
+ return { error };
226
+ let readFailure;
227
+ const state = await readLockFile(path, (cause) => {
228
+ readFailure = cause;
229
+ }, options.signal);
230
+ const diagnosis = {
231
+ ...await diagnose(state?.owner, options.machineIdentity),
232
+ ...readFailure !== undefined && { cause: readFailure }
233
+ };
234
+ if (options.signal?.aborted)
235
+ return { error, diagnosis };
236
+ if (!state || !reclaimable(state, diagnosis, options.ownerlessGraceMs)) {
237
+ return { error, diagnosis };
238
+ }
239
+ const reclaimed = await reclaimUnderGuard(path, options);
240
+ if (reclaimed !== undefined && reclaimed !== "refused")
241
+ return { held: reclaimed };
242
+ return { error, diagnosis };
243
+ }
244
+ }
245
+
246
+ export { attemptExclusiveLock };
@@ -0,0 +1,20 @@
1
+ import { type Stats } from 'node:fs';
2
+ interface LockRecordDescriptor {
3
+ stat(): Promise<Stats>;
4
+ read(buffer: Buffer, offset: number, length: number, position: number): Promise<{
5
+ bytesRead: number;
6
+ }>;
7
+ close(): Promise<void>;
8
+ }
9
+ export declare class LockRecordError extends Error {
10
+ readonly code: 'LOCK_UNSAFE_RECORD' | 'LOCK_RECORD_CHANGED' | 'LOCK_RECORD_TOO_LARGE';
11
+ name: string;
12
+ constructor(code: 'LOCK_UNSAFE_RECORD' | 'LOCK_RECORD_CHANGED' | 'LOCK_RECORD_TOO_LARGE', message: string);
13
+ }
14
+ /** A descriptor-bound observation, never a pathname stat followed by an unbounded read. */
15
+ export declare function readLockRecord(path: string, openDescriptor?: (path: string, flags: number) => Promise<LockRecordDescriptor>, signal?: AbortSignal): Promise<{
16
+ text: string;
17
+ info: Stats;
18
+ }>;
19
+ export {};
20
+ //# sourceMappingURL=exclusive-lock-read.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exclusive-lock-read.d.ts","sourceRoot":"","sources":["../../src/internal/exclusive-lock-read.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAMhD,UAAU,oBAAoB;IAC5B,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;IACvB,IAAI,CACF,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,qBAAa,eAAgB,SAAQ,KAAK;IAGtC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,GAAG,qBAAqB,GAAG,uBAAuB;IAF9E,IAAI,SAAqB;IAClC,YACW,IAAI,EAAE,oBAAoB,GAAG,qBAAqB,GAAG,uBAAuB,EACrF,OAAO,EAAE,MAAM,EAGhB;CACF;AAED,2FAA2F;AAC3F,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,cAAc,GAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,CAAQ,EACrF,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CA8DxC"}
@@ -23,6 +23,7 @@ export interface ExclusiveLockDiagnosis {
23
23
  readonly liveness: 'alive' | 'gone' | 'not-probed';
24
24
  readonly identity?: ProcessOwnerEvidence['identity'];
25
25
  readonly owner: ExclusiveLockOwner | null;
26
+ readonly cause?: unknown;
26
27
  }
27
28
  /** A lock this process holds. */
28
29
  export interface HeldExclusiveLock {
@@ -34,6 +35,7 @@ export interface HeldExclusiveLock {
34
35
  release(): Promise<void>;
35
36
  }
36
37
  export interface ExclusiveLockAttemptOptions {
38
+ readonly signal?: AbortSignal;
37
39
  readonly mode: number;
38
40
  /** Take a lock whose owner is provably gone. `false` refuses every present lock. */
39
41
  readonly reclaim: boolean;
@@ -42,7 +44,7 @@ export interface ExclusiveLockAttemptOptions {
42
44
  * How old a lock with no readable owner must be before it is taken. Absent,
43
45
  * an ownerless lock is never taken — it may predate owner records.
44
46
  */
45
- readonly ownerlessGraceMs?: number;
47
+ readonly ownerlessGraceMs?: number | null;
46
48
  }
47
49
  export type ExclusiveLockAttempt = {
48
50
  readonly held: HeldExclusiveLock;
@@ -1 +1 @@
1
- {"version":3,"file":"exclusive-lock.d.ts","sourceRoot":"","sources":["../../src/internal/exclusive-lock.ts"],"names":[],"mappings":"AA0BA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAEL,KAAK,oBAAoB,EAG1B,MAAM,oBAAoB,CAAC;AAK5B,gDAAgD;AAChD,QAAA,MAAM,wBAAwB;;;;;;;;;;;;;;iBAO5B,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,wCAAwC;AACxC,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,WAAW,EAAE,cAAc,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;IAC5E,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,YAAY,CAAC;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,oBAAoB,CAAC,UAAU,CAAC,CAAC;IACrD,QAAQ,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAAC;CAC3C;AAED,iCAAiC;AACjC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,kFAAkF;IAClF,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,uFAAuF;IACvF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED,MAAM,MAAM,oBAAoB,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAA;CAAE,GACpC;IACE,kDAAkD;IAClD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,6CAA6C;IAC7C,QAAQ,CAAC,SAAS,CAAC,EAAE,sBAAsB,CAAC;CAC7C,CAAC;AAmLN;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,oBAAoB,CAAC,CAe/B;AAED,gFAAgF;AAChF,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAEpC"}
1
+ {"version":3,"file":"exclusive-lock.d.ts","sourceRoot":"","sources":["../../src/internal/exclusive-lock.ts"],"names":[],"mappings":"AAyBA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAEL,KAAK,oBAAoB,EAG1B,MAAM,oBAAoB,CAAC;AAG5B,gDAAgD;AAChD,QAAA,MAAM,wBAAwB;;;;;;;;;;;;;;iBAO5B,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,wCAAwC;AACxC,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,WAAW,EAAE,cAAc,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;IAC5E,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,YAAY,CAAC;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,oBAAoB,CAAC,UAAU,CAAC,CAAC;IACrD,QAAQ,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,iCAAiC;AACjC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,kFAAkF;IAClF,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,uFAAuF;IACvF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3C;AAED,MAAM,MAAM,oBAAoB,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAA;CAAE,GACpC;IACE,kDAAkD;IAClD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,6CAA6C;IAC7C,QAAQ,CAAC,SAAS,CAAC,EAAE,sBAAsB,CAAC;CAC7C,CAAC;AAkMN;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,oBAAoB,CAAC,CA0B/B;AAED,gFAAgF;AAChF,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAEpC"}
@@ -1,5 +1,4 @@
1
1
  import { z } from 'zod';
2
- import { probeLiveness } from './process-identity.js';
3
2
  export declare const ProcessInstanceSchema: z.ZodObject<{
4
3
  platform: z.ZodEnum<{
5
4
  darwin: "darwin";
@@ -10,17 +9,55 @@ export declare const ProcessInstanceSchema: z.ZodObject<{
10
9
  startId: z.ZodString;
11
10
  }, z.core.$strict>;
12
11
  export type ProcessInstance = z.infer<typeof ProcessInstanceSchema>;
12
+ /** An unavailable observation preserves its native or validation cause; it never proves death. */
13
+ declare const ProcessInstanceObservationSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
14
+ state: z.ZodLiteral<"observed">;
15
+ instance: z.ZodObject<{
16
+ platform: z.ZodEnum<{
17
+ darwin: "darwin";
18
+ linux: "linux";
19
+ }>;
20
+ bootId: z.ZodString;
21
+ namespace: z.ZodString;
22
+ startId: z.ZodString;
23
+ }, z.core.$strict>;
24
+ }, z.core.$strip>, z.ZodObject<{
25
+ state: z.ZodLiteral<"unavailable">;
26
+ cause: z.ZodUnknown;
27
+ }, z.core.$strip>], "state">;
28
+ export type ProcessInstanceObservation = z.infer<typeof ProcessInstanceObservationSchema>;
29
+ export declare function observeProcessInstance(pid: number): Promise<ProcessInstanceObservation>;
13
30
  /** /proc stat field 22 follows a command name that may itself contain spaces and parentheses. */
14
31
  export declare function linuxProcessStart(stat: string, pid: number): string | null;
15
32
  /** @internal procRoot permits kernel-format fixtures without changing a real process or boot. */
16
33
  export declare function readProcessInstance(pid: number, procRoot?: string): Promise<ProcessInstance | null>;
17
- export interface ProcessOwnerEvidence {
18
- readonly liveness: 'alive' | 'gone' | 'not-probed';
19
- readonly identity: 'matched' | 'different-boot' | 'reused-pid' | 'pid-gone' | 'legacy' | 'unavailable';
20
- }
34
+ /** @internal The fixture root is never a public owner option. */
35
+ export declare function observeProcessInstanceAt(pid: number, procRoot: string): Promise<ProcessInstanceObservation>;
36
+ declare const ProcessOwnerEvidenceSchema: z.ZodObject<{
37
+ liveness: z.ZodEnum<{
38
+ alive: "alive";
39
+ gone: "gone";
40
+ "not-probed": "not-probed";
41
+ }>;
42
+ identity: z.ZodEnum<{
43
+ "different-boot": "different-boot";
44
+ legacy: "legacy";
45
+ matched: "matched";
46
+ "pid-gone": "pid-gone";
47
+ "reused-pid": "reused-pid";
48
+ unavailable: "unavailable";
49
+ }>;
50
+ cause: z.ZodOptional<z.ZodUnknown>;
51
+ }, z.core.$strip>;
52
+ export type ProcessOwnerEvidence = z.infer<typeof ProcessOwnerEvidenceSchema>;
21
53
  /** Compare identities only inside one machine (the caller establishes that boundary). */
22
- export declare function probeProcessOwner(pid: number, recorded: ProcessInstance | null | undefined, probes?: {
23
- read: typeof readProcessInstance;
24
- liveness: typeof probeLiveness;
25
- }): Promise<ProcessOwnerEvidence>;
54
+ export declare function probeProcessOwner(pid: number, recorded: ProcessInstance | null | undefined): Promise<ProcessOwnerEvidence>;
55
+ interface ProcessOwnerProbes {
56
+ read(pid: number): Promise<ProcessInstance | null>;
57
+ liveness(pid: number): Promise<'alive' | 'gone'>;
58
+ observe?(pid: number): Promise<ProcessInstanceObservation>;
59
+ }
60
+ /** @internal Injection is for kernel-format controls, not a public ownership assertion. */
61
+ export declare function probeProcessOwnerWith(pid: number, recorded: ProcessInstance | null | undefined, probes?: ProcessOwnerProbes): Promise<ProcessOwnerEvidence>;
62
+ export {};
26
63
  //# sourceMappingURL=process-instance.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"process-instance.d.ts","sourceRoot":"","sources":["../../src/internal/process-instance.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,eAAO,MAAM,qBAAqB;;;;;;;;kBAOvB,CAAC;AACZ,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,iGAAiG;AACjG,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS1E;AAED,iGAAiG;AACjG,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,QAAQ,SAAU,GACjB,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CA6CjC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,YAAY,CAAC;IACnD,QAAQ,CAAC,QAAQ,EACb,SAAS,GACT,gBAAgB,GAChB,YAAY,GACZ,UAAU,GACV,QAAQ,GACR,aAAa,CAAC;CACnB;AAED,yFAAyF;AACzF,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,EAC5C,MAAM;IAAK,IAAI;IAAuB,QAAQ;CAAiB,GAC9D,OAAO,CAAC,oBAAoB,CAAC,CAyB/B"}
1
+ {"version":3,"file":"process-instance.d.ts","sourceRoot":"","sources":["../../src/internal/process-instance.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,qBAAqB;;;;;;;;kBAOvB,CAAC;AACZ,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,kGAAkG;AAClG,QAAA,MAAM,gCAAgC;;;;;;;;;;;;;;4BAGpC,CAAC;AACH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAC;AAE1F,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,0BAA0B,CAAC,CAGrC;AAED,iGAAiG;AACjG,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS1E;AAED,iGAAiG;AACjG,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,QAAQ,SAAU,GACjB,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAGjC;AAED,iEAAiE;AACjE,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,0BAA0B,CAAC,CAsDrC;AAED,QAAA,MAAM,0BAA0B;;;;;;;;;;;;;;;iBAW9B,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E,yFAAyF;AACzF,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,GAC3C,OAAO,CAAC,oBAAoB,CAAC,CAQ/B;AAED,UAAU,kBAAkB;IAC1B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IACnD,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC;IACjD,OAAO,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAAC;CAC5D;AAED,2FAA2F;AAC3F,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,EAC5C,MAAM,GAAE,kBAA2E,GAClF,OAAO,CAAC,oBAAoB,CAAC,CA2C/B"}
@@ -18,7 +18,7 @@ export interface ExclusiveLockOptions {
18
18
  timeoutMs?: number;
19
19
  /** Stops the wait; an abort while waiting rejects at once with its reason as the cause. */
20
20
  signal?: AbortSignal;
21
- /** Permission bits of the lock file. Default `0o600`. */
21
+ /** Exact permission bits, independent of umask. Default `0o600`. Shared readers need a common group and traversable parents. */
22
22
  mode?: number;
23
23
  /**
24
24
  * This machine's identity, for a platform that offers none (`/etc/machine-id`
@@ -29,9 +29,10 @@ export interface ExclusiveLockOptions {
29
29
  /**
30
30
  * How old a lock with no readable owner must be before it is taken — the one
31
31
  * case where time decides, left by a process that died between creating the
32
- * file and recording itself. Default 5 000.
32
+ * file and recording itself. Default 5 000; `null` disables age-based reclaim,
33
+ * including abandoned ownerless reclaim guards.
33
34
  */
34
- ownerlessGraceMs?: number;
35
+ ownerlessGraceMs?: number | null;
35
36
  }
36
37
  /** The lock `run` executes under. */
37
38
  export interface ExclusiveLock {
@@ -1 +1 @@
1
- {"version":3,"file":"with-exclusive-lock.d.ts","sourceRoot":"","sources":["../../src/internal/with-exclusive-lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,4CAA4C;AAC5C,MAAM,WAAW,oBAAoB;IACnC,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gGAAgG;IAChG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2FAA2F;IAC3F,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,qCAAqC;AACrC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,iFAAiF;IACjF,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,qEAAqE;AACrE,qBAAa,kBAAmB,SAAQ,KAAK;IAGzC,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,cAAc;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM;IACtB,wFAAwF;IACxF,QAAQ,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI;IALnC,IAAI,SAAwB;IACrC,YACW,IAAI,EAAE,cAAc,GAAG,cAAc,EACrC,KAAK,EAAE,MAAM;IACtB,wFAAwF;IAC/E,MAAM,EAAE,kBAAkB,GAAG,IAAI,EAC1C,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAG9B;CACF;AAyCD;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,EACvC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAC5C,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,CAAC,CAAC,CAwDZ"}
1
+ {"version":3,"file":"with-exclusive-lock.d.ts","sourceRoot":"","sources":["../../src/internal/with-exclusive-lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,4CAA4C;AAC5C,MAAM,WAAW,oBAAoB;IACnC,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gGAAgG;IAChG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2FAA2F;IAC3F,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,gIAAgI;IAChI,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,qCAAqC;AACrC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,iFAAiF;IACjF,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,qEAAqE;AACrE,qBAAa,kBAAmB,SAAQ,KAAK;IAGzC,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,cAAc;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM;IACtB,wFAAwF;IACxF,QAAQ,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI;IALnC,IAAI,SAAwB;IACrC,YACW,IAAI,EAAE,cAAc,GAAG,cAAc,EACrC,KAAK,EAAE,MAAM;IACtB,wFAAwF;IAC/E,MAAM,EAAE,kBAAkB,GAAG,IAAI,EAC1C,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAG9B;CACF;AAyCD;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,EACvC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAC5C,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,CAAC,CAAC,CAuEZ"}
@@ -1,13 +1,18 @@
1
- import { type ChildProcessWithoutNullStreams } from 'node:child_process';
1
+ import type { ChildProcessWithoutNullStreams } from 'node:child_process';
2
2
  import { type NativeCommandOptions } from './contract.js';
3
+ import { type NativeCommandLaunchDriver } from './launch.js';
3
4
  /** One-shot native execution; sandbox policy/admission is composed above this owner. */
4
- export declare function startNativeCommand(input: NativeCommandOptions, onSpawn?: (child: ChildProcessWithoutNullStreams) => void): {
5
+ export declare function startNativeCommand(input: NativeCommandOptions, onSpawn?: (child: ChildProcessWithoutNullStreams) => void, driver?: NativeCommandLaunchDriver): {
6
+ result: Promise<never>;
7
+ stop(): Promise<void>;
8
+ } | {
5
9
  result: Promise<{
6
10
  exitCode: number | null;
7
11
  signal: string | null;
8
12
  stdout: Uint8Array<ArrayBuffer>;
9
13
  stderr: Uint8Array<ArrayBuffer>;
10
14
  }>;
15
+ terminate(): Promise<void>;
11
16
  stop(): Promise<void>;
12
17
  };
13
18
  //# sourceMappingURL=command-owner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"command-owner.d.ts","sourceRoot":"","sources":["../../src/process/command-owner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,8BAA8B,EAAS,MAAM,oBAAoB,CAAC;AAGhF,OAAO,EAEL,KAAK,oBAAoB,EAG1B,MAAM,YAAY,CAAC;AAGpB,wFAAwF;AACxF,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,oBAAoB,EAC3B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,8BAA8B,KAAK,IAAI;;;;;;;;EA0H1D"}
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;AAEzE,OAAO,EAEL,KAAK,oBAAoB,EAG1B,MAAM,YAAY,CAAC;AAOpB,OAAO,EAEL,KAAK,yBAAyB,EAG/B,MAAM,UAAU,CAAC;AAIlB,wFAAwF;AACxF,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,oBAAoB,EAC3B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,8BAA8B,KAAK,IAAI,EACzD,MAAM,CAAC,EAAE,yBAAyB;;;;;;;;;;;;EA+LnC"}
@@ -1,4 +1,13 @@
1
1
  import { z } from 'zod';
2
+ declare const NativeCommandSettlementSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
3
+ kind: z.ZodLiteral<"exit">;
4
+ exitCode: z.ZodNullable<z.ZodNumber>;
5
+ signal: z.ZodNullable<z.ZodString>;
6
+ }, z.core.$strip>, z.ZodObject<{
7
+ kind: z.ZodLiteral<"error">;
8
+ cause: z.ZodUnknown;
9
+ }, z.core.$strip>], "kind">;
10
+ export type NativeCommandSettlement = z.infer<typeof NativeCommandSettlementSchema>;
2
11
  export declare const NativeCommandOptionsSchema: z.ZodObject<{
3
12
  executable: z.ZodString;
4
13
  args: z.ZodDefault<z.ZodArray<z.ZodString>>;
@@ -15,6 +24,7 @@ export declare const NativeCommandOptionsSchema: z.ZodObject<{
15
24
  stdin: z.ZodOptional<z.ZodCustom<Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>>>;
16
25
  maxStdinBytes: z.ZodDefault<z.ZodNumber>;
17
26
  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>>>;
27
+ onLeaderSettled: z.ZodOptional<z.ZodCustom<(event: NativeCommandSettlement, signal: AbortSignal) => void | Promise<void>, (event: NativeCommandSettlement, signal: AbortSignal) => void | Promise<void>>>;
18
28
  killGraceMs: z.ZodDefault<z.ZodNumber>;
19
29
  cleanupTimeoutMs: z.ZodDefault<z.ZodNumber>;
20
30
  }, z.core.$strict>;
@@ -27,9 +37,20 @@ declare const NativeCommandResultSchema: z.ZodObject<{
27
37
  stderr: z.ZodInstanceOf<Uint8Array<ArrayBuffer>>;
28
38
  }, z.core.$strip>;
29
39
  export type NativeCommandResult = z.infer<typeof NativeCommandResultSchema>;
40
+ declare const NativeCommandLimitReasonSchema: z.ZodEnum<{
41
+ deadline: "deadline";
42
+ "output-budget": "output-budget";
43
+ }>;
30
44
  export declare class NativeCommandError extends Error {
31
45
  readonly code: 'COMMAND_LIMIT' | 'COMMAND_UNAVAILABLE' | 'COMMAND_CLEANUP';
32
- constructor(code: 'COMMAND_LIMIT' | 'COMMAND_UNAVAILABLE' | 'COMMAND_CLEANUP', message: string, options?: ErrorOptions);
46
+ /** Observed owner limit; absent on non-limit and caller-constructed errors without evidence. */
47
+ readonly reason: z.infer<typeof NativeCommandLimitReasonSchema> | undefined;
48
+ constructor(code: 'COMMAND_LIMIT', message: string, options?: ErrorOptions & {
49
+ reason?: z.infer<typeof NativeCommandLimitReasonSchema>;
50
+ });
51
+ constructor(code: 'COMMAND_LIMIT' | 'COMMAND_UNAVAILABLE' | 'COMMAND_CLEANUP', message: string, options?: ErrorOptions & {
52
+ reason?: never;
53
+ });
33
54
  }
34
55
  export {};
35
56
  //# sourceMappingURL=contract.d.ts.map
@@ -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;AAExB,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;gDAoBtB,UAAU,WACR,QAAQ,GAAG,QAAQ,UACpB,WAAW,KAChB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;;;kBAgB7B,CAAC;AACL,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,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E,qBAAa,kBAAmB,SAAQ,KAAK;aAEzB,IAAI,EAAE,eAAe,GAAG,qBAAqB,GAAG,iBAAiB;IADnF,YACkB,IAAI,EAAE,eAAe,GAAG,qBAAqB,GAAG,iBAAiB,EACjF,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,YAAY,EAIvB;CACF"}
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../src/process/contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,QAAA,MAAM,6BAA6B;;;;;;;2BAOjC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEpF,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;;;kBAiBvF,CAAC;AACL,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,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E,QAAA,MAAM,8BAA8B;;;EAAwC,CAAC;AAE7E,qBAAa,kBAAmB,SAAQ,KAAK;aAezB,IAAI,EAAE,eAAe,GAAG,qBAAqB,GAAG,iBAAiB;IAdnF,gGAAgG;IAChG,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;CAeH"}
@@ -1,6 +1,11 @@
1
1
  import { NativeCommandError } from './contract.js';
2
+ /** Chain native-sized timers; internal callers retain their declared safe-integer deadline. */
3
+ export declare function createCommandDeadline(timeoutMs: number, reason: unknown): {
4
+ signal: AbortSignal;
5
+ cancel(): void;
6
+ };
2
7
  export declare function signalGroup(pid: number | undefined, signal: NodeJS.Signals): void;
3
- export declare function stopCommandGroup(pid: number | undefined, graceMs: number): Promise<void>;
8
+ export declare function stopCommandGroup(pid: number | undefined, graceMs: number, cleanupTimeoutMs?: number, force?: boolean): Promise<void>;
4
9
  export declare function commandCleanupError(cause: unknown): NativeCommandError;
5
10
  export declare function waitForCommandClose<T>(closed: Promise<T>, timeoutMs: number): Promise<T>;
6
11
  //# sourceMappingURL=group.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"group.d.ts","sourceRoot":"","sources":["../../src/process/group.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAOjF;AAYD,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAQf;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,CAExF"}
1
+ {"version":3,"file":"group.d.ts","sourceRoot":"","sources":["../../src/process/group.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,+FAA+F;AAC/F,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO;IAapE,MAAM;IACN,MAAM;EAIT;AAWD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAOjF;AAiCD,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,OAAO,EAAE,MAAM,EACf,gBAAgB,SAAO,EACvB,KAAK,UAAQ,GACZ,OAAO,CAAC,IAAI,CAAC,CAaf;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"}
@@ -0,0 +1,65 @@
1
+ import { type ChildProcessWithoutNullStreams } from 'node:child_process';
2
+ import { type ParsedNativeCommandOptions } from './contract.js';
3
+ /** A structural host launcher may supply pipes without importing Node ambient types. */
4
+ export interface NativeCommandLaunchedProcess {
5
+ readonly pid?: number;
6
+ readonly exitCode: number | null;
7
+ readonly signalCode: string | null;
8
+ readonly stdout: NativeCommandLaunchedOutput;
9
+ readonly stderr: NativeCommandLaunchedOutput;
10
+ kill(signal: 'SIGKILL'): boolean;
11
+ on(event: 'error', listener: (error: Error) => void): unknown;
12
+ on(event: 'exit' | 'close', listener: (code: number | null, signal: string | null) => void): unknown;
13
+ }
14
+ interface NativeCommandLaunchedOutput {
15
+ readonly destroyed: boolean;
16
+ on(event: 'data', listener: (chunk: Uint8Array) => void): unknown;
17
+ destroy(): unknown;
18
+ }
19
+ /** Internal transport selection; application policy never enters the public command contract. */
20
+ export interface NativeCommandLaunchDriver {
21
+ launch?: () => NativeCommandLaunchedProcess;
22
+ maxBufferedBytes?: number;
23
+ group?: boolean;
24
+ force?: boolean;
25
+ cleanupTimeoutMs?: number;
26
+ timeoutMs?: number;
27
+ closeTimeoutMs?: number;
28
+ }
29
+ /** Driver overrides retain the same finite, safe-integer budget admission. */
30
+ export declare function nativeCommandBudgets(options: ParsedNativeCommandOptions, driver: NativeCommandLaunchDriver | undefined): {
31
+ cleanupTimeoutMs: number;
32
+ timeoutMs: number | undefined;
33
+ };
34
+ interface NativeCommandOwner {
35
+ result: Promise<unknown>;
36
+ stop(): Promise<void>;
37
+ terminate(): Promise<void>;
38
+ }
39
+ /** A launcher and its admission owner share the execution owner's shutdown barrier. */
40
+ export declare function registerNativeCommandOwner(child: object, owner: NativeCommandOwner): void;
41
+ export declare function nativeCommandOwner(child: object): NativeCommandOwner | undefined;
42
+ /** Install every observation before starting stdin or invoking an admission callback. */
43
+ export declare function launchNativeCommand(options: ParsedNativeCommandOptions, driver: NativeCommandLaunchDriver | undefined, onSpawn: ((child: ChildProcessWithoutNullStreams) => void) | undefined, onFailure: (error: Error) => void, onInputFailure: (error: Error) => void): {
44
+ child: NativeCommandLaunchedProcess;
45
+ stdout: AsyncIterable<Uint8Array<ArrayBufferLike>>;
46
+ stderr: AsyncIterable<Uint8Array<ArrayBufferLike>>;
47
+ leader: Promise<{
48
+ kind: "exit";
49
+ exitCode: number | null;
50
+ signal: string | null;
51
+ } | {
52
+ kind: "error";
53
+ cause: unknown;
54
+ }>;
55
+ closed: Promise<{
56
+ exitCode: number | null;
57
+ signal: string | null;
58
+ }>;
59
+ released: Promise<[boolean, ...boolean[]]>;
60
+ pendingHandles: Set<string>;
61
+ start(): void;
62
+ destroy(): void;
63
+ };
64
+ export {};
65
+ //# sourceMappingURL=launch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../../src/process/launch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,8BAA8B,EAAS,MAAM,oBAAoB,CAAC;AAEhF,OAAO,EAGL,KAAK,0BAA0B,EAChC,MAAM,YAAY,CAAC;AAEpB,wFAAwF;AACxF,MAAM,WAAW,4BAA4B;IAC3C,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;IACnC,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAC;IAC7C,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAC;IAC7C,IAAI,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IACjC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC;IAC9D,EAAE,CACA,KAAK,EAAE,MAAM,GAAG,OAAO,EACvB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAC7D,OAAO,CAAC;CACZ;AAED,UAAU,2BAA2B;IACnC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC;IAClE,OAAO,IAAI,OAAO,CAAC;CACpB;AAED,iGAAiG;AACjG,MAAM,WAAW,yBAAyB;IACxC,MAAM,CAAC,EAAE,MAAM,4BAA4B,CAAC;IAC5C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,8EAA8E;AAC9E,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,0BAA0B,EACnC,MAAM,EAAE,yBAAyB,GAAG,SAAS;;;EAY9C;AAED,UAAU,kBAAkB;IAC1B,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACzB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAGD,uFAAuF;AACvF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAEzF;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAEhF;AA4ED,yFAAyF;AACzF,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,0BAA0B,EACnC,MAAM,EAAE,yBAAyB,GAAG,SAAS,EAC7C,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,8BAA8B,KAAK,IAAI,CAAC,GAAG,SAAS,EACtE,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,EACjC,cAAc,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI;;;;;;;;;;;;;kBAuBC,MAAM,GAAG,IAAI;gBAAU,MAAM,GAAG,IAAI;;;;;;EA0D5E"}
@@ -0,0 +1,6 @@
1
+ import type { NativeCommandSettlement, ParsedNativeCommandOptions } from './contract.js';
2
+ /** An internal caller may bound drain/close after leader settlement without changing generic drain. */
3
+ export declare function createLeaderCloseDeadline(leader: Promise<NativeCommandSettlement>, timeoutMs: number | undefined, controller: AbortController): () => void;
4
+ /** One bounded external resource settlement, shared by observed exit and terminal failure. */
5
+ export declare function createLeaderSettlement(options: ParsedNativeCommandOptions, signal: AbortSignal): (event: NativeCommandSettlement) => Promise<void>;
6
+ //# sourceMappingURL=leader-settlement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"leader-settlement.d.ts","sourceRoot":"","sources":["../../src/process/leader-settlement.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAGtF,uGAAuG;AACvG,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,OAAO,CAAC,uBAAuB,CAAC,EACxC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,UAAU,EAAE,eAAe,cAmB5B;AAED,8FAA8F;AAC9F,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,0BAA0B,EACnC,MAAM,EAAE,WAAW,WAGJ,uBAAuB,KAAG,OAAO,CAAC,IAAI,CAAC,CAmCvD"}
@@ -0,0 +1,7 @@
1
+ import { type NativeCommandSettlement } from './contract.js';
2
+ /** A failed native admission still owns one bounded external-resource settlement. */
3
+ export declare function failedCommandStart(cause: unknown, settle: (event: NativeCommandSettlement) => Promise<void>): {
4
+ result: Promise<never>;
5
+ stop(): Promise<void>;
6
+ };
7
+ //# sourceMappingURL=start-failure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-failure.d.ts","sourceRoot":"","sources":["../../src/process/start-failure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAG9E,qFAAqF;AACrF,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,OAAO,CAAC,IAAI,CAAC;;;EAyB1D"}
@@ -19,7 +19,7 @@ description: Configure Stitchkit's optional durable history, stream loop, run co
19
19
  type: architecture
20
20
  status: active
21
21
  created: 2026-08-22
22
- updated: 2026-09-28 18:39 +07:00
22
+ updated: 2026-10-02 16:28 +07:00
23
23
  ---
24
24
 
25
25
  # Agent application runtime
@@ -376,6 +376,12 @@ second host executable, so Windows kills the direct child, destroys retained pip
376
376
  deadline and makes no descendant-cleanup claim. A signal already aborted before execution returns
377
377
  `cancelled` without spawning.
378
378
 
379
+ Coding commands compose the shared native execution owner. Artifact retention and UTF-8
380
+ previews remain coding-tool policy; normal leader exit still forcibly stops remaining POSIX
381
+ group members before draining. A structural sandbox launcher uses the same settlement owner
382
+ with a finite output queue. Sandbox shutdown waits for actual owned completion and surfaces
383
+ cleanup refusal rather than treating it as successful teardown.
384
+
379
385
  One `createAgentHarnessFileResources` instance represents one immutable discovery generation:
380
386
  concurrent and repeated `load()` calls share it, so a direct resource read cannot cross into a
381
387
  new catalog unexpectedly. Discovery uses the same descriptor-anchored traversal as coding search;