@bluewombat/integrator 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 +92 -0
  2. package/SPECS.md +381 -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 +222 -0
  6. package/dist/args/parse-args.js.map +1 -0
  7. package/dist/child/run-child.d.ts +41 -0
  8. package/dist/child/run-child.d.ts.map +1 -0
  9. package/dist/child/run-child.js +145 -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/fold/backend.d.ts +32 -0
  16. package/dist/fold/backend.d.ts.map +1 -0
  17. package/dist/fold/backend.js +2 -0
  18. package/dist/fold/backend.js.map +1 -0
  19. package/dist/fold/fold.d.ts +32 -0
  20. package/dist/fold/fold.d.ts.map +1 -0
  21. package/dist/fold/fold.js +49 -0
  22. package/dist/fold/fold.js.map +1 -0
  23. package/dist/fold/working-files.d.ts +28 -0
  24. package/dist/fold/working-files.d.ts.map +1 -0
  25. package/dist/fold/working-files.js +122 -0
  26. package/dist/fold/working-files.js.map +1 -0
  27. package/dist/index.d.ts +17 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +12 -0
  30. package/dist/index.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-integrator.d.ts +35 -0
  36. package/dist/run/run-integrator.d.ts.map +1 -0
  37. package/dist/run/run-integrator.js +172 -0
  38. package/dist/run/run-integrator.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 +32 -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
@@ -0,0 +1,222 @@
1
+ import { existsSync, statSync } from "node:fs";
2
+ import { isAbsolute, relative, resolve } from "node:path";
3
+ const INTEGRATOR_FLAGS = new Set([
4
+ "--id",
5
+ "--parent",
6
+ "--child",
7
+ "--duration-ms",
8
+ "--on-status",
9
+ "--strategy",
10
+ ]);
11
+ function isIntegratorFlag(token) {
12
+ return INTEGRATOR_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 && isIntegratorFlag(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 Integrator 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 does not exist: ${child}`, id, onStatusArgv);
204
+ }
205
+ if (!isDirectory(child)) {
206
+ return withPartial(`--child is not a directory: ${child}`, id, onStatusArgv);
207
+ }
208
+ if (pathsOverlap(parent, child)) {
209
+ return withPartial("--parent and --child must not be the same path, and neither may be a prefix of the other.", id, onStatusArgv);
210
+ }
211
+ const invocation = {
212
+ id,
213
+ parent: resolve(parent),
214
+ child: resolve(child),
215
+ durationMs,
216
+ };
217
+ if (onStatusArgv !== undefined) {
218
+ invocation.onStatusArgv = onStatusArgv;
219
+ }
220
+ return { ok: true, invocation, strategy };
221
+ }
222
+ //# 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,41 @@
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
+ /** Layered on top of the inherited environment. Ignored when `env` is set. */
15
+ envOverrides?: NodeJS.ProcessEnv | undefined;
16
+ };
17
+ export type SpawnOutcome = {
18
+ kind: "exited";
19
+ exitCode: number | null;
20
+ signal: NodeJS.Signals | null;
21
+ stdout: string;
22
+ stderr: string;
23
+ } | {
24
+ kind: "timed_out";
25
+ clock: ClockName;
26
+ stdout: string;
27
+ stderr: string;
28
+ } | {
29
+ kind: "interrupted";
30
+ stdout: string;
31
+ stderr: string;
32
+ } | {
33
+ kind: "spawn_error";
34
+ detail: string;
35
+ };
36
+ /**
37
+ * Run one child with a wall-clock timeout. Does not inherit Integrator stdin.
38
+ */
39
+ export declare function runChild(request: SpawnRequest): Promise<SpawnOutcome>;
40
+ export declare function combinedOutput(stdout: string, stderr: string): string;
41
+ //# 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;IACpC,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC;CAC9C,CAAC;AAgBF,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"}
@@ -0,0 +1,145 @@
1
+ import { spawn } from "node:child_process";
2
+ const OUTPUT_TRUNCATE = 8_192;
3
+ const OUTPUT_LIMIT_CHARS = 8 * 1024 * 1024;
4
+ /**
5
+ * The one place ambient environment enters a child. `env` replaces it outright;
6
+ * `envOverrides` layers on top of what the child would inherit anyway.
7
+ */
8
+ function childEnv(request) {
9
+ if (request.env !== undefined) {
10
+ return request.env;
11
+ }
12
+ if (request.envOverrides !== undefined) {
13
+ return { ...process.env, ...request.envOverrides };
14
+ }
15
+ return undefined;
16
+ }
17
+ function truncate(text) {
18
+ if (text.length <= OUTPUT_TRUNCATE) {
19
+ return text;
20
+ }
21
+ return `${text.slice(0, OUTPUT_TRUNCATE)}…[truncated]`;
22
+ }
23
+ function killProcessTree(child) {
24
+ try {
25
+ child.kill("SIGKILL");
26
+ }
27
+ catch {
28
+ // already gone
29
+ }
30
+ }
31
+ /**
32
+ * Run one child with a wall-clock timeout. Does not inherit Integrator stdin.
33
+ */
34
+ export function runChild(request) {
35
+ return new Promise((resolve) => {
36
+ const [file, ...args] = request.argv;
37
+ if (file === undefined) {
38
+ resolve({ kind: "spawn_error", detail: "Empty command." });
39
+ return;
40
+ }
41
+ let settled = false;
42
+ let timedOut = false;
43
+ let interrupted = false;
44
+ let stdout = "";
45
+ let stderr = "";
46
+ let timer;
47
+ let interruptPoll;
48
+ const finish = (outcome) => {
49
+ if (settled) {
50
+ return;
51
+ }
52
+ settled = true;
53
+ if (timer !== undefined) {
54
+ clearTimeout(timer);
55
+ }
56
+ if (interruptPoll !== undefined) {
57
+ clearInterval(interruptPoll);
58
+ }
59
+ resolve(outcome);
60
+ };
61
+ let child;
62
+ try {
63
+ child = spawn(file, args, {
64
+ cwd: request.cwd,
65
+ env: childEnv(request),
66
+ stdio: ["ignore", "pipe", "pipe"],
67
+ });
68
+ }
69
+ catch (error) {
70
+ const detail = error instanceof Error ? error.message : String(error);
71
+ finish({ kind: "spawn_error", detail });
72
+ return;
73
+ }
74
+ if (!child.stdout || !child.stderr) {
75
+ finish({ kind: "spawn_error", detail: "Child stdout/stderr pipes unavailable." });
76
+ return;
77
+ }
78
+ child.stdout.setEncoding("utf8");
79
+ child.stderr.setEncoding("utf8");
80
+ let overflowed = false;
81
+ const take = (chunk) => {
82
+ if (overflowed) {
83
+ return false;
84
+ }
85
+ if (stdout.length + stderr.length + chunk.length > OUTPUT_LIMIT_CHARS) {
86
+ overflowed = true;
87
+ killProcessTree(child);
88
+ return false;
89
+ }
90
+ return true;
91
+ };
92
+ child.stdout.on("data", (chunk) => {
93
+ if (take(chunk)) {
94
+ stdout += chunk;
95
+ }
96
+ });
97
+ child.stderr.on("data", (chunk) => {
98
+ if (take(chunk)) {
99
+ stderr += chunk;
100
+ }
101
+ });
102
+ child.on("error", (error) => {
103
+ finish({ kind: "spawn_error", detail: error.message });
104
+ });
105
+ timer = setTimeout(() => {
106
+ timedOut = true;
107
+ killProcessTree(child);
108
+ }, Math.max(1, request.timeoutMs));
109
+ interruptPoll = setInterval(() => {
110
+ if (request.shouldInterrupt()) {
111
+ interrupted = true;
112
+ killProcessTree(child);
113
+ }
114
+ }, 20);
115
+ if (request.shouldInterrupt()) {
116
+ interrupted = true;
117
+ killProcessTree(child);
118
+ }
119
+ child.on("close", (exitCode, signal) => {
120
+ const out = truncate(stdout);
121
+ const err = truncate(stderr);
122
+ if (overflowed) {
123
+ finish({
124
+ kind: "spawn_error",
125
+ detail: `Child wrote more than ${OUTPUT_LIMIT_CHARS} characters; its answer cannot be read.`,
126
+ });
127
+ return;
128
+ }
129
+ if (interrupted || request.shouldInterrupt()) {
130
+ finish({ kind: "interrupted", stdout: out, stderr: err });
131
+ return;
132
+ }
133
+ if (timedOut) {
134
+ finish({ kind: "timed_out", clock: request.timeoutClock, stdout: out, stderr: err });
135
+ return;
136
+ }
137
+ finish({ kind: "exited", exitCode, signal, stdout: out, stderr: err });
138
+ });
139
+ });
140
+ }
141
+ export function combinedOutput(stdout, stderr) {
142
+ const parts = [stdout, stderr].filter((p) => p.length > 0);
143
+ return truncate(parts.join("\n"));
144
+ }
145
+ //# sourceMappingURL=run-child.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-child.js","sourceRoot":"","sources":["../../src/child/run-child.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAG9D,MAAM,eAAe,GAAG,KAAK,CAAC;AAC9B,MAAM,kBAAkB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAkB3C;;;GAGG;AACH,SAAS,QAAQ,CAAC,OAAqB;IACrC,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,OAAO,CAAC,GAAG,CAAC;IACrB,CAAC;IACD,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;QACvC,OAAO,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IACrD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AA0BD,SAAS,QAAQ,CAAC,IAAY;IAC5B,IAAI,IAAI,CAAC,MAAM,IAAI,eAAe,EAAE,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,cAAc,CAAC;AACzD,CAAC;AAED,SAAS,eAAe,CAAC,KAAmB;IAC1C,IAAI,CAAC;QACH,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAqB;IAC5C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;QACrC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,OAAO,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;YAC3D,OAAO;QACT,CAAC;QAED,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,IAAI,WAAW,GAAG,KAAK,CAAC;QACxB,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,KAAiC,CAAC;QACtC,IAAI,aAAyC,CAAC;QAE9C,MAAM,MAAM,GAAG,CAAC,OAAqB,EAAQ,EAAE;YAC7C,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO;YACT,CAAC;YACD,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,YAAY,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;YACD,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;gBAChC,aAAa,CAAC,aAAa,CAAC,CAAC;YAC/B,CAAC;YACD,OAAO,CAAC,OAAO,CAAC,CAAC;QACnB,CAAC,CAAC;QAEF,IAAI,KAAmB,CAAC;QACxB,IAAI,CAAC;YACH,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE;gBACxB,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,GAAG,EAAE,QAAQ,CAAC,OAAO,CAAC;gBACtB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;aAClC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACtE,MAAM,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC;YACxC,OAAO;QACT,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACnC,MAAM,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,wCAAwC,EAAE,CAAC,CAAC;YAClF,OAAO;QACT,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACjC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACjC,IAAI,UAAU,GAAG,KAAK,CAAC;QACvB,MAAM,IAAI,GAAG,CAAC,KAAa,EAAW,EAAE;YACtC,IAAI,UAAU,EAAE,CAAC;gBACf,OAAO,KAAK,CAAC;YACf,CAAC;YACD,IAAI,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,kBAAkB,EAAE,CAAC;gBACtE,UAAU,GAAG,IAAI,CAAC;gBAClB,eAAe,CAAC,KAAK,CAAC,CAAC;gBACvB,OAAO,KAAK,CAAC;YACf,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC,CAAC;QACF,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACxC,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC;YAClB,CAAC;QACH,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACxC,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC;YAClB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC1B,MAAM,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;QAEH,KAAK,GAAG,UAAU,CAChB,GAAG,EAAE;YACH,QAAQ,GAAG,IAAI,CAAC;YAChB,eAAe,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC,EACD,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAC/B,CAAC;QAEF,aAAa,GAAG,WAAW,CAAC,GAAG,EAAE;YAC/B,IAAI,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC;gBAC9B,WAAW,GAAG,IAAI,CAAC;gBACnB,eAAe,CAAC,KAAK,CAAC,CAAC;YACzB,CAAC;QACH,CAAC,EAAE,EAAE,CAAC,CAAC;QAEP,IAAI,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC;YAC9B,WAAW,GAAG,IAAI,CAAC;YACnB,eAAe,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;QAED,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC7B,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC7B,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,CAAC;oBACL,IAAI,EAAE,aAAa;oBACnB,MAAM,EAAE,yBAAyB,kBAAkB,yCAAyC;iBAC7F,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YACD,IAAI,WAAW,IAAI,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC;gBAC7C,MAAM,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;gBAC1D,OAAO;YACT,CAAC;YACD,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;gBACrF,OAAO;YACT,CAAC;YACD,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,MAAc;IAC3D,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC3D,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACpC,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync } from "node:fs";
3
+ import { isAbsolute, resolve } from "node:path";
4
+ import { pathToFileURL } from "node:url";
5
+ import { parseArgs } from "./args/parse-args.js";
6
+ import { createStdoutProgressWriter } from "./progress/emit.js";
7
+ import { invalidInvocationResult, runIntegrator } from "./run/run-integrator.js";
8
+ /**
9
+ * Process signals belong to the binary, not to the Transformer: a Transformer imported into
10
+ * a host must not hijack the host's SIGINT. The CLI owns the flag it passes in.
11
+ */
12
+ function installSignalHandlers(state) {
13
+ const onSignal = () => {
14
+ state.interrupted = true;
15
+ };
16
+ process.on("SIGINT", onSignal);
17
+ process.on("SIGTERM", onSignal);
18
+ return () => {
19
+ process.off("SIGINT", onSignal);
20
+ process.off("SIGTERM", onSignal);
21
+ };
22
+ }
23
+ /**
24
+ * Load an isolation strategy package. Same contract Host uses: export `strategy`.
25
+ */
26
+ async function loadStrategy(specifier) {
27
+ let url = specifier;
28
+ if (specifier.startsWith(".") || isAbsolute(specifier)) {
29
+ const path = resolve(process.cwd(), specifier);
30
+ if (!existsSync(path)) {
31
+ return { ok: false, reason: `Strategy "${specifier}" is not a file: ${path}` };
32
+ }
33
+ url = pathToFileURL(path).href;
34
+ }
35
+ let loaded;
36
+ try {
37
+ loaded = await import(url);
38
+ }
39
+ catch (error) {
40
+ return {
41
+ ok: false,
42
+ reason: `Strategy "${specifier}" could not be loaded: ${error instanceof Error ? error.message : String(error)}`,
43
+ };
44
+ }
45
+ const strategy = loaded.strategy;
46
+ if (strategy === null ||
47
+ typeof strategy !== "object" ||
48
+ typeof strategy.fold !== "object" ||
49
+ strategy === undefined) {
50
+ return {
51
+ ok: false,
52
+ reason: `Strategy "${specifier}" does not export strategy with a fold backend.`,
53
+ };
54
+ }
55
+ return { ok: true, fold: strategy.fold };
56
+ }
57
+ async function main(argv) {
58
+ const write = createStdoutProgressWriter();
59
+ const parsed = parseArgs(argv);
60
+ if (!parsed.ok) {
61
+ const result = await invalidInvocationResult({
62
+ cwd: process.cwd(),
63
+ id: parsed.id,
64
+ onStatusArgv: parsed.onStatusArgv,
65
+ write,
66
+ reason: parsed.reason,
67
+ });
68
+ return result.exitCode;
69
+ }
70
+ const loaded = await loadStrategy(parsed.strategy);
71
+ if (!loaded.ok) {
72
+ const result = await invalidInvocationResult({
73
+ cwd: process.cwd(),
74
+ id: parsed.invocation.id,
75
+ onStatusArgv: parsed.invocation.onStatusArgv,
76
+ write,
77
+ reason: loaded.reason,
78
+ });
79
+ return result.exitCode;
80
+ }
81
+ const interruptFlag = { interrupted: false };
82
+ const detachSignals = installSignalHandlers(interruptFlag);
83
+ try {
84
+ const result = await runIntegrator({
85
+ invocation: parsed.invocation,
86
+ backend: loaded.fold,
87
+ write,
88
+ interruptFlag,
89
+ cwd: process.cwd(),
90
+ });
91
+ return result.exitCode;
92
+ }
93
+ finally {
94
+ detachSignals();
95
+ }
96
+ }
97
+ const exitCode = await main(process.argv.slice(2));
98
+ process.exitCode = exitCode;
99
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type { FoldStop } from "./working-files.js";
2
+ export type FoldBackendResult = {
3
+ ok: true;
4
+ } | {
5
+ ok: false;
6
+ stop: FoldStop;
7
+ } | {
8
+ ok: false;
9
+ conflict: true;
10
+ report: string;
11
+ } | {
12
+ ok: false;
13
+ detail: string;
14
+ };
15
+ /**
16
+ * How Integrator folds the Child into the Parent. The caller injects one;
17
+ * Integrator does not choose a strategy or know git versus copy.
18
+ */
19
+ export type FoldBackend = {
20
+ fold(input: {
21
+ parent: string;
22
+ child: string;
23
+ id?: string;
24
+ subject?: string;
25
+ mergeSubject?: string;
26
+ deadlineMs: number;
27
+ now: () => number;
28
+ shouldInterrupt: () => boolean;
29
+ shouldStop: () => FoldStop | undefined;
30
+ }): Promise<FoldBackendResult>;
31
+ };
32
+ //# sourceMappingURL=backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/fold/backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,MAAM,iBAAiB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAC7B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC7C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,CAAC,KAAK,EAAE;QACV,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;QACnB,GAAG,EAAE,MAAM,MAAM,CAAC;QAClB,eAAe,EAAE,MAAM,OAAO,CAAC;QAC/B,UAAU,EAAE,MAAM,QAAQ,GAAG,SAAS,CAAC;KACxC,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAChC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.js","sourceRoot":"","sources":["../../src/fold/backend.ts"],"names":[],"mappings":""}
@@ -0,0 +1,32 @@
1
+ import type { FoldBackend } from "./backend.js";
2
+ import { type FoldStop } from "./working-files.js";
3
+ export type FoldResult = {
4
+ ok: true;
5
+ } | {
6
+ ok: false;
7
+ stop: FoldStop;
8
+ } | {
9
+ ok: false;
10
+ conflict: true;
11
+ report: string;
12
+ } | {
13
+ ok: false;
14
+ detail: string;
15
+ };
16
+ /**
17
+ * Fold Child working files into Parent through the injected backend.
18
+ * Parent is restored unless the fold completes.
19
+ */
20
+ export declare function fold(input: {
21
+ parent: string;
22
+ child: string;
23
+ backend: FoldBackend;
24
+ /** Names this Integration in what it writes. */
25
+ id?: string;
26
+ subject?: string;
27
+ mergeSubject?: string;
28
+ deadlineMs: number;
29
+ now: () => number;
30
+ shouldInterrupt: () => boolean;
31
+ }): Promise<FoldResult>;
32
+ //# sourceMappingURL=fold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fold.d.ts","sourceRoot":"","sources":["../../src/fold/fold.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EACL,KAAK,QAAQ,EAId,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,UAAU,GAClB;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAC7B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC7C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC;;;GAGG;AACH,wBAAsB,IAAI,CAAC,KAAK,EAAE;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,WAAW,CAAC;IACrB,gDAAgD;IAChD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,OAAO,CAAC;CAChC,GAAG,OAAO,CAAC,UAAU,CAAC,CA8CtB"}