sneakoscope 2.0.9 → 2.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -4
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/crates/sks-core/src/main.rs +1 -1
- package/dist/.sks-build-stamp.json +4 -4
- package/dist/bin/sks.js +1 -1
- package/dist/build-manifest.json +37 -8
- package/dist/cli/command-registry.js +2 -0
- package/dist/cli/install-helpers.js +8 -20
- package/dist/commands/doctor.js +23 -10
- package/dist/commands/zellij-slot-column-anchor.js +23 -0
- package/dist/commands/zellij-slot-pane.js +26 -0
- package/dist/core/agents/agent-orchestrator.js +255 -16
- package/dist/core/agents/agent-patch-schema.js +8 -1
- package/dist/core/agents/agent-role-config.js +92 -0
- package/dist/core/agents/native-cli-session-swarm.js +186 -71
- package/dist/core/commands/naruto-command.js +165 -11
- package/dist/core/doctor/doctor-readiness-matrix.js +6 -0
- package/dist/core/fsx.js +1 -1
- package/dist/core/git/git-worktree-checkpoint.js +52 -0
- package/dist/core/git/git-worktree-cross-rebase.js +54 -0
- package/dist/core/git/git-worktree-merge-queue.js +69 -0
- package/dist/core/git/git-worktree-patch-envelope.js +8 -1
- package/dist/core/hooks-runtime.js +4 -0
- package/dist/core/init.js +3 -2
- package/dist/core/naruto/naruto-active-pool.js +35 -2
- package/dist/core/naruto/naruto-allocation-policy.js +99 -0
- package/dist/core/naruto/naruto-concurrency-governor.js +1 -1
- package/dist/core/naruto/naruto-real-worker-child.js +134 -0
- package/dist/core/naruto/naruto-real-worker-runtime.js +121 -0
- package/dist/core/naruto/naruto-rebalance-policy.js +36 -0
- package/dist/core/naruto/naruto-task-hints.js +71 -0
- package/dist/core/pipeline/finalize-pipeline-result.js +3 -1
- package/dist/core/pipeline/gpt-final-required.js +22 -2
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/zellij-right-column-manager.js +111 -9
- package/dist/core/zellij/zellij-slot-column-anchor.js +59 -0
- package/dist/core/zellij/zellij-slot-pane-renderer.js +82 -0
- package/dist/core/zellij/zellij-ui-mode.js +16 -0
- package/dist/core/zellij/zellij-worker-pane-manager.js +104 -13
- package/dist/scripts/agent-role-config-repair-check.js +33 -0
- package/dist/scripts/git-worktree-checkpoint-check.js +20 -0
- package/dist/scripts/git-worktree-cross-rebase-check.js +27 -0
- package/dist/scripts/git-worktree-integration-primary-check.js +4 -2
- package/dist/scripts/git-worktree-integration-primary-runtime-check.js +20 -0
- package/dist/scripts/mutation-callsite-coverage-check.js +2 -1
- package/dist/scripts/naruto-actual-worker-control-plane-check.js +29 -0
- package/dist/scripts/naruto-allocation-policy-check.js +33 -0
- package/dist/scripts/naruto-extreme-parallelism-check.js +1 -1
- package/dist/scripts/naruto-extreme-parallelism-real-check.js +43 -0
- package/dist/scripts/naruto-orchestrator-runtime-source-check.js +11 -0
- package/dist/scripts/naruto-real-active-pool-check.js +3 -2
- package/dist/scripts/naruto-real-active-pool-runtime-check.js +55 -0
- package/dist/scripts/naruto-rebalance-policy-check.js +28 -0
- package/dist/scripts/naruto-shadow-clone-swarm-check.js +7 -3
- package/dist/scripts/naruto-zellij-dynamic-right-column-check.js +29 -2
- package/dist/scripts/readme-architecture-imagegen-official-check.js +4 -3
- package/dist/scripts/release-check-dynamic-execute.js +27 -1
- package/dist/scripts/release-check-dynamic.js +38 -11
- package/dist/scripts/release-check-stamp.js +7 -2
- package/dist/scripts/release-dag-full-coverage-check.js +15 -1
- package/dist/scripts/release-dynamic-performance-check.js +31 -1
- package/dist/scripts/release-gate-existence-audit.js +29 -33
- package/dist/scripts/release-readiness-report.js +14 -3
- package/dist/scripts/zellij-first-slot-down-stack-check.js +20 -0
- package/dist/scripts/zellij-first-slot-down-stack-real-check.js +16 -0
- package/dist/scripts/zellij-right-column-geometry-proof.js +155 -22
- package/dist/scripts/zellij-right-column-headless-overflow-check.js +22 -0
- package/dist/scripts/zellij-right-column-manager-check.js +9 -4
- package/dist/scripts/zellij-slot-column-anchor-check.js +24 -0
- package/dist/scripts/zellij-slot-only-ui-check.js +24 -0
- package/dist/scripts/zellij-slot-pane-renderer-check.js +38 -0
- package/dist/scripts/zellij-worker-pane-manager-single-owner-check.js +11 -4
- package/package.json +22 -5
|
@@ -5,8 +5,10 @@ import { appendJsonl, ensureDir, exists, nowIso, packageRoot, readJson, writeJso
|
|
|
5
5
|
import { fastModeEnv } from './fast-mode-policy.js';
|
|
6
6
|
import { validateAgentWorkerResult } from './agent-worker-pipeline.js';
|
|
7
7
|
import { closeWorkerPane, openWorkerPane } from '../zellij/zellij-worker-pane-manager.js';
|
|
8
|
-
import { recordHeadlessWorkerInRightColumn } from '../zellij/zellij-right-column-manager.js';
|
|
8
|
+
import { closeWorkerInRightColumn, recordHeadlessWorkerInRightColumn } from '../zellij/zellij-right-column-manager.js';
|
|
9
9
|
import { resolveProviderContext } from '../provider/provider-context.js';
|
|
10
|
+
import { buildZellijSlotPaneCommand } from '../zellij/zellij-slot-pane-renderer.js';
|
|
11
|
+
import { resolveZellijUiMode } from '../zellij/zellij-ui-mode.js';
|
|
10
12
|
export const NATIVE_CLI_SESSION_SWARM_SCHEMA = 'sks.agent-native-cli-session-swarm.v1';
|
|
11
13
|
export function createNativeCliSessionSwarmRecorder(root, input) {
|
|
12
14
|
return new NativeCliSessionSwarmRecorder(root, input);
|
|
@@ -19,6 +21,7 @@ class NativeCliSessionSwarmRecorder {
|
|
|
19
21
|
maxObserved = 0;
|
|
20
22
|
writeLock = Promise.resolve();
|
|
21
23
|
nextPaneToken = -1;
|
|
24
|
+
visibleZellijReservations = new Set();
|
|
22
25
|
constructor(root, input) {
|
|
23
26
|
this.root = root;
|
|
24
27
|
this.input = input;
|
|
@@ -103,10 +106,12 @@ class NativeCliSessionSwarmRecorder {
|
|
|
103
106
|
const stdout = fs.createWriteStream(path.join(this.root, stdoutRel), { flags: 'a' });
|
|
104
107
|
const stderr = fs.createWriteStream(path.join(this.root, stderrRel), { flags: 'a' });
|
|
105
108
|
const placement = String(ctx.opts.workerPlacement || this.input.workerPlacement || (this.input.backend === 'zellij' ? 'zellij-pane' : 'process'));
|
|
106
|
-
const
|
|
109
|
+
const zellijReservation = placement === 'zellij-pane'
|
|
107
110
|
&& ctx.opts.zellijPaneWorker !== false
|
|
108
111
|
&& (ctx.opts.zellijSessionName || this.input.missionId)
|
|
109
|
-
|
|
112
|
+
? this.reserveVisibleZellijPane(ctx.opts, String(ctx.agent.session_id || ctx.agent.id || `${Date.now()}:${Math.random()}`))
|
|
113
|
+
: null;
|
|
114
|
+
const useZellijPane = Boolean(zellijReservation);
|
|
110
115
|
if (useZellijPane) {
|
|
111
116
|
stdout.end();
|
|
112
117
|
stderr.end();
|
|
@@ -118,7 +123,8 @@ class NativeCliSessionSwarmRecorder {
|
|
|
118
123
|
stdoutRel,
|
|
119
124
|
stderrRel,
|
|
120
125
|
heartbeatRel,
|
|
121
|
-
workerDirRel
|
|
126
|
+
workerDirRel,
|
|
127
|
+
zellijReservation
|
|
122
128
|
});
|
|
123
129
|
}
|
|
124
130
|
if (placement === 'zellij-pane' && ctx.opts.zellijPaneWorker !== false && !useZellijPane) {
|
|
@@ -174,6 +180,17 @@ class NativeCliSessionSwarmRecorder {
|
|
|
174
180
|
record.exit_code = exit.code;
|
|
175
181
|
record.signal = exit.signal;
|
|
176
182
|
record.status = exit.code === 0 ? 'closed' : 'failed';
|
|
183
|
+
if (record.worker_placement === 'headless') {
|
|
184
|
+
await closeWorkerInRightColumn({
|
|
185
|
+
root: this.root,
|
|
186
|
+
projectRoot: ctx.opts.projectRoot || this.input.projectRoot || ctx.opts.cwd,
|
|
187
|
+
missionId: this.input.missionId,
|
|
188
|
+
slotId: String(ctx.agent.slot_id || ctx.agent.id || 'slot-001'),
|
|
189
|
+
generationIndex: Number(ctx.agent.generation_index || 1),
|
|
190
|
+
paneId: null,
|
|
191
|
+
status: record.status === 'closed' ? 'closed' : 'failed'
|
|
192
|
+
}).catch(() => null);
|
|
193
|
+
}
|
|
177
194
|
const parsed = await readJson(path.join(this.root, resultRel), null).catch(() => null);
|
|
178
195
|
if (!parsed) {
|
|
179
196
|
record.blockers = ['native_cli_worker_result_missing'];
|
|
@@ -217,77 +234,102 @@ class NativeCliSessionSwarmRecorder {
|
|
|
217
234
|
route: this.input.route,
|
|
218
235
|
serviceTier: this.input.fastModePolicy.service_tier
|
|
219
236
|
});
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
237
|
+
const uiMode = resolveZellijUiMode(Array.isArray(input.ctx.opts.args) ? input.ctx.opts.args : [], process.env);
|
|
238
|
+
const workerEnv = {
|
|
239
|
+
...(input.ctx.opts.env || {}),
|
|
240
|
+
...fastModeEnv(this.input.fastModePolicy),
|
|
241
|
+
SKS_AGENT_WORKER: '1',
|
|
242
|
+
SKS_PIPELINE_MODE: 'agent-worker',
|
|
243
|
+
SKS_DISABLE_ROUTE_RECURSION: '1',
|
|
244
|
+
SKS_PARENT_MISSION_ID: this.input.missionId,
|
|
245
|
+
SKS_AGENT_SESSION_ID: String(input.ctx.agent.session_id || ''),
|
|
246
|
+
SKS_AGENT_SLOT_ID: slotId,
|
|
247
|
+
SKS_AGENT_GENERATION_INDEX: String(input.ctx.agent.generation_index || 1),
|
|
248
|
+
...(input.ctx.opts.ollamaModel ? { SKS_OLLAMA_MODEL: String(input.ctx.opts.ollamaModel) } : {}),
|
|
249
|
+
...(input.ctx.opts.ollamaBaseUrl ? { SKS_OLLAMA_BASE_URL: String(input.ctx.opts.ollamaBaseUrl) } : {}),
|
|
250
|
+
SKS_ZELLIJ_SESSION_NAME: sessionName
|
|
251
|
+
};
|
|
252
|
+
const role = String(input.ctx.agent.naruto_role || input.ctx.agent.role || input.ctx.agent.persona_id || 'worker');
|
|
253
|
+
const workerCommand = uiMode === 'full-debug'
|
|
254
|
+
? buildPaneWorkerCommand({
|
|
255
|
+
args: input.args,
|
|
256
|
+
stdoutPath: path.join(this.root, input.stdoutRel),
|
|
257
|
+
stderrPath: path.join(this.root, input.stderrRel),
|
|
258
|
+
heartbeatPath: path.join(this.root, input.heartbeatRel),
|
|
259
|
+
header: buildPaneWorkerHeader({
|
|
260
|
+
slotId,
|
|
261
|
+
generationIndex: Number(input.ctx.agent.generation_index || 1),
|
|
262
|
+
role,
|
|
263
|
+
backend: this.input.backend,
|
|
264
|
+
provider: providerContext.provider,
|
|
265
|
+
serviceTier: this.input.fastModePolicy.service_tier,
|
|
266
|
+
worktree,
|
|
267
|
+
task: input.ctx.slice?.description || input.ctx.slice?.title || input.ctx.slice?.id || ''
|
|
268
|
+
}),
|
|
269
|
+
env: {
|
|
270
|
+
...workerEnv,
|
|
271
|
+
SKS_ZELLIJ_WORKER_PANE: '1'
|
|
272
|
+
}
|
|
273
|
+
})
|
|
274
|
+
: buildZellijSlotPaneCommand({
|
|
275
|
+
cliPath: String(input.args[0] || ''),
|
|
276
|
+
missionId: this.input.missionId,
|
|
226
277
|
slotId,
|
|
227
278
|
generationIndex: Number(input.ctx.agent.generation_index || 1),
|
|
228
|
-
|
|
279
|
+
artifactDir: path.join(this.root, input.workerDirRel),
|
|
229
280
|
backend: this.input.backend,
|
|
230
|
-
|
|
281
|
+
role,
|
|
282
|
+
mode: uiMode,
|
|
283
|
+
watch: true
|
|
284
|
+
});
|
|
285
|
+
let paneRecord;
|
|
286
|
+
try {
|
|
287
|
+
paneRecord = await openWorkerPane({
|
|
288
|
+
root: this.root,
|
|
289
|
+
missionId: this.input.missionId,
|
|
290
|
+
sessionName,
|
|
291
|
+
slotId,
|
|
292
|
+
generationIndex: Number(input.ctx.agent.generation_index || 1),
|
|
293
|
+
sessionId: String(input.ctx.agent.session_id || ''),
|
|
294
|
+
workerArtifactDir: input.workerDirRel,
|
|
295
|
+
workerCommand,
|
|
296
|
+
resultPath: input.resultRel,
|
|
297
|
+
heartbeatPath: input.heartbeatRel,
|
|
298
|
+
patchEnvelopePath: input.record.patch_envelope_path,
|
|
299
|
+
stdoutLog: input.stdoutRel,
|
|
300
|
+
stderrLog: input.stderrRel,
|
|
301
|
+
cwd: workerCwd,
|
|
302
|
+
providerContext,
|
|
231
303
|
serviceTier: this.input.fastModePolicy.service_tier,
|
|
232
|
-
worktree,
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
workerCommand,
|
|
260
|
-
resultPath: input.resultRel,
|
|
261
|
-
heartbeatPath: input.heartbeatRel,
|
|
262
|
-
patchEnvelopePath: input.record.patch_envelope_path,
|
|
263
|
-
stdoutLog: input.stdoutRel,
|
|
264
|
-
stderrLog: input.stderrRel,
|
|
265
|
-
cwd: workerCwd,
|
|
266
|
-
providerContext,
|
|
267
|
-
serviceTier: this.input.fastModePolicy.service_tier,
|
|
268
|
-
worktree: worktree ? { id: worktree.id, path: worktree.path, branch: worktree.branch } : null,
|
|
269
|
-
backend: this.input.backend,
|
|
270
|
-
projectRoot: input.ctx.opts.projectRoot || this.input.projectRoot || input.ctx.opts.cwd,
|
|
271
|
-
rightColumnMode: 'spawn-on-first-worker',
|
|
272
|
-
visiblePaneCap: this.zellijVisiblePaneCap(input.ctx.opts),
|
|
273
|
-
dashboardSnapshot: {
|
|
274
|
-
mode: this.input.route || '$Agent',
|
|
275
|
-
backend_counts: { [this.input.backend]: this.input.targetActiveSlots },
|
|
276
|
-
placement_counts: {
|
|
277
|
-
'zellij-pane': this.zellijVisiblePaneCap(input.ctx.opts),
|
|
278
|
-
headless: Math.max(0, this.input.targetActiveSlots - this.zellijVisiblePaneCap(input.ctx.opts))
|
|
279
|
-
},
|
|
280
|
-
active_workers: this.input.targetActiveSlots,
|
|
281
|
-
visible_panes: this.zellijVisiblePaneCap(input.ctx.opts),
|
|
282
|
-
headless_workers: Math.max(0, this.input.targetActiveSlots - this.zellijVisiblePaneCap(input.ctx.opts)),
|
|
283
|
-
queue_depth: Math.max(0, this.input.requestedAgents - this.input.targetActiveSlots),
|
|
284
|
-
local_llm: { tps: 0, queue: 0 },
|
|
285
|
-
gpt_final_status: 'pending',
|
|
286
|
-
gate_progress: 'worker-spawn'
|
|
287
|
-
}
|
|
288
|
-
});
|
|
304
|
+
worktree: worktree ? { id: worktree.id, path: worktree.path, branch: worktree.branch } : null,
|
|
305
|
+
backend: this.input.backend,
|
|
306
|
+
uiMode,
|
|
307
|
+
projectRoot: input.ctx.opts.projectRoot || this.input.projectRoot || input.ctx.opts.cwd,
|
|
308
|
+
rightColumnMode: 'spawn-on-first-worker',
|
|
309
|
+
visiblePaneCap: this.zellijVisiblePaneCap(input.ctx.opts),
|
|
310
|
+
dashboardSnapshot: {
|
|
311
|
+
mode: this.input.route || '$Agent',
|
|
312
|
+
backend_counts: { [this.input.backend]: this.input.targetActiveSlots },
|
|
313
|
+
placement_counts: {
|
|
314
|
+
'zellij-pane': this.zellijVisiblePaneCap(input.ctx.opts),
|
|
315
|
+
headless: Math.max(0, this.input.targetActiveSlots - this.zellijVisiblePaneCap(input.ctx.opts))
|
|
316
|
+
},
|
|
317
|
+
active_workers: this.input.targetActiveSlots,
|
|
318
|
+
visible_panes: this.zellijVisiblePaneCap(input.ctx.opts),
|
|
319
|
+
headless_workers: Math.max(0, this.input.targetActiveSlots - this.zellijVisiblePaneCap(input.ctx.opts)),
|
|
320
|
+
queue_depth: Math.max(0, this.input.requestedAgents - this.input.targetActiveSlots),
|
|
321
|
+
local_llm: { tps: 0, queue: 0 },
|
|
322
|
+
gpt_final_status: 'pending',
|
|
323
|
+
gate_progress: 'worker-spawn'
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
finally {
|
|
328
|
+
if (input.zellijReservation)
|
|
329
|
+
this.releaseVisibleZellijReservation(input.zellijReservation);
|
|
330
|
+
}
|
|
289
331
|
const launchBlockers = paneRecord.blockers || [];
|
|
290
|
-
input.record.command_line = ['zellij', '--session', sessionName, 'action', 'new-pane', '--direction', paneRecord.direction_applied, '--name', paneRecord.pane_name, '--', 'sh', '-lc', '<native-cli-worker-command>'];
|
|
332
|
+
input.record.command_line = ['zellij', '--session', sessionName, 'action', 'new-pane', '--direction', paneRecord.direction_applied, '--name', paneRecord.pane_name, '--', 'sh', '-lc', uiMode === 'full-debug' ? '<native-cli-worker-command>' : '<zellij-slot-pane-renderer-command>'];
|
|
291
333
|
input.record.zellij_session_name = sessionName;
|
|
292
334
|
input.record.zellij_pane_id = paneRecord.pane_id || null;
|
|
293
335
|
input.record.zellij_pane_id_source = paneRecord.pane_id_source;
|
|
@@ -300,6 +342,8 @@ class NativeCliSessionSwarmRecorder {
|
|
|
300
342
|
input.record.service_tier = paneRecord.service_tier;
|
|
301
343
|
input.record.provider_context = paneRecord.provider_context;
|
|
302
344
|
input.record.worktree = worktree;
|
|
345
|
+
input.record.zellij_ui_mode = uiMode;
|
|
346
|
+
input.record.slot_visualization = uiMode === 'full-debug' ? 'worker-command-pane' : 'zellij-slot-pane-renderer';
|
|
303
347
|
input.record.status = launchBlockers.length ? 'failed' : 'running';
|
|
304
348
|
input.record.blockers = launchBlockers;
|
|
305
349
|
await this.record(input.record);
|
|
@@ -325,6 +369,20 @@ class NativeCliSessionSwarmRecorder {
|
|
|
325
369
|
goal_mode_ref: input.ctx.agent.goal_mode_ref || null
|
|
326
370
|
});
|
|
327
371
|
}
|
|
372
|
+
const processRun = uiMode === 'full-debug'
|
|
373
|
+
? null
|
|
374
|
+
: await this.spawnCompactSlotWorkerProcess({
|
|
375
|
+
args: input.args,
|
|
376
|
+
cwd: workerCwd,
|
|
377
|
+
env: workerEnv,
|
|
378
|
+
stdoutRel: input.stdoutRel,
|
|
379
|
+
stderrRel: input.stderrRel
|
|
380
|
+
});
|
|
381
|
+
if (processRun?.pid) {
|
|
382
|
+
input.record.pid = processRun.pid;
|
|
383
|
+
input.record.process_id = processRun.pid;
|
|
384
|
+
await this.record(input.record);
|
|
385
|
+
}
|
|
328
386
|
await waitForWorkerHeartbeat(path.join(this.root, input.heartbeatRel), Number(process.env.SKS_ZELLIJ_WORKER_HEARTBEAT_TIMEOUT_MS || 30000));
|
|
329
387
|
await appendJsonl(path.join(this.root, input.workerDirRel, 'zellij-worker-pane-events.jsonl'), {
|
|
330
388
|
schema: 'sks.zellij-worker-pane-event.v1',
|
|
@@ -337,6 +395,7 @@ class NativeCliSessionSwarmRecorder {
|
|
|
337
395
|
worker_artifact_dir: input.workerDirRel
|
|
338
396
|
});
|
|
339
397
|
const parsed = await waitForWorkerResult(path.join(this.root, input.resultRel), Number(process.env.SKS_ZELLIJ_WORKER_RESULT_TIMEOUT_MS || 120000));
|
|
398
|
+
const compactExit = processRun ? await processRun.wait(parsed ? 10000 : 1000) : null;
|
|
340
399
|
this.active.delete(activeToken);
|
|
341
400
|
input.record.closed_at = nowIso();
|
|
342
401
|
const workerProcessReport = await readJson(path.join(this.root, input.workerDirRel, 'worker-process-report.json'), null).catch(() => null);
|
|
@@ -368,8 +427,10 @@ class NativeCliSessionSwarmRecorder {
|
|
|
368
427
|
result_path: input.resultRel
|
|
369
428
|
});
|
|
370
429
|
}
|
|
371
|
-
input.record.pid = Number(workerProcessReport?.pid) || null;
|
|
430
|
+
input.record.pid = Number(workerProcessReport?.pid || processRun?.pid) || null;
|
|
372
431
|
input.record.process_id = input.record.pid;
|
|
432
|
+
input.record.compact_worker_exit_code = compactExit?.code ?? null;
|
|
433
|
+
input.record.compact_worker_signal = compactExit?.signal ?? null;
|
|
373
434
|
input.record.sdk_thread_id = sdkThreadId;
|
|
374
435
|
input.record.sdk_run_id = sdkRunId;
|
|
375
436
|
input.record.stream_event_count = Number(workerProcessReport?.stream_event_count || workerProcessReport?.backend_router_report?.stream_event_count || 0);
|
|
@@ -479,6 +540,46 @@ class NativeCliSessionSwarmRecorder {
|
|
|
479
540
|
visibleZellijPaneCount() {
|
|
480
541
|
return this.records.filter((row) => row.scaling_primitive === 'native_cli_process_in_zellij_worker_pane' && (row.status === 'launching' || row.status === 'running')).length;
|
|
481
542
|
}
|
|
543
|
+
reserveVisibleZellijPane(opts = {}, token) {
|
|
544
|
+
const cap = this.zellijVisiblePaneCap(opts);
|
|
545
|
+
if (this.visibleZellijPaneCount() + this.visibleZellijReservations.size >= cap)
|
|
546
|
+
return null;
|
|
547
|
+
this.visibleZellijReservations.add(token);
|
|
548
|
+
return token;
|
|
549
|
+
}
|
|
550
|
+
releaseVisibleZellijReservation(token) {
|
|
551
|
+
this.visibleZellijReservations.delete(token);
|
|
552
|
+
}
|
|
553
|
+
async spawnCompactSlotWorkerProcess(input) {
|
|
554
|
+
const stdout = fs.createWriteStream(path.join(this.root, input.stdoutRel), { flags: 'a' });
|
|
555
|
+
const stderr = fs.createWriteStream(path.join(this.root, input.stderrRel), { flags: 'a' });
|
|
556
|
+
const child = spawn(process.execPath, input.args, {
|
|
557
|
+
cwd: input.cwd,
|
|
558
|
+
env: {
|
|
559
|
+
...process.env,
|
|
560
|
+
...Object.fromEntries(Object.entries(input.env).filter(([, value]) => value != null).map(([key, value]) => [key, String(value)]))
|
|
561
|
+
},
|
|
562
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
563
|
+
});
|
|
564
|
+
child.stdout?.pipe(stdout);
|
|
565
|
+
child.stderr?.pipe(stderr);
|
|
566
|
+
const exitPromise = new Promise((resolve) => {
|
|
567
|
+
child.on('close', (code, signal) => {
|
|
568
|
+
stdout.end();
|
|
569
|
+
stderr.end();
|
|
570
|
+
resolve({ code, signal });
|
|
571
|
+
});
|
|
572
|
+
child.on('error', () => {
|
|
573
|
+
stdout.end();
|
|
574
|
+
stderr.end();
|
|
575
|
+
resolve({ code: 1, signal: null });
|
|
576
|
+
});
|
|
577
|
+
});
|
|
578
|
+
return {
|
|
579
|
+
pid: child.pid || null,
|
|
580
|
+
wait: async (timeoutMs) => waitForChildExit(child, exitPromise, timeoutMs)
|
|
581
|
+
};
|
|
582
|
+
}
|
|
482
583
|
}
|
|
483
584
|
export function buildPaneWorkerCommand(input) {
|
|
484
585
|
const envPrefix = Object.entries(input.env)
|
|
@@ -555,4 +656,18 @@ function normalizeWorkerWorktree(value) {
|
|
|
555
656
|
main_repo_root: value?.main_repo_root == null ? null : String(value.main_repo_root)
|
|
556
657
|
};
|
|
557
658
|
}
|
|
659
|
+
async function waitForChildExit(child, exitPromise, timeoutMs) {
|
|
660
|
+
let timer = null;
|
|
661
|
+
const timeout = new Promise((resolve) => {
|
|
662
|
+
timer = setTimeout(() => {
|
|
663
|
+
if (!child.killed)
|
|
664
|
+
child.kill();
|
|
665
|
+
resolve({ code: null, signal: 'SIGTERM' });
|
|
666
|
+
}, Math.max(1000, timeoutMs));
|
|
667
|
+
});
|
|
668
|
+
const result = await Promise.race([exitPromise, timeout]);
|
|
669
|
+
if (timer)
|
|
670
|
+
clearTimeout(timer);
|
|
671
|
+
return result;
|
|
672
|
+
}
|
|
558
673
|
//# sourceMappingURL=native-cli-session-swarm.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { createMission, findLatestMission, loadMission } from '../mission.js';
|
|
3
|
-
import { readJson, sksRoot, writeJsonAtomic } from '../fsx.js';
|
|
3
|
+
import { nowIso, readJson, sksRoot, writeJsonAtomic } from '../fsx.js';
|
|
4
4
|
import { runNativeAgentOrchestrator } from '../agents/agent-orchestrator.js';
|
|
5
5
|
import { classifyOllamaWorkerSlice } from '../agents/agent-runner-ollama.js';
|
|
6
6
|
import { buildNarutoCloneRoster, systemSafeNarutoConcurrency } from '../agents/agent-roster.js';
|
|
@@ -11,6 +11,9 @@ import { buildNarutoWorkGraph } from '../naruto/naruto-work-graph.js';
|
|
|
11
11
|
import { buildNarutoRoleDistribution } from '../naruto/naruto-role-policy.js';
|
|
12
12
|
import { decideNarutoConcurrency } from '../naruto/naruto-concurrency-governor.js';
|
|
13
13
|
import { runNarutoActivePool, runNarutoRealActivePool } from '../naruto/naruto-active-pool.js';
|
|
14
|
+
import { collectActualNarutoWorker, spawnActualNarutoWorker } from '../naruto/naruto-real-worker-runtime.js';
|
|
15
|
+
import { allocateNarutoTasksToWorkers } from '../naruto/naruto-allocation-policy.js';
|
|
16
|
+
import { rebalanceNarutoReadyWork } from '../naruto/naruto-rebalance-policy.js';
|
|
14
17
|
import { buildNarutoVerificationDag } from '../naruto/naruto-verification-dag.js';
|
|
15
18
|
import { buildNarutoGptFinalPack } from '../naruto/naruto-gpt-final-pack.js';
|
|
16
19
|
import { planNarutoZellijDashboard } from '../zellij/zellij-naruto-dashboard.js';
|
|
@@ -102,6 +105,50 @@ async function narutoRun(parsed) {
|
|
|
102
105
|
worktreePolicy
|
|
103
106
|
});
|
|
104
107
|
const roleDistribution = buildNarutoRoleDistribution(workGraph.work_items, { readonly: parsed.readonly });
|
|
108
|
+
const allocationWorkers = buildNarutoAllocationWorkers(workGraph, roleDistribution, roster);
|
|
109
|
+
const allocationAssignments = allocateNarutoTasksToWorkers(workGraph.work_items, allocationWorkers);
|
|
110
|
+
const allocationPolicy = {
|
|
111
|
+
schema: 'sks.naruto-allocation-policy.v1',
|
|
112
|
+
generated_at: nowIso(),
|
|
113
|
+
ok: allocationWorkers.length > 0 && allocationAssignments.length === workGraph.work_items.length,
|
|
114
|
+
scoring_model: {
|
|
115
|
+
same_primary_role: 18,
|
|
116
|
+
declared_role: 12,
|
|
117
|
+
same_path_lane: 12,
|
|
118
|
+
overlap_each: 4,
|
|
119
|
+
assigned_task_penalty_each: -4,
|
|
120
|
+
write_conflict_penalty: -20,
|
|
121
|
+
dependency_incomplete: '-Infinity'
|
|
122
|
+
},
|
|
123
|
+
workers: allocationWorkers,
|
|
124
|
+
assignments: allocationAssignments.map((row) => ({
|
|
125
|
+
task_id: row.id,
|
|
126
|
+
owner: row.owner,
|
|
127
|
+
score: Number.isFinite(row.allocation_score) ? row.allocation_score : '-Infinity',
|
|
128
|
+
reason: row.allocation_reason,
|
|
129
|
+
role: row.required_role,
|
|
130
|
+
kind: row.kind,
|
|
131
|
+
paths: row.hints.paths,
|
|
132
|
+
domains: row.hints.domains,
|
|
133
|
+
write_paths: row.hints.writePaths
|
|
134
|
+
})),
|
|
135
|
+
blockers: allocationWorkers.length ? [] : ['naruto_allocation_workers_missing']
|
|
136
|
+
};
|
|
137
|
+
const rebalanceDecisions = rebalanceNarutoReadyWork({
|
|
138
|
+
tasks: workGraph.work_items.map((item) => ({ ...item, owner: null, status: 'pending' })),
|
|
139
|
+
workers: allocationWorkers.map((worker) => ({ ...worker, alive: true, state: 'idle' })),
|
|
140
|
+
completedTaskIds: [],
|
|
141
|
+
reclaimedTaskIds: []
|
|
142
|
+
});
|
|
143
|
+
const rebalancePolicy = {
|
|
144
|
+
schema: 'sks.naruto-rebalance-policy.v1',
|
|
145
|
+
generated_at: nowIso(),
|
|
146
|
+
ok: true,
|
|
147
|
+
trigger: 'idle_worker_ready_queue',
|
|
148
|
+
decisions: rebalanceDecisions,
|
|
149
|
+
blocked_by_dependency_count: workGraph.work_items.filter((item) => item.dependencies.length > 0).length,
|
|
150
|
+
blockers: []
|
|
151
|
+
};
|
|
105
152
|
const governor = decideNarutoConcurrency({
|
|
106
153
|
requestedClones: roster.agent_count,
|
|
107
154
|
totalWorkItems: workGraph.total_work_items,
|
|
@@ -112,14 +159,52 @@ async function narutoRun(parsed) {
|
|
|
112
159
|
const activeSlots = Math.max(1, Math.min(roster.agent_count, parsed.concurrency || Math.max(governor.safe_active_workers, backendMinimum), safe.cap));
|
|
113
160
|
const zellijVisiblePanes = Math.max(1, Math.min(activeSlots, governor.safe_zellij_visible_panes));
|
|
114
161
|
const activePool = await runNarutoActivePool({ graph: workGraph, governor: { ...governor, safe_active_workers: activeSlots } });
|
|
162
|
+
const realRuntimeSmokeGraph = buildNarutoWorkGraph({
|
|
163
|
+
prompt: parsed.prompt,
|
|
164
|
+
requestedClones: Math.min(2, roster.agent_count),
|
|
165
|
+
totalWorkItems: Math.min(2, workGraph.total_work_items),
|
|
166
|
+
readonly: true,
|
|
167
|
+
writeCapable: false,
|
|
168
|
+
leaseBasePath: patchEnvelopeBasePath,
|
|
169
|
+
maxActiveWorkers: Math.min(2, activeSlots),
|
|
170
|
+
worktreePolicy: {
|
|
171
|
+
mode: 'patch-envelope-only',
|
|
172
|
+
required: false,
|
|
173
|
+
main_repo_root: worktreePolicy.main_repo_root,
|
|
174
|
+
worktree_root: null,
|
|
175
|
+
fallback_reason: 'pre_run_smoke_never_owns_production_runtime'
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
const realRuntimeWorktreePolicy = {
|
|
179
|
+
mode: 'patch-envelope-only',
|
|
180
|
+
required: false,
|
|
181
|
+
main_repo_root: worktreePolicy.main_repo_root,
|
|
182
|
+
worktree_root: null,
|
|
183
|
+
fallback_reason: 'pre_run_smoke_never_owns_production_runtime'
|
|
184
|
+
};
|
|
115
185
|
const realActivePool = await runNarutoRealActivePool({
|
|
116
|
-
graph:
|
|
117
|
-
governor: { ...governor, safe_active_workers: activeSlots },
|
|
118
|
-
spawnWorker: async (item, placement) => ({
|
|
119
|
-
|
|
186
|
+
graph: realRuntimeSmokeGraph,
|
|
187
|
+
governor: { ...governor, safe_active_workers: Math.min(2, activeSlots), safe_zellij_visible_panes: Math.min(1, zellijVisiblePanes) },
|
|
188
|
+
spawnWorker: async (item, placement) => spawnActualNarutoWorker({
|
|
189
|
+
root,
|
|
190
|
+
missionId: mission.id,
|
|
191
|
+
item,
|
|
192
|
+
placement,
|
|
193
|
+
backend: 'fake',
|
|
194
|
+
worktreePolicy: realRuntimeWorktreePolicy,
|
|
195
|
+
zellijSessionName: `sks-${mission.id}`,
|
|
196
|
+
visiblePaneCap: zellijVisiblePanes
|
|
197
|
+
}),
|
|
198
|
+
collectWorker: async (handle) => collectActualNarutoWorker(handle),
|
|
120
199
|
enqueueVerification: async () => undefined,
|
|
121
200
|
updateDashboard: async () => undefined
|
|
122
201
|
});
|
|
202
|
+
const realActivePoolSmoke = {
|
|
203
|
+
...realActivePool,
|
|
204
|
+
runtime_source_of_truth: 'pre_run_smoke_only',
|
|
205
|
+
production_runtime_source_of_truth: 'agent-orchestrator-scheduler',
|
|
206
|
+
smoke_graph_total_work_items: realRuntimeSmokeGraph.total_work_items
|
|
207
|
+
};
|
|
123
208
|
const verificationDag = buildNarutoVerificationDag(workGraph, { cwd: root });
|
|
124
209
|
const gptFinalPack = buildNarutoGptFinalPack({
|
|
125
210
|
missionId: mission.id,
|
|
@@ -143,7 +228,9 @@ async function narutoRun(parsed) {
|
|
|
143
228
|
roleDistribution,
|
|
144
229
|
governor,
|
|
145
230
|
activePool,
|
|
146
|
-
realActivePool,
|
|
231
|
+
realActivePool: realActivePoolSmoke,
|
|
232
|
+
allocationPolicy,
|
|
233
|
+
rebalancePolicy,
|
|
147
234
|
verificationDag,
|
|
148
235
|
gptFinalPack,
|
|
149
236
|
zellijDashboard,
|
|
@@ -235,6 +322,8 @@ async function narutoRun(parsed) {
|
|
|
235
322
|
max_clones: MAX_NARUTO_AGENT_COUNT,
|
|
236
323
|
concurrency: result.target_active_slots ?? activeSlots,
|
|
237
324
|
target_active_slots: result.target_active_slots ?? activeSlots,
|
|
325
|
+
runtime_source_of_truth: 'agent-orchestrator-scheduler',
|
|
326
|
+
pre_run_real_active_pool_source: 'smoke_only',
|
|
238
327
|
concurrency_capped: clones > (result.target_active_slots ?? activeSlots),
|
|
239
328
|
system: { cores: safe.cores, free_gb: safe.free_gb, safe_concurrency: safe.cap, heavy_backend: safe.heavy },
|
|
240
329
|
work_graph: {
|
|
@@ -248,6 +337,8 @@ async function narutoRun(parsed) {
|
|
|
248
337
|
},
|
|
249
338
|
git_worktree: gitWorktreeCapability,
|
|
250
339
|
role_distribution: roleDistribution,
|
|
340
|
+
allocation_policy: allocationPolicy,
|
|
341
|
+
rebalance_policy: rebalancePolicy,
|
|
251
342
|
concurrency_governor: governor,
|
|
252
343
|
active_pool: {
|
|
253
344
|
ok: activePool.ok,
|
|
@@ -255,15 +346,23 @@ async function narutoRun(parsed) {
|
|
|
255
346
|
refill_events: activePool.refill_events,
|
|
256
347
|
completed_count: activePool.completed_count,
|
|
257
348
|
real_runtime: {
|
|
258
|
-
ok:
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
349
|
+
ok: realActivePoolSmoke.ok,
|
|
350
|
+
runtime_source_of_truth: realActivePoolSmoke.runtime_source_of_truth,
|
|
351
|
+
production_runtime_source_of_truth: realActivePoolSmoke.production_runtime_source_of_truth,
|
|
352
|
+
active_cap: realActivePoolSmoke.active_cap,
|
|
353
|
+
max_observed_active_workers: realActivePoolSmoke.max_observed_active_workers,
|
|
354
|
+
average_active_workers: realActivePoolSmoke.average_active_workers,
|
|
355
|
+
active_pool_utilization: realActivePoolSmoke.active_pool_utilization,
|
|
356
|
+
refill_latency_ms_p95: realActivePoolSmoke.refill_latency_ms_p95,
|
|
357
|
+
visible_workers: realActivePoolSmoke.visible_workers,
|
|
358
|
+
headless_workers: realActivePoolSmoke.headless_workers,
|
|
359
|
+
worker_lifecycle_count: realActivePoolSmoke.worker_lifecycle.length,
|
|
360
|
+
worker_lifecycle_sample: realActivePoolSmoke.worker_lifecycle.slice(0, 5)
|
|
262
361
|
}
|
|
263
362
|
},
|
|
264
363
|
local_worker: localWorkerSummary,
|
|
265
364
|
proof: result.proof?.status || 'missing',
|
|
266
|
-
run: result,
|
|
365
|
+
run: compactNarutoRunResult(result),
|
|
267
366
|
zellij: null
|
|
268
367
|
};
|
|
269
368
|
summary.zellij = liveZellij;
|
|
@@ -280,6 +379,57 @@ async function narutoRun(parsed) {
|
|
|
280
379
|
console.log('Zellij: optional live panes unavailable (' + ((summary.zellij.warnings || []).join('; ') || summary.zellij.capability?.status || 'unknown') + ')');
|
|
281
380
|
});
|
|
282
381
|
}
|
|
382
|
+
function compactNarutoRunResult(result) {
|
|
383
|
+
return {
|
|
384
|
+
schema: result?.schema || 'sks.agent-run.v1',
|
|
385
|
+
ok: result?.ok === true,
|
|
386
|
+
mission_id: result?.mission_id || null,
|
|
387
|
+
route: result?.route || NARUTO_ROUTE,
|
|
388
|
+
backend: result?.backend || null,
|
|
389
|
+
target_active_slots: result?.target_active_slots ?? null,
|
|
390
|
+
proof: result?.proof ? {
|
|
391
|
+
ok: result.proof.ok === true,
|
|
392
|
+
status: result.proof.status || null,
|
|
393
|
+
blockers: result.proof.blockers || []
|
|
394
|
+
} : null,
|
|
395
|
+
scheduler: result?.scheduler ? {
|
|
396
|
+
state: {
|
|
397
|
+
completed_count: result.scheduler.state?.completed_count ?? result.scheduler.completed_count ?? null,
|
|
398
|
+
failed_count: result.scheduler.state?.failed_count ?? result.scheduler.failed_count ?? null,
|
|
399
|
+
blocked_count: result.scheduler.state?.blocked_count ?? result.scheduler.blocked_count ?? null,
|
|
400
|
+
max_observed_active_slots: result.scheduler.state?.max_observed_active_slots ?? result.scheduler.max_observed_active_slots ?? null
|
|
401
|
+
}
|
|
402
|
+
} : null,
|
|
403
|
+
artifacts: {
|
|
404
|
+
ledger_root: result?.ledger_root || null,
|
|
405
|
+
proof: 'agent-proof-evidence.json',
|
|
406
|
+
scheduler: 'agent-scheduler-state.json',
|
|
407
|
+
native_cli_session_swarm: 'agent-native-cli-session-swarm.json',
|
|
408
|
+
naruto_real_active_pool: 'naruto-real-active-pool.json'
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
function buildNarutoAllocationWorkers(workGraph, roleDistribution, roster) {
|
|
413
|
+
const workItems = Array.isArray(workGraph?.work_items) ? workGraph.work_items : [];
|
|
414
|
+
const roleByWorkItem = new Map((roleDistribution?.work_item_roles || []).map((row) => [String(row.work_item_id), String(row.role || '')]));
|
|
415
|
+
const rosterRows = Array.isArray(roster?.roster) ? roster.roster : [];
|
|
416
|
+
const count = Math.max(1, Math.min(Number(roster?.agent_count || rosterRows.length || workItems.length || 1), Math.max(1, workItems.length || 1)));
|
|
417
|
+
return Array.from({ length: count }, (_unused, index) => {
|
|
418
|
+
const agent = rosterRows[index] || {};
|
|
419
|
+
const item = workItems[index % Math.max(1, workItems.length)] || {};
|
|
420
|
+
const role = String(agent.naruto_role || agent.role || roleByWorkItem.get(String(item.id || '')) || item.required_role || 'worker');
|
|
421
|
+
return {
|
|
422
|
+
id: String(agent.id || `clone-${String(index + 1).padStart(3, '0')}`),
|
|
423
|
+
role,
|
|
424
|
+
lane: narutoAllocationLane(item)
|
|
425
|
+
};
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
function narutoAllocationLane(item) {
|
|
429
|
+
const firstPath = String((item?.write_paths || item?.target_paths || item?.readonly_paths || [])[0] || '');
|
|
430
|
+
const parts = firstPath.replace(/\\/g, '/').split('/').filter(Boolean);
|
|
431
|
+
return parts.slice(0, Math.min(2, parts.length)).join('/') || null;
|
|
432
|
+
}
|
|
283
433
|
function summarizeNarutoLocalWorkerResult(localWorker, result) {
|
|
284
434
|
const backendCounts = {};
|
|
285
435
|
const rows = Array.isArray(result?.results) ? result.results : [];
|
|
@@ -443,6 +593,10 @@ async function writeNarutoArtifacts(ledgerRoot, artifacts) {
|
|
|
443
593
|
await writeJsonAtomic(path.join(ledgerRoot, 'naruto-active-pool.json'), artifacts.activePool);
|
|
444
594
|
if (artifacts.realActivePool)
|
|
445
595
|
await writeJsonAtomic(path.join(ledgerRoot, 'naruto-real-active-pool.json'), artifacts.realActivePool);
|
|
596
|
+
if (artifacts.allocationPolicy)
|
|
597
|
+
await writeJsonAtomic(path.join(ledgerRoot, 'naruto-allocation-policy.json'), artifacts.allocationPolicy);
|
|
598
|
+
if (artifacts.rebalancePolicy)
|
|
599
|
+
await writeJsonAtomic(path.join(ledgerRoot, 'naruto-rebalance-policy.json'), artifacts.rebalancePolicy);
|
|
446
600
|
await writeJsonAtomic(path.join(ledgerRoot, 'naruto-verification-dag.json'), artifacts.verificationDag);
|
|
447
601
|
await writeJsonAtomic(path.join(ledgerRoot, 'naruto-gpt-final-pack.json'), artifacts.gptFinalPack);
|
|
448
602
|
await writeJsonAtomic(path.join(ledgerRoot, 'naruto-zellij-dashboard.json'), artifacts.zellijDashboard);
|
|
@@ -62,6 +62,11 @@ export function buildDoctorReadinessMatrix(input = {}) {
|
|
|
62
62
|
warnings.add('local_llm_degraded');
|
|
63
63
|
if (localModel.enabled === true && localStatus === 'blocked')
|
|
64
64
|
warnings.add('local_llm_blocked_worker_tier_disabled');
|
|
65
|
+
const agentRoleConfig = input.agent_role_config || {};
|
|
66
|
+
if (agentRoleConfig.ok === false)
|
|
67
|
+
blockers.add('agent_role_config_repair_failed');
|
|
68
|
+
if (Array.isArray(agentRoleConfig.missing) && agentRoleConfig.missing.length && agentRoleConfig.apply !== true)
|
|
69
|
+
warnings.add('agent_role_config_missing_repair_available');
|
|
65
70
|
const localCollaborationPolicy = resolveLocalCollaborationPolicy({ mode: input.local_collaboration?.mode || null });
|
|
66
71
|
const gptFinalAvailable = input.local_collaboration?.gpt_final_arbiter_available === undefined
|
|
67
72
|
? codexBinOk
|
|
@@ -126,6 +131,7 @@ export function buildDoctorReadinessMatrix(input = {}) {
|
|
|
126
131
|
worker_tier_enabled: localModel.enabled === true && localStatus === 'verified',
|
|
127
132
|
blockers: normalizeList(localModel.blockers)
|
|
128
133
|
},
|
|
134
|
+
agent_role_config: agentRoleConfig,
|
|
129
135
|
ready: blockers.size === 0 && cliReady,
|
|
130
136
|
primary_blocker: [...blockers][0] || null,
|
|
131
137
|
blockers: [...blockers],
|
package/dist/core/fsx.js
CHANGED
|
@@ -5,7 +5,7 @@ import os from 'node:os';
|
|
|
5
5
|
import crypto from 'node:crypto';
|
|
6
6
|
import { spawn } from 'node:child_process';
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
|
-
export const PACKAGE_VERSION = '2.0.
|
|
8
|
+
export const PACKAGE_VERSION = '2.0.11';
|
|
9
9
|
export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
|
|
10
10
|
export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
|
|
11
11
|
export function nowIso() {
|