@agwab/pi-workflow 0.2.0 → 0.3.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 (79) hide show
  1. package/README.md +2 -0
  2. package/dist/compiler.d.ts +4 -6
  3. package/dist/compiler.js +70 -39
  4. package/dist/dynamic-decision.d.ts +0 -1
  5. package/dist/dynamic-decision.js +0 -7
  6. package/dist/dynamic-generated-task-runtime.d.ts +2 -0
  7. package/dist/dynamic-generated-task-runtime.js +21 -8
  8. package/dist/dynamic-profiles.d.ts +0 -1
  9. package/dist/dynamic-profiles.js +0 -3
  10. package/dist/engine-run-graph.d.ts +1 -0
  11. package/dist/engine-run-graph.js +142 -2
  12. package/dist/engine.d.ts +10 -6
  13. package/dist/engine.js +146 -77
  14. package/dist/extension.d.ts +2 -1
  15. package/dist/extension.js +38 -15
  16. package/dist/index.d.ts +3 -3
  17. package/dist/index.js +2 -1
  18. package/dist/store.d.ts +3 -1
  19. package/dist/store.js +189 -49
  20. package/dist/subagent-backend.d.ts +4 -0
  21. package/dist/subagent-backend.js +281 -31
  22. package/dist/types.d.ts +9 -1
  23. package/dist/workflow-runtime.d.ts +2 -0
  24. package/dist/workflow-runtime.js +40 -1
  25. package/dist/workflow-view.js +3 -1
  26. package/dist/workflow-web-source-extension.js +167 -48
  27. package/dist/workflow-web-source.d.ts +2 -1
  28. package/dist/workflow-web-source.js +84 -19
  29. package/docs/usage.md +11 -0
  30. package/node_modules/@agwab/pi-subagent/README.md +3 -3
  31. package/node_modules/@agwab/pi-subagent/api.mjs +1 -0
  32. package/node_modules/@agwab/pi-subagent/docs/usage.md +63 -12
  33. package/node_modules/@agwab/pi-subagent/package.json +2 -2
  34. package/node_modules/@agwab/pi-subagent/src/api.ts +54 -1
  35. package/node_modules/@agwab/pi-subagent/src/artifacts/registry.ts +9 -4
  36. package/node_modules/@agwab/pi-subagent/src/artifacts/result.ts +8 -0
  37. package/node_modules/@agwab/pi-subagent/src/core/constants.ts +9 -0
  38. package/node_modules/@agwab/pi-subagent/src/core/validation.ts +21 -0
  39. package/node_modules/@agwab/pi-subagent/src/index.ts +995 -573
  40. package/node_modules/@agwab/pi-subagent/src/orchestrate/async.ts +279 -156
  41. package/node_modules/@agwab/pi-subagent/src/orchestrate/interrupt.ts +165 -89
  42. package/node_modules/@agwab/pi-subagent/src/orchestrate/reconcile.ts +111 -65
  43. package/node_modules/@agwab/pi-subagent/src/orchestrate/run-ref.ts +219 -0
  44. package/node_modules/@agwab/pi-subagent/src/orchestrate/run.ts +88 -8
  45. package/node_modules/@agwab/pi-subagent/src/orchestrate/status.ts +614 -298
  46. package/node_modules/@agwab/pi-subagent/src/panel.ts +1352 -560
  47. package/node_modules/@agwab/pi-subagent/src/runners/headless-model.ts +53 -5
  48. package/node_modules/@agwab/pi-subagent/src/runners/tmux.ts +13 -6
  49. package/package.json +2 -2
  50. package/src/compiler.ts +127 -66
  51. package/src/dynamic-decision.ts +0 -11
  52. package/src/dynamic-generated-task-runtime.ts +47 -12
  53. package/src/dynamic-profiles.ts +0 -4
  54. package/src/engine-run-graph.ts +185 -2
  55. package/src/engine.ts +192 -107
  56. package/src/extension.ts +50 -17
  57. package/src/index.ts +3 -1
  58. package/src/store.ts +253 -55
  59. package/src/subagent-backend.ts +369 -32
  60. package/src/types.ts +13 -1
  61. package/src/workflow-runtime.ts +53 -2
  62. package/src/workflow-view.ts +2 -1
  63. package/src/workflow-web-source-extension.ts +621 -228
  64. package/src/workflow-web-source.ts +118 -28
  65. package/workflows/deep-research/helpers/claim-evidence-gate.mjs +56 -16
  66. package/workflows/deep-research/helpers/final-audit-packet.mjs +1 -4
  67. package/workflows/deep-research/helpers/normalize-input-packet.mjs +1 -1
  68. package/workflows/deep-research/helpers/render-executive.mjs +8 -21
  69. package/workflows/deep-research/helpers/sanitize-verification-candidates.mjs +89 -15
  70. package/workflows/deep-research/schemas/deep-research-executive-render-control.schema.json +0 -1
  71. package/workflows/deep-research/schemas/deep-research-verify-claims-control.schema.json +4 -1
  72. package/workflows/impact-review/spec.json +3 -3
  73. package/workflows/spec-review/helpers/spec-review-pipeline.mjs +1 -8
  74. package/dist/dynamic-loader.d.ts +0 -25
  75. package/dist/dynamic-loader.js +0 -13
  76. package/src/dynamic-loader.ts +0 -49
  77. package/workflows/impact-review/schemas/docs-release-impact-control.schema.json +0 -42
  78. package/workflows/impact-review/schemas/security-performance-impact-control.schema.json +0 -42
  79. package/workflows/impact-review/schemas/state-data-impact-control.schema.json +0 -42
@@ -4,185 +4,308 @@ import { writeFile } from "node:fs/promises";
4
4
  import { dirname, join } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import {
7
- appendRunEvent,
8
- beginRunRecord,
9
- createAttemptArtifactStore,
10
- createAttemptId,
11
- createRunId,
12
- finishAttemptFromResult,
13
- updateAttemptProcess,
14
- type ResultEnvelope,
7
+ appendRunEvent,
8
+ beginRunRecord,
9
+ createAttemptArtifactStore,
10
+ createAttemptId,
11
+ createRunId,
12
+ finishAttemptFromResult,
13
+ updateAttemptProcess,
14
+ type ResultEnvelope,
15
15
  } from "../artifacts/index.ts";
16
- import type { ExecutionMode, ResolveInput, ResolvedBackend, SubagentTaskInput } from "../core/constants.ts";
16
+ import type {
17
+ ExecutionMode,
18
+ ResolveInput,
19
+ ResolvedBackend,
20
+ SubagentTaskInput,
21
+ } from "../core/constants.ts";
17
22
  import { resolveBackend } from "../core/resolver.ts";
18
- import { DEFAULT_PARALLEL_CONCURRENCY, MAX_PARALLEL_CONCURRENCY, MAX_PARALLEL_TASKS, SubagentToolAuthorityError, type ParallelRunResult } from "./run.ts";
23
+ import {
24
+ DEFAULT_PARALLEL_CONCURRENCY,
25
+ MAX_PARALLEL_CONCURRENCY,
26
+ MAX_PARALLEL_TASKS,
27
+ SubagentToolAuthorityError,
28
+ type ParallelRunResult,
29
+ } from "./run.ts";
30
+ import { writeRunLocator } from "./run-ref.ts";
19
31
  import { readRunResult, waitForRun } from "./status.ts";
20
32
 
21
33
  export interface StartAsyncSubagentRunOptions {
22
- input: ResolveInput;
23
- cwd: string;
24
- backend: ResolvedBackend;
25
- signal?: AbortSignal;
26
- runId?: string;
27
- attemptId?: string;
28
- onComplete?: (result: ResultEnvelope, mode: ExecutionMode) => number | Promise<number>;
34
+ input: ResolveInput;
35
+ cwd: string;
36
+ backend: ResolvedBackend;
37
+ signal?: AbortSignal;
38
+ runId?: string;
39
+ attemptId?: string;
40
+ onComplete?: (
41
+ result: ResultEnvelope,
42
+ mode: ExecutionMode,
43
+ ) => number | Promise<number>;
29
44
  }
30
45
 
31
46
  function executionMode(input: ResolveInput): ExecutionMode {
32
- if (input.mode !== undefined) return input.mode;
33
- if (input.tasks !== undefined) return "parallel";
34
- return "single";
47
+ if (input.mode !== undefined) return input.mode;
48
+ if (input.tasks !== undefined) return "parallel";
49
+ return "single";
35
50
  }
36
51
 
37
52
  function parallelConcurrency(input: ResolveInput): number {
38
- const requested = input.concurrency ?? DEFAULT_PARALLEL_CONCURRENCY;
39
- return Math.max(1, Math.min(MAX_PARALLEL_CONCURRENCY, requested));
53
+ const requested = input.concurrency ?? DEFAULT_PARALLEL_CONCURRENCY;
54
+ return Math.max(1, Math.min(MAX_PARALLEL_CONCURRENCY, requested));
40
55
  }
41
56
 
42
- function mergeTaskInput(parent: ResolveInput, task: SubagentTaskInput): ResolveInput {
43
- return {
44
- ...parent,
45
- ...task,
46
- tasks: undefined,
47
- mode: "single",
48
- workspace: parent.workspace,
49
- worktree: parent.worktree,
50
- worktreePolicy: parent.worktreePolicy,
51
- concurrency: undefined,
52
- asyncDependency: parent.asyncDependency,
53
- runsDir: parent.runsDir,
54
- correlationId: parent.correlationId,
55
- parentSessionId: parent.parentSessionId,
56
- };
57
+ function mergeTaskInput(
58
+ parent: ResolveInput,
59
+ task: SubagentTaskInput,
60
+ ): ResolveInput {
61
+ return {
62
+ ...parent,
63
+ ...task,
64
+ tasks: undefined,
65
+ mode: "single",
66
+ workspace: parent.workspace,
67
+ worktree: parent.worktree,
68
+ worktreePolicy: parent.worktreePolicy,
69
+ concurrency: undefined,
70
+ failFast: undefined,
71
+ cancelSiblingsOnFailure: undefined,
72
+ asyncDependency: parent.asyncDependency,
73
+ runsDir: parent.runsDir,
74
+ correlationId: parent.correlationId,
75
+ parentSessionId: parent.parentSessionId,
76
+ };
57
77
  }
58
78
 
59
79
  function sandboxEnabled(input: ResolveInput): boolean {
60
- return input.sandbox !== undefined && input.sandbox !== null;
80
+ return input.sandbox !== undefined && input.sandbox !== null;
61
81
  }
62
82
 
63
- function armCompletionMonitor(options: StartAsyncSubagentRunOptions & { runId: string; attemptId: string; mode: ExecutionMode; store: Awaited<ReturnType<typeof createAttemptArtifactStore>> }): void {
64
- if (options.onComplete === undefined || options.input.onComplete !== "notify") return;
65
- void (async () => {
66
- const waited = await waitForRun({ cwd: options.cwd, runsDir: options.input.runsDir, runId: options.runId, attemptId: options.attemptId, timeoutMs: options.input.timeoutMs ?? 86_400_000, pollIntervalMs: 500 });
67
- if (waited.status !== "completed") return;
68
- const result = await readRunResult({ cwd: options.cwd, runsDir: options.input.runsDir, runId: options.runId, attemptId: options.attemptId });
69
- if (result === null) return;
70
- const updatesSent = await options.onComplete!(result, options.mode);
71
- const completed = await options.store.writeResult({
72
- ...result,
73
- completion: { onComplete: options.input.onComplete ?? null, notified: true, updatesSent },
74
- });
75
- await finishAttemptFromResult({ cwd: options.cwd, runsDir: options.input.runsDir, runId: options.runId }, completed);
76
- })().catch(() => undefined);
83
+ function armCompletionMonitor(
84
+ options: StartAsyncSubagentRunOptions & {
85
+ runId: string;
86
+ attemptId: string;
87
+ mode: ExecutionMode;
88
+ store: Awaited<ReturnType<typeof createAttemptArtifactStore>>;
89
+ },
90
+ ): void {
91
+ if (options.onComplete === undefined || options.input.onComplete !== "notify")
92
+ return;
93
+ void (async () => {
94
+ const waited = await waitForRun({
95
+ cwd: options.cwd,
96
+ runsDir: options.input.runsDir,
97
+ runId: options.runId,
98
+ attemptId: options.attemptId,
99
+ timeoutMs: options.input.timeoutMs ?? 86_400_000,
100
+ pollIntervalMs: 500,
101
+ });
102
+ if (waited.status !== "completed") return;
103
+ const result = await readRunResult({
104
+ cwd: options.cwd,
105
+ runsDir: options.input.runsDir,
106
+ runId: options.runId,
107
+ attemptId: options.attemptId,
108
+ });
109
+ if (result === null) return;
110
+ const updatesSent = await options.onComplete!(result, options.mode);
111
+ const completed = await options.store.writeResult({
112
+ ...result,
113
+ completion: {
114
+ onComplete: options.input.onComplete ?? null,
115
+ notified: true,
116
+ updatesSent,
117
+ },
118
+ });
119
+ await finishAttemptFromResult(
120
+ {
121
+ cwd: options.cwd,
122
+ runsDir: options.input.runsDir,
123
+ runId: options.runId,
124
+ },
125
+ completed,
126
+ );
127
+ })().catch(() => undefined);
77
128
  }
78
129
 
79
130
  function workerPath(): string {
80
- return join(dirname(fileURLToPath(import.meta.url)), "../workers/durable-worker.mjs");
131
+ return join(
132
+ dirname(fileURLToPath(import.meta.url)),
133
+ "../workers/durable-worker.mjs",
134
+ );
81
135
  }
82
136
 
83
- export async function startAsyncParallelSubagentRuns(input: ResolveInput, cwd: string, signal?: AbortSignal, onComplete?: StartAsyncSubagentRunOptions["onComplete"]): Promise<ParallelRunResult> {
84
- if (!input.tasks || input.tasks.length === 0) throw new SubagentToolAuthorityError("parallel mode requires a non-empty tasks array.");
85
- if (input.tasks.length > MAX_PARALLEL_TASKS) throw new SubagentToolAuthorityError(`too many parallel tasks (${input.tasks.length}); max is ${MAX_PARALLEL_TASKS}.`);
86
- for (const [index, task] of input.tasks.entries()) {
87
- if (task.task === undefined) throw new SubagentToolAuthorityError(`parallel tasks[${index}] requires a non-empty task.`);
88
- }
89
-
90
- const concurrency = Math.min(parallelConcurrency(input), input.tasks.length);
91
- const results: ResultEnvelope[] = new Array(input.tasks.length);
92
- let nextIndex = 0;
93
-
94
- async function worker(): Promise<void> {
95
- while (true) {
96
- const index = nextIndex;
97
- nextIndex += 1;
98
- if (index >= input.tasks!.length) return;
99
- const taskInput = mergeTaskInput(input, input.tasks![index]);
100
- const resolved = resolveBackend(taskInput);
101
- if (resolved.status === "failed") throw new SubagentToolAuthorityError(resolved.error);
102
- results[index] = await startAsyncSubagentRun({ input: taskInput, cwd: taskInput.cwd ?? cwd, backend: resolved.backend, signal, onComplete });
103
- }
104
- }
105
-
106
- await Promise.all(Array.from({ length: concurrency }, () => worker()));
107
- return { mode: "parallel", runIds: results.map((result) => result.runId), results, concurrency };
137
+ export async function startAsyncParallelSubagentRuns(
138
+ input: ResolveInput,
139
+ cwd: string,
140
+ signal?: AbortSignal,
141
+ onComplete?: StartAsyncSubagentRunOptions["onComplete"],
142
+ ): Promise<ParallelRunResult> {
143
+ if (!input.tasks || input.tasks.length === 0)
144
+ throw new SubagentToolAuthorityError(
145
+ "parallel mode requires a non-empty tasks array.",
146
+ );
147
+ if (input.tasks.length > MAX_PARALLEL_TASKS)
148
+ throw new SubagentToolAuthorityError(
149
+ `too many parallel tasks (${input.tasks.length}); max is ${MAX_PARALLEL_TASKS}.`,
150
+ );
151
+ for (const [index, task] of input.tasks.entries()) {
152
+ if (task.task === undefined)
153
+ throw new SubagentToolAuthorityError(
154
+ `parallel tasks[${index}] requires a non-empty task.`,
155
+ );
156
+ }
157
+
158
+ const concurrency = Math.min(parallelConcurrency(input), input.tasks.length);
159
+ const results: ResultEnvelope[] = new Array(input.tasks.length);
160
+ let nextIndex = 0;
161
+
162
+ async function worker(): Promise<void> {
163
+ while (true) {
164
+ const index = nextIndex;
165
+ nextIndex += 1;
166
+ if (index >= input.tasks!.length) return;
167
+ const taskInput = mergeTaskInput(input, input.tasks![index]);
168
+ const resolved = resolveBackend(taskInput);
169
+ if (resolved.status === "failed")
170
+ throw new SubagentToolAuthorityError(resolved.error);
171
+ results[index] = await startAsyncSubagentRun({
172
+ input: taskInput,
173
+ cwd: taskInput.cwd ?? cwd,
174
+ backend: resolved.backend,
175
+ signal,
176
+ onComplete,
177
+ });
178
+ }
179
+ }
180
+
181
+ await Promise.all(Array.from({ length: concurrency }, () => worker()));
182
+ return {
183
+ mode: "parallel",
184
+ runIds: results.map((result) => result.runId),
185
+ results,
186
+ concurrency,
187
+ totalTasks: input.tasks.length,
188
+ startedCount: results.length,
189
+ skippedCount: 0,
190
+ failFastTriggered: false,
191
+ };
108
192
  }
109
193
 
110
- export async function startAsyncSubagentRun(options: StartAsyncSubagentRunOptions): Promise<ResultEnvelope> {
111
- const input = options.input;
112
- const startedAt = new Date();
113
- const runId = options.runId ?? createRunId(startedAt);
114
- const attemptId = options.attemptId ?? createAttemptId(startedAt);
115
- const mode = executionMode(input);
116
- if (mode === "parallel") {
117
- throw new SubagentToolAuthorityError("startAsyncSubagentRun handles one run; use startAsyncParallelSubagentRuns for parallel inputs.");
118
- }
119
- const dependency = input.asyncDependency ?? "unclassified";
120
- const store = await createAttemptArtifactStore({ cwd: options.cwd, runId, attemptId, runsDir: input.runsDir });
121
- const payloadPath = store.pathFor("worker");
122
- const payloadText = `${JSON.stringify({ input, cwd: options.cwd, backend: options.backend, runId, attemptId, startedAt: startedAt.toISOString() }, null, 2)}\n`;
123
- await writeFile(payloadPath, payloadText);
124
- const workerRef = store.refFor("worker", Buffer.byteLength(payloadText, "utf8"));
125
-
126
- const running = await store.writeResult({
127
- backend: options.backend,
128
- status: "running",
129
- failureKind: null,
130
- cwd: options.cwd,
131
- startedAt,
132
- completedAt: null,
133
- workspace: { mode: "shared", cwd: options.cwd },
134
- sandbox: { enabled: sandboxEnabled(input) },
135
- exitCode: null,
136
- signal: null,
137
- artifacts: [workerRef],
138
- correlationId: input.correlationId,
139
- metadata: { contextLengthExceeded: false },
140
- });
141
-
142
- await beginRunRecord({
143
- cwd: options.cwd,
144
- runsDir: input.runsDir,
145
- runId,
146
- mode,
147
- backend: options.backend,
148
- startedAt,
149
- dependency,
150
- correlationId: input.correlationId,
151
- parentSessionId: input.parentSessionId,
152
- activeAttemptId: attemptId,
153
- attempts: [{ attemptId, status: "running", backend: options.backend, startedAt: startedAt.toISOString(), artifactCwd: options.cwd, resultPath: running.artifacts.find((artifact) => artifact.type === "result")?.path }],
154
- });
155
- await appendRunEvent({ cwd: options.cwd, runsDir: input.runsDir, runId }, { type: "run.started", status: "running", message: `${mode} durable async run started`, data: { dependency, attemptId } });
156
-
157
- const workerLogFd = openSync(join(store.attemptDir, "worker.log"), "a");
158
- let child;
159
- try {
160
- child = spawn(process.execPath, [workerPath(), payloadPath], {
161
- cwd: options.cwd,
162
- detached: process.platform !== "win32",
163
- stdio: ["ignore", workerLogFd, workerLogFd],
164
- });
165
- } finally {
166
- closeSync(workerLogFd);
167
- }
168
- child.unref();
169
-
170
- if (child.pid !== undefined) {
171
- await updateAttemptProcess({
172
- cwd: options.cwd,
173
- runsDir: input.runsDir,
174
- runId,
175
- attemptId,
176
- process: {
177
- pid: child.pid,
178
- processGroupId: process.platform === "win32" ? undefined : child.pid,
179
- command: process.execPath,
180
- workerPid: child.pid,
181
- workerProcessGroupId: process.platform === "win32" ? undefined : child.pid,
182
- },
183
- }).catch(() => undefined);
184
- }
185
-
186
- armCompletionMonitor({ ...options, runId, attemptId, mode, store });
187
- return running;
194
+ export async function startAsyncSubagentRun(
195
+ options: StartAsyncSubagentRunOptions,
196
+ ): Promise<ResultEnvelope> {
197
+ const input = options.input;
198
+ const startedAt = new Date();
199
+ const runId = options.runId ?? createRunId(startedAt);
200
+ const attemptId = options.attemptId ?? createAttemptId(startedAt);
201
+ const mode = executionMode(input);
202
+ if (mode === "parallel") {
203
+ throw new SubagentToolAuthorityError(
204
+ "startAsyncSubagentRun handles one run; use startAsyncParallelSubagentRuns for parallel inputs.",
205
+ );
206
+ }
207
+ const dependency = input.asyncDependency ?? "unclassified";
208
+ const store = await createAttemptArtifactStore({
209
+ cwd: options.cwd,
210
+ runId,
211
+ attemptId,
212
+ runsDir: input.runsDir,
213
+ });
214
+ const payloadPath = store.pathFor("worker");
215
+ const payloadText = `${JSON.stringify({ input, cwd: options.cwd, backend: options.backend, runId, attemptId, startedAt: startedAt.toISOString() }, null, 2)}\n`;
216
+ await writeFile(payloadPath, payloadText);
217
+ const workerRef = store.refFor(
218
+ "worker",
219
+ Buffer.byteLength(payloadText, "utf8"),
220
+ );
221
+
222
+ const running = await store.writeResult({
223
+ backend: options.backend,
224
+ status: "running",
225
+ failureKind: null,
226
+ cwd: options.cwd,
227
+ startedAt,
228
+ completedAt: null,
229
+ workspace: { mode: "shared", cwd: options.cwd },
230
+ sandbox: { enabled: sandboxEnabled(input) },
231
+ exitCode: null,
232
+ signal: null,
233
+ artifacts: [workerRef],
234
+ correlationId: input.correlationId,
235
+ metadata: { contextLengthExceeded: false },
236
+ });
237
+
238
+ await beginRunRecord({
239
+ cwd: options.cwd,
240
+ runsDir: input.runsDir,
241
+ runId,
242
+ mode,
243
+ backend: options.backend,
244
+ startedAt,
245
+ dependency,
246
+ correlationId: input.correlationId,
247
+ parentSessionId: input.parentSessionId,
248
+ activeAttemptId: attemptId,
249
+ attempts: [
250
+ {
251
+ attemptId,
252
+ status: "running",
253
+ backend: options.backend,
254
+ startedAt: startedAt.toISOString(),
255
+ artifactCwd: options.cwd,
256
+ resultPath: running.artifacts.find(
257
+ (artifact) => artifact.type === "result",
258
+ )?.path,
259
+ },
260
+ ],
261
+ });
262
+ await writeRunLocator({
263
+ cwd: options.cwd,
264
+ runsDir: input.runsDir,
265
+ runId,
266
+ parentSessionId: input.parentSessionId,
267
+ correlationId: input.correlationId,
268
+ }).catch(() => undefined);
269
+ await appendRunEvent(
270
+ { cwd: options.cwd, runsDir: input.runsDir, runId },
271
+ {
272
+ type: "run.started",
273
+ status: "running",
274
+ message: `${mode} durable async run started`,
275
+ data: { dependency, attemptId },
276
+ },
277
+ );
278
+
279
+ const workerLogFd = openSync(join(store.attemptDir, "worker.log"), "a");
280
+ let child;
281
+ try {
282
+ child = spawn(process.execPath, [workerPath(), payloadPath], {
283
+ cwd: options.cwd,
284
+ detached: process.platform !== "win32",
285
+ stdio: ["ignore", workerLogFd, workerLogFd],
286
+ });
287
+ } finally {
288
+ closeSync(workerLogFd);
289
+ }
290
+ child.unref();
291
+
292
+ if (child.pid !== undefined) {
293
+ await updateAttemptProcess({
294
+ cwd: options.cwd,
295
+ runsDir: input.runsDir,
296
+ runId,
297
+ attemptId,
298
+ process: {
299
+ pid: child.pid,
300
+ processGroupId: process.platform === "win32" ? undefined : child.pid,
301
+ command: process.execPath,
302
+ workerPid: child.pid,
303
+ workerProcessGroupId:
304
+ process.platform === "win32" ? undefined : child.pid,
305
+ },
306
+ }).catch(() => undefined);
307
+ }
308
+
309
+ armCompletionMonitor({ ...options, runId, attemptId, mode, store });
310
+ return running;
188
311
  }