@mu-crew/mu 3.5.0 → 3.6.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/dist/cli.js CHANGED
@@ -5188,6 +5188,7 @@ function mapMurmurState(token, since) {
5188
5188
  break;
5189
5189
  case "idle":
5190
5190
  case "done":
5191
+ case "error":
5191
5192
  case "crashed":
5192
5193
  state = "needs_input";
5193
5194
  break;
@@ -5241,7 +5242,7 @@ function remoteReading(agent, panes) {
5241
5242
  (entry) => typeof entry === "object" && entry !== null && "kind" in entry && typeof entry.kind === "string" ? [entry.kind] : []
5242
5243
  )
5243
5244
  ) : /* @__PURE__ */ new Set();
5244
- const state = kinds.has("crashed") ? "needs_input" : kinds.has("blocked") ? "needs_permission" : kinds.has("done") ? "needs_input" : row2.activity === "running" ? "busy" : "needs_input";
5245
+ const state = kinds.has("crashed") || kinds.has("error") ? "needs_input" : kinds.has("blocked") ? "needs_permission" : kinds.has("done") ? "needs_input" : row2.activity === "running" ? "busy" : "needs_input";
5245
5246
  return {
5246
5247
  state,
5247
5248
  source: "murmur",
@@ -7345,7 +7346,7 @@ async function waitForTasks(db, input, opts) {
7345
7346
  const wantAny = opts.any === true;
7346
7347
  const timeoutMs = opts.timeoutMs ?? 6e5;
7347
7348
  const pollMs = opts.pollMs ?? 1e3;
7348
- const stuckAfterMs = opts.stuckAfterMs ?? 3e5;
7349
+ const stuckAfterMs = opts.stuckAfterMs ?? DEFAULT_STUCK_AFTER_MS;
7349
7350
  const onStall = opts.onStall ?? "warn";
7350
7351
  const deadline = timeoutMs > 0 ? Date.now() + timeoutMs : Number.POSITIVE_INFINITY;
7351
7352
  for (const ref of refs) {
@@ -7450,7 +7451,7 @@ async function waitForTasks(db, input, opts) {
7450
7451
  if (isDone(snap)) return snap;
7451
7452
  }
7452
7453
  }
7453
- var currentWaitSleep, pollCount, defaultStuckWarn, currentStuckWarn;
7454
+ var currentWaitSleep, pollCount, DEFAULT_STUCK_AFTER_MS, defaultStuckWarn, currentStuckWarn;
7454
7455
  var init_wait = __esm({
7455
7456
  "src/tasks/wait.ts"() {
7456
7457
  "use strict";
@@ -7460,6 +7461,7 @@ var init_wait = __esm({
7460
7461
  init_status();
7461
7462
  currentWaitSleep = (ms) => new Promise((resolve9) => setTimeout(resolve9, ms));
7462
7463
  pollCount = 0;
7464
+ DEFAULT_STUCK_AFTER_MS = 12e4;
7463
7465
  defaultStuckWarn = (msg) => {
7464
7466
  process.stderr.write(msg);
7465
7467
  };
@@ -19402,7 +19404,7 @@ async function cmdTaskWait(db, ids, opts) {
19402
19404
  if (ids.length === 0) {
19403
19405
  throw new UsageError("mu task wait: at least one task id is required");
19404
19406
  }
19405
- const onStallRaw = opts.onStall ?? "warn";
19407
+ const onStallRaw = opts.onStall ?? "exit";
19406
19408
  if (onStallRaw !== "warn" && onStallRaw !== "exit") {
19407
19409
  throw new UsageError(`--on-stall: expected 'warn' or 'exit', got '${onStallRaw}'`);
19408
19410
  }
@@ -19415,7 +19417,7 @@ async function cmdTaskWait(db, ids, opts) {
19415
19417
  }
19416
19418
  const workstreamSet = new Set(refs.map((r) => r.workstreamName));
19417
19419
  const timeoutMs = opts.timeout !== void 0 ? opts.timeout * 1e3 : 6e5;
19418
- const stuckAfterMs = opts.stuckAfter !== void 0 ? opts.stuckAfter * 1e3 : 3e5;
19420
+ const stuckAfterMs = opts.stuckAfter !== void 0 ? opts.stuckAfter * 1e3 : DEFAULT_STUCK_AFTER_MS;
19419
19421
  const sdkOpts = { timeoutMs, stuckAfterMs };
19420
19422
  if (statusOpt !== void 0) sdkOpts.status = statusOpt;
19421
19423
  if (wantAny) sdkOpts.any = true;
@@ -20170,7 +20172,7 @@ function wireTaskCommands(program) {
20170
20172
  return handle((db) => cmdTaskReparent(db, id, opts), this)();
20171
20173
  });
20172
20174
  task.command("wait <ids...>").description(
20173
- "Block until the listed tasks reach --status (default CLOSED). Each <id> may be bare (resolves via -w / $MU_SESSION / tmux) or qualified `<workstream>/<name>` (cross-workstream waits don't need -w). Default: every task must reach the target (--all). --any / --first exit on the first one that does; --first additionally prints the firing ref's qualified id to stdout. For unattended waits, pass --on-stall exit so a worker needing attention terminates the wait with exit 7. Exit 0 = condition met; 5 = timeout; 6 = a watched task was reaper-flipped IN_PROGRESS\u2192OPEN (target=CLOSED only); 7 = a worker needs attention (--on-stall exit)."
20175
+ "Block until the listed tasks reach --status (default CLOSED). Each <id> may be bare (resolves via -w / $MU_SESSION / tmux) or qualified `<workstream>/<name>` (cross-workstream waits don't need -w). Default: every task must reach the target (--all). --any / --first exit on the first one that does; --first additionally prints the firing ref's qualified id to stdout. A worker needing attention terminates the wait with exit 7 (--on-stall exit, the default). Exit 0 = condition met; 5 = timeout; 6 = a watched task was reaper-flipped IN_PROGRESS\u2192OPEN (target=CLOSED only); 7 = a worker needs attention (target=CLOSED, unless --on-stall warn)."
20174
20176
  ).option(
20175
20177
  "--status <status>",
20176
20178
  `target status (${TASK_STATUS_LIST}, case-insensitive); default CLOSED`
@@ -20179,14 +20181,14 @@ function wireTaskCommands(program) {
20179
20181
  "succeed as soon as ONE listed task reaches the target (default: all must). Reports THAT one fired, not which: --json leaves `firing` null even on success, so use --first if you need to identify the ref."
20180
20182
  ).option(
20181
20183
  "--first",
20182
- "alias for --any that ALSO prints the firing ref's qualified id to stdout and populates `firing` in --json (which --any leaves null). Use to drive a single-shot dispatch loop: `closed=$(mu task wait a b --first --on-stall exit --json | jq -r .firing.qualifiedId)`."
20184
+ "alias for --any that ALSO prints the firing ref's qualified id to stdout and populates `firing` in --json (which --any leaves null). Use to drive a single-shot dispatch loop: `closed=$(mu task wait a b --first --json | jq -r .firing.qualifiedId)`."
20183
20185
  ).option("--timeout <seconds>", "max seconds to wait (0 = forever, default 600)", parseLines).option(
20184
20186
  "--stuck-after <seconds>",
20185
- "the TRIGGER: mark an IN_PROGRESS task as needing attention when its owner has been in needs_input for >= N seconds since their last status change (0 = disable, default 300). needs_input has several causes \u2014 the worker may have finished without closing, be waiting on an answer, or be sitting at a prompt \u2014 so the warning names the observation and points at `mu agent read <owner>`, which is the next move in every case. The default ACTION is `warn` (keep polling); see --on-stall exit to terminate the wait instead.",
20187
+ "the TRIGGER: mark an IN_PROGRESS task as needing attention when its owner has been in needs_input for >= N seconds since their last status change (0 = disable, default 120). needs_input has several causes \u2014 the worker may have finished without closing, be waiting on an answer, or be sitting at a prompt \u2014 so the warning names the observation and points at `mu agent read <owner>`, which is the next move in every case. The default ACTION is `exit` (exit 7); see --on-stall warn to keep polling instead.",
20186
20188
  parseLines
20187
20189
  ).option(
20188
20190
  "--on-stall <action>",
20189
- "the ACTION when --stuck-after fires: 'warn' (default; yellow attention warning naming the owner + age, plus a corroborating agent_logs event; wait keeps polling) or 'exit' (same emit + persist, then exit 7 = STALL_DETECTED so an unattended orchestrator can branch on the idle-vs-dead distinction). Suppressed when --status is anything other than CLOSED (mirrors exit-6's carve-out). If exit-6 (dead pane) and exit-7 (stall) would fire in the same poll, exit 6 wins (dead pane is unambiguous; stall is ambiguous)."
20191
+ "the ACTION when --stuck-after fires: 'exit' (default; yellow attention warning naming the owner + age, plus a corroborating agent_logs event, then exit 7 = STALL_DETECTED so an orchestrator can branch on the idle-vs-dead distinction) or 'warn' (same emit + persist; wait keeps polling). Suppressed when --status is anything other than CLOSED (mirrors exit-6's carve-out). If exit-6 (dead pane) and exit-7 (stall) would fire in the same poll, exit 6 wins (dead pane is unambiguous; stall is ambiguous)."
20190
20192
  ).option(...WORKSTREAM_OPT).option(...JSON_OPT).action(function(ids) {
20191
20193
  const opts = this.opts();
20192
20194
  return handle((db) => cmdTaskWait(db, ids, opts), this)();