@bluewombat/isolator 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +94 -0
  2. package/SPECS.md +294 -0
  3. package/dist/args/parse-args.d.ts +6 -0
  4. package/dist/args/parse-args.d.ts.map +1 -0
  5. package/dist/args/parse-args.js +223 -0
  6. package/dist/args/parse-args.js.map +1 -0
  7. package/dist/child/run-child.d.ts +39 -0
  8. package/dist/child/run-child.d.ts.map +1 -0
  9. package/dist/child/run-child.js +132 -0
  10. package/dist/child/run-child.js.map +1 -0
  11. package/dist/cli.d.ts +3 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +99 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/index.d.ts +17 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +12 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/isolate/backend.d.ts +31 -0
  20. package/dist/isolate/backend.d.ts.map +1 -0
  21. package/dist/isolate/backend.js +2 -0
  22. package/dist/isolate/backend.js.map +1 -0
  23. package/dist/isolate/create-child.d.ts +26 -0
  24. package/dist/isolate/create-child.d.ts.map +1 -0
  25. package/dist/isolate/create-child.js +62 -0
  26. package/dist/isolate/create-child.js.map +1 -0
  27. package/dist/isolate/stop.d.ts +7 -0
  28. package/dist/isolate/stop.d.ts.map +1 -0
  29. package/dist/isolate/stop.js +17 -0
  30. package/dist/isolate/stop.js.map +1 -0
  31. package/dist/progress/emit.d.ts +5 -0
  32. package/dist/progress/emit.d.ts.map +1 -0
  33. package/dist/progress/emit.js +17 -0
  34. package/dist/progress/emit.js.map +1 -0
  35. package/dist/run/run-isolator.d.ts +35 -0
  36. package/dist/run/run-isolator.d.ts.map +1 -0
  37. package/dist/run/run-isolator.js +164 -0
  38. package/dist/run/run-isolator.js.map +1 -0
  39. package/dist/status/announce.d.ts +14 -0
  40. package/dist/status/announce.d.ts.map +1 -0
  41. package/dist/status/announce.js +28 -0
  42. package/dist/status/announce.js.map +1 -0
  43. package/dist/status/make-status.d.ts +7 -0
  44. package/dist/status/make-status.d.ts.map +1 -0
  45. package/dist/status/make-status.js +19 -0
  46. package/dist/status/make-status.js.map +1 -0
  47. package/dist/types.d.ts +28 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +3 -0
  50. package/dist/types.js.map +1 -0
  51. package/package.json +46 -0
package/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # Isolator
2
+
3
+ Transformer: runs **one Isolation**. It takes a Parent directory that
4
+ already exists and creates a Child directory that did not. The Child is a
5
+ snapshot of the Parent's working files at Isolation time, then independent of
6
+ the Parent.
7
+
8
+ Behavioural contract: [SPECS.md](./SPECS.md).
9
+
10
+ ## Stack
11
+
12
+ Repository stack — TypeScript, Node 24.20, Biome, `node:test`. See [docs/DEVELOPMENT.md](../../../docs/DEVELOPMENT.md).
13
+
14
+ ## Setup
15
+
16
+ From the repository root:
17
+
18
+ ```bash
19
+ nvm use
20
+ npm install
21
+ ```
22
+
23
+ ## Commands
24
+
25
+ | Task | Command |
26
+ | --------- | ---------------- |
27
+ | Lint | `npm run lint` |
28
+ | Format | `npm run format` |
29
+ | Typecheck | `npm run tsc` |
30
+ | Test | `npm test` |
31
+ | Build | `npm run build` |
32
+
33
+ Binary after build: `dist/cli.js` (package bin name `isolator`).
34
+
35
+ ## Run
36
+
37
+ Parent must already exist. Child must not. Missing ancestors of `--child` are
38
+ created. Example:
39
+
40
+ ```bash
41
+ npm run build
42
+ node dist/cli.js \
43
+ --id feat-1 \
44
+ --parent /absolute/path/to/parent \
45
+ --child /absolute/path/to/child \
46
+ --duration-ms 60000 \
47
+ --strategy @bluewombat/isolation-copy
48
+ ```
49
+
50
+ The CLI requires `--strategy`: a package name or path that exports `strategy` with an `isolation` backend. Isolator does not sniff `.git` and does not choose git versus copy.
51
+
52
+ Progress is JSON lines on stdout (`status`, `isolation-started`,
53
+ `isolation-finished`). Exit codes: `0` isolated, `1` failed, `2`
54
+ invalid-invocation, `130` interrupted.
55
+
56
+ ## Import
57
+
58
+ Same Transformer, in process. `cli.ts` is an adapter over this function — it reads argv
59
+ and stdin, calls `runIsolator`, and maps the outcome to an exit code. Nothing the CLI
60
+ can do is unreachable from here.
61
+
62
+ ```ts
63
+ import { strategy } from "@bluewombat/isolation-copy";
64
+ import { runIsolator } from "@bluewombat/isolator";
65
+
66
+ const result = await runIsolator({
67
+ invocation, // same shape the CLI builds from argv
68
+ backend: strategy.isolation, // Host / CLI loads a strategy package
69
+ write: (line) => events.push(line), // progress as values, not stdout
70
+ });
71
+ ```
72
+
73
+ `src/index.ts` exports `runIsolator`, `IsolationBackend`, `RunOptions` /
74
+ `RunResult`, `ProgressWriter`, and this Transformer's domain types. Isolation
75
+ strategies live under `packages/plugins/isolation-*`.
76
+
77
+ ## Layout
78
+
79
+ ```
80
+ SPECS.md behavioural contract
81
+ README.md how to build and run
82
+ src/
83
+ cli.ts entry
84
+ types.ts Transformer-owned types
85
+ args/ CLI parsing
86
+ status/ Status labels and --on-status
87
+ progress/ JSON-line progress writer
88
+ child/ spawn (--on-status)
89
+ isolate/ snapshot via injected IsolationBackend (stop + create-child)
90
+ run/ invocation orchestration
91
+ fixtures/ fake --on-status scripts for tests
92
+ ```
93
+
94
+ Sources stay colocated: helpers used once live next to their caller.
package/SPECS.md ADDED
@@ -0,0 +1,294 @@
1
+ # Isolator
2
+
3
+ Independent Transformer: it has a binary, a contract, and nothing else. Isolator is
4
+ alone. Its code, identifiers, comments, and messages name only what it owns: the
5
+ Isolation, its arguments, the Parent path, the Child path, Status, clocks, and
6
+ the Isolation outcome. No other component is mentioned there, because none of
7
+ them exist inside this perimeter.
8
+
9
+ Isolator runs **one Isolation**. It takes a Parent directory it did not create
10
+ and produces a Child directory that did not exist. The Child is a snapshot of
11
+ the Parent's working files at Isolation time, then independent of the Parent.
12
+
13
+ The invocation is always the same. How Isolator produces the Child is an
14
+ injected **Isolation backend** (`attach` / `abort`). Isolator does not choose a
15
+ strategy. The CLI requires `--strategy <specifier>`; Host loads the package
16
+ named in `workLine.isolation`. Strategies live under `packages/plugins/isolation-*`.
17
+
18
+ Isolator does not run work in either directory. It does not fold the Child back
19
+ into the Parent. It does not delete a Child that reached `isolated`.
20
+
21
+ Stack and binary layout: [README.md](./README.md).
22
+
23
+ ## 1. Job
24
+
25
+ ```
26
+ arguments Isolator disk
27
+ --------- -------- ----
28
+ Isolation one invocation create the Child
29
+ Parent snapshot Parent working files do not write Parent working files
30
+ Child path then independent
31
+ bounds
32
+ ← Isolation outcome + Child path + Status
33
+ ```
34
+
35
+ **In:** arguments. **Out:** one Isolation outcome, the Child path when the
36
+ outcome is `isolated`, and a live Status each time it changes. Isolator does
37
+ not wait for a listener to acknowledge.
38
+
39
+ A Child of one Isolation may be the Parent of a later Isolation. Isolator does
40
+ not know or care; every invocation is the same job.
41
+
42
+ ## 2. Options
43
+
44
+ Isolator is invoked with arguments. It does not read an input file. It does not
45
+ read configuration from the Parent or the Child.
46
+
47
+ | Argument | Content |
48
+ | ------------------------ | -------------------------------------------------------------------------------------------------- |
49
+ | `--id` | Isolation id. Copied onto every Status and progress line. Non-empty. |
50
+ | `--parent` | Absolute path. Must already exist as a directory. Working files here are the snapshot source. |
51
+ | `--child` | Absolute path. Must not exist. Isolator creates this directory, including missing ancestors. |
52
+ | `--duration-ms` | Positive integer. Wall clock of the Isolation, from the moment Isolator starts creating the Child. |
53
+ | `--strategy` | Package name or path. CLI only. Loads `strategy.isolation`. `runIsolator` receives the backend as an argument; it never chooses one. |
54
+ | `--on-status -- <argv…>` | Optional. Command to run each time Status changes. Omitted: Status still goes to stdout. |
55
+
56
+ No other argument is read.
57
+
58
+ Malformed arguments, empty id, non-absolute path, missing Parent, Parent not a
59
+ directory, Child already exists, Child's containing path exists but is not a
60
+ directory, Parent and Child the same path, Parent a prefix of Child, Child a
61
+ prefix of Parent, or a non-positive `--duration-ms` → Isolation outcome
62
+ `invalid-invocation`. No Child is created. Parent is left as it was.
63
+
64
+ ## 3. Workflow
65
+
66
+ One invocation runs one Isolation. There is no loop.
67
+
68
+ ```
69
+ Check arguments and paths (§2). Unusable → `invalid-invocation`.
70
+ Announce Status `isolating`.
71
+ Start the Isolation clock.
72
+ Create the Child as a snapshot of the Parent's working files (§4).
73
+ If the clock fires, a stop signal arrives, or creation cannot complete
74
+ → remove any incomplete Child → Isolation outcome `failed` or `interrupted` (§5).
75
+ If creation completes
76
+ → Isolation outcome `isolated`. The Child stays.
77
+ ```
78
+
79
+ ```mermaid
80
+ flowchart TD
81
+ START[Check arguments] --> OK{Usable?}
82
+ OK -->|no| INV[invalid-invocation]
83
+ OK -->|yes| ISO[Create Child from Parent]
84
+ ISO -->|complete| DONE[isolated]
85
+ ISO -->|clock| FAIL[failed — incomplete Child removed]
86
+ ISO -->|stop signal| INT[interrupted — incomplete Child removed]
87
+ ISO -->|cannot complete| FAIL
88
+ ```
89
+
90
+ ## 4. Isolation
91
+
92
+ Isolation is a property of two directories after a successful invocation. It is
93
+ not a later process, not a merge, and not a lock on the Parent.
94
+
95
+ ### Isolation backend
96
+
97
+ Isolator does not choose a strategy. The caller injects an `IsolationBackend`
98
+ (`attach` / `abort`). Strategies live under `packages/plugins/isolation-*` and export
99
+ `strategy: { isolation, fold }`.
100
+
101
+ | Field on `attach` | Meaning |
102
+ | ----------------- | ------- |
103
+ | `id?` | Isolation id; a strategy may derive a branch or other label from it |
104
+ | `parent` / `child` | Absolute paths |
105
+ | `timeoutMs` / `shouldInterrupt` / `shouldStop` | Budgets and stop signals |
106
+
107
+ The binary's `cli.ts` requires `--strategy <specifier>` and loads that package.
108
+ Host resolves `workLine.isolation` the same way. There is no `.git` sniff and no
109
+ `"git"` / `"copy"` alias. A strategy failure is `failed`, not a silent switch.
110
+
111
+ Git bookkeeping under the Parent (when using `@bluewombat/isolation-git`) is
112
+ Isolation bookkeeping, not working files. A copy strategy writes nothing on the
113
+ Parent.
114
+
115
+ Same `--id`, `--parent`, `--child`. Same outcomes. Snapshot and independence
116
+ (§4) hold either way.
117
+
118
+ ### Snapshot
119
+
120
+ At Isolation start, Isolator reads the Parent's **working files**: the tree a
121
+ process with that directory as its working directory would see as the work.
122
+ When the Isolation outcome is `isolated`, the Child has the same relative paths
123
+ and the same content for those working files.
124
+
125
+ Isolator adds no working file of its own under the Child. The Child is the
126
+ snapshot, not a wrapper around it.
127
+
128
+ The contract is the working files. Git vs copy is how Isolator produces them.
129
+
130
+ ### Independence
131
+
132
+ After `isolated`:
133
+
134
+ - A write under the Child does not change the Parent's working files.
135
+ - A write under the Parent does not change the Child's working files.
136
+
137
+ The two trees may then diverge. Isolator does not keep them in sync. A new
138
+ Isolation is a new invocation.
139
+
140
+ ### Parent
141
+
142
+ Isolator does not add, remove, or edit the Parent's working files. After any
143
+ outcome, those files are what they were at invocation start.
144
+
145
+ Isolator may write Isolation bookkeeping that is not working content, if the
146
+ Parent's storage requires it to attach a Child. That bookkeeping is not a
147
+ working file.
148
+
149
+ Isolator never deletes the Parent.
150
+
151
+ ### Child
152
+
153
+ Isolator creates `--child`. Missing ancestor directories are created. A
154
+ containing path that already exists and is not a directory is
155
+ `invalid-invocation`.
156
+
157
+ Isolator does not delete a Child whose Isolation outcome is `isolated`.
158
+ Callers that destroy a Child do so outside this process.
159
+
160
+ If Isolation does not complete, Isolator removes the incomplete Child so a
161
+ retry with the same `--child` is not blocked by a half-created directory. A
162
+ directory that already existed before this invocation is never that incomplete
163
+ Child — that case is `invalid-invocation` and Isolator does not touch it.
164
+
165
+ ### What Isolator does not do
166
+
167
+ - Interpret files in the Parent or the Child.
168
+ - Spawn a worker whose job is the content.
169
+ - Fold the Child into the Parent.
170
+ - Reuse an existing Child.
171
+ - Overwrite `--child`.
172
+ - Choose a Child path of its own: `--child` is the path.
173
+
174
+ ## 5. Clocks and interrupt
175
+
176
+ **Isolation clock.** Starts when Isolator begins creating the Child. On
177
+ `--duration-ms`, Isolator stops creation, removes any incomplete Child, Isolation
178
+ outcome `failed`. The report names the clock.
179
+
180
+ **Interrupt.** SIGINT and SIGTERM stop this invocation. Isolator stops creation,
181
+ removes any incomplete Child, Isolation outcome `interrupted`. It does **not**
182
+ delete the Parent. It does **not** delete a Child that already reached
183
+ `isolated` (that Isolation is finished).
184
+
185
+ A stop signal that races a clock uses `interrupted`.
186
+
187
+ ## 6. Status
188
+
189
+ Status is the live snapshot of this invocation. It changes at phase boundaries
190
+ (Isolation about to run, Isolation outcome known). It is not a history. The
191
+ `label` is meant to be shown as-is.
192
+
193
+ ### Shape
194
+
195
+ | Field | Content |
196
+ | ------- | ---------------------------------------------------------------- |
197
+ | `phase` | `isolating`, `isolated`, `failed`, `interrupted`, or `invalid` |
198
+ | `id` | From `--id`. Absent on `invalid` when `--id` itself is unusable. |
199
+ | `label` | Canonical display string. See below. |
200
+
201
+ ### Label
202
+
203
+ Built by Isolator. Do not invent another spelling.
204
+
205
+ | `phase` | `label` | Example |
206
+ | ------------- | ------------------ | -------------------- |
207
+ | `isolating` | `isolating:<id>` | `isolating:feat-1` |
208
+ | `isolated` | `isolated:<id>` | `isolated:feat-1` |
209
+ | `failed` | `failed:<id>` | `failed:feat-1` |
210
+ | `interrupted` | `interrupted:<id>` | `interrupted:feat-1` |
211
+ | `invalid` | `invalid` | `invalid` |
212
+
213
+ `<id>` is the `--id` argument, as given.
214
+
215
+ ### When it is announced
216
+
217
+ | Moment | `phase` |
218
+ | ------------------------------------------------------- | ------------ |
219
+ | Arguments or paths unusable | `invalid` |
220
+ | Child about to be created | `isolating` |
221
+ | Isolation outcome `isolated` / `failed` / `interrupted` | that outcome |
222
+
223
+ Announced on stdout as a JSON line (`event`: `status`) carrying the fields
224
+ above. If `--on-status` was given, Isolator also runs that command, cwd
225
+ unchanged (not the Parent, not the Child), and appends:
226
+
227
+ | Argument | Content |
228
+ | --------- | -------------------------- |
229
+ | `--id` | Isolation id, when present |
230
+ | `--label` | The label |
231
+ | `--phase` | The phase |
232
+
233
+ `--on-status` does not count against the Isolation clock. A non-zero exit, a
234
+ missing command, or a hang that Isolator must kill does **not** change the
235
+ Isolation outcome. Visibility must not take the Isolation down.
236
+
237
+ ## 7. Progress
238
+
239
+ JSON lines on stdout. A `status` line is the live snapshot (§6). The other
240
+ lines record the Isolation.
241
+
242
+ | `event` | When |
243
+ | -------------------- | -------------------------- |
244
+ | `status` | Each time Status changes |
245
+ | `isolation-started` | Child about to be created |
246
+ | `isolation-finished` | Isolation outcome is known |
247
+
248
+ Each line carries `id` when the Isolation id is usable.
249
+
250
+ `isolation-finished` also carries:
251
+
252
+ | Field | Content |
253
+ | --------- | -------------------------------------------------------------------------- |
254
+ | `outcome` | The Isolation outcome (§8). |
255
+ | `child` | Absolute `--child` path. Present only when `outcome` is `isolated`. |
256
+ | `report` | Why, when `outcome` is `failed` or `invalid-invocation`. Absent otherwise. |
257
+
258
+ Isolator creates no working file under the Parent. It creates no working file
259
+ under the Child other than the snapshot. It deletes nothing under the Parent.
260
+
261
+ ## 8. Isolation outcomes
262
+
263
+ Exactly one per invocation. The meaning is entirely inside this process.
264
+
265
+ | Outcome | Meaning |
266
+ | -------------------- | --------------------------------------------------------------------------------------------------------------- |
267
+ | `invalid-invocation` | Arguments or paths unusable. No Child created. Parent untouched. |
268
+ | `isolated` | Child exists, snapshot taken, independence holds. Child stays. |
269
+ | `failed` | Isolation started and could not complete (clock, I/O, spawn of Isolator's own tools). Incomplete Child removed. |
270
+ | `interrupted` | Stop signal before `isolated`. Incomplete Child removed. |
271
+
272
+ No partial Isolation. A Child that exists after this process exits was either
273
+ already there (`invalid-invocation`, left alone) or fully `isolated`.
274
+
275
+ ## 9. Acceptance
276
+
277
+ 1. Parent has working files; Isolation completes → `isolated`; Child has those files at the same relative paths; Parent working files unchanged.
278
+ 2. After `isolated`, a new file written only under the Child is absent from the Parent.
279
+ 3. After `isolated`, a new file written only under the Parent is absent from the Child.
280
+ 4. `--child` already exists → `invalid-invocation`; that directory unchanged; Parent unchanged.
281
+ 5. Missing Parent, relative path, empty `--id`, `--child` inside `--parent`, or `--parent` inside `--child` → `invalid-invocation`; no Child created.
282
+ 6. SIGTERM during creation → `interrupted`; `--child` does not exist afterwards; Parent remains.
283
+ 7. Isolation clock fires during creation → `failed`; `--child` does not exist afterwards; Parent remains.
284
+ 8. Isolator never deletes the Parent, never deletes an `isolated` Child, never writes a working file of its own into the Child, never folds the Child into the Parent.
285
+ 9. A Child produced by one Isolation can be `--parent` of another Isolation; that second Isolation is the same job.
286
+ 10. Entering creation with `--id feat-1` announces `label` `isolating:feat-1` on stdout, and via `--on-status` when that argument is set.
287
+ 11. `--on-status` exiting non-zero does not change an `isolated` Isolation.
288
+ 12. `@bluewombat/isolation-git` → `isolated` via git; Child is a worktree; Parent working files unchanged; independence holds.
289
+ 13. `@bluewombat/isolation-copy` → `isolated` via copy; same snapshot and independence; Parent unchanged.
290
+ 14. `@bluewombat/isolation-git` and git cannot complete → `failed`, not a copy.
291
+ 15. `--child` whose containing directory is missing → Isolator creates the ancestors; `isolated`.
292
+ 16. The CLI requires `--strategy <specifier>`; `runIsolator` never chooses a strategy.
293
+
294
+ How to build and run this Transformer: [README.md](./README.md).
@@ -0,0 +1,6 @@
1
+ import type { ParseResult } from "../types.js";
2
+ /**
3
+ * Parse Isolator CLI argv (without node/script). Malformed input → not ok.
4
+ */
5
+ export declare function parseArgs(argv: string[]): ParseResult;
6
+ //# sourceMappingURL=parse-args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-args.d.ts","sourceRoot":"","sources":["../../src/args/parse-args.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAc,WAAW,EAAE,MAAM,aAAa,CAAC;AAgH3D;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,WAAW,CAyJrD"}
@@ -0,0 +1,223 @@
1
+ import { existsSync, statSync } from "node:fs";
2
+ import { dirname, isAbsolute, relative, resolve } from "node:path";
3
+ const ISOLATOR_FLAGS = new Set([
4
+ "--id",
5
+ "--parent",
6
+ "--child",
7
+ "--duration-ms",
8
+ "--on-status",
9
+ "--strategy",
10
+ ]);
11
+ function isIsolatorFlag(token) {
12
+ return ISOLATOR_FLAGS.has(token);
13
+ }
14
+ function takeValue(argv, index) {
15
+ const value = argv[index + 1];
16
+ if (value === undefined || value.startsWith("--")) {
17
+ return null;
18
+ }
19
+ return { value, next: index + 2 };
20
+ }
21
+ function takeCommandArgv(argv, start) {
22
+ if (argv[start] !== "--") {
23
+ return null;
24
+ }
25
+ const command = [];
26
+ let i = start + 1;
27
+ while (i < argv.length) {
28
+ const token = argv[i];
29
+ if (token !== undefined && isIsolatorFlag(token)) {
30
+ break;
31
+ }
32
+ if (token !== undefined) {
33
+ command.push(token);
34
+ }
35
+ i += 1;
36
+ }
37
+ if (command.length === 0) {
38
+ return null;
39
+ }
40
+ return { command, next: i };
41
+ }
42
+ function parsePositiveInt(raw) {
43
+ if (!/^\d+$/.test(raw)) {
44
+ return null;
45
+ }
46
+ const value = Number(raw);
47
+ if (!Number.isSafeInteger(value) || value < 1) {
48
+ return null;
49
+ }
50
+ return value;
51
+ }
52
+ function isDirectory(path) {
53
+ try {
54
+ return statSync(path).isDirectory();
55
+ }
56
+ catch {
57
+ return false;
58
+ }
59
+ }
60
+ function pathsOverlap(parent, child) {
61
+ const parentResolved = resolve(parent);
62
+ const childResolved = resolve(child);
63
+ if (parentResolved === childResolved) {
64
+ return true;
65
+ }
66
+ const fromParent = relative(parentResolved, childResolved);
67
+ const fromChild = relative(childResolved, parentResolved);
68
+ const childInsideParent = fromParent !== "" && !fromParent.startsWith("..") && !isAbsolute(fromParent);
69
+ const parentInsideChild = fromChild !== "" && !fromChild.startsWith("..") && !isAbsolute(fromChild);
70
+ return childInsideParent || parentInsideChild;
71
+ }
72
+ function snapshotPartial(id, onStatusArgv) {
73
+ const partial = {};
74
+ if (id !== undefined && id.length > 0) {
75
+ partial.id = id;
76
+ }
77
+ if (onStatusArgv !== undefined) {
78
+ partial.onStatusArgv = onStatusArgv;
79
+ }
80
+ return partial;
81
+ }
82
+ function withPartial(reason, id, onStatusArgv) {
83
+ const failure = { ok: false, reason };
84
+ const partial = snapshotPartial(id, onStatusArgv);
85
+ if (partial.id !== undefined) {
86
+ failure.id = partial.id;
87
+ }
88
+ if (partial.onStatusArgv !== undefined) {
89
+ failure.onStatusArgv = partial.onStatusArgv;
90
+ }
91
+ return failure;
92
+ }
93
+ /**
94
+ * Parse Isolator CLI argv (without node/script). Malformed input → not ok.
95
+ */
96
+ export function parseArgs(argv) {
97
+ let id;
98
+ let parent;
99
+ let child;
100
+ let durationMs;
101
+ let strategy;
102
+ let onStatusArgv;
103
+ let i = 0;
104
+ while (i < argv.length) {
105
+ const token = argv[i];
106
+ if (token === undefined) {
107
+ break;
108
+ }
109
+ if (token === "--id") {
110
+ const taken = takeValue(argv, i);
111
+ if (!taken) {
112
+ return withPartial("Missing value for --id.", id, onStatusArgv);
113
+ }
114
+ id = taken.value;
115
+ i = taken.next;
116
+ continue;
117
+ }
118
+ if (token === "--parent") {
119
+ const taken = takeValue(argv, i);
120
+ if (!taken) {
121
+ return withPartial("Missing value for --parent.", id, onStatusArgv);
122
+ }
123
+ parent = taken.value;
124
+ i = taken.next;
125
+ continue;
126
+ }
127
+ if (token === "--child") {
128
+ const taken = takeValue(argv, i);
129
+ if (!taken) {
130
+ return withPartial("Missing value for --child.", id, onStatusArgv);
131
+ }
132
+ child = taken.value;
133
+ i = taken.next;
134
+ continue;
135
+ }
136
+ if (token === "--duration-ms") {
137
+ const taken = takeValue(argv, i);
138
+ if (!taken) {
139
+ return withPartial("Missing value for --duration-ms.", id, onStatusArgv);
140
+ }
141
+ const value = parsePositiveInt(taken.value);
142
+ if (value === null) {
143
+ return withPartial("--duration-ms must be a positive integer.", id, onStatusArgv);
144
+ }
145
+ durationMs = value;
146
+ i = taken.next;
147
+ continue;
148
+ }
149
+ if (token === "--strategy") {
150
+ const taken = takeValue(argv, i);
151
+ if (!taken) {
152
+ return withPartial("Missing value for --strategy.", id, onStatusArgv);
153
+ }
154
+ if (taken.value.length === 0) {
155
+ return withPartial("--strategy must be a non-empty package name or path.", id, onStatusArgv);
156
+ }
157
+ strategy = taken.value;
158
+ i = taken.next;
159
+ continue;
160
+ }
161
+ if (token === "--on-status") {
162
+ const command = takeCommandArgv(argv, i + 1);
163
+ if (!command) {
164
+ return withPartial("Missing non-empty command after --on-status --.", id, onStatusArgv);
165
+ }
166
+ onStatusArgv = command.command;
167
+ i = command.next;
168
+ continue;
169
+ }
170
+ return withPartial(`Unknown argument "${token}".`, id, onStatusArgv);
171
+ }
172
+ if (id === undefined) {
173
+ return withPartial("Missing required --id.", id, onStatusArgv);
174
+ }
175
+ if (id.length === 0) {
176
+ return withPartial("--id must be non-empty.", undefined, onStatusArgv);
177
+ }
178
+ if (parent === undefined) {
179
+ return withPartial("Missing required --parent.", id, onStatusArgv);
180
+ }
181
+ if (child === undefined) {
182
+ return withPartial("Missing required --child.", id, onStatusArgv);
183
+ }
184
+ if (durationMs === undefined) {
185
+ return withPartial("Missing required --duration-ms.", id, onStatusArgv);
186
+ }
187
+ if (strategy === undefined) {
188
+ return withPartial("Missing required --strategy. Pass a package name or path that exports strategy.", id, onStatusArgv);
189
+ }
190
+ if (!isAbsolute(parent)) {
191
+ return withPartial("--parent must be an absolute path.", id, onStatusArgv);
192
+ }
193
+ if (!isAbsolute(child)) {
194
+ return withPartial("--child must be an absolute path.", id, onStatusArgv);
195
+ }
196
+ if (!existsSync(parent)) {
197
+ return withPartial(`--parent does not exist: ${parent}`, id, onStatusArgv);
198
+ }
199
+ if (!isDirectory(parent)) {
200
+ return withPartial(`--parent is not a directory: ${parent}`, id, onStatusArgv);
201
+ }
202
+ if (existsSync(child)) {
203
+ return withPartial(`--child already exists: ${child}`, id, onStatusArgv);
204
+ }
205
+ const childContainer = dirname(child);
206
+ if (existsSync(childContainer) && !isDirectory(childContainer)) {
207
+ return withPartial(`Child containing directory is not a directory: ${childContainer}`, id, onStatusArgv);
208
+ }
209
+ if (pathsOverlap(parent, child)) {
210
+ return withPartial("--parent and --child must not be the same path, and neither may be a prefix of the other.", id, onStatusArgv);
211
+ }
212
+ const invocation = {
213
+ id,
214
+ parent: resolve(parent),
215
+ child: resolve(child),
216
+ durationMs,
217
+ };
218
+ if (onStatusArgv !== undefined) {
219
+ invocation.onStatusArgv = onStatusArgv;
220
+ }
221
+ return { ok: true, invocation, strategy };
222
+ }
223
+ //# sourceMappingURL=parse-args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-args.js","sourceRoot":"","sources":["../../src/args/parse-args.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { ClockName } from "../types.js";
2
+ export type SpawnRequest = {
3
+ argv: string[];
4
+ /** Undefined lets the child inherit the caller's directory. */
5
+ cwd?: string | undefined;
6
+ /** Wall-clock budget for this child (ms). */
7
+ timeoutMs: number;
8
+ /** Which clock owns the nearer deadline when timeoutMs hits. */
9
+ timeoutClock: ClockName;
10
+ /** When true, treat kill as interrupted (stop signal). */
11
+ shouldInterrupt: () => boolean;
12
+ /** Undefined lets the child inherit the caller's environment. */
13
+ env?: NodeJS.ProcessEnv | undefined;
14
+ };
15
+ export type SpawnOutcome = {
16
+ kind: "exited";
17
+ exitCode: number | null;
18
+ signal: NodeJS.Signals | null;
19
+ stdout: string;
20
+ stderr: string;
21
+ } | {
22
+ kind: "timed_out";
23
+ clock: ClockName;
24
+ stdout: string;
25
+ stderr: string;
26
+ } | {
27
+ kind: "interrupted";
28
+ stdout: string;
29
+ stderr: string;
30
+ } | {
31
+ kind: "spawn_error";
32
+ detail: string;
33
+ };
34
+ /**
35
+ * Run one child with a wall-clock timeout. Does not inherit Isolator stdin.
36
+ */
37
+ export declare function runChild(request: SpawnRequest): Promise<SpawnOutcome>;
38
+ export declare function combinedOutput(stdout: string, stderr: string): string;
39
+ //# sourceMappingURL=run-child.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-child.d.ts","sourceRoot":"","sources":["../../src/child/run-child.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAK7C,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,YAAY,EAAE,SAAS,CAAC;IACxB,0DAA0D;IAC1D,eAAe,EAAE,MAAM,OAAO,CAAC;IAC/B,iEAAiE;IACjE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,YAAY,GACpB;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,GACD;IACE,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,GACD;IACE,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,GACD;IACE,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAiBN;;GAEG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAsHrE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGrE"}