zelari-code 1.26.0 → 1.27.1

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.
@@ -0,0 +1,420 @@
1
+ /**
2
+ * KrakenGraphExecutor — F3: drives a TaskGraph to convergence.
3
+ *
4
+ * Consumes the pure primitives from `@zelari/core` (getReadyNodes,
5
+ * selectParallelWave, isSettled/isConverged) and the F2 tentacle runner
6
+ * (`runTentacle`) to execute a validated `TaskGraph`:
7
+ * - repeatedly forms a parallel-safe "wave" of ready nodes (bounded by
8
+ * ZELARI_KRAKEN_MAX_PARALLEL) and runs it concurrently;
9
+ * - retries a failed node up to `node.maxRetries`, then spawns a `fix`
10
+ * node (bounded by a global fix budget) that inherits the failed
11
+ * node's deps/scope/acceptance; a node that still fails is left
12
+ * terminally `error` and does NOT abort independent branches — nodes
13
+ * that transitively depend on it are cascade-marked `skipped` so the
14
+ * graph can still settle;
15
+ * - merges worktree-isolated `general`/`fix` tentacles SEQUENTIALLY when
16
+ * a `merge` node's deps complete (Correction 4 — no concurrent merges
17
+ * into the same parent HEAD); on conflict the branch/worktree is kept
18
+ * and surfaced, never auto-resolved;
19
+ * - optionally gates final convergence on `run_backtest` (Level 3) when
20
+ * `.zelari/world/checks.json` exists and ZELARI_SCHEMA_LOOP != '0'.
21
+ *
22
+ * Also drives the F5 observability surface: the graph-level live tracker
23
+ * in `./graphStatus.js` (start/update/end around the scheduling loop, for
24
+ * the StatusBar "graph x/y · n↑" chip) alongside the `graph_*`/`node_*`
25
+ * radio events emitted throughout.
26
+ *
27
+ * Explicitly NOT this module's job (deferred to F6):
28
+ * - planning a graph from a prompt — that's `./planner.js` (F4); the
29
+ * executor only executes the graph it's given;
30
+ * - wiring into any slash command, headless flag, or `useChatTurn`.
31
+ *
32
+ * @since v0.10.x — Kraken graph engine (F3)
33
+ */
34
+ import { getReadyNodes, isSettled, isConverged, failedNodeIds, countByStatus, selectParallelWave, } from '@zelari/core';
35
+ import { runTentacle, } from './tentacle.js';
36
+ import { mergeKrakenWorktree, } from '../tools/krakenWorktree.js';
37
+ import { appendKrakenRadio } from '../tools/krakenRadio.js';
38
+ import { runBacktest } from '../workspace/worldModel.js';
39
+ import { startKrakenGraphLive, updateKrakenGraphLive, endKrakenGraphLive, } from './graphStatus.js';
40
+ import { existsSync } from 'node:fs';
41
+ import path from 'node:path';
42
+ /** Default cap on concurrently-running tentacles across the whole graph. */
43
+ export const DEFAULT_MAX_PARALLEL = 12;
44
+ /** Default number of `fix` nodes the executor may spawn across one graph run. */
45
+ export const DEFAULT_FIX_BUDGET = 3;
46
+ export function resolveMaxParallel(env = process.env) {
47
+ const raw = env.ZELARI_KRAKEN_MAX_PARALLEL;
48
+ if (raw === undefined || raw === '')
49
+ return DEFAULT_MAX_PARALLEL;
50
+ const n = Number.parseInt(raw, 10);
51
+ return Number.isFinite(n) && n > 0 ? n : DEFAULT_MAX_PARALLEL;
52
+ }
53
+ export function resolveFixBudget(env = process.env) {
54
+ const raw = env.ZELARI_KRAKEN_FIX_BUDGET;
55
+ if (raw === undefined || raw === '')
56
+ return DEFAULT_FIX_BUDGET;
57
+ const n = Number.parseInt(raw, 10);
58
+ return Number.isFinite(n) && n >= 0 ? n : DEFAULT_FIX_BUDGET;
59
+ }
60
+ /**
61
+ * Default wall-clock bound per tentacle run (ms). The graph executor calls
62
+ * `runTentacle` directly, bypassing the `task` tool's own `timeoutMs: 300_000`
63
+ * enforcement (that only applies when a parent AgentHarness invokes `task`
64
+ * as a tool-call) — so without an executor-level bound, one stuck sub-agent
65
+ * (a hung bash command, a stalled fetch) hangs `execute()` forever, which
66
+ * hangs the whole headless process (main.ts only calls `process.exit()`
67
+ * after `runHeadless()`'s promise resolves), which leaves the Desktop app's
68
+ * "running" state stuck permanently. Matches the task tool's own budget.
69
+ */
70
+ export const DEFAULT_NODE_TIMEOUT_MS = 300_000;
71
+ /** Set ZELARI_KRAKEN_NODE_TIMEOUT_MS=0 to disable (not recommended). */
72
+ export function resolveNodeTimeoutMs(env = process.env) {
73
+ const raw = env.ZELARI_KRAKEN_NODE_TIMEOUT_MS;
74
+ if (raw === undefined || raw === '')
75
+ return DEFAULT_NODE_TIMEOUT_MS;
76
+ const n = Number.parseInt(raw, 10);
77
+ return Number.isFinite(n) && n >= 0 ? n : DEFAULT_NODE_TIMEOUT_MS;
78
+ }
79
+ /**
80
+ * F6 kill-switch: the `/kraken graph` slash command and `--kraken-graph`
81
+ * headless flag both check this before planning/executing anything. On by
82
+ * default, like every other Kraken env toggle (only the literal '0' turns
83
+ * it off — see ZELARI_SCHEMA_LOOP / ZELARI_MEMORY / ZELARI_BROWSER).
84
+ */
85
+ export function isKrakenGraphEnabled(env = process.env) {
86
+ return env.ZELARI_KRAKEN_GRAPH !== '0';
87
+ }
88
+ /** Whether the optional Level-3 world-model convergence gate should run. */
89
+ export function isWorldModelGateEnabled(cwd, env = process.env, checksExists = defaultChecksExists) {
90
+ if ((env.ZELARI_SCHEMA_LOOP ?? '').trim() === '0')
91
+ return false;
92
+ return checksExists(cwd);
93
+ }
94
+ function defaultChecksExists(cwd) {
95
+ try {
96
+ return existsSync(path.join(cwd, '.zelari', 'world', 'checks.json'));
97
+ }
98
+ catch {
99
+ return false;
100
+ }
101
+ }
102
+ export class KrakenGraphExecutor {
103
+ deps;
104
+ parentCwd;
105
+ sessionId;
106
+ maxParallel;
107
+ nodeTimeoutMs;
108
+ fixBudgetRemaining;
109
+ worldModelGateOverride;
110
+ runTentacleFn;
111
+ mergeFn;
112
+ backtestFn;
113
+ nodeRunState = new Map();
114
+ fixCounter = 0;
115
+ constructor(opts) {
116
+ this.deps = opts.taskToolDeps;
117
+ this.parentCwd = opts.parentCwd;
118
+ this.sessionId = opts.sessionId;
119
+ this.maxParallel = opts.maxParallel ?? resolveMaxParallel();
120
+ this.nodeTimeoutMs = opts.nodeTimeoutMs ?? resolveNodeTimeoutMs();
121
+ this.fixBudgetRemaining = opts.fixBudget ?? resolveFixBudget();
122
+ this.worldModelGateOverride = opts.worldModelGate;
123
+ this.runTentacleFn = opts.runTentacleFn ?? runTentacle;
124
+ this.mergeFn = opts.mergeFn ?? mergeKrakenWorktree;
125
+ this.backtestFn = opts.backtestFn ?? runBacktest;
126
+ }
127
+ /** Execute the graph in place (mutates node statuses) until it settles. */
128
+ async execute(graph) {
129
+ // Anti-explosion / self-inflicted-hang guard: cap total loop iterations
130
+ // at a generous multiple of the node count instead of trusting the
131
+ // graph to always shrink monotonically (fix-node spawns grow it).
132
+ const maxIterations = Math.max(64, graph.nodes.size * 8);
133
+ let iterations = 0;
134
+ startKrakenGraphLive(graph);
135
+ while (!isSettled(graph)) {
136
+ iterations += 1;
137
+ if (iterations > maxIterations) {
138
+ this.radio('graph_failed', {
139
+ description: 'graph executor',
140
+ detail: `exceeded ${maxIterations} scheduling iterations without settling`,
141
+ ok: false,
142
+ });
143
+ break;
144
+ }
145
+ const ready = getReadyNodes(graph);
146
+ if (ready.length === 0) {
147
+ // Nothing is ready but the graph hasn't settled: some pending nodes
148
+ // are permanently blocked by a failed/skipped dependency. Cascade
149
+ // skip them so the loop can terminate.
150
+ const skippedAny = this.skipBlockedNodes(graph);
151
+ if (!skippedAny) {
152
+ // Nothing ready and nothing to skip — should not happen for a
153
+ // validated DAG, but bail out rather than spin forever.
154
+ break;
155
+ }
156
+ continue;
157
+ }
158
+ const wave = selectParallelWave(ready).slice(0, this.maxParallel);
159
+ for (const node of wave)
160
+ node.status = 'running';
161
+ const results = await Promise.all(wave.map((node) => this.runNode(node, graph)));
162
+ for (let i = 0; i < wave.length; i++) {
163
+ this.applyResult(graph, wave[i], results[i]);
164
+ }
165
+ updateKrakenGraphLive(graph);
166
+ }
167
+ let backtest;
168
+ const converged = isConverged(graph);
169
+ if (converged) {
170
+ const gateOn = this.worldModelGateOverride ?? isWorldModelGateEnabled(this.parentCwd);
171
+ if (gateOn) {
172
+ backtest = await this.backtestFn(this.parentCwd);
173
+ }
174
+ this.radio('graph_converged', {
175
+ description: 'graph executor',
176
+ detail: backtest ? `backtest: ${backtest.passed}/${backtest.total} passed` : undefined,
177
+ ok: backtest ? backtest.ok : true,
178
+ });
179
+ }
180
+ else {
181
+ this.radio('graph_failed', {
182
+ description: 'graph executor',
183
+ detail: `failed nodes: ${failedNodeIds(graph).join(', ') || 'none'}`,
184
+ ok: false,
185
+ });
186
+ }
187
+ endKrakenGraphLive(graph, converged);
188
+ return {
189
+ graph,
190
+ converged,
191
+ failedNodeIds: failedNodeIds(graph),
192
+ counts: countByStatus(graph),
193
+ ...(backtest ? { backtest } : {}),
194
+ };
195
+ }
196
+ /** Run one node: dispatch to the merge handler for `merge` nodes, else a tentacle. */
197
+ async runNode(node, graph) {
198
+ this.radio('node_start', { description: node.label, agent: node.kind });
199
+ if (node.kind === 'merge') {
200
+ return this.runMergeNode(node, graph);
201
+ }
202
+ const usesWorktree = node.kind === 'general' || node.kind === 'fix';
203
+ const agent = node.kind === 'fix' ? 'general' : node.kind;
204
+ const res = await this.withNodeTimeout(this.runTentacleFn({
205
+ deps: this.deps,
206
+ args: {
207
+ description: node.label,
208
+ prompt: node.prompt,
209
+ scope: node.scope,
210
+ acceptance: node.acceptance,
211
+ },
212
+ agent,
213
+ thoroughness: 'medium',
214
+ parentCwd: this.parentCwd,
215
+ sessionId: this.sessionId,
216
+ // Defer merge for writers so the executor controls merge ordering
217
+ // (Correction 4); explore/verify never create a worktree.
218
+ deferMerge: usesWorktree,
219
+ graphId: graph.id,
220
+ nodeId: node.id,
221
+ }), agent);
222
+ if (res.ok && usesWorktree) {
223
+ this.nodeRunState.set(node.id, { worktreeHandle: res.worktreeHandle });
224
+ }
225
+ return res;
226
+ }
227
+ /**
228
+ * Bound a tentacle run to `nodeTimeoutMs` wall-clock. On timeout, resolves
229
+ * to a synthetic `TentacleFailure` so the normal retry/fix/cascade-skip
230
+ * path handles it — this only bounds how long the EXECUTOR waits, it does
231
+ * not (cannot) forcibly cancel the underlying sub-agent run; the point is
232
+ * to guarantee `execute()` itself always settles so the caller's process
233
+ * can exit instead of hanging forever on one stuck node.
234
+ */
235
+ withNodeTimeout(promise, agent) {
236
+ if (this.nodeTimeoutMs <= 0)
237
+ return promise;
238
+ const ms = this.nodeTimeoutMs;
239
+ let timer;
240
+ const timeout = new Promise((resolve) => {
241
+ timer = setTimeout(() => {
242
+ resolve({ ok: false, agent, error: `tentacle timed out after ${ms}ms` });
243
+ }, ms);
244
+ });
245
+ return Promise.race([promise, timeout]).finally(() => {
246
+ if (timer)
247
+ clearTimeout(timer);
248
+ });
249
+ }
250
+ /**
251
+ * Sequentially merge every dep node's deferred worktree (in dep order) into
252
+ * parent HEAD. Deps without a recorded worktree handle (worktree isolation
253
+ * disabled, or a read-only node) are a no-op. On conflict the branch is
254
+ * kept and the conflict is surfaced in the merge node's error — remaining
255
+ * deps still attempt to merge (independent branches shouldn't be blocked
256
+ * by one conflict).
257
+ */
258
+ async runMergeNode(node, graph) {
259
+ const conflicts = [];
260
+ const merged = [];
261
+ for (const depId of node.deps) {
262
+ const state = this.nodeRunState.get(depId);
263
+ const handle = state?.worktreeHandle;
264
+ if (!handle)
265
+ continue; // nothing to merge for this dep
266
+ let result;
267
+ try {
268
+ result = await this.mergeFn(handle, {
269
+ message: `kraken: merge ${graph.nodes.get(depId)?.label ?? depId}`.slice(0, 200),
270
+ });
271
+ }
272
+ catch (err) {
273
+ result = {
274
+ ok: false,
275
+ merged: false,
276
+ committed: false,
277
+ conflict: true,
278
+ message: `merge threw: ${err instanceof Error ? err.message : String(err)}`,
279
+ };
280
+ }
281
+ if (!result.ok) {
282
+ conflicts.push(`${depId}: ${result.message}`);
283
+ }
284
+ else {
285
+ merged.push(depId);
286
+ }
287
+ }
288
+ if (conflicts.length > 0) {
289
+ return {
290
+ ok: false,
291
+ agent: 'general',
292
+ error: `merge: ${conflicts.length} conflict(s) — ${conflicts.join('; ')}`,
293
+ };
294
+ }
295
+ return {
296
+ ok: true,
297
+ agent: 'general',
298
+ thoroughness: 'medium',
299
+ model: 'n/a',
300
+ result: merged.length > 0 ? `merged: ${merged.join(', ')}` : 'nothing to merge',
301
+ footer: '',
302
+ worktreePath: null,
303
+ worktreeHandle: null,
304
+ };
305
+ }
306
+ /** Apply a tentacle result to its node: success, retry, fix-spawn, or terminal failure. */
307
+ applyResult(graph, node, res) {
308
+ if (res.ok) {
309
+ node.status = 'done';
310
+ node.result = res.result;
311
+ this.radio('node_end', { description: node.label, agent: node.kind, ok: true });
312
+ return;
313
+ }
314
+ node.error = res.error;
315
+ if (node.retryCount < node.maxRetries) {
316
+ node.retryCount += 1;
317
+ node.status = 'pending';
318
+ this.radio('node_retry', {
319
+ description: node.label,
320
+ agent: node.kind,
321
+ detail: `retry ${node.retryCount}/${node.maxRetries}: ${res.error}`,
322
+ ok: false,
323
+ });
324
+ return;
325
+ }
326
+ if (this.fixBudgetRemaining > 0 && node.kind !== 'fix') {
327
+ this.fixBudgetRemaining -= 1;
328
+ this.fixCounter += 1;
329
+ const fixNode = this.spawnFixNode(graph, node);
330
+ this.radio('node_fix', {
331
+ description: fixNode.label,
332
+ agent: fixNode.kind,
333
+ detail: `spawned to address failure of "${node.label}": ${res.error}`,
334
+ ok: false,
335
+ });
336
+ node.status = 'error';
337
+ return;
338
+ }
339
+ // Retries and fix budget exhausted (or this was itself a fix node):
340
+ // terminal failure. Independent branches keep running; dependents are
341
+ // cascade-skipped by the scheduling loop.
342
+ node.status = 'error';
343
+ this.radio('node_end', {
344
+ description: node.label,
345
+ agent: node.kind,
346
+ detail: res.error,
347
+ ok: false,
348
+ });
349
+ }
350
+ /**
351
+ * Create a `fix` node that attempts to redo the failed node's work, wired
352
+ * so downstream dependents of the failed node also wait on the fix.
353
+ */
354
+ spawnFixNode(graph, failed) {
355
+ const fixId = `fix-${failed.id}-${this.fixCounter}`;
356
+ const fixNode = {
357
+ id: fixId,
358
+ kind: 'fix',
359
+ label: `fix: ${failed.label}`,
360
+ prompt: `The previous attempt at this task failed and must be redone/repaired.\n\n` +
361
+ `## Original task\n${failed.prompt}\n\n` +
362
+ `## Failure\n${failed.error ?? 'unknown error'}`,
363
+ scope: failed.scope,
364
+ acceptance: failed.acceptance,
365
+ deps: [...failed.deps],
366
+ status: 'pending',
367
+ retryCount: 0,
368
+ maxRetries: 0,
369
+ // no further retries — one fix attempt per failed node in v1
370
+ };
371
+ graph.nodes.set(fixId, fixNode);
372
+ // Downstream dependents wait on the fix attempt INSTEAD of the failed
373
+ // node (not in addition to it) — the failed node never becomes `done`,
374
+ // so leaving it in `deps` would strand dependents forever.
375
+ for (const other of graph.nodes.values()) {
376
+ if (other.id === fixId)
377
+ continue;
378
+ if (other.deps.includes(failed.id)) {
379
+ other.deps = other.deps.map((d) => (d === failed.id ? fixId : d));
380
+ }
381
+ }
382
+ return fixNode;
383
+ }
384
+ /**
385
+ * Mark every `pending` node whose deps include a terminally-failed or
386
+ * skipped node as `skipped`, transitively, so the graph can settle.
387
+ * Returns true if any node was newly skipped.
388
+ */
389
+ skipBlockedNodes(graph) {
390
+ let changed = false;
391
+ let progressed = true;
392
+ while (progressed) {
393
+ progressed = false;
394
+ for (const node of graph.nodes.values()) {
395
+ if (node.status !== 'pending')
396
+ continue;
397
+ const blocked = node.deps.some((d) => {
398
+ const dep = graph.nodes.get(d);
399
+ return dep?.status === 'error' || dep?.status === 'skipped';
400
+ });
401
+ if (blocked) {
402
+ node.status = 'skipped';
403
+ changed = true;
404
+ progressed = true;
405
+ }
406
+ }
407
+ }
408
+ return changed;
409
+ }
410
+ radio(kind, fields) {
411
+ appendKrakenRadio(this.parentCwd, this.sessionId, {
412
+ kind,
413
+ agent: fields.agent ?? 'graph',
414
+ description: fields.description,
415
+ ...(fields.detail !== undefined ? { detail: fields.detail } : {}),
416
+ ...(fields.ok !== undefined ? { ok: fields.ok } : {}),
417
+ });
418
+ }
419
+ }
420
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../src/cli/kraken/executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Kraken graph engine — observability (F5).
3
+ *
4
+ * Two independent pieces:
5
+ * - `formatKrakenGraphAscii` — a pure renderer of a `TaskGraph`'s topology
6
+ * and current node statuses (`/kraken graph` status block).
7
+ * - a lightweight in-process "current graph" live tracker, mirroring
8
+ * `krakenLive.ts`'s per-tentacle tracker but at the whole-graph level
9
+ * (needed for accurate pending/skipped/merge-node counts that a
10
+ * per-tentacle view can't see), feeding a StatusBar chip
11
+ * ("graph 3/8 · 2↑") the same way `formatKrakenLiveSummary` does for
12
+ * individual tentacles.
13
+ *
14
+ * Complements the `graph_*`/`node_*` radio events emitted by the F3
15
+ * executor (`src/cli/kraken/executor.ts`), which is also what drives this
16
+ * tracker via start/update/end calls around its scheduling loop.
17
+ *
18
+ * @since v0.10.x — Kraken graph engine (F5)
19
+ */
20
+ import { topoLevels, countByStatus, } from '@zelari/core';
21
+ const STATUS_ICON = {
22
+ pending: '·',
23
+ running: '…',
24
+ done: '✓',
25
+ error: '✗',
26
+ skipped: '»',
27
+ };
28
+ /** Multi-line ASCII rendering of a graph's topology + current node statuses. */
29
+ export function formatKrakenGraphAscii(graph) {
30
+ const counts = countByStatus(graph);
31
+ const summaryParts = [`${counts.done}/${graph.nodes.size} done`];
32
+ if (counts.running)
33
+ summaryParts.push(`${counts.running} running`);
34
+ if (counts.error)
35
+ summaryParts.push(`${counts.error} failed`);
36
+ if (counts.skipped)
37
+ summaryParts.push(`${counts.skipped} skipped`);
38
+ const summary = `Kraken graph "${graph.id}" — ${summaryParts.join(', ')}`;
39
+ const levels = topoLevels(graph);
40
+ const lines = levels.map((ids, i) => {
41
+ const cells = ids.map((id) => {
42
+ const n = graph.nodes.get(id);
43
+ if (!n)
44
+ return `[?] ${id}`;
45
+ const icon = STATUS_ICON[n.status];
46
+ const scope = n.scope && n.scope.length > 0 ? `(${n.scope.join(',')})` : '';
47
+ return `[${icon}] ${n.id}${scope}`;
48
+ });
49
+ return `L${i}: ${cells.join(' ')}`;
50
+ });
51
+ if (lines.length === 0)
52
+ return summary;
53
+ return [summary, ...lines].join('\n');
54
+ }
55
+ function state() {
56
+ return globalThis;
57
+ }
58
+ /** Called by the executor when a graph run starts. */
59
+ export function startKrakenGraphLive(graph) {
60
+ const counts = countByStatus(graph);
61
+ state().__zelariKrakenGraphLive = {
62
+ graphId: graph.id,
63
+ total: graph.nodes.size,
64
+ pending: counts.pending,
65
+ running: counts.running,
66
+ done: counts.done,
67
+ error: counts.error,
68
+ skipped: counts.skipped,
69
+ startedAt: Date.now(),
70
+ };
71
+ }
72
+ /** Called by the executor after each scheduling pass to refresh counts. */
73
+ export function updateKrakenGraphLive(graph) {
74
+ const live = state().__zelariKrakenGraphLive;
75
+ if (!live || live.graphId !== graph.id)
76
+ return;
77
+ const counts = countByStatus(graph);
78
+ live.total = graph.nodes.size;
79
+ live.pending = counts.pending;
80
+ live.running = counts.running;
81
+ live.done = counts.done;
82
+ live.error = counts.error;
83
+ live.skipped = counts.skipped;
84
+ }
85
+ /** Called by the executor once the graph settles. */
86
+ export function endKrakenGraphLive(graph, converged) {
87
+ updateKrakenGraphLive(graph);
88
+ const live = state().__zelariKrakenGraphLive;
89
+ if (!live || live.graphId !== graph.id)
90
+ return;
91
+ live.endedAt = Date.now();
92
+ live.converged = converged;
93
+ }
94
+ /** Clear the tracked graph (e.g. before starting a new one, or in tests). */
95
+ export function resetKrakenGraphLive() {
96
+ state().__zelariKrakenGraphLive = null;
97
+ }
98
+ /** The currently (or most recently) tracked graph's live summary, if any. */
99
+ export function getKrakenGraphLive() {
100
+ return state().__zelariKrakenGraphLive ?? null;
101
+ }
102
+ /** One-line chip for StatusBar: "graph 3/8 · 2↑" or null if no graph tracked. */
103
+ export function formatKrakenGraphSummary() {
104
+ const live = getKrakenGraphLive();
105
+ if (!live)
106
+ return null;
107
+ const parts = [`${live.done}/${live.total}`];
108
+ if (live.running)
109
+ parts.push(`${live.running}↑`);
110
+ if (live.error)
111
+ parts.push(`${live.error}✗`);
112
+ return `graph ${parts.join(' · ')}`;
113
+ }
114
+ //# sourceMappingURL=graphStatus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graphStatus.js","sourceRoot":"","sources":["../../../src/cli/kraken/graphStatus.ts"],"names":[],"mappings":"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"}