@h-rig/supervisor-plugin 0.0.6-alpha.157 → 0.0.6-alpha.159
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.
- package/dist/src/analysis/blockers.d.ts +35 -0
- package/dist/src/analysis/blockers.js +355 -0
- package/dist/src/analysis/taskGraphPrimitives.d.ts +58 -0
- package/dist/src/analysis/taskGraphPrimitives.js +528 -0
- package/dist/src/analysis/taskRanking.d.ts +24 -0
- package/dist/src/analysis/taskRanking.js +374 -0
- package/dist/src/analysis/taskScore.d.ts +17 -0
- package/dist/src/analysis/taskScore.js +49 -0
- package/dist/src/cli.d.ts +1 -7
- package/dist/src/cli.js +611 -91
- package/dist/src/index.js +682 -155
- package/dist/src/loop.d.ts +3 -5
- package/dist/src/loop.js +503 -23
- package/dist/src/plugin.js +655 -134
- package/dist/src/run-status.d.ts +2 -0
- package/dist/src/run-status.js +20 -0
- package/dist/src/supervisor.js +345 -6
- package/package.json +3 -7
package/dist/src/cli.js
CHANGED
|
@@ -1,45 +1,455 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"closing-out": false,
|
|
16
|
-
"needs-attention": true,
|
|
17
|
-
completed: true,
|
|
18
|
-
failed: true,
|
|
19
|
-
stopped: true
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __returnValue = (v) => v;
|
|
4
|
+
function __exportSetter(name, newValue) {
|
|
5
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
6
|
+
}
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
set: __exportSetter.bind(all, name)
|
|
14
|
+
});
|
|
20
15
|
};
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
16
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
17
|
+
|
|
18
|
+
// packages/supervisor-plugin/src/run-status.ts
|
|
19
|
+
function coerceRunStatus(value, fallback) {
|
|
20
|
+
return KNOWN_RUN_STATUS.has(value) ? value : fallback;
|
|
21
|
+
}
|
|
22
|
+
var KNOWN_RUN_STATUS;
|
|
23
|
+
var init_run_status = __esm(() => {
|
|
24
|
+
KNOWN_RUN_STATUS = new Set([
|
|
25
|
+
"created",
|
|
26
|
+
"queued",
|
|
27
|
+
"preparing",
|
|
28
|
+
"running",
|
|
29
|
+
"validating",
|
|
30
|
+
"reviewing",
|
|
31
|
+
"closing-out",
|
|
32
|
+
"completed",
|
|
33
|
+
"failed",
|
|
34
|
+
"stopped"
|
|
35
|
+
]);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// packages/supervisor-plugin/src/analysis/taskGraphPrimitives.ts
|
|
39
|
+
import {
|
|
40
|
+
OPERATOR_INACTIVE_RUN_STATUSES
|
|
41
|
+
} from "@rig/contracts";
|
|
42
|
+
function isObjectRecord(value) {
|
|
43
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
44
|
+
}
|
|
45
|
+
function readStringList(value) {
|
|
46
|
+
return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && entry.length > 0) : [];
|
|
47
|
+
}
|
|
48
|
+
function unique(values) {
|
|
49
|
+
return Array.from(new Set(values));
|
|
50
|
+
}
|
|
51
|
+
function readTaskMetadataStringList(task, key) {
|
|
52
|
+
const taskRecord = task;
|
|
53
|
+
const topLevel = readStringList(taskRecord[key]);
|
|
54
|
+
if (topLevel.length > 0)
|
|
55
|
+
return topLevel;
|
|
56
|
+
const metadata = isObjectRecord(task.metadata) ? task.metadata : null;
|
|
57
|
+
const metadataList = readStringList(metadata?.[key]);
|
|
58
|
+
if (metadataList.length > 0)
|
|
59
|
+
return metadataList;
|
|
60
|
+
if (key === "dependencies") {
|
|
61
|
+
return readStringList(metadata?.deps);
|
|
62
|
+
}
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
function readTaskBlockingDependencyRefs(task) {
|
|
66
|
+
return readTaskMetadataStringList(task, "dependencies");
|
|
67
|
+
}
|
|
68
|
+
function readTaskSourceIssueId(task) {
|
|
69
|
+
if (typeof task.sourceIssueId === "string" && task.sourceIssueId.length > 0) {
|
|
70
|
+
return task.sourceIssueId;
|
|
71
|
+
}
|
|
72
|
+
const metadata = isObjectRecord(task.metadata) ? task.metadata : null;
|
|
73
|
+
if (typeof metadata?.sourceIssueId === "string" && metadata.sourceIssueId.length > 0) {
|
|
74
|
+
return metadata.sourceIssueId;
|
|
75
|
+
}
|
|
76
|
+
const rigMetadata = isObjectRecord(metadata?._rig) ? metadata._rig : null;
|
|
77
|
+
return typeof rigMetadata?.sourceIssueId === "string" && rigMetadata.sourceIssueId.length > 0 ? rigMetadata.sourceIssueId : null;
|
|
78
|
+
}
|
|
79
|
+
function readTaskScope(task) {
|
|
80
|
+
const taskRecord = task;
|
|
81
|
+
const topLevel = readStringList(taskRecord.scope);
|
|
82
|
+
if (topLevel.length > 0)
|
|
83
|
+
return unique(topLevel.map((entry) => entry.trim()).filter((entry) => entry.length > 0));
|
|
84
|
+
const metadata = isObjectRecord(task.metadata) ? task.metadata : null;
|
|
85
|
+
const metadataScope = readStringList(metadata?.scope);
|
|
86
|
+
if (metadataScope.length > 0)
|
|
87
|
+
return unique(metadataScope.map((entry) => entry.trim()).filter((entry) => entry.length > 0));
|
|
88
|
+
return unique([
|
|
89
|
+
...readStringList(metadata?.files),
|
|
90
|
+
...readStringList(metadata?.paths)
|
|
91
|
+
].map((entry) => entry.trim()).filter((entry) => entry.length > 0));
|
|
92
|
+
}
|
|
93
|
+
function resolveTaskReference(ref, tasksById, taskIdByExternalRef, taskIdBySourceIssueId) {
|
|
94
|
+
if (tasksById.has(ref))
|
|
95
|
+
return ref;
|
|
96
|
+
return taskIdBySourceIssueId.get(ref) ?? taskIdByExternalRef.get(ref) ?? null;
|
|
97
|
+
}
|
|
98
|
+
function buildTaskReferenceIndex(tasks) {
|
|
99
|
+
return {
|
|
100
|
+
tasksById: new Map(tasks.map((task) => [task.id, task])),
|
|
101
|
+
taskIdByExternalRef: new Map(tasks.flatMap((task) => task.externalId ? [[task.externalId, task.id]] : [])),
|
|
102
|
+
taskIdBySourceIssueId: new Map(tasks.flatMap((task) => {
|
|
103
|
+
const sourceIssueId = readTaskSourceIssueId(task);
|
|
104
|
+
return sourceIssueId ? [[sourceIssueId, task.id]] : [];
|
|
105
|
+
}))
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function computeTaskBlockingDepths(tasks) {
|
|
109
|
+
const { tasksById, taskIdByExternalRef, taskIdBySourceIssueId } = buildTaskReferenceIndex(tasks);
|
|
110
|
+
const memo = new Map;
|
|
111
|
+
const visit = (taskId, stack) => {
|
|
112
|
+
const cached = memo.get(taskId);
|
|
113
|
+
if (cached !== undefined)
|
|
114
|
+
return cached;
|
|
115
|
+
if (stack.has(taskId))
|
|
116
|
+
return 0;
|
|
117
|
+
const task = tasksById.get(taskId);
|
|
118
|
+
if (!task)
|
|
119
|
+
return 0;
|
|
120
|
+
stack.add(taskId);
|
|
121
|
+
const blockers = readTaskBlockingDependencyRefs(task).map((ref) => resolveTaskReference(ref, tasksById, taskIdByExternalRef, taskIdBySourceIssueId)).filter((ref) => ref !== null && ref !== taskId);
|
|
122
|
+
const depth = blockers.length === 0 ? 0 : Math.max(...blockers.map((blockerId) => visit(blockerId, stack) + 1));
|
|
123
|
+
stack.delete(taskId);
|
|
124
|
+
memo.set(taskId, depth);
|
|
125
|
+
return depth;
|
|
126
|
+
};
|
|
127
|
+
for (const task of tasks) {
|
|
128
|
+
visit(task.id, new Set);
|
|
129
|
+
}
|
|
130
|
+
return memo;
|
|
131
|
+
}
|
|
132
|
+
function isTaskTerminalStatus(status) {
|
|
133
|
+
switch (status) {
|
|
134
|
+
case "closed":
|
|
135
|
+
case "completed":
|
|
136
|
+
case "done":
|
|
137
|
+
case "cancelled":
|
|
138
|
+
case "canceled":
|
|
139
|
+
return true;
|
|
140
|
+
default:
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function isTaskBlockedStatus(status) {
|
|
145
|
+
return status === "blocked";
|
|
146
|
+
}
|
|
147
|
+
function isTaskRunnableStatus(status) {
|
|
148
|
+
if (status === null || status === undefined || status === "")
|
|
149
|
+
return true;
|
|
150
|
+
if (isTaskTerminalStatus(status) || isTaskBlockedStatus(status))
|
|
151
|
+
return false;
|
|
152
|
+
switch (status) {
|
|
153
|
+
case "ready":
|
|
154
|
+
case "open":
|
|
155
|
+
case "failed":
|
|
156
|
+
return true;
|
|
157
|
+
default:
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
function computeTaskDependencyBadges(tasks) {
|
|
162
|
+
const index = buildTaskReferenceIndex(tasks);
|
|
163
|
+
const blockingDepths = computeTaskBlockingDepths(tasks);
|
|
164
|
+
const dependencyIdsByTask = new Map;
|
|
165
|
+
const unresolvedRefsByTask = new Map;
|
|
166
|
+
const blocksByTask = new Map;
|
|
167
|
+
for (const task of tasks) {
|
|
168
|
+
const dependencyIds = [];
|
|
169
|
+
const unresolvedRefs = [];
|
|
170
|
+
for (const ref of readTaskBlockingDependencyRefs(task)) {
|
|
171
|
+
const dependencyId = resolveTaskReference(ref, index.tasksById, index.taskIdByExternalRef, index.taskIdBySourceIssueId);
|
|
172
|
+
if (dependencyId && dependencyId !== task.id) {
|
|
173
|
+
dependencyIds.push(dependencyId);
|
|
174
|
+
const blocks = blocksByTask.get(dependencyId);
|
|
175
|
+
if (blocks) {
|
|
176
|
+
blocks.push(task.id);
|
|
177
|
+
} else {
|
|
178
|
+
blocksByTask.set(dependencyId, [task.id]);
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
unresolvedRefs.push(ref);
|
|
182
|
+
}
|
|
32
183
|
}
|
|
33
|
-
|
|
34
|
-
|
|
184
|
+
dependencyIdsByTask.set(task.id, unique(dependencyIds));
|
|
185
|
+
unresolvedRefsByTask.set(task.id, unique(unresolvedRefs));
|
|
186
|
+
}
|
|
187
|
+
const summaries = new Map;
|
|
188
|
+
for (const task of tasks) {
|
|
189
|
+
const dependencyIds = dependencyIdsByTask.get(task.id) ?? [];
|
|
190
|
+
const unresolvedDependencyRefs = unresolvedRefsByTask.get(task.id) ?? [];
|
|
191
|
+
const blockedBy = dependencyIds.filter((dependencyId) => {
|
|
192
|
+
const dependency = index.tasksById.get(dependencyId);
|
|
193
|
+
return dependency ? !isTaskTerminalStatus(dependency.status) : false;
|
|
194
|
+
});
|
|
195
|
+
const blocks = unique(blocksByTask.get(task.id) ?? []);
|
|
196
|
+
const blocked = isTaskBlockedStatus(task.status) || blockedBy.length > 0;
|
|
197
|
+
const ready = isTaskRunnableStatus(task.status) && !blocked;
|
|
198
|
+
const badges = [];
|
|
199
|
+
if (blocked) {
|
|
200
|
+
badges.push({
|
|
201
|
+
kind: "blocked",
|
|
202
|
+
label: blockedBy.length > 0 ? `blocked \xD7${blockedBy.length}` : "blocked",
|
|
203
|
+
description: blockedBy.length > 0 ? `Waiting on ${blockedBy.join(", ")}.` : "Task source marks this task blocked.",
|
|
204
|
+
...blockedBy.length > 0 ? { count: blockedBy.length } : {},
|
|
205
|
+
taskIds: blockedBy
|
|
206
|
+
});
|
|
207
|
+
} else if (ready) {
|
|
208
|
+
badges.push({
|
|
209
|
+
kind: "ready",
|
|
210
|
+
label: "ready",
|
|
211
|
+
description: "No open dependencies block this task."
|
|
212
|
+
});
|
|
35
213
|
}
|
|
36
|
-
|
|
214
|
+
if (dependencyIds.length > 0 || blocks.length > 0 || unresolvedDependencyRefs.length > 0) {
|
|
215
|
+
badges.push({
|
|
216
|
+
kind: "dependency",
|
|
217
|
+
label: `deps ${dependencyIds.length}/${blocks.length}`,
|
|
218
|
+
description: [
|
|
219
|
+
dependencyIds.length > 0 ? `Depends on ${dependencyIds.join(", ")}.` : null,
|
|
220
|
+
blocks.length > 0 ? `Blocks ${blocks.join(", ")}.` : null,
|
|
221
|
+
unresolvedDependencyRefs.length > 0 ? `Unresolved refs: ${unresolvedDependencyRefs.join(", ")}.` : null
|
|
222
|
+
].filter((part) => part !== null).join(" "),
|
|
223
|
+
count: dependencyIds.length + blocks.length,
|
|
224
|
+
taskIds: unique([...dependencyIds, ...blocks])
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
summaries.set(task.id, {
|
|
228
|
+
taskId: task.id,
|
|
229
|
+
blockingDepth: blockingDepths.get(task.id) ?? 0,
|
|
230
|
+
dependencyIds,
|
|
231
|
+
unresolvedDependencyRefs,
|
|
232
|
+
blockedBy,
|
|
233
|
+
blocks,
|
|
234
|
+
blocked,
|
|
235
|
+
ready,
|
|
236
|
+
dependencyCount: dependencyIds.length,
|
|
237
|
+
dependentCount: blocks.length,
|
|
238
|
+
badges
|
|
239
|
+
});
|
|
37
240
|
}
|
|
241
|
+
return summaries;
|
|
242
|
+
}
|
|
243
|
+
function stringValue(value) {
|
|
244
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
245
|
+
}
|
|
246
|
+
function stringArray(value) {
|
|
247
|
+
return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && entry.trim().length > 0).map((entry) => entry.trim()) : [];
|
|
248
|
+
}
|
|
249
|
+
function numberOrNull(value) {
|
|
250
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : null;
|
|
251
|
+
}
|
|
252
|
+
function metadataOf(task) {
|
|
253
|
+
return isObjectRecord(task.metadata) ? task.metadata : {};
|
|
38
254
|
}
|
|
255
|
+
function normalizeTaskStatus(status) {
|
|
256
|
+
const token = typeof status === "string" ? status.trim().toLowerCase() : "";
|
|
257
|
+
if (token === "done")
|
|
258
|
+
return "completed";
|
|
259
|
+
if (token === "canceled")
|
|
260
|
+
return "cancelled";
|
|
261
|
+
return TASK_STATUSES.has(token) ? token : "unknown";
|
|
262
|
+
}
|
|
263
|
+
function toTaskDependencyProjection(task) {
|
|
264
|
+
const metadata = metadataOf(task);
|
|
265
|
+
return {
|
|
266
|
+
id: String(task.id),
|
|
267
|
+
title: stringValue(task.title),
|
|
268
|
+
status: normalizeTaskStatus(task.status),
|
|
269
|
+
priority: numberOrNull(task.priority),
|
|
270
|
+
metadata,
|
|
271
|
+
externalId: stringValue(task.externalId),
|
|
272
|
+
sourceIssueId: stringValue(task.sourceIssueId),
|
|
273
|
+
dependencies: stringArray(task.dependencies),
|
|
274
|
+
parentChildDeps: stringArray(task.parentChildDeps),
|
|
275
|
+
createdAt: stringValue(task.createdAt) ?? "",
|
|
276
|
+
updatedAt: stringValue(task.updatedAt) ?? "",
|
|
277
|
+
role: stringValue(task.role),
|
|
278
|
+
scope: stringArray(task.scope),
|
|
279
|
+
validationKeys: stringArray(task.validationKeys),
|
|
280
|
+
labels: stringArray(task.labels),
|
|
281
|
+
assignees: task.assignees ?? null,
|
|
282
|
+
assignedTo: task.assignedTo ?? null
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
function latestRunByTaskId(runs) {
|
|
286
|
+
const byTask = new Map;
|
|
287
|
+
const stamp = (run) => Date.parse(run.updatedAt ?? run.startedAt ?? "") || 0;
|
|
288
|
+
for (const run of runs) {
|
|
289
|
+
if (!run.taskId)
|
|
290
|
+
continue;
|
|
291
|
+
const current = byTask.get(run.taskId);
|
|
292
|
+
if (!current || stamp(run) >= stamp(current))
|
|
293
|
+
byTask.set(run.taskId, run);
|
|
294
|
+
}
|
|
295
|
+
return byTask;
|
|
296
|
+
}
|
|
297
|
+
var TASK_STATUSES;
|
|
298
|
+
var init_taskGraphPrimitives = __esm(() => {
|
|
299
|
+
TASK_STATUSES = new Set([
|
|
300
|
+
"draft",
|
|
301
|
+
"open",
|
|
302
|
+
"ready",
|
|
303
|
+
"queued",
|
|
304
|
+
"running",
|
|
305
|
+
"in_progress",
|
|
306
|
+
"under_review",
|
|
307
|
+
"blocked",
|
|
308
|
+
"unknown",
|
|
309
|
+
"completed",
|
|
310
|
+
"failed",
|
|
311
|
+
"cancelled",
|
|
312
|
+
"closed"
|
|
313
|
+
]);
|
|
314
|
+
});
|
|
39
315
|
|
|
40
|
-
// packages/supervisor-plugin/src/
|
|
41
|
-
|
|
42
|
-
|
|
316
|
+
// packages/supervisor-plugin/src/analysis/taskScore.ts
|
|
317
|
+
function finiteNumber(value, fallback) {
|
|
318
|
+
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
319
|
+
}
|
|
320
|
+
function scoreTask(input) {
|
|
321
|
+
const priority = finiteNumber(input.priority, 3);
|
|
322
|
+
const unblockCount = Math.max(0, finiteNumber(input.unblockCount, 0));
|
|
323
|
+
const roleWeight = input.role ? ROLE_WEIGHT[input.role] ?? 0 : 0;
|
|
324
|
+
const criticalityWeight = input.criticality ? CRITICALITY_WEIGHT[input.criticality] ?? 0 : 0;
|
|
325
|
+
const validationWeight = (input.validation ?? []).some((entry) => entry.includes("test-contract") || entry.includes("test-boundary")) ? 8 : 0;
|
|
326
|
+
const queueWeight = finiteNumber(input.queueWeight, 0);
|
|
327
|
+
return unblockCount * 100 + (10 - priority) + roleWeight + criticalityWeight + validationWeight + queueWeight;
|
|
328
|
+
}
|
|
329
|
+
function rankTasks(tasks, scoreInput, idOf) {
|
|
330
|
+
return tasks.map((task) => {
|
|
331
|
+
const input = scoreInput(task);
|
|
332
|
+
return {
|
|
333
|
+
task,
|
|
334
|
+
score: scoreTask(input),
|
|
335
|
+
priority: finiteNumber(input.priority, 3),
|
|
336
|
+
unblockCount: Math.max(0, finiteNumber(input.unblockCount, 0))
|
|
337
|
+
};
|
|
338
|
+
}).toSorted((left, right) => {
|
|
339
|
+
const scoreDelta = right.score - left.score;
|
|
340
|
+
if (scoreDelta !== 0)
|
|
341
|
+
return scoreDelta;
|
|
342
|
+
const unblockDelta = right.unblockCount - left.unblockCount;
|
|
343
|
+
if (unblockDelta !== 0)
|
|
344
|
+
return unblockDelta;
|
|
345
|
+
const priorityDelta = left.priority - right.priority;
|
|
346
|
+
if (priorityDelta !== 0)
|
|
347
|
+
return priorityDelta;
|
|
348
|
+
return idOf(left.task).localeCompare(idOf(right.task));
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
var ROLE_WEIGHT, CRITICALITY_WEIGHT;
|
|
352
|
+
var init_taskScore = __esm(() => {
|
|
353
|
+
ROLE_WEIGHT = {
|
|
354
|
+
architect: 25,
|
|
355
|
+
extractor: 10
|
|
356
|
+
};
|
|
357
|
+
CRITICALITY_WEIGHT = {
|
|
358
|
+
core: 20,
|
|
359
|
+
high: 10,
|
|
360
|
+
normal: 0
|
|
361
|
+
};
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
// packages/supervisor-plugin/src/analysis/taskRanking.ts
|
|
365
|
+
function isObjectRecord2(value) {
|
|
366
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
367
|
+
}
|
|
368
|
+
function readStringList2(value) {
|
|
369
|
+
return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && entry.length > 0) : [];
|
|
370
|
+
}
|
|
371
|
+
function readTaskRole(task) {
|
|
372
|
+
if (typeof task.role === "string" && task.role.trim())
|
|
373
|
+
return task.role.trim();
|
|
374
|
+
const metadata = isObjectRecord2(task.metadata) ? task.metadata : null;
|
|
375
|
+
return typeof metadata?.role === "string" && metadata.role.trim() ? metadata.role.trim() : null;
|
|
376
|
+
}
|
|
377
|
+
function readTaskCriticality(task) {
|
|
378
|
+
const metadata = isObjectRecord2(task.metadata) ? task.metadata : null;
|
|
379
|
+
return typeof metadata?.criticality === "string" && metadata.criticality.trim() ? metadata.criticality.trim() : null;
|
|
380
|
+
}
|
|
381
|
+
function readTaskValidationKeys(task) {
|
|
382
|
+
const taskRecord = task;
|
|
383
|
+
const topLevel = readStringList2(taskRecord.validationKeys);
|
|
384
|
+
if (topLevel.length > 0)
|
|
385
|
+
return topLevel;
|
|
386
|
+
const metadata = isObjectRecord2(task.metadata) ? task.metadata : null;
|
|
387
|
+
return readStringList2(metadata?.validation);
|
|
388
|
+
}
|
|
389
|
+
function readTaskQueueWeight(task) {
|
|
390
|
+
const metadata = isObjectRecord2(task.metadata) ? task.metadata : null;
|
|
391
|
+
const queueWeight = metadata?.queueWeight ?? metadata?.queue_weight;
|
|
392
|
+
return typeof queueWeight === "number" && Number.isFinite(queueWeight) ? queueWeight : 0;
|
|
393
|
+
}
|
|
394
|
+
function scoreInputForTask(task, unblockCount) {
|
|
395
|
+
return {
|
|
396
|
+
priority: task.priority,
|
|
397
|
+
unblockCount,
|
|
398
|
+
role: readTaskRole(task),
|
|
399
|
+
criticality: readTaskCriticality(task),
|
|
400
|
+
validation: readTaskValidationKeys(task),
|
|
401
|
+
queueWeight: readTaskQueueWeight(task)
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
function rankReadyTasks(tasks, options = {}) {
|
|
405
|
+
const excluded = new Set(options.excludeTaskIds ?? []);
|
|
406
|
+
const activeTaskIds = new Set(options.activeTaskIds ?? []);
|
|
407
|
+
const badges = computeTaskDependencyBadges(tasks);
|
|
408
|
+
const tasksById = new Map(tasks.map((task) => [String(task.id), task]));
|
|
409
|
+
const openBlockCount = (task) => (badges.get(task.id)?.blocks ?? []).filter((blockedTaskId) => {
|
|
410
|
+
const blockedTask = tasksById.get(blockedTaskId);
|
|
411
|
+
return blockedTask ? !isTaskTerminalStatus(blockedTask.status) : false;
|
|
412
|
+
}).length;
|
|
413
|
+
const readyTasks = tasks.filter((task) => !excluded.has(task.id)).filter((task) => !activeTaskIds.has(task.id)).filter((task) => options.filter?.(task) ?? true).filter((task) => badges.get(task.id)?.ready === true);
|
|
414
|
+
const maxUnblockCount = Math.max(0, ...readyTasks.map(openBlockCount));
|
|
415
|
+
const selectedByMode = readyTasks.filter((task) => {
|
|
416
|
+
const unblockCount = openBlockCount(task);
|
|
417
|
+
if (options.selection === "blocking-only")
|
|
418
|
+
return unblockCount > 0;
|
|
419
|
+
if (options.selection === "max-unblock")
|
|
420
|
+
return maxUnblockCount > 0 && unblockCount === maxUnblockCount;
|
|
421
|
+
return true;
|
|
422
|
+
});
|
|
423
|
+
return rankTasks(selectedByMode, (task) => scoreInputForTask(task, openBlockCount(task)), (task) => task.id).map((entry) => ({
|
|
424
|
+
task: entry.task,
|
|
425
|
+
score: entry.score,
|
|
426
|
+
priority: entry.priority,
|
|
427
|
+
unblockCount: entry.unblockCount,
|
|
428
|
+
scope: readTaskScope(entry.task)
|
|
429
|
+
}));
|
|
430
|
+
}
|
|
431
|
+
function selectRankedReadyTasks(tasks, options = {}) {
|
|
432
|
+
const ranked = rankReadyTasks(tasks, options);
|
|
433
|
+
if (options.requireDisjointScopes !== true && !options.disjointWithScopes) {
|
|
434
|
+
return ranked.slice(0, options.limit).map((entry) => entry.task);
|
|
435
|
+
}
|
|
436
|
+
const occupiedScopes = new Set(options.disjointWithScopes ?? []);
|
|
437
|
+
const selected = [];
|
|
438
|
+
for (const entry of ranked) {
|
|
439
|
+
if (entry.scope.some((scope) => occupiedScopes.has(scope)))
|
|
440
|
+
continue;
|
|
441
|
+
selected.push(entry.task);
|
|
442
|
+
for (const scope of entry.scope)
|
|
443
|
+
occupiedScopes.add(scope);
|
|
444
|
+
if (options.limit !== undefined && selected.length >= options.limit)
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
return selected;
|
|
448
|
+
}
|
|
449
|
+
var init_taskRanking = __esm(() => {
|
|
450
|
+
init_taskGraphPrimitives();
|
|
451
|
+
init_taskScore();
|
|
452
|
+
});
|
|
43
453
|
|
|
44
454
|
// packages/supervisor-plugin/src/journal.ts
|
|
45
455
|
import { Schema } from "effect";
|
|
@@ -119,9 +529,100 @@ function reduceSupervisorJournal(events) {
|
|
|
119
529
|
}
|
|
120
530
|
return { status, processed, succeeded, failed, skipped, current, plannedOrder, selectionPolicy, concurrency, idleReason, stopReason, closures, anomalies };
|
|
121
531
|
}
|
|
532
|
+
var init_journal = () => {};
|
|
533
|
+
|
|
534
|
+
// packages/supervisor-plugin/src/analysis/blockers.ts
|
|
535
|
+
function labelsFor(task) {
|
|
536
|
+
return readTaskMetadataStringList(task, "labels").map((label) => label.toLowerCase());
|
|
537
|
+
}
|
|
538
|
+
function configuredTier(task, labels) {
|
|
539
|
+
const metadata = task.metadata && typeof task.metadata === "object" && !Array.isArray(task.metadata) ? task.metadata : {};
|
|
540
|
+
const tier = metadata.riskTier ?? metadata.actionRiskTier;
|
|
541
|
+
if (tier === "t1-read" || tier === "t2-reversible" || tier === "t3-external" || tier === "t4-irreversible")
|
|
542
|
+
return tier;
|
|
543
|
+
if (labels.some((label) => /prod|deploy|migration|billing|delete|irreversible/.test(label)))
|
|
544
|
+
return "t4-irreversible";
|
|
545
|
+
if (labels.some((label) => /customer|vendor|external|secret|credential|approval|decision/.test(label)))
|
|
546
|
+
return "t3-external";
|
|
547
|
+
const scopes = task.scope ?? [];
|
|
548
|
+
if (scopes.some((scope) => /docs|readme|test|spec/.test(scope.toLowerCase())))
|
|
549
|
+
return "t1-read";
|
|
550
|
+
return "t2-reversible";
|
|
551
|
+
}
|
|
552
|
+
function tierOf(task, labels = []) {
|
|
553
|
+
const projection = "metadata" in task && "id" in task && typeof task.id === "string" ? toTaskDependencyProjection(task) : task;
|
|
554
|
+
return configuredTier(projection, labels.length > 0 ? labels : labelsFor(projection)) ?? "t2-reversible";
|
|
555
|
+
}
|
|
556
|
+
function baseClassification(task, blockerClass, source, rationale, labels) {
|
|
557
|
+
return {
|
|
558
|
+
taskId: task.id,
|
|
559
|
+
blockerClass,
|
|
560
|
+
actionRiskTier: tierOf(task, labels),
|
|
561
|
+
rationale,
|
|
562
|
+
source,
|
|
563
|
+
autoApplied: source === "llm"
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
function normalizeRunStatus(status) {
|
|
567
|
+
if (status === "waiting-approval" || status === "waiting-user-input" || status === "needs-attention" || status === "completed" || status === "failed" || status === "stopped" || status === "running")
|
|
568
|
+
return status;
|
|
569
|
+
return null;
|
|
570
|
+
}
|
|
571
|
+
function isHumanBlockerClass(blockerClass) {
|
|
572
|
+
return HUMAN_BLOCKERS.has(blockerClass);
|
|
573
|
+
}
|
|
574
|
+
function classifyBlocker(input) {
|
|
575
|
+
const labels = input.labels ?? labelsFor(input.task);
|
|
576
|
+
const runStatus = normalizeRunStatus(input.run?.status);
|
|
577
|
+
if (runStatus === "waiting-approval")
|
|
578
|
+
return baseClassification(input.task, "human-approval", "status", "run awaiting approval", labels);
|
|
579
|
+
if (runStatus === "waiting-user-input")
|
|
580
|
+
return baseClassification(input.task, "external-input", "status", "run awaiting user input", labels);
|
|
581
|
+
if (input.task.status !== "blocked")
|
|
582
|
+
return baseClassification(input.task, "not-blocked", "elimination", "task is not blocked", labels);
|
|
583
|
+
const incomplete = (input.badges.get(input.task.id)?.blockedBy ?? []).filter((dependencyId) => {
|
|
584
|
+
const dependency = input.tasksById.get(dependencyId);
|
|
585
|
+
return dependency ? !isTaskTerminalStatus(dependency.status) : false;
|
|
586
|
+
});
|
|
587
|
+
if (incomplete.length > 0)
|
|
588
|
+
return baseClassification(input.task, "task-blocked", "elimination", `blocked by ${incomplete.length} incomplete task(s)`, labels);
|
|
589
|
+
if (labels.includes("needs-decision"))
|
|
590
|
+
return baseClassification(input.task, "human-decision", "label", "needs-decision label", labels);
|
|
591
|
+
if (labels.some((label) => /^waiting-on-/.test(label)))
|
|
592
|
+
return baseClassification(input.task, "external-input", "label", "waiting-on-* label", labels);
|
|
593
|
+
if (input.config?.llm)
|
|
594
|
+
return baseClassification(input.task, "human-decision", "llm", "LLM residue classifier marked this as human-gated", labels);
|
|
595
|
+
return baseClassification(input.task, "human-decision", "elimination", "blocked, all task dependencies terminal; non-task gate remains", labels);
|
|
596
|
+
}
|
|
597
|
+
function classifyTasks(tasks, runs = [], options = {}) {
|
|
598
|
+
const projected = tasks.map(toTaskDependencyProjection);
|
|
599
|
+
const badges = computeTaskDependencyBadges(projected);
|
|
600
|
+
const tasksById = new Map(projected.map((task) => [task.id, task]));
|
|
601
|
+
const runByTask = latestRunByTaskId(runs);
|
|
602
|
+
const classifier = options.classifier ?? classifyBlocker;
|
|
603
|
+
const classifications = projected.map((task) => classifier({ task, badges, tasksById, run: runByTask.get(task.id) ?? null, labels: labelsFor(task) })).filter((classification) => options.humanOnly !== true || isHumanBlockerClass(classification.blockerClass));
|
|
604
|
+
return {
|
|
605
|
+
classifications,
|
|
606
|
+
byTaskId: new Map(classifications.map((classification) => [classification.taskId, classification])),
|
|
607
|
+
human: classifications.filter((classification) => isHumanBlockerClass(classification.blockerClass)),
|
|
608
|
+
machine: classifications.filter((classification) => !isHumanBlockerClass(classification.blockerClass)),
|
|
609
|
+
generatedAt: options.generatedAt ?? new Date().toISOString()
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
var HUMAN_BLOCKERS;
|
|
613
|
+
var init_blockers = __esm(() => {
|
|
614
|
+
init_taskGraphPrimitives();
|
|
615
|
+
HUMAN_BLOCKERS = new Set(["human-decision", "human-approval", "external-input"]);
|
|
616
|
+
});
|
|
122
617
|
|
|
123
618
|
// packages/supervisor-plugin/src/loop.ts
|
|
124
|
-
|
|
619
|
+
var exports_loop = {};
|
|
620
|
+
__export(exports_loop, {
|
|
621
|
+
unblockTask: () => unblockTask,
|
|
622
|
+
runSupervisorLoop: () => runSupervisorLoop,
|
|
623
|
+
planSupervisorLoop: () => planSupervisorLoop,
|
|
624
|
+
controlSupervisorRun: () => controlSupervisorRun
|
|
625
|
+
});
|
|
125
626
|
function selectionMode(policy) {
|
|
126
627
|
return policy === "blocking-only" || policy === "max-unblock" ? policy : "all-ready";
|
|
127
628
|
}
|
|
@@ -180,25 +681,7 @@ function failedOutcome(outcome) {
|
|
|
180
681
|
return outcome.status === "failed" || outcome.status === "stopped" || outcome.status === "needs-attention" || outcome.status === "waiting-approval" || outcome.status === "waiting-user-input";
|
|
181
682
|
}
|
|
182
683
|
function runStatus(value) {
|
|
183
|
-
|
|
184
|
-
case "created":
|
|
185
|
-
case "queued":
|
|
186
|
-
case "preparing":
|
|
187
|
-
case "running":
|
|
188
|
-
case "waiting-approval":
|
|
189
|
-
case "waiting-user-input":
|
|
190
|
-
case "paused":
|
|
191
|
-
case "validating":
|
|
192
|
-
case "reviewing":
|
|
193
|
-
case "closing-out":
|
|
194
|
-
case "needs-attention":
|
|
195
|
-
case "completed":
|
|
196
|
-
case "failed":
|
|
197
|
-
case "stopped":
|
|
198
|
-
return value;
|
|
199
|
-
default:
|
|
200
|
-
return "failed";
|
|
201
|
-
}
|
|
684
|
+
return coerceRunStatus(value, "failed");
|
|
202
685
|
}
|
|
203
686
|
async function runSupervisorLoop(projectRoot, deps, options = {}) {
|
|
204
687
|
const events = [{ kind: "supervisor.started", at: at(deps), options }];
|
|
@@ -269,6 +752,10 @@ async function runSupervisorLoop(projectRoot, deps, options = {}) {
|
|
|
269
752
|
const projection = reduceSupervisorJournal(events);
|
|
270
753
|
return { ok: failed === 0, dryRun: options.dryRun === true, plannedOrder: plannedAll, events, projection };
|
|
271
754
|
}
|
|
755
|
+
async function controlSupervisorRun(projectRoot, runId, control, deps) {
|
|
756
|
+
await deps.deliverRunControl(projectRoot, runId, control);
|
|
757
|
+
return { ok: true, runId, control: control.kind };
|
|
758
|
+
}
|
|
272
759
|
function collectBlockingClosure(taskId, badges) {
|
|
273
760
|
const closure = new Set;
|
|
274
761
|
const visit = (currentTaskId) => {
|
|
@@ -291,10 +778,60 @@ async function unblockTask(projectRoot, taskId, deps, options = {}) {
|
|
|
291
778
|
const blockers = collectBlockingClosure(taskId, badges);
|
|
292
779
|
return runSupervisorLoop(projectRoot, deps, { ...options, candidateTaskIds: blockers, selectionPolicy: "rank", maxTasks: 1 });
|
|
293
780
|
}
|
|
781
|
+
var init_loop = __esm(() => {
|
|
782
|
+
init_taskGraphPrimitives();
|
|
783
|
+
init_taskRanking();
|
|
784
|
+
init_journal();
|
|
785
|
+
init_run_status();
|
|
786
|
+
init_blockers();
|
|
787
|
+
});
|
|
294
788
|
|
|
295
789
|
// packages/supervisor-plugin/src/cli.ts
|
|
790
|
+
import { RUN_DISPATCH, RUN_READ_MODEL, TASK_IO_SERVICE_CAPABILITY } from "@rig/contracts";
|
|
791
|
+
import { defineCapability } from "@rig/core/capability";
|
|
792
|
+
import { requireCapabilityForRoot } from "@rig/core/capability-loaders";
|
|
793
|
+
|
|
794
|
+
// packages/supervisor-plugin/src/awaiter.ts
|
|
795
|
+
var TERMINAL_RUN_STATUSES = {
|
|
796
|
+
created: false,
|
|
797
|
+
queued: false,
|
|
798
|
+
preparing: false,
|
|
799
|
+
running: false,
|
|
800
|
+
"waiting-approval": false,
|
|
801
|
+
"waiting-user-input": false,
|
|
802
|
+
paused: false,
|
|
803
|
+
validating: false,
|
|
804
|
+
reviewing: false,
|
|
805
|
+
"closing-out": false,
|
|
806
|
+
"needs-attention": true,
|
|
807
|
+
completed: true,
|
|
808
|
+
failed: true,
|
|
809
|
+
stopped: true
|
|
810
|
+
};
|
|
811
|
+
async function awaitTerminalRun(options) {
|
|
812
|
+
const startedAt = Date.now();
|
|
813
|
+
const pollMs = Math.max(0, Math.floor(options.pollMs ?? 5000));
|
|
814
|
+
while (true) {
|
|
815
|
+
const snapshot = await options.readStatus(options.runId);
|
|
816
|
+
if (snapshot && TERMINAL_RUN_STATUSES[snapshot.status]) {
|
|
817
|
+
return {
|
|
818
|
+
runId: options.runId,
|
|
819
|
+
status: snapshot.status,
|
|
820
|
+
failed: snapshot.status !== "completed"
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
if (options.timeoutMs !== undefined && Date.now() - startedAt >= options.timeoutMs) {
|
|
824
|
+
return { runId: options.runId, status: "needs-attention", failed: true };
|
|
825
|
+
}
|
|
826
|
+
await options.waitForChange(pollMs);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
// packages/supervisor-plugin/src/cli.ts
|
|
831
|
+
init_run_status();
|
|
296
832
|
var SUPERVISOR_LOOP_CLI_ID = "supervisor.loop";
|
|
297
833
|
var SUPERVISOR_UNBLOCK_CLI_ID = "supervisor.unblock";
|
|
834
|
+
var RunReadModelCap = defineCapability(RUN_READ_MODEL);
|
|
298
835
|
function printJson(value) {
|
|
299
836
|
console.log(JSON.stringify(value, null, 2));
|
|
300
837
|
}
|
|
@@ -331,55 +868,36 @@ function parsePositiveInt(value, flag, fallback) {
|
|
|
331
868
|
}
|
|
332
869
|
return parsed;
|
|
333
870
|
}
|
|
334
|
-
function parseCsv(value) {
|
|
335
|
-
return value?.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0) ?? [];
|
|
336
|
-
}
|
|
337
871
|
function asRunStatus(value) {
|
|
338
|
-
|
|
339
|
-
case "created":
|
|
340
|
-
case "queued":
|
|
341
|
-
case "preparing":
|
|
342
|
-
case "running":
|
|
343
|
-
case "waiting-approval":
|
|
344
|
-
case "waiting-user-input":
|
|
345
|
-
case "paused":
|
|
346
|
-
case "validating":
|
|
347
|
-
case "reviewing":
|
|
348
|
-
case "closing-out":
|
|
349
|
-
case "needs-attention":
|
|
350
|
-
case "completed":
|
|
351
|
-
case "failed":
|
|
352
|
-
case "stopped":
|
|
353
|
-
return value;
|
|
354
|
-
default:
|
|
355
|
-
return "needs-attention";
|
|
356
|
-
}
|
|
872
|
+
return coerceRunStatus(value, "needs-attention");
|
|
357
873
|
}
|
|
358
874
|
function delay(ms) {
|
|
359
875
|
const { promise, resolve } = Promise.withResolvers();
|
|
360
876
|
setTimeout(resolve, ms);
|
|
361
877
|
return promise;
|
|
362
878
|
}
|
|
363
|
-
async function loadSupervisorClient() {
|
|
364
|
-
const [taskIo,
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
import("@rig/runtime/control-plane/dispatch")
|
|
879
|
+
async function loadSupervisorClient(projectRoot) {
|
|
880
|
+
const [taskIo, runReadModel] = await Promise.all([
|
|
881
|
+
requireCapabilityForRoot(projectRoot, defineCapability(TASK_IO_SERVICE_CAPABILITY), "No task-sources plugin provides task IO for this project root."),
|
|
882
|
+
requireCapabilityForRoot(projectRoot, RunReadModelCap, "No run-worker plugin provides run read-model for this project root.")
|
|
368
883
|
]);
|
|
369
|
-
return { listTasks: taskIo.listTasks, listRuns:
|
|
884
|
+
return { listTasks: taskIo.listTasks, listRuns: (root) => runReadModel.listRuns({ projectRoot: root }) };
|
|
370
885
|
}
|
|
371
886
|
function supervisorDeps(timeoutMs) {
|
|
372
887
|
return {
|
|
373
|
-
listTasks: async (projectRoot) => (await loadSupervisorClient()).listTasks(projectRoot),
|
|
374
|
-
listRuns: async (projectRoot) => (await loadSupervisorClient()).listRuns(projectRoot),
|
|
375
|
-
dispatchRun: async (
|
|
888
|
+
listTasks: async (projectRoot) => (await loadSupervisorClient(projectRoot)).listTasks(projectRoot),
|
|
889
|
+
listRuns: async (projectRoot) => (await loadSupervisorClient(projectRoot)).listRuns(projectRoot),
|
|
890
|
+
dispatchRun: async (input) => {
|
|
891
|
+
const service = await requireCapabilityForRoot(input.projectRoot, defineCapability(RUN_DISPATCH), "No transport plugin provides run dispatch for this project root.");
|
|
892
|
+
return service.dispatchRun(input);
|
|
893
|
+
},
|
|
376
894
|
awaitRunTerminal: async (projectRoot, runId) => {
|
|
377
895
|
const awaitedRunId = runId;
|
|
378
896
|
return awaitTerminalRun({
|
|
379
897
|
runId: awaitedRunId,
|
|
380
898
|
timeoutMs,
|
|
381
899
|
readStatus: async (id) => {
|
|
382
|
-
const { listRuns } = await loadSupervisorClient();
|
|
900
|
+
const { listRuns } = await loadSupervisorClient(projectRoot);
|
|
383
901
|
const run = (await listRuns(projectRoot)).find((candidate) => candidate.runId === id);
|
|
384
902
|
return run ? { runId: id, status: asRunStatus(run.status), ...run.errorSummary ? { diagnostic: run.errorSummary } : {} } : null;
|
|
385
903
|
},
|
|
@@ -409,13 +927,14 @@ async function executeLoop(context, args) {
|
|
|
409
927
|
const stopWhen = takeOption(task.rest, "--stop-when");
|
|
410
928
|
const timeout = takeOption(stopWhen.rest, "--timeout-ms");
|
|
411
929
|
requireNoExtraArgs(timeout.rest, "rig loop [--task <id>] [--max-tasks <n>] [--concurrency <n>] [--stop-when <csv>] [--dry-run] [--json]");
|
|
412
|
-
const
|
|
930
|
+
const { runSupervisorLoop: runSupervisorLoop2 } = await Promise.resolve().then(() => (init_loop(), exports_loop));
|
|
931
|
+
const result = await runSupervisorLoop2(context.projectRoot, supervisorDeps(parsePositiveInt(timeout.value, "--timeout-ms", 1800000)), {
|
|
413
932
|
maxTasks: parsePositiveInt(maxTasks.value, "--max-tasks", 1),
|
|
414
933
|
concurrency: parsePositiveInt(concurrency.value, "--concurrency", 1),
|
|
415
934
|
...task.value ? { candidateTaskIds: [task.value] } : {},
|
|
416
|
-
dryRun: dry.value || context.dryRun
|
|
935
|
+
dryRun: Boolean(dry.value || context.dryRun)
|
|
417
936
|
});
|
|
418
|
-
const details = { ...result, stopWhen:
|
|
937
|
+
const details = { ...result, stopWhen: stopWhen.value?.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0) ?? [] };
|
|
419
938
|
if (context.outputMode === "text") {
|
|
420
939
|
if (json.value)
|
|
421
940
|
printJson(details);
|
|
@@ -430,7 +949,8 @@ async function executeUnblock(context, args) {
|
|
|
430
949
|
const timeout = takeOption(json.rest, "--timeout-ms");
|
|
431
950
|
const taskId = timeout.rest[0]?.startsWith("-") ? undefined : timeout.rest[0];
|
|
432
951
|
requireNoExtraArgs(taskId ? timeout.rest.slice(1) : timeout.rest, "rig unblock [task-id] [--dry-run] [--json]");
|
|
433
|
-
const
|
|
952
|
+
const { unblockTask: unblockTask2 } = await Promise.resolve().then(() => (init_loop(), exports_loop));
|
|
953
|
+
const result = await unblockTask2(context.projectRoot, taskId ?? null, supervisorDeps(parsePositiveInt(timeout.value, "--timeout-ms", 1800000)), { dryRun: Boolean(dry.value || context.dryRun) });
|
|
434
954
|
if (context.outputMode === "text") {
|
|
435
955
|
if (json.value)
|
|
436
956
|
printJson(result);
|