@mu-crew/mu 3.3.0 → 3.4.0

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.
Files changed (43) hide show
  1. package/README.md +45 -31
  2. package/dist/cli.js +186 -20
  3. package/dist/cli.js.map +1 -1
  4. package/dist/extension/mu-pi.js +103 -74
  5. package/dist/extension/mu-pi.js.map +1 -1
  6. package/dist/index.d.ts +33 -4
  7. package/dist/index.js +70 -4
  8. package/dist/index.js.map +1 -1
  9. package/docs/VISION.md +3 -1
  10. package/docs/VOCABULARY.md +4 -1
  11. package/docs/architecture/dag.md +3 -3
  12. package/docs/guide/delegate.md +30 -3
  13. package/docs/reference/env.md +1 -0
  14. package/docs/reference/naming.md +18 -0
  15. package/docs/specs/2026-09-29-task-substates.md +1 -1
  16. package/package.json +1 -1
  17. package/prompts/mu-debug.md +8 -0
  18. package/prompts/mu-sweep.md +8 -0
  19. package/prompts/mu-until.md +8 -0
  20. package/prompts/ultrathink.md +2 -1
  21. package/skills/mu/SKILL.md +70 -31
  22. package/skills/mu/recipes/adversarial-review.md +27 -19
  23. package/skills/mu/recipes/{triage.md → backlog-triage.md} +9 -4
  24. package/skills/mu/recipes/codemode-driver.md +68 -20
  25. package/skills/mu/recipes/deep-research.md +23 -8
  26. package/skills/mu/recipes/fan-out.md +15 -11
  27. package/skills/mu/recipes/findings.md +103 -0
  28. package/skills/mu/recipes/hypothesis-panel.md +18 -13
  29. package/skills/mu/recipes/long-run.md +4 -4
  30. package/skills/mu/recipes/loop-until-done.md +7 -3
  31. package/skills/mu/recipes/orchestrator-loop.md +38 -27
  32. package/skills/mu/recipes/plan.md +8 -3
  33. package/skills/mu/recipes/recovery.md +2 -0
  34. package/skills/mu/recipes/refute.md +38 -36
  35. package/skills/mu/recipes/remote-workers.md +7 -2
  36. package/skills/mu/recipes/review-panel.md +36 -31
  37. package/skills/mu/recipes/rules-audit.md +30 -17
  38. package/skills/mu/recipes/tasks-or-calls.md +67 -0
  39. package/skills/mu/recipes/tournament.md +13 -10
  40. package/skills/mu/recipes/ultrathink.md +20 -11
  41. package/skills/mu/recipes/watcher.md +4 -1
  42. package/skills/mu/recipes/waves.md +6 -5
  43. package/skills/mu/recipes/worker.md +3 -1
package/dist/index.js CHANGED
@@ -359,7 +359,7 @@ function isTaskStatus(s) {
359
359
  }
360
360
  var TASK_STATUS_LIST = TASK_STATUSES.join(" | ");
361
361
  var TASK_SUBSTATES = {
362
- OPEN: ["todo", "parked"],
362
+ OPEN: ["todo", "parked", "triage"],
363
363
  IN_PROGRESS: ["active"],
364
364
  CLOSED: ["done", "rejected", "wontfix", "duplicate", "superseded"]
365
365
  };
@@ -590,7 +590,7 @@ CREATE VIEW ready AS
590
590
  SELECT t.*
591
591
  FROM tasks t
592
592
  WHERE t.status = 'OPEN'
593
- AND t.substate <> 'parked'
593
+ AND t.substate NOT IN ('parked', 'triage')
594
594
  AND NOT EXISTS (
595
595
  SELECT 1
596
596
  FROM task_edges e
@@ -4560,6 +4560,30 @@ var TaskParkStateError = class extends Error {
4560
4560
  ];
4561
4561
  }
4562
4562
  };
4563
+ var TaskInTriageError = class extends Error {
4564
+ constructor(taskId, workstream) {
4565
+ super(`task ${taskId} is in triage (OPEN/triage); accept it or claim with --force`);
4566
+ this.taskId = taskId;
4567
+ this.workstream = workstream;
4568
+ }
4569
+ taskId;
4570
+ workstream;
4571
+ name = "TaskInTriageError";
4572
+ errorNextSteps() {
4573
+ const ws = this.workstream;
4574
+ return [
4575
+ {
4576
+ intent: "Accept it as work, then claim",
4577
+ command: `mu task accept ${this.taskId} -w ${ws}`
4578
+ },
4579
+ {
4580
+ intent: "Decline it",
4581
+ command: `mu task close ${this.taskId} --as rejected --why "<reason>" -w ${ws}`
4582
+ },
4583
+ { intent: "Claim it anyway", command: `mu task claim ${this.taskId} --force -w ${ws}` }
4584
+ ];
4585
+ }
4586
+ };
4563
4587
  var TaskParkedError = class extends Error {
4564
4588
  constructor(taskId, workstream) {
4565
4589
  super(`task ${taskId} is parked (OPEN/parked); unpark it or claim with --force`);
@@ -5015,8 +5039,17 @@ function addTaskImpl(db, opts) {
5015
5039
  const now = (/* @__PURE__ */ new Date()).toISOString();
5016
5040
  const insertResult = db.prepare(
5017
5041
  `INSERT INTO tasks (workstream_id, local_id, title, status, substate, impact, effort_days, created_at, updated_at)
5018
- VALUES (?, ?, ?, 'OPEN', 'todo', ?, ?, ?, ?)`
5019
- ).run(wsId, opts.localId, opts.title, opts.impact, opts.effortDays, now, now);
5042
+ VALUES (?, ?, ?, 'OPEN', ?, ?, ?, ?, ?)`
5043
+ ).run(
5044
+ wsId,
5045
+ opts.localId,
5046
+ opts.title,
5047
+ opts.triage === true ? "triage" : "todo",
5048
+ opts.impact,
5049
+ opts.effortDays,
5050
+ now,
5051
+ now
5052
+ );
5020
5053
  const newTaskId = Number(insertResult.lastInsertRowid);
5021
5054
  if (opts.blockedBy && opts.blockedBy.length > 0) {
5022
5055
  const blockerLookupSameWs = db.prepare(
@@ -5291,6 +5324,28 @@ function parkTask(db, localId, opts) {
5291
5324
  })()
5292
5325
  );
5293
5326
  }
5327
+ function acceptTask(db, localId, opts) {
5328
+ return withOpContext(
5329
+ db,
5330
+ { intent: "task.accept", group: "new" },
5331
+ () => db.transaction(() => {
5332
+ const before = getTask(db, localId, opts.workstream);
5333
+ if (!before) throw new TaskNotFoundError(localId);
5334
+ if (before.status !== "OPEN" || before.substate !== "triage") {
5335
+ return {
5336
+ previousStatus: before.status,
5337
+ status: before.status,
5338
+ previousSubstate: before.substate,
5339
+ substate: before.substate,
5340
+ changed: false
5341
+ };
5342
+ }
5343
+ const r = setTaskStatus(db, localId, "OPEN", { workstream: opts.workstream });
5344
+ recordEvidenceNote(db, localId, before.workstreamName, "ACCEPT", opts);
5345
+ return r;
5346
+ })()
5347
+ );
5348
+ }
5294
5349
  function unparkTask(db, localId, opts) {
5295
5350
  return withOpContext(
5296
5351
  db,
@@ -5421,6 +5476,9 @@ function assertNotParked(task, opts) {
5421
5476
  if (task.status === "OPEN" && task.substate === "parked" && opts.force !== true) {
5422
5477
  throw new TaskParkedError(task.name, task.workstreamName);
5423
5478
  }
5479
+ if (task.status === "OPEN" && task.substate === "triage" && opts.force !== true) {
5480
+ throw new TaskInTriageError(task.name, task.workstreamName);
5481
+ }
5424
5482
  }
5425
5483
  async function resolveActorIdentity() {
5426
5484
  const worker = await resolveWorkerIdentity();
@@ -10022,6 +10080,10 @@ async function loadWorkstreamSnapshotFast(db, workstream, opts = {}) {
10022
10080
  blocked: listBlocked(db, workstream),
10023
10081
  recentClosed: listRecentClosed(db, workstream),
10024
10082
  parkedCount: listTasks(db, workstream, { status: "OPEN", substate: "parked" }).length,
10083
+ triage: listTasks(db, workstream, { status: "OPEN", substate: "triage" }),
10084
+ taskCount: db.prepare(
10085
+ "SELECT count(*) AS n FROM tasks t JOIN workstreams w ON w.id = t.workstream_id WHERE w.name = ?"
10086
+ ).get(workstream).n,
10025
10087
  allTasks: opts.withAllTasks === true ? listTasks(db, workstream) : [],
10026
10088
  workspaces: listWorkspaces2(db, workstream),
10027
10089
  workspaceOrphans: listWorkspaceOrphans(db, workstream),
@@ -10095,6 +10157,8 @@ function minimalSnapshot(workstream) {
10095
10157
  blocked: [],
10096
10158
  recentClosed: [],
10097
10159
  parkedCount: 0,
10160
+ triage: [],
10161
+ taskCount: 0,
10098
10162
  allTasks: [],
10099
10163
  workspaces: [],
10100
10164
  workspaceOrphans: [],
@@ -10991,6 +11055,7 @@ export {
10991
11055
  TASK_SUBSTATE_ROWS,
10992
11056
  TaskAlreadyOwnedError,
10993
11057
  TaskExistsError,
11058
+ TaskInTriageError,
10994
11059
  TaskNotFoundError,
10995
11060
  TaskNotInWorkstreamError,
10996
11061
  TaskParkStateError,
@@ -11007,6 +11072,7 @@ export {
11007
11072
  WorkstreamExistsError,
11008
11073
  WorkstreamNameInvalidError,
11009
11074
  abortAgent,
11075
+ acceptTask,
11010
11076
  activeMux,
11011
11077
  addBlockEdge,
11012
11078
  addNote,