@mu-crew/mu 4.0.0 → 4.1.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.
- package/README.md +1 -1
- package/dist/{chunk-5HECDBK3.js → chunk-B74N2EAS.js} +16 -16
- package/dist/{chunk-GQNHIPJN.js → chunk-DEYBQDTO.js} +21 -421
- package/dist/chunk-DEYBQDTO.js.map +1 -0
- package/dist/{chunk-S424D5EP.js → chunk-L7I3BLXP.js} +635 -142
- package/dist/chunk-L7I3BLXP.js.map +1 -0
- package/dist/{chunk-AW2NONYU.js → chunk-LBBZAG5C.js} +81 -7
- package/dist/chunk-LBBZAG5C.js.map +1 -0
- package/dist/{cli-GB2CAVVW.js → cli-H2PWJAJN.js} +346 -44
- package/dist/cli-H2PWJAJN.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/{errors-KHOYKD7D.js → errors-G5IVXSMY.js} +2 -2
- package/dist/extension/mu-pi.js +28 -14
- package/dist/extension/mu-pi.js.map +1 -1
- package/dist/index.d.ts +63 -11
- package/dist/index.js +15 -15
- package/dist/{tui-ALPHYTA2.js → tui-EN2CDP6G.js} +102 -27
- package/dist/tui-EN2CDP6G.js.map +1 -0
- package/docs/ARCHITECTURE.md +5 -4
- package/docs/VOCABULARY.md +6 -5
- package/docs/guide/cleanup.md +8 -0
- package/docs/guide/delegate.md +11 -3
- package/docs/guide/remote.md +19 -12
- package/docs/guide/sql.md +1 -0
- package/docs/reference/env.md +1 -0
- package/docs/reference/naming.md +2 -0
- package/package.json +1 -1
- package/skills/mu/recipes/remote-workers.md +7 -6
- package/dist/chunk-AW2NONYU.js.map +0 -1
- package/dist/chunk-GQNHIPJN.js.map +0 -1
- package/dist/chunk-S424D5EP.js.map +0 -1
- package/dist/cli-GB2CAVVW.js.map +0 -1
- package/dist/tui-ALPHYTA2.js.map +0 -1
- /package/dist/{chunk-5HECDBK3.js.map → chunk-B74N2EAS.js.map} +0 -0
- /package/dist/{errors-KHOYKD7D.js.map → errors-G5IVXSMY.js.map} +0 -0
|
@@ -41,11 +41,8 @@ import {
|
|
|
41
41
|
steerStallHandler,
|
|
42
42
|
waitForEvents,
|
|
43
43
|
waitWithActions
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-B74N2EAS.js";
|
|
45
45
|
import {
|
|
46
|
-
DelegateCallConflictError,
|
|
47
|
-
DelegateNotFoundError,
|
|
48
|
-
DelegateStateError,
|
|
49
46
|
FRONTIER_MAX_DEPTH,
|
|
50
47
|
HumanNeededInvalidError,
|
|
51
48
|
NEXT_BYTES,
|
|
@@ -56,7 +53,6 @@ import {
|
|
|
56
53
|
SyncPeerRefAmbiguousError,
|
|
57
54
|
SyncSourceNotFoundError,
|
|
58
55
|
SyncSourceTooNewError,
|
|
59
|
-
TERMINAL_DELEGATE_STATES,
|
|
60
56
|
TaskAutoArgError,
|
|
61
57
|
TaskAutoRefusedError,
|
|
62
58
|
TaskBriefMissingError,
|
|
@@ -75,27 +71,23 @@ import {
|
|
|
75
71
|
currentCallers,
|
|
76
72
|
encodeEnvelope,
|
|
77
73
|
escapeRecordText,
|
|
78
|
-
finishDelegate,
|
|
79
74
|
footerLine,
|
|
80
75
|
foreignVersionMessage,
|
|
81
|
-
getDelegateCall,
|
|
82
76
|
ingestFromDb,
|
|
83
77
|
jsonDocument,
|
|
84
78
|
linesBytes,
|
|
85
|
-
listDelegates,
|
|
86
79
|
liveAgentToOutput,
|
|
87
80
|
loadOpenTaskFrontier,
|
|
81
|
+
localMachineId,
|
|
88
82
|
logOut,
|
|
89
83
|
logPage,
|
|
90
84
|
logReceipt,
|
|
91
|
-
markDelegate,
|
|
92
85
|
noticesField,
|
|
93
86
|
okEnvelope,
|
|
94
87
|
pageOut,
|
|
95
88
|
pageRecords,
|
|
96
89
|
peerStatuses,
|
|
97
90
|
recordHumanNeeded,
|
|
98
|
-
registerDelegateCall,
|
|
99
91
|
renderArgv,
|
|
100
92
|
repairPeer,
|
|
101
93
|
resumeArgv,
|
|
@@ -108,9 +100,8 @@ import {
|
|
|
108
100
|
taskPage,
|
|
109
101
|
taskRecordCut,
|
|
110
102
|
taskToOutput,
|
|
111
|
-
verdictTally,
|
|
112
103
|
workstreamIdOf
|
|
113
|
-
} from "./chunk-
|
|
104
|
+
} from "./chunk-DEYBQDTO.js";
|
|
114
105
|
import {
|
|
115
106
|
AgentAbortNeedsCtlError,
|
|
116
107
|
AgentAbortTimeoutError,
|
|
@@ -141,6 +132,9 @@ import {
|
|
|
141
132
|
CrossWorkstreamEdgeError,
|
|
142
133
|
CtlDeliveryUnknownError,
|
|
143
134
|
CycleError,
|
|
135
|
+
DelegateCallConflictError,
|
|
136
|
+
DelegateNotFoundError,
|
|
137
|
+
DelegateStateError,
|
|
144
138
|
EXPECTED_TABLES,
|
|
145
139
|
GUARD_ALREADY_OWNED,
|
|
146
140
|
GUARD_HUGE_ID,
|
|
@@ -182,6 +176,7 @@ import {
|
|
|
182
176
|
SubstateReasonRequiredError,
|
|
183
177
|
TASK_STATUS_LIST,
|
|
184
178
|
TASK_SUBSTATES,
|
|
179
|
+
TERMINAL_DELEGATE_STATES,
|
|
185
180
|
TaskAlreadyOwnedError,
|
|
186
181
|
TaskExistsError,
|
|
187
182
|
TaskHasOpenBlockersError,
|
|
@@ -240,6 +235,8 @@ import {
|
|
|
240
235
|
deadStagings,
|
|
241
236
|
defaultDbPath,
|
|
242
237
|
delegateOutcome,
|
|
238
|
+
delegateProcessDir,
|
|
239
|
+
delegateSessionDir,
|
|
243
240
|
deleteTask,
|
|
244
241
|
dirtyFiles,
|
|
245
242
|
ensureWorkstream,
|
|
@@ -247,10 +244,12 @@ import {
|
|
|
247
244
|
errCode,
|
|
248
245
|
expectsCtl,
|
|
249
246
|
findEdgeCycles,
|
|
247
|
+
finishDelegate,
|
|
250
248
|
forget,
|
|
251
249
|
formatPair,
|
|
252
250
|
getAgent,
|
|
253
251
|
getAgentByPane,
|
|
252
|
+
getDelegateCall,
|
|
254
253
|
getHost,
|
|
255
254
|
getTask,
|
|
256
255
|
getTaskEdgesWithStatus,
|
|
@@ -263,6 +262,7 @@ import {
|
|
|
263
262
|
headSha,
|
|
264
263
|
hostStarter,
|
|
265
264
|
interruptAgent,
|
|
265
|
+
isAgentListArgv,
|
|
266
266
|
isCommandGate,
|
|
267
267
|
isJsonMode,
|
|
268
268
|
isScratchWorkstream,
|
|
@@ -274,6 +274,7 @@ import {
|
|
|
274
274
|
lastClaimActor,
|
|
275
275
|
latestSeq,
|
|
276
276
|
listAgents,
|
|
277
|
+
listDelegates,
|
|
277
278
|
listEmptyWorkstreams,
|
|
278
279
|
listForgetCandidates,
|
|
279
280
|
listHostChannels,
|
|
@@ -288,6 +289,7 @@ import {
|
|
|
288
289
|
listTornDownWorkstreams,
|
|
289
290
|
listWorkstreams,
|
|
290
291
|
listWorktrees,
|
|
292
|
+
markDelegate,
|
|
291
293
|
muTable,
|
|
292
294
|
murmurAvailable,
|
|
293
295
|
openDb,
|
|
@@ -307,6 +309,7 @@ import {
|
|
|
307
309
|
reconcile,
|
|
308
310
|
recoveriesFor,
|
|
309
311
|
recoveryWorkstreams,
|
|
312
|
+
registerDelegateCall,
|
|
310
313
|
registerOwnedWait,
|
|
311
314
|
registerWorktree,
|
|
312
315
|
reinitWorkstream,
|
|
@@ -340,20 +343,21 @@ import {
|
|
|
340
343
|
unparkTask,
|
|
341
344
|
updateTask,
|
|
342
345
|
usageLines,
|
|
346
|
+
verdictTally,
|
|
343
347
|
weakDecisionWarning,
|
|
344
348
|
withOpContext,
|
|
345
349
|
withTaskFence,
|
|
346
350
|
workstreamRevision,
|
|
347
351
|
worktreePath,
|
|
348
352
|
worktreesRoot
|
|
349
|
-
} from "./chunk-
|
|
353
|
+
} from "./chunk-L7I3BLXP.js";
|
|
350
354
|
import {
|
|
351
355
|
defaultStateDir
|
|
352
356
|
} from "./chunk-PZ5GOCWH.js";
|
|
353
357
|
|
|
354
358
|
// src/cli.ts
|
|
355
359
|
import { readFileSync as readFileSync3 } from "fs";
|
|
356
|
-
import { dirname as
|
|
360
|
+
import { dirname as dirname7, join as join5 } from "path";
|
|
357
361
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
358
362
|
|
|
359
363
|
// node_modules/commander/lib/error.js
|
|
@@ -4049,7 +4053,7 @@ function emitError(err) {
|
|
|
4049
4053
|
agentId: err.agentId
|
|
4050
4054
|
});
|
|
4051
4055
|
}
|
|
4052
|
-
const humanNoMux = err instanceof NoMultiplexerError && isStateVerbArgv(process.argv) && !process.argv.some((a) => a === "--json" || a.startsWith("--json="));
|
|
4056
|
+
const humanNoMux = err instanceof NoMultiplexerError && (isStateVerbArgv(process.argv) || isAgentListArgv(process.argv)) && !process.argv.some((a) => a === "--json" || a.startsWith("--json="));
|
|
4053
4057
|
if (isJsonMode() && !humanNoMux) {
|
|
4054
4058
|
const extra = {};
|
|
4055
4059
|
if (usageCmd) extra.usage = usageLines(usageCmd);
|
|
@@ -4650,7 +4654,7 @@ async function parseWaitRef(db, raw, scope, legacy = {}) {
|
|
|
4650
4654
|
return { kind, workstream, id: parsed.name };
|
|
4651
4655
|
}
|
|
4652
4656
|
if (getAgent(db, parsed.name, workstream) === void 0) {
|
|
4653
|
-
const { AgentNotFoundError: AgentNotFoundError2 } = await import("./errors-
|
|
4657
|
+
const { AgentNotFoundError: AgentNotFoundError2 } = await import("./errors-G5IVXSMY.js");
|
|
4654
4658
|
throw new AgentNotFoundError2(parsed.name);
|
|
4655
4659
|
}
|
|
4656
4660
|
return {
|
|
@@ -6994,6 +6998,7 @@ function assertWorktreeFlags(opts) {
|
|
|
6994
6998
|
return;
|
|
6995
6999
|
}
|
|
6996
7000
|
for (const flag of ["from", "root"]) {
|
|
7001
|
+
if (flag === "root" && opts.host !== void 0) continue;
|
|
6997
7002
|
if (opts[flag] !== void 0) throw new UsageError(say("agent.spawn_needs_worktree", flag));
|
|
6998
7003
|
}
|
|
6999
7004
|
}
|
|
@@ -7847,10 +7852,10 @@ function wireAgentCommands(program2) {
|
|
|
7847
7852
|
"run in its own git worktree (git worktree add --detach under the state dir); its path is the cwd"
|
|
7848
7853
|
).option("--from <ref>", "with --worktree: start at this commit or branch (default: HEAD)").option(
|
|
7849
7854
|
"--root <repo>",
|
|
7850
|
-
"with --worktree: the repo to add it to (default: the git root of your cwd)"
|
|
7855
|
+
"with --worktree: the repo to add it to (default: the git root of your cwd). With --host: a REMOTE repo (default the profile's --repo), also without --worktree, as the start directory"
|
|
7851
7856
|
).option(
|
|
7852
7857
|
"--host <profile>",
|
|
7853
|
-
"run on this host profile (mu host add): the pane runs its --shell template, which starts the remote pi and forwards its control socket here; --cwd and --worktree name REMOTE paths (the worktree is made by its --exec, under ~/.local/state/mu-next/remote-worktrees/<ws>/<name>); the pane dying is the agent dying. tmux only
|
|
7858
|
+
"run on this host profile (mu host add): the pane runs its --shell template, which starts the remote pi and forwards its control socket here; --cwd and --worktree name REMOTE paths (the worktree is made by its --exec, under ~/.local/state/mu-next/remote-worktrees/<ws>/<name>); --root names the remote repo; the pane dying is the agent dying. tmux only"
|
|
7854
7859
|
).option("--no-ctl", "skip the control-socket handshake with the mu pi extension").option(
|
|
7855
7860
|
"--next-free",
|
|
7856
7861
|
"if <name> is taken, take the next free one (worker-1 \u2192 worker-2, review \u2192 review-2); --json's agent.name says which"
|
|
@@ -7912,8 +7917,11 @@ function wireAgentCommands(program2) {
|
|
|
7912
7917
|
const opts = this.opts();
|
|
7913
7918
|
return handle((db) => cmdRead(db, name, opts), this)();
|
|
7914
7919
|
});
|
|
7915
|
-
agent.command("list").description(
|
|
7920
|
+
agent.command("list").description(
|
|
7921
|
+
"List agents in the current workstream (reconciled with the active mux). One JSON document by default; --table for the human table"
|
|
7922
|
+
).option(...WORKSTREAM_OPT).option(...JSON_OPT).option("--table", "print the human table instead of the JSON document").action(function() {
|
|
7916
7923
|
const opts = this.opts();
|
|
7924
|
+
opts.json = opts.json === true || opts.table !== true;
|
|
7917
7925
|
return handle((db) => cmdList(db, opts), this)();
|
|
7918
7926
|
});
|
|
7919
7927
|
agent.command("show <name>").description("Show an agent: registry row + recent scrollback (last N lines, default 20)").option("-n, --lines <n>", "how many scrollback lines to show (default 20)", parseLines).option(...WORKSTREAM_OPT).option(...JSON_OPT).action(function(name) {
|
|
@@ -8037,7 +8045,7 @@ function openDashboardOrHelp(program2) {
|
|
|
8037
8045
|
(syncDb) => withShutdown(syncDb, async (shutdown) => {
|
|
8038
8046
|
const key = "NODE_ENV";
|
|
8039
8047
|
process.env[key] ??= "production";
|
|
8040
|
-
const { runDashboard } = await import("./tui-
|
|
8048
|
+
const { runDashboard } = await import("./tui-EN2CDP6G.js");
|
|
8041
8049
|
const first = program2.opts().workstream?.[0];
|
|
8042
8050
|
await runDashboard({ dbPath: defaultDbPath(), syncDb, shutdown, initialWorkstream: first });
|
|
8043
8051
|
}),
|
|
@@ -8176,7 +8184,7 @@ function checkStrayDbFiles() {
|
|
|
8176
8184
|
`Live DB: ${defaultDbPath()}`,
|
|
8177
8185
|
"",
|
|
8178
8186
|
"These are hand-made copies, pre-upgrade saves, and the backups",
|
|
8179
|
-
"`mu db compact` / `mu db forget` write first (mu.db.pre-<verb>-<time>).",
|
|
8187
|
+
"`mu db compact` / `mu db forget` / `mu delegates prune` write first (mu.db.pre-<verb>-<time>).",
|
|
8180
8188
|
"No mu code path reads them and none prunes them. Keep a pre-forget",
|
|
8181
8189
|
"backup until you are sure: it is the only way back from a forget.",
|
|
8182
8190
|
"Otherwise disaster recovery is the ops log, so a copy is a convenience:",
|
|
@@ -9106,7 +9114,7 @@ var LOG_TAIL_BYTES = 2e3;
|
|
|
9106
9114
|
var sha = (s, n) => createHash("sha256").update(s).digest("hex").slice(0, n);
|
|
9107
9115
|
function delegateProcessPaths(db, row) {
|
|
9108
9116
|
const base = dirname3(db.name);
|
|
9109
|
-
const dir =
|
|
9117
|
+
const dir = delegateProcessDir(db.name, row.callId);
|
|
9110
9118
|
return {
|
|
9111
9119
|
dir,
|
|
9112
9120
|
log: join2(dir, "pi.log"),
|
|
@@ -9437,6 +9445,196 @@ ${tail(p.log)}` : void 0
|
|
|
9437
9445
|
}
|
|
9438
9446
|
}
|
|
9439
9447
|
|
|
9448
|
+
// src/delegate-prune.ts
|
|
9449
|
+
import { lstatSync, readdirSync as readdirSync2, rmSync as rmSync2 } from "fs";
|
|
9450
|
+
import { dirname as dirname4, join as join3 } from "path";
|
|
9451
|
+
var PRUNE_DEFAULT_DAYS = 30;
|
|
9452
|
+
function sizeOf3(p) {
|
|
9453
|
+
let st;
|
|
9454
|
+
try {
|
|
9455
|
+
st = lstatSync(p);
|
|
9456
|
+
} catch {
|
|
9457
|
+
return 0;
|
|
9458
|
+
}
|
|
9459
|
+
if (!st.isDirectory()) return st.size;
|
|
9460
|
+
let n = 0;
|
|
9461
|
+
for (const e of readdirSync2(p)) n += sizeOf3(join3(p, e));
|
|
9462
|
+
return n;
|
|
9463
|
+
}
|
|
9464
|
+
var hasFileDir = (db) => db.name !== "" && db.name !== ":memory:";
|
|
9465
|
+
var LOOSE_MIN_AGE_MS = 864e5;
|
|
9466
|
+
function looseSessions(db, cutoff, workstream, now) {
|
|
9467
|
+
const root = join3(dirname4(db.name), "delegate-sessions");
|
|
9468
|
+
const before = Math.min(Date.parse(cutoff), now - LOOSE_MIN_AGE_MS);
|
|
9469
|
+
const out = [];
|
|
9470
|
+
const wss = db.prepare(
|
|
9471
|
+
"SELECT name FROM workstreams WHERE torn_down_at IS NULL AND (? IS NULL OR name = ?)"
|
|
9472
|
+
).all(workstream ?? null, workstream ?? null).map((r) => r.name);
|
|
9473
|
+
for (const ws of wss) {
|
|
9474
|
+
let names;
|
|
9475
|
+
try {
|
|
9476
|
+
names = readdirSync2(join3(root, ws));
|
|
9477
|
+
} catch {
|
|
9478
|
+
continue;
|
|
9479
|
+
}
|
|
9480
|
+
for (const f of names) {
|
|
9481
|
+
const p = join3(root, ws, f);
|
|
9482
|
+
if (!f.endsWith(".jsonl")) continue;
|
|
9483
|
+
try {
|
|
9484
|
+
const st = lstatSync(p);
|
|
9485
|
+
if (st.isFile() && st.mtimeMs < before) out.push(p);
|
|
9486
|
+
} catch {
|
|
9487
|
+
}
|
|
9488
|
+
}
|
|
9489
|
+
}
|
|
9490
|
+
return out.sort();
|
|
9491
|
+
}
|
|
9492
|
+
var callFiles = (db, c) => [
|
|
9493
|
+
delegateSessionDir(db.name, c.workstream, c.task),
|
|
9494
|
+
delegateProcessDir(db.name, c.callId)
|
|
9495
|
+
];
|
|
9496
|
+
var TASK_PUTS_WHERE = `entity IN ('task', 'note') AND op = 'put'
|
|
9497
|
+
AND key >= @k AND key < @k || '$' AND (key = @k OR key >= @k || '#')
|
|
9498
|
+
AND (@own = 1 OR machine_id <> @me)`;
|
|
9499
|
+
var MIN_DATE_MS = -864e13;
|
|
9500
|
+
function planDelegatePrune(db, opts = {}) {
|
|
9501
|
+
const days2 = opts.days ?? PRUNE_DEFAULT_DAYS;
|
|
9502
|
+
const ownHistory = opts.ownHistory ?? !syncEnabled();
|
|
9503
|
+
const cutoff = new Date(
|
|
9504
|
+
Math.max(MIN_DATE_MS, (opts.now ?? Date.now()) - days2 * 864e5)
|
|
9505
|
+
).toISOString();
|
|
9506
|
+
const rows = db.prepare(
|
|
9507
|
+
`SELECT t.id AS id, w.name AS workstream, t.local_id AS task, t.updated_at AS updated_at,
|
|
9508
|
+
d.call_id AS call_id, d.state AS call_state,
|
|
9509
|
+
(SELECT COUNT(*) FROM task_edges e WHERE e.from_task_id = t.id OR e.to_task_id = t.id) AS edges,
|
|
9510
|
+
EXISTS (SELECT 1 FROM tasks jt JOIN workstreams jw ON jw.id = jt.workstream_id
|
|
9511
|
+
JOIN task_auto ja ON ja.task_id = jt.id AND ja.enabled = 1
|
|
9512
|
+
WHERE jw.name = d.record_workstream AND jt.local_id = d.record_task) AS judged_auto
|
|
9513
|
+
FROM tasks t
|
|
9514
|
+
JOIN workstreams w ON w.id = t.workstream_id AND w.torn_down_at IS NULL
|
|
9515
|
+
JOIN delegate_calls d ON d.task_id = t.id
|
|
9516
|
+
WHERE t.kind = 'delegate' AND t.status = 'CLOSED' AND t.updated_at < ?
|
|
9517
|
+
AND (? IS NULL OR w.name = ?)
|
|
9518
|
+
ORDER BY w.name, t.updated_at, t.local_id`
|
|
9519
|
+
).all(cutoff, opts.workstream ?? null, opts.workstream ?? null);
|
|
9520
|
+
const plan = {
|
|
9521
|
+
cutoff,
|
|
9522
|
+
days: days2,
|
|
9523
|
+
candidates: [],
|
|
9524
|
+
kept: { edges: 0, refuteTarget: 0 },
|
|
9525
|
+
ownHistory,
|
|
9526
|
+
ops: 0,
|
|
9527
|
+
bytes: 0,
|
|
9528
|
+
files: { paths: [], bytes: 0 }
|
|
9529
|
+
};
|
|
9530
|
+
const cost = db.prepare(
|
|
9531
|
+
`SELECT COUNT(*) AS n, COALESCE(SUM(length(payload)), 0) AS b FROM ops WHERE ${TASK_PUTS_WHERE}`
|
|
9532
|
+
);
|
|
9533
|
+
const me = localMachineId(db);
|
|
9534
|
+
const own = ownHistory ? 1 : 0;
|
|
9535
|
+
for (const r of rows) {
|
|
9536
|
+
if (!["done", "failed", "cancelled"].includes(r.call_state)) continue;
|
|
9537
|
+
if (r.edges > 0) {
|
|
9538
|
+
plan.kept.edges++;
|
|
9539
|
+
continue;
|
|
9540
|
+
}
|
|
9541
|
+
if (r.call_id.startsWith("refute:") && r.judged_auto === 1) {
|
|
9542
|
+
plan.kept.refuteTarget++;
|
|
9543
|
+
continue;
|
|
9544
|
+
}
|
|
9545
|
+
plan.candidates.push({
|
|
9546
|
+
workstream: r.workstream,
|
|
9547
|
+
task: r.task,
|
|
9548
|
+
callId: r.call_id,
|
|
9549
|
+
closedAt: r.updated_at
|
|
9550
|
+
});
|
|
9551
|
+
const c = cost.get({ k: `${r.workstream}/${r.task}`, own, me });
|
|
9552
|
+
plan.ops += c.n;
|
|
9553
|
+
plan.bytes += c.b;
|
|
9554
|
+
}
|
|
9555
|
+
if (hasFileDir(db)) {
|
|
9556
|
+
const paths = [
|
|
9557
|
+
...plan.candidates.flatMap((c) => callFiles(db, c)).filter(exists2),
|
|
9558
|
+
...looseSessions(db, cutoff, opts.workstream, opts.now ?? Date.now())
|
|
9559
|
+
];
|
|
9560
|
+
plan.files = { paths, bytes: paths.reduce((n, p) => n + sizeOf3(p), 0) };
|
|
9561
|
+
}
|
|
9562
|
+
return plan;
|
|
9563
|
+
}
|
|
9564
|
+
function exists2(p) {
|
|
9565
|
+
try {
|
|
9566
|
+
lstatSync(p);
|
|
9567
|
+
return true;
|
|
9568
|
+
} catch {
|
|
9569
|
+
return false;
|
|
9570
|
+
}
|
|
9571
|
+
}
|
|
9572
|
+
function pruneDelegates(db, plan) {
|
|
9573
|
+
let tasks = 0;
|
|
9574
|
+
let ops = 0;
|
|
9575
|
+
const pruned = [];
|
|
9576
|
+
withOpContext(
|
|
9577
|
+
db,
|
|
9578
|
+
{ intent: "delegate.prune", actor: "mu delegates prune", group: "new" },
|
|
9579
|
+
() => db.transaction(() => {
|
|
9580
|
+
const del = db.prepare(
|
|
9581
|
+
`DELETE FROM tasks WHERE kind = 'delegate' AND status = 'CLOSED' AND updated_at < ?
|
|
9582
|
+
AND local_id = ? AND workstream_id = (SELECT id FROM workstreams WHERE name = ?)
|
|
9583
|
+
AND NOT EXISTS (SELECT 1 FROM task_edges e
|
|
9584
|
+
WHERE e.from_task_id = tasks.id OR e.to_task_id = tasks.id)`
|
|
9585
|
+
);
|
|
9586
|
+
const puts = db.prepare(`DELETE FROM ops WHERE ${TASK_PUTS_WHERE}`);
|
|
9587
|
+
const me = localMachineId(db);
|
|
9588
|
+
const own = plan.ownHistory ? 1 : 0;
|
|
9589
|
+
const cursor = db.prepare("DELETE FROM wait_cursors WHERE ref = ?");
|
|
9590
|
+
for (const c of plan.candidates) {
|
|
9591
|
+
if (del.run(plan.cutoff, c.task, c.workstream).changes === 0) continue;
|
|
9592
|
+
tasks++;
|
|
9593
|
+
pruned.push(c);
|
|
9594
|
+
ops += puts.run({ k: `${c.workstream}/${c.task}`, own, me }).changes;
|
|
9595
|
+
cursor.run(`delegate:${c.workstream}/${c.callId}`);
|
|
9596
|
+
}
|
|
9597
|
+
}).immediate()
|
|
9598
|
+
);
|
|
9599
|
+
let files = 0;
|
|
9600
|
+
if (hasFileDir(db)) {
|
|
9601
|
+
const loose = new Set(plan.files.paths);
|
|
9602
|
+
const go = [
|
|
9603
|
+
...pruned.flatMap((c) => callFiles(db, c)),
|
|
9604
|
+
...looseSessions(db, plan.cutoff, void 0, Date.now()).filter((p) => loose.has(p))
|
|
9605
|
+
];
|
|
9606
|
+
for (const p of go) {
|
|
9607
|
+
if (!exists2(p)) continue;
|
|
9608
|
+
try {
|
|
9609
|
+
rmSync2(p, { recursive: true, force: true });
|
|
9610
|
+
files++;
|
|
9611
|
+
} catch {
|
|
9612
|
+
}
|
|
9613
|
+
}
|
|
9614
|
+
}
|
|
9615
|
+
return { tasks, ops, files };
|
|
9616
|
+
}
|
|
9617
|
+
function checkOldDelegates(db, opts = {}) {
|
|
9618
|
+
const plan = planDelegatePrune(db, opts);
|
|
9619
|
+
const n = plan.candidates.length;
|
|
9620
|
+
if (n === 0)
|
|
9621
|
+
return {
|
|
9622
|
+
name: "delegates-old",
|
|
9623
|
+
severity: "ok",
|
|
9624
|
+
detail: `no closed delegate task older than ${plan.days} days`
|
|
9625
|
+
};
|
|
9626
|
+
return {
|
|
9627
|
+
name: "delegates-old",
|
|
9628
|
+
severity: "ok",
|
|
9629
|
+
detail: `${n} closed delegate task(s) older than ${plan.days} days (${plan.ops} ops)`,
|
|
9630
|
+
remediation: [
|
|
9631
|
+
"Each holds its whole brief and report, synced to every peer. Their verdicts stay on the judged tasks.",
|
|
9632
|
+
" mu delegates prune # dry run: what goes, and what is kept",
|
|
9633
|
+
" mu delegates prune --yes # backs up beside the DB first; irreversible"
|
|
9634
|
+
]
|
|
9635
|
+
};
|
|
9636
|
+
}
|
|
9637
|
+
|
|
9440
9638
|
// src/workstream-scope.ts
|
|
9441
9639
|
function workstreamNameProblem(value, flag = "-w/--workstream") {
|
|
9442
9640
|
if (value.length > 0 && value.trim().length === 0) {
|
|
@@ -9648,6 +9846,82 @@ async function cmdDelegatesRun(db, callId, opts) {
|
|
|
9648
9846
|
}
|
|
9649
9847
|
if (r.ran && r.state !== "done") throw new CliExitError(1);
|
|
9650
9848
|
}
|
|
9849
|
+
function keptLine(plan) {
|
|
9850
|
+
const parts = [
|
|
9851
|
+
plan.kept.edges > 0 ? `${plan.kept.edges} with edges` : "",
|
|
9852
|
+
plan.kept.refuteTarget > 0 ? `${plan.kept.refuteTarget} refute checks of tasks still under mu task auto` : ""
|
|
9853
|
+
].filter((p) => p !== "");
|
|
9854
|
+
return parts.length > 0 ? `kept: ${parts.join(", ")}` : "";
|
|
9855
|
+
}
|
|
9856
|
+
async function cmdDelegatesPrune(db, opts) {
|
|
9857
|
+
if (opts.workstream !== void 0) await resolveExistingWorkstream(db, opts.workstream);
|
|
9858
|
+
const plan = planDelegatePrune(db, {
|
|
9859
|
+
...opts.olderThan !== void 0 ? { days: opts.olderThan } : {},
|
|
9860
|
+
...opts.workstream !== void 0 ? { workstream: opts.workstream } : {}
|
|
9861
|
+
});
|
|
9862
|
+
const n = plan.candidates.length;
|
|
9863
|
+
const files = plan.files.paths.length;
|
|
9864
|
+
const filesNote = files > 0 ? `, ${files} pi session(s) (${formatBytes(plan.files.bytes)})` : "";
|
|
9865
|
+
if (opts.yes === true && n === 0 && files === 0) {
|
|
9866
|
+
if (opts.json)
|
|
9867
|
+
return emitJson({ dryRun: false, ...plan, pruned: 0, deletedOps: 0, deletedFiles: 0 });
|
|
9868
|
+
console.log(pc.dim(`nothing to prune: no closed delegate task older than ${plan.days} days`));
|
|
9869
|
+
const kept2 = keptLine(plan);
|
|
9870
|
+
if (kept2) console.log(pc.dim(kept2));
|
|
9871
|
+
return;
|
|
9872
|
+
}
|
|
9873
|
+
if (opts.yes !== true) {
|
|
9874
|
+
if (opts.json) return emitJson({ dryRun: true, ...plan });
|
|
9875
|
+
if (n === 0 && files === 0)
|
|
9876
|
+
console.log(pc.dim(`nothing to prune: no closed delegate task older than ${plan.days} days`));
|
|
9877
|
+
else {
|
|
9878
|
+
const t = muTable({ head: ["TASK", "CALL", "CLOSED"] });
|
|
9879
|
+
for (const c of plan.candidates.slice(0, 20))
|
|
9880
|
+
t.push([`${c.workstream}/${c.task}`, c.callId, c.closedAt.slice(0, 10)]);
|
|
9881
|
+
console.log(t.toString());
|
|
9882
|
+
if (n > 20) console.log(pc.dim(`... and ${n - 20} more`));
|
|
9883
|
+
console.log(
|
|
9884
|
+
`${n} closed delegate task(s) older than ${plan.days} days: ${plan.ops} ops (${formatBytes(plan.bytes)})${filesNote}. Dry run; nothing changed (--yes applies; irreversible).`
|
|
9885
|
+
);
|
|
9886
|
+
if (!plan.ownHistory)
|
|
9887
|
+
console.log(
|
|
9888
|
+
pc.dim(
|
|
9889
|
+
"sync is on: the rows go everywhere, but this machine's own history stays (its segment is rebuilt from it)"
|
|
9890
|
+
)
|
|
9891
|
+
);
|
|
9892
|
+
}
|
|
9893
|
+
const kept2 = keptLine(plan);
|
|
9894
|
+
if (kept2) console.log(pc.dim(kept2));
|
|
9895
|
+
return;
|
|
9896
|
+
}
|
|
9897
|
+
if (n === 0) {
|
|
9898
|
+
const r2 = pruneDelegates(db, plan);
|
|
9899
|
+
if (opts.json)
|
|
9900
|
+
return emitJson({ dryRun: false, ...plan, pruned: 0, deletedOps: 0, deletedFiles: r2.files });
|
|
9901
|
+
console.log(`Pruned ${r2.files} pi session(s); no delegate task was old enough.`);
|
|
9902
|
+
return;
|
|
9903
|
+
}
|
|
9904
|
+
const backup = backupBeside(db, "prune");
|
|
9905
|
+
const r = pruneDelegates(db, plan);
|
|
9906
|
+
const size = vacuumAndCheck(db, backup);
|
|
9907
|
+
if (opts.json)
|
|
9908
|
+
return emitJson({
|
|
9909
|
+
dryRun: false,
|
|
9910
|
+
...plan,
|
|
9911
|
+
pruned: r.tasks,
|
|
9912
|
+
deletedOps: r.ops,
|
|
9913
|
+
deletedFiles: r.files,
|
|
9914
|
+
backup,
|
|
9915
|
+
...size
|
|
9916
|
+
});
|
|
9917
|
+
console.log(
|
|
9918
|
+
`Pruned ${r.tasks} delegate task(s), ${r.ops} ops${r.files > 0 ? `, ${r.files} pi session(s)` : ""}: ${formatBytes(size.before)} \u2192 ${formatBytes(size.after)}. Drift check clean.`
|
|
9919
|
+
);
|
|
9920
|
+
const kept = keptLine(plan);
|
|
9921
|
+
if (kept) console.log(pc.dim(kept));
|
|
9922
|
+
if (!size.checkpointed) console.log(pc.dim(CHECKPOINT_PENDING));
|
|
9923
|
+
console.log(pc.dim(`backup (the only way back): ${backup}`));
|
|
9924
|
+
}
|
|
9651
9925
|
async function cmdDelegatesReissue(_db, callId, _opts) {
|
|
9652
9926
|
throw new UsageError(
|
|
9653
9927
|
`reissue runs inside the pi session that owns the call: use ${reissueHint(callId)} there (a shell would leave it queued with nothing to start it)`,
|
|
@@ -9699,6 +9973,12 @@ function wireDelegatesCommands(program2) {
|
|
|
9699
9973
|
const opts = this.optsWithGlobals();
|
|
9700
9974
|
return handle((db) => cmdDelegatesRun(db, callId, opts), this)();
|
|
9701
9975
|
});
|
|
9976
|
+
d.command("prune").description(
|
|
9977
|
+
`Delete this machine's closed delegate tasks older than --older-than days (default ${PRUNE_DEFAULT_DAYS}) and their pi session files; the deletion syncs. Dry run without --yes; --yes backs up, VACUUMs, checks drift`
|
|
9978
|
+
).option("--older-than <days>", "age in days since the task closed", parsePositiveNumber).option("--yes", "apply (default: dry run)").option("-w, --workstream <name>", "only this workstream (default: every live one)").option(...JSON_OPT).action(function() {
|
|
9979
|
+
const opts = this.optsWithGlobals();
|
|
9980
|
+
return handle((db) => cmdDelegatesPrune(db, opts), this)();
|
|
9981
|
+
});
|
|
9702
9982
|
d.command("reissue <call-id>").description(
|
|
9703
9983
|
"Refuses: reissue a refused call with the `mu_delegate_reissue` tool in its pi session (only that runtime can start or drain it)"
|
|
9704
9984
|
).option(...JSON_OPT).action(function(callId) {
|
|
@@ -9708,15 +9988,15 @@ function wireDelegatesCommands(program2) {
|
|
|
9708
9988
|
}
|
|
9709
9989
|
|
|
9710
9990
|
// src/cli/doctor.ts
|
|
9711
|
-
import { dirname as
|
|
9991
|
+
import { dirname as dirname6 } from "path";
|
|
9712
9992
|
|
|
9713
9993
|
// src/doctor-summary.ts
|
|
9714
9994
|
import { accessSync, constants, existsSync as existsSync3, readFileSync as readFileSync2, realpathSync } from "fs";
|
|
9715
|
-
import { delimiter, dirname as
|
|
9995
|
+
import { delimiter, dirname as dirname5, join as join4, parse } from "path";
|
|
9716
9996
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9717
9997
|
function resolveExecutable(name) {
|
|
9718
9998
|
for (const dir of (process.env.PATH ?? "").split(delimiter).filter(Boolean)) {
|
|
9719
|
-
const candidate =
|
|
9999
|
+
const candidate = join4(dir, name);
|
|
9720
10000
|
try {
|
|
9721
10001
|
accessSync(candidate, constants.X_OK);
|
|
9722
10002
|
return realpathSync(candidate);
|
|
@@ -9726,10 +10006,10 @@ function resolveExecutable(name) {
|
|
|
9726
10006
|
return null;
|
|
9727
10007
|
}
|
|
9728
10008
|
function murmurVersion(executable) {
|
|
9729
|
-
let dir =
|
|
10009
|
+
let dir = dirname5(executable);
|
|
9730
10010
|
const root = parse(dir).root;
|
|
9731
10011
|
while (dir !== root) {
|
|
9732
|
-
const packagePath =
|
|
10012
|
+
const packagePath = join4(dir, "package.json");
|
|
9733
10013
|
if (existsSync3(packagePath)) {
|
|
9734
10014
|
try {
|
|
9735
10015
|
const pkg = JSON.parse(readFileSync2(packagePath, "utf8"));
|
|
@@ -9739,7 +10019,7 @@ function murmurVersion(executable) {
|
|
|
9739
10019
|
} catch {
|
|
9740
10020
|
}
|
|
9741
10021
|
}
|
|
9742
|
-
dir =
|
|
10022
|
+
dir = dirname5(dir);
|
|
9743
10023
|
}
|
|
9744
10024
|
return null;
|
|
9745
10025
|
}
|
|
@@ -9811,7 +10091,7 @@ function ctlExtensionDoctorCheck(reports) {
|
|
|
9811
10091
|
var DOCTOR_CTL_TIMEOUT_MS = 500;
|
|
9812
10092
|
function installedMuVersion() {
|
|
9813
10093
|
try {
|
|
9814
|
-
const pkgPath =
|
|
10094
|
+
const pkgPath = join4(dirname5(fileURLToPath2(import.meta.url)), "..", "package.json");
|
|
9815
10095
|
const pkg = JSON.parse(readFileSync2(pkgPath, "utf8"));
|
|
9816
10096
|
const v = typeof pkg === "object" && pkg !== null ? pkg.version : null;
|
|
9817
10097
|
return typeof v === "string" ? v : null;
|
|
@@ -10055,7 +10335,7 @@ async function cmdDoctor(db, opts = {}) {
|
|
|
10055
10335
|
console.log(` ${pad(fact.name)}: ${fact.value ? pc.green(fact.value) : pc.dim("not set")}`);
|
|
10056
10336
|
}
|
|
10057
10337
|
}
|
|
10058
|
-
const ctlSockets = await ctlSocketsDoctorCheck(listAgents(db), { stateDir:
|
|
10338
|
+
const ctlSockets = await ctlSocketsDoctorCheck(listAgents(db), { stateDir: dirname6(db.name) });
|
|
10059
10339
|
const muExt = ctlExtensionDoctorCheck(ctlSockets.agents);
|
|
10060
10340
|
printCheck("agent state", agentStateCheck(health, extensionLive(ctlSockets.agents)));
|
|
10061
10341
|
printCheck("mu ext", muExt);
|
|
@@ -10199,6 +10479,14 @@ state (workstream=${ws})`));
|
|
|
10199
10479
|
console.log("");
|
|
10200
10480
|
for (const line2 of dormant.remediation) console.log(` ${line2}`);
|
|
10201
10481
|
}
|
|
10482
|
+
const oldDelegates = checkOldDelegates(db);
|
|
10483
|
+
console.log(
|
|
10484
|
+
` ${oldDelegates.name.padEnd(16)} : ${oldDelegates.remediation === void 0 ? pc.green("ok") : pc.yellow("note")} ${pc.dim(oldDelegates.detail)}`
|
|
10485
|
+
);
|
|
10486
|
+
if (oldDelegates.remediation !== void 0) {
|
|
10487
|
+
console.log("");
|
|
10488
|
+
for (const line2 of oldDelegates.remediation) console.log(` ${line2}`);
|
|
10489
|
+
}
|
|
10202
10490
|
console.log(pc.bold("\ndisk"));
|
|
10203
10491
|
const disk = checkDiskRecon(db);
|
|
10204
10492
|
if (printHazards(disk)) sawHazard = true;
|
|
@@ -10301,7 +10589,7 @@ function opsSizeHint(db) {
|
|
|
10301
10589
|
}
|
|
10302
10590
|
async function cmdDoctorJson(db, opts = {}) {
|
|
10303
10591
|
const health = await muxHealth();
|
|
10304
|
-
const ctlSockets = await ctlSocketsDoctorCheck(listAgents(db), { stateDir:
|
|
10592
|
+
const ctlSockets = await ctlSocketsDoctorCheck(listAgents(db), { stateDir: dirname6(db.name) });
|
|
10305
10593
|
const muExt = ctlExtensionDoctorCheck(ctlSockets.agents);
|
|
10306
10594
|
const env = {
|
|
10307
10595
|
// `mux` is the backend-agnostic key. `tmux` is kept as an alias for
|
|
@@ -10410,7 +10698,16 @@ async function cmdDoctorJson(db, opts = {}) {
|
|
|
10410
10698
|
remediation: dormantHazard.remediation ?? [],
|
|
10411
10699
|
workstreams: findDormantWorkstreams(db, { currentWorkstream }),
|
|
10412
10700
|
thresholds: { finishedIdleDays: FINISHED_IDLE_DAYS, abandonedIdleDays: ABANDONED_IDLE_DAYS }
|
|
10413
|
-
}
|
|
10701
|
+
},
|
|
10702
|
+
oldDelegates: (() => {
|
|
10703
|
+
const h = checkOldDelegates(db);
|
|
10704
|
+
return {
|
|
10705
|
+
name: h.name,
|
|
10706
|
+
severity: h.severity,
|
|
10707
|
+
detail: h.detail,
|
|
10708
|
+
remediation: h.remediation ?? []
|
|
10709
|
+
};
|
|
10710
|
+
})()
|
|
10414
10711
|
};
|
|
10415
10712
|
const worktreeUsage = opts.disk === true ? measureWorktreeUsage(db) : null;
|
|
10416
10713
|
let drift;
|
|
@@ -10514,7 +10811,7 @@ function cmdHostAdd(db, name, opts) {
|
|
|
10514
10811
|
shell: opts.shell,
|
|
10515
10812
|
exec: opts.exec,
|
|
10516
10813
|
fetch: opts.fetch,
|
|
10517
|
-
repo: opts.repo,
|
|
10814
|
+
repo: opts.repo ?? null,
|
|
10518
10815
|
max_sessions: opts.maxSessions ?? null
|
|
10519
10816
|
});
|
|
10520
10817
|
if (isJsonMode()) {
|
|
@@ -10535,9 +10832,9 @@ function cmdHostList(db) {
|
|
|
10535
10832
|
}
|
|
10536
10833
|
const held = /* @__PURE__ */ new Map();
|
|
10537
10834
|
for (const c of listHostChannels(db)) held.set(c.host, (held.get(c.host) ?? 0) + 1);
|
|
10538
|
-
const t = muTable({ head: ["HOST", "REPO", "CHANNELS"] });
|
|
10835
|
+
const t = muTable({ head: ["HOST", "DEFAULT REPO", "CHANNELS"] });
|
|
10539
10836
|
for (const h of hosts) {
|
|
10540
|
-
t.push([h.name, h.repo, `${held.get(h.name) ?? 0}/${h.max_sessions ?? "\u221E"}`]);
|
|
10837
|
+
t.push([h.name, h.repo ?? "-", `${held.get(h.name) ?? 0}/${h.max_sessions ?? "\u221E"}`]);
|
|
10541
10838
|
}
|
|
10542
10839
|
console.log(t.toString());
|
|
10543
10840
|
}
|
|
@@ -10549,7 +10846,7 @@ function cmdHostShow(db, name) {
|
|
|
10549
10846
|
return;
|
|
10550
10847
|
}
|
|
10551
10848
|
console.log(
|
|
10552
|
-
`${pc.bold(host.name)} repo ${host.repo} max-sessions ${host.max_sessions ?? "none"}`
|
|
10849
|
+
`${pc.bold(host.name)} default repo ${host.repo ?? "-"} max-sessions ${host.max_sessions ?? "none"}`
|
|
10553
10850
|
);
|
|
10554
10851
|
for (const f of ["shell", "exec", "fetch"]) console.log(` ${f.padEnd(6)} ${host[f]}`);
|
|
10555
10852
|
console.log(
|
|
@@ -10580,7 +10877,6 @@ function cmdHostInit(name, opts) {
|
|
|
10580
10877
|
`--shell ${shellQuote(s.shell)}`,
|
|
10581
10878
|
`--exec ${shellQuote(s.exec)}`,
|
|
10582
10879
|
`--fetch ${shellQuote(s.fetch)}`,
|
|
10583
|
-
"--repo '<remote repo path>'",
|
|
10584
10880
|
"--max-sessions 1"
|
|
10585
10881
|
].join(" \\\n ");
|
|
10586
10882
|
if (isJsonMode()) {
|
|
@@ -10593,7 +10889,10 @@ function cmdHostInit(name, opts) {
|
|
|
10593
10889
|
}
|
|
10594
10890
|
async function cmdHostCheck(db, name, opts) {
|
|
10595
10891
|
const agent = opts.agent === void 0 ? void 0 : { name: opts.agent, workstream: await resolveWorkstream(opts.workstream) };
|
|
10596
|
-
const report = await checkHost(db, name,
|
|
10892
|
+
const report = await checkHost(db, name, {
|
|
10893
|
+
...agent !== void 0 ? { agent } : {},
|
|
10894
|
+
...opts.root !== void 0 ? { root: opts.root } : {}
|
|
10895
|
+
});
|
|
10597
10896
|
if (isJsonMode()) {
|
|
10598
10897
|
if (!report.ok) throw failureWithData(failedError(report), report);
|
|
10599
10898
|
emitJson(report);
|
|
@@ -10617,7 +10916,10 @@ function wireHostCommands(program2) {
|
|
|
10617
10916
|
);
|
|
10618
10917
|
host.command("add <name>").description(
|
|
10619
10918
|
"Store a machine-local host profile of command templates: --shell opens the pane, --exec runs one remote command, --fetch brings commits home. Placeholders {env} {cmd} {local_sock} {remote_sock} {cwd}; grammar in docs/guide/remote.md."
|
|
10620
|
-
).requiredOption("--shell <template>", "pane command template (opens the remote shell)").requiredOption("--exec <template>", "template that runs one remote command ({cmd})").requiredOption("--fetch <template>", "local template that fetches commits home ({cwd})").
|
|
10919
|
+
).requiredOption("--shell <template>", "pane command template (opens the remote shell)").requiredOption("--exec <template>", "template that runs one remote command ({cmd})").requiredOption("--fetch <template>", "local template that fetches commits home ({cwd})").option(
|
|
10920
|
+
"--repo <path>",
|
|
10921
|
+
"default remote repo for `agent spawn --host` without --root (a profile names a machine, not a repo)"
|
|
10922
|
+
).option(
|
|
10621
10923
|
"--max-sessions <n>",
|
|
10622
10924
|
"cap on channels mu holds to this host at once (panes, --exec, --fetch)",
|
|
10623
10925
|
parseNonNegativeInt
|
|
@@ -10641,8 +10943,8 @@ function wireHostCommands(program2) {
|
|
|
10641
10943
|
return handle(async () => cmdHostInit(name, opts), this)();
|
|
10642
10944
|
});
|
|
10643
10945
|
host.command("check <name>").description(
|
|
10644
|
-
"Run the profile's --exec under one channel: host answers, repo is git, pi runs, `pi list` names mu. --agent also probes that agent's
|
|
10645
|
-
).option("--agent <name>", "also probe this agent's control socket (the forward rides its pane)").option(...WORKSTREAM_OPT).option(...JSON_OPT).action(function(name) {
|
|
10946
|
+
"Run the profile's --exec under one channel: host answers, the repo (--root, else the default) is git, pi runs, `pi list` names mu. --agent also probes that agent's control socket. Exit 5 if a step fails; retries nothing."
|
|
10947
|
+
).option("--agent <name>", "also probe this agent's control socket (the forward rides its pane)").option("--root <path>", "the remote repo the repo step checks (default: the profile's)").option(...WORKSTREAM_OPT).option(...JSON_OPT).action(function(name) {
|
|
10646
10948
|
const opts = this.optsWithGlobals();
|
|
10647
10949
|
return handle((db) => cmdHostCheck(db, name, opts), this)();
|
|
10648
10950
|
});
|
|
@@ -11994,8 +12296,8 @@ function emitJsonCollection(items) {
|
|
|
11994
12296
|
}
|
|
11995
12297
|
function readPackageVersion() {
|
|
11996
12298
|
try {
|
|
11997
|
-
const here =
|
|
11998
|
-
const pkgPath =
|
|
12299
|
+
const here = dirname7(fileURLToPath3(import.meta.url));
|
|
12300
|
+
const pkgPath = join5(here, "..", "package.json");
|
|
11999
12301
|
const raw = readFileSync3(pkgPath, "utf8");
|
|
12000
12302
|
const parsed = JSON.parse(raw);
|
|
12001
12303
|
return typeof parsed.version === "string" ? parsed.version : "unknown";
|
|
@@ -12170,4 +12472,4 @@ export {
|
|
|
12170
12472
|
truncate,
|
|
12171
12473
|
truncateFront
|
|
12172
12474
|
};
|
|
12173
|
-
//# sourceMappingURL=cli-
|
|
12475
|
+
//# sourceMappingURL=cli-H2PWJAJN.js.map
|