@dunnewold-labs/mr-manager 0.4.55 → 0.4.56

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 (2) hide show
  1. package/dist/index.mjs +392 -157
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // cli/index.ts
4
- import { Command as Command34 } from "commander";
4
+ import { Command as Command37 } from "commander";
5
5
  import { existsSync as existsSync19 } from "fs";
6
6
  import { homedir as homedir3 } from "os";
7
7
  import { join as join12 } from "path";
@@ -185,7 +185,7 @@ import { fileURLToPath } from "url";
185
185
  // cli/package.json
186
186
  var package_default = {
187
187
  name: "@dunnewold-labs/mr-manager",
188
- version: "0.4.55",
188
+ version: "0.4.56",
189
189
  description: "Mr. Manager - Task and project management CLI",
190
190
  bin: {
191
191
  mr: "./dist/index.mjs"
@@ -1415,6 +1415,22 @@ function tokenLogLine(jobType, identifier, prompt2, systemPrompt) {
1415
1415
  return parts[0];
1416
1416
  }
1417
1417
 
1418
+ // cli/watch-options.ts
1419
+ var EXECUTION_SYSTEM_SECTIONS = [
1420
+ "status-updates",
1421
+ "screenshots",
1422
+ "no-mr",
1423
+ "features-workflow"
1424
+ ];
1425
+ var TEST_PLAN_SYSTEM_SECTIONS = ["test-plan", "mr-tests"];
1426
+ function getExecutionSystemSections(includeTestPlan) {
1427
+ return [
1428
+ "quiet-mode",
1429
+ ...EXECUTION_SYSTEM_SECTIONS,
1430
+ ...includeTestPlan ? TEST_PLAN_SYSTEM_SECTIONS : []
1431
+ ];
1432
+ }
1433
+
1418
1434
  // cli/commands/watch.ts
1419
1435
  var FEATURES_FILE2 = ".mr-features.md";
1420
1436
  var SYSTEM_SECTION_STATUS_UPDATES = `## Status Updates
@@ -1561,7 +1577,6 @@ var SYSTEM_SECTIONS = {
1561
1577
  function composeSystemPrompt(sections) {
1562
1578
  return sections.map((s) => SYSTEM_SECTIONS[s]).join("\n\n");
1563
1579
  }
1564
- var EXECUTION_SYSTEM_SECTIONS = ["status-updates", "screenshots", "test-plan", "mr-tests", "no-mr", "features-workflow"];
1565
1580
  var PRD_SYSTEM_SECTIONS = ["prd-format", "prd-open-questions"];
1566
1581
  var c = {
1567
1582
  reset: "\x1B[0m",
@@ -3123,13 +3138,14 @@ function spawnAgent(agent, repoDir, prompt2, prefix, onActivity, sessionId, name
3123
3138
  }
3124
3139
  var watchCommand = new Command9("watch").description(
3125
3140
  "Watch for in-progress tasks and autonomously dispatch an AI coding agent to work on them"
3126
- ).option("--interval <seconds>", "Polling interval in seconds", "15").option("--dry-run", "Show what would be dispatched without spawning the agent", false).option("--plan-approval", "Show the agent's plan and ask for approval before executing", false).option("--root <dir>", "Root directory filter for linked repos (default: cwd)").option("--agent <agent>", "AI agent to use: claude, codex, or antigravity", "claude").option("--scan-at <HH:MM>", "Run a product scan daily at this time (e.g., 02:00)").action(async (opts) => {
3141
+ ).option("--interval <seconds>", "Polling interval in seconds", "15").option("--dry-run", "Show what would be dispatched without spawning the agent", false).option("--plan-approval", "Show the agent's plan and ask for approval before executing", false).option("--root <dir>", "Root directory filter for linked repos (default: cwd)").option("--agent <agent>", "AI agent to use: claude, codex, or antigravity", "claude").option("--scan-at <HH:MM>", "Run a product scan daily at this time (e.g., 02:00)").option("--test-plan", "Ask build agents to create a structured browser test plan", false).action(async (opts) => {
3127
3142
  const intervalMs = parseInt(opts.interval, 10) * 1e3;
3128
3143
  const dryRun = opts.dryRun;
3129
3144
  const planApproval = opts.planApproval;
3130
3145
  const rootDir = opts.root ? resolve2(opts.root) : process.cwd();
3131
3146
  const agent = opts.agent === "codex" ? "codex" : opts.agent === "antigravity" ? "antigravity" : "claude";
3132
3147
  const scanAt = opts.scanAt;
3148
+ const includeTestPlan = opts.testPlan;
3133
3149
  const taskStallTimeoutMs = getTaskStallTimeoutMs();
3134
3150
  const hungTaskTimeoutMinutes = Math.max(5, parseInt(process.env.MR_WATCH_HUNG_TASK_TIMEOUT_MINUTES ?? "60", 10) || 60);
3135
3151
  const hungTaskTimeoutMs = hungTaskTimeoutMinutes * 6e4;
@@ -3151,6 +3167,7 @@ var watchCommand = new Command9("watch").description(
3151
3167
  ...planApproval ? [paint("yellow", "plan-approval")] : [],
3152
3168
  ...dryRun ? [paint("yellow", "dry-run")] : [],
3153
3169
  ...scanAt ? [`scan-at=${paint("cyan", scanAt)}`] : [],
3170
+ ...includeTestPlan ? [paint("yellow", "test-plan")] : [],
3154
3171
  `hung-timeout=${paint("cyan", `${hungTaskTimeoutMinutes}m`)}`
3155
3172
  ].join(" ");
3156
3173
  const banner = [
@@ -3385,7 +3402,7 @@ var watchCommand = new Command9("watch").description(
3385
3402
  const shouldResumeClaudeSession = attemptAgent === "claude" && !!task.claudeSessionId && !resumeAlreadyRetried && (hasFeedback || pausedForNetwork?.resumeSession === true);
3386
3403
  const sessionId = attemptAgent === "claude" ? shouldResumeClaudeSession ? task.claudeSessionId : randomUUID() : void 0;
3387
3404
  const effectiveClaudeModel = attemptAgent === "claude" ? taskClaudeModel : void 0;
3388
- const systemSections = ["quiet-mode", ...EXECUTION_SYSTEM_SECTIONS];
3405
+ const systemSections = getExecutionSystemSections(includeTestPlan);
3389
3406
  const executionSystemPrompt = composeSystemPrompt(systemSections);
3390
3407
  const child = spawnAgent(
3391
3408
  attemptAgent,
@@ -4143,6 +4160,7 @@ var watchCommand = new Command9("watch").description(
4143
4160
  function dispatchCodeReview(review, prefix, key) {
4144
4161
  logDispatch(prefix, `Running code review on branch ${paint("cyan", review.branch)}`);
4145
4162
  const reviewArgs = [process.argv[1], "review", "--project", review.projectId, "--report", review.id, "--branch", review.branch, "--base", review.baseBranch];
4163
+ if (review.depth) reviewArgs.push("--depth", review.depth);
4146
4164
  if (review.branchUrl) reviewArgs.push("--pr-url", review.branchUrl);
4147
4165
  if (review.prNumber != null) reviewArgs.push("--pr-number", String(review.prNumber));
4148
4166
  const reviewProc = spawn4(process.execPath, reviewArgs, {
@@ -4980,9 +4998,125 @@ var completeCommand = new Command12("complete").description("Mark a task as comp
4980
4998
  printTaskBanner2(paint3("green", "complete \u2713"), task.title, task.id);
4981
4999
  });
4982
5000
 
4983
- // cli/commands/subtask-complete.ts
5001
+ // cli/commands/show.ts
4984
5002
  import { Command as Command13 } from "commander";
4985
- var subtaskCompleteCommand = new Command13("subtask-complete").description("Mark a subtask as completed").argument("<task-id>", "Parent task ID").argument("<subtask-id>", "Subtask ID to complete").action(async (taskId, subtaskId) => {
5003
+ var showCommand = new Command13("show").description("Show a single task").argument("<task-id>", "Task ID to show").option("--json", "Output raw JSON").option(
5004
+ "--include <fields>",
5005
+ "Comma-separated relations to include (e.g. project,resources)"
5006
+ ).action(async (taskId, opts) => {
5007
+ let path = `/api/tasks/${taskId}`;
5008
+ if (opts.include) {
5009
+ path += `?include=${encodeURIComponent(opts.include)}`;
5010
+ }
5011
+ const task = await api.get(path);
5012
+ if (opts.json) {
5013
+ console.log(JSON.stringify(task, null, 2));
5014
+ return;
5015
+ }
5016
+ const c15 = {
5017
+ reset: "\x1B[0m",
5018
+ bold: "\x1B[1m",
5019
+ dim: "\x1B[2m",
5020
+ cyan: "\x1B[36m"
5021
+ };
5022
+ const row = (label, value) => {
5023
+ if (value == null || value === "") return;
5024
+ console.log(`${c15.dim}${label.padEnd(14)}${c15.reset}${value}`);
5025
+ };
5026
+ console.log(`${c15.bold}${c15.cyan}${task.title}${c15.reset} ${c15.dim}(${task.id})${c15.reset}`);
5027
+ row("Status", task.status);
5028
+ row("Mode", task.mode);
5029
+ row("Project", task.projectId);
5030
+ row("Due", task.dueDate);
5031
+ row("Jira", task.jiraTicketKey);
5032
+ row("Branch", task.attachedBranch);
5033
+ row("Link", task.link ?? task.attachedBranchLink);
5034
+ row("Auto-merge", task.autoMergeEnabled ? "enabled" : void 0);
5035
+ row("Created", task.createdAt);
5036
+ row("Completed", task.completedAt);
5037
+ if (task.notes) {
5038
+ console.log(`${c15.dim}Notes${c15.reset}`);
5039
+ console.log(task.notes);
5040
+ }
5041
+ });
5042
+
5043
+ // cli/commands/edit.ts
5044
+ import { Command as Command14 } from "commander";
5045
+ var VALID_STATUSES = [
5046
+ "todo",
5047
+ "in_progress",
5048
+ "queued",
5049
+ "delegated",
5050
+ "review",
5051
+ "completed",
5052
+ "error"
5053
+ ];
5054
+ var VALID_MODES = ["development", "planning", "testing"];
5055
+ var editCommand = new Command14("edit").description("Update fields on an existing task").argument("<task-id>", "Task ID to update").option("--title <title>", "New task title").option("--notes <notes>", "New task notes").option("--status <status>", `New status (${VALID_STATUSES.join(", ")})`).option("--mode <mode>", `New mode (${VALID_MODES.join(", ")})`).option("--due-date <date>", "Due date (ISO string), or 'none' to clear").option("--link <url>", "Task link, or 'none' to clear").option("--jira <key>", "Jira ticket key, or 'none' to clear").option("--branch <input>", "Attached branch name or PR/MR URL, or 'none' to clear").option("--auto-merge <bool>", "Enable/disable auto-merge (true/false)").action(async (taskId, opts) => {
5056
+ const body = {};
5057
+ if (opts.title != null) body.title = opts.title;
5058
+ if (opts.notes != null) body.notes = opts.notes;
5059
+ if (opts.status != null) {
5060
+ if (!VALID_STATUSES.includes(opts.status)) {
5061
+ console.error(`Invalid status. Must be one of: ${VALID_STATUSES.join(", ")}`);
5062
+ process.exit(1);
5063
+ }
5064
+ body.status = opts.status;
5065
+ }
5066
+ if (opts.mode != null) {
5067
+ if (!VALID_MODES.includes(opts.mode)) {
5068
+ console.error(`Invalid mode. Must be one of: ${VALID_MODES.join(", ")}`);
5069
+ process.exit(1);
5070
+ }
5071
+ body.mode = opts.mode;
5072
+ }
5073
+ const clearable = (v) => v.toLowerCase() === "none" ? null : v;
5074
+ if (opts.dueDate != null) body.dueDate = clearable(opts.dueDate);
5075
+ if (opts.link != null) body.link = clearable(opts.link);
5076
+ if (opts.jira != null) body.jiraTicketKey = clearable(opts.jira);
5077
+ if (opts.branch != null) body.attachedBranchInput = clearable(opts.branch) ?? "";
5078
+ if (opts.autoMerge != null) body.autoMergeEnabled = opts.autoMerge === "true";
5079
+ if (Object.keys(body).length === 0) {
5080
+ console.error("No fields to update. Pass at least one option (e.g. --title, --status).");
5081
+ process.exit(1);
5082
+ }
5083
+ const task = await api.patch(`/api/tasks/${taskId}`, body);
5084
+ console.log(`\u2713 Updated: ${task.title} (${task.id})`);
5085
+ });
5086
+
5087
+ // cli/commands/delete.ts
5088
+ import { Command as Command15 } from "commander";
5089
+ import { createInterface as createInterface3 } from "readline/promises";
5090
+ var c4 = {
5091
+ reset: "\x1B[0m",
5092
+ bold: "\x1B[1m",
5093
+ dim: "\x1B[2m"
5094
+ };
5095
+ var deleteCommand = new Command15("delete").description("Delete a task").argument("<task-id>", "Task ID to delete").option("-y, --yes", "Skip the confirmation prompt").action(async (taskId, opts) => {
5096
+ let title = taskId;
5097
+ try {
5098
+ const task = await api.get(`/api/tasks/${taskId}`);
5099
+ if (task?.title) title = task.title;
5100
+ } catch {
5101
+ }
5102
+ if (!opts.yes) {
5103
+ const rl = createInterface3({ input: process.stdin, output: process.stdout });
5104
+ const answer = (await rl.question(
5105
+ `Delete task ${c4.bold}${title}${c4.reset} ${c4.dim}(${taskId})${c4.reset}? [y/N] `
5106
+ )).trim().toLowerCase();
5107
+ rl.close();
5108
+ if (answer !== "y" && answer !== "yes") {
5109
+ console.log("Aborted.");
5110
+ return;
5111
+ }
5112
+ }
5113
+ await api.del(`/api/tasks/${taskId}`);
5114
+ console.log(`\u2713 Deleted task ${title} (${taskId})`);
5115
+ });
5116
+
5117
+ // cli/commands/subtask-complete.ts
5118
+ import { Command as Command16 } from "commander";
5119
+ var subtaskCompleteCommand = new Command16("subtask-complete").description("Mark a subtask as completed").argument("<task-id>", "Parent task ID").argument("<subtask-id>", "Subtask ID to complete").action(async (taskId, subtaskId) => {
4986
5120
  const subtask = await api.patch(
4987
5121
  `/api/tasks/${taskId}/subtasks/${subtaskId}`,
4988
5122
  { completed: true }
@@ -4991,8 +5125,8 @@ var subtaskCompleteCommand = new Command13("subtask-complete").description("Mark
4991
5125
  });
4992
5126
 
4993
5127
  // cli/commands/subtask-add.ts
4994
- import { Command as Command14 } from "commander";
4995
- var subtaskAddCommand = new Command14("subtask-add").description("Add a subtask to a task (used by the agent to plan work as it starts)").argument("<task-id>", "Parent task ID").argument("<title...>", "Subtask title").action(async (taskId, titleParts) => {
5128
+ import { Command as Command17 } from "commander";
5129
+ var subtaskAddCommand = new Command17("subtask-add").description("Add a subtask to a task (used by the agent to plan work as it starts)").argument("<task-id>", "Parent task ID").argument("<title...>", "Subtask title").action(async (taskId, titleParts) => {
4996
5130
  const title = titleParts.join(" ").trim();
4997
5131
  if (!title) {
4998
5132
  console.error("Subtask title is required.");
@@ -5005,8 +5139,8 @@ var subtaskAddCommand = new Command14("subtask-add").description("Add a subtask
5005
5139
  });
5006
5140
 
5007
5141
  // cli/commands/prototype.ts
5008
- import { Command as Command15 } from "commander";
5009
- var c4 = {
5142
+ import { Command as Command18 } from "commander";
5143
+ var c5 = {
5010
5144
  reset: "\x1B[0m",
5011
5145
  bold: "\x1B[1m",
5012
5146
  dim: "\x1B[2m",
@@ -5018,7 +5152,7 @@ var c4 = {
5018
5152
  gray: "\x1B[90m"
5019
5153
  };
5020
5154
  function paint4(color, text) {
5021
- return `${c4[color]}${text}${c4.reset}`;
5155
+ return `${c5[color]}${text}${c5.reset}`;
5022
5156
  }
5023
5157
  function statusBadge(status) {
5024
5158
  switch (status) {
@@ -5034,8 +5168,8 @@ function statusBadge(status) {
5034
5168
  return paint4("gray", status);
5035
5169
  }
5036
5170
  }
5037
- var prototypeCommand = new Command15("prototype").description("Manage prototypes").addCommand(
5038
- new Command15("list").description("List prototypes for the linked project").option("--all", "Show prototypes for all projects").action(async (opts) => {
5171
+ var prototypeCommand = new Command18("prototype").description("Manage prototypes").addCommand(
5172
+ new Command18("list").description("List prototypes for the linked project").option("--all", "Show prototypes for all projects").action(async (opts) => {
5039
5173
  const params = new URLSearchParams();
5040
5174
  if (!opts.all) {
5041
5175
  const projectId = getLinkedProjectId();
@@ -5069,7 +5203,7 @@ var prototypeCommand = new Command15("prototype").description("Manage prototypes
5069
5203
  }
5070
5204
  })
5071
5205
  ).addCommand(
5072
- new Command15("create").description("Create a new prototype").argument("<title>", "Title of the prototype").requiredOption("--prompt <prompt>", "Design description / prompt").option("--project <projectId>", "Project ID (defaults to linked project, when available)").option("--variants <count>", "Number of variants to generate (1-50)", "5").option("--type <type>", "Prototype type: web_app, mobile_app, desktop_app, logo (default: web_app)", "web_app").option("--fidelity <fidelity>", "Fidelity level: low, high (default: high)", "high").action(async (title, opts) => {
5206
+ new Command18("create").description("Create a new prototype").argument("<title>", "Title of the prototype").requiredOption("--prompt <prompt>", "Design description / prompt").option("--project <projectId>", "Project ID (defaults to linked project, when available)").option("--variants <count>", "Number of variants to generate (1-50)", "5").option("--type <type>", "Prototype type: web_app, mobile_app, desktop_app, logo (default: web_app)", "web_app").option("--fidelity <fidelity>", "Fidelity level: low, high (default: high)", "high").action(async (title, opts) => {
5073
5207
  const projectId = opts.project ?? getLinkedProjectId();
5074
5208
  const variantCount = Math.max(1, Math.min(50, parseInt(opts.variants, 10) || 5));
5075
5209
  const validTypes = ["web_app", "mobile_app", "desktop_app", "logo"];
@@ -5110,7 +5244,7 @@ var prototypeCommand = new Command15("prototype").description("Manage prototypes
5110
5244
  console.log();
5111
5245
  })
5112
5246
  ).addCommand(
5113
- new Command15("start").description("Start prototype generation (sets status to in_progress)").argument("<id>", "Prototype ID").action(async (id) => {
5247
+ new Command18("start").description("Start prototype generation (sets status to in_progress)").argument("<id>", "Prototype ID").action(async (id) => {
5114
5248
  const prototype = await api.patch(`/api/prototypes/${id}`, {
5115
5249
  status: "in_progress"
5116
5250
  });
@@ -5120,7 +5254,7 @@ var prototypeCommand = new Command15("prototype").description("Manage prototypes
5120
5254
  console.log();
5121
5255
  })
5122
5256
  ).addCommand(
5123
- new Command15("retry").description("Retry a failed prototype").argument("<id>", "Prototype ID").action(async (id) => {
5257
+ new Command18("retry").description("Retry a failed prototype").argument("<id>", "Prototype ID").action(async (id) => {
5124
5258
  const prototype = await api.patch(`/api/prototypes/${id}`, {
5125
5259
  status: "in_progress",
5126
5260
  files: null
@@ -5132,9 +5266,9 @@ var prototypeCommand = new Command15("prototype").description("Manage prototypes
5132
5266
  );
5133
5267
 
5134
5268
  // cli/commands/setup.ts
5135
- import { Command as Command16 } from "commander";
5269
+ import { Command as Command19 } from "commander";
5136
5270
  import { exec as exec2 } from "child_process";
5137
- var c5 = {
5271
+ var c6 = {
5138
5272
  reset: "\x1B[0m",
5139
5273
  bold: "\x1B[1m",
5140
5274
  dim: "\x1B[2m",
@@ -5146,7 +5280,7 @@ var c5 = {
5146
5280
  gray: "\x1B[90m"
5147
5281
  };
5148
5282
  function paint5(color, text) {
5149
- return `${c5[color]}${text}${c5.reset}`;
5283
+ return `${c6[color]}${text}${c6.reset}`;
5150
5284
  }
5151
5285
  function commandExists2(cmd) {
5152
5286
  return new Promise((resolve9) => {
@@ -5390,7 +5524,7 @@ async function checkApiConnectivity() {
5390
5524
  }
5391
5525
  }
5392
5526
  function printResults(checks) {
5393
- const maxNameLen = Math.max(...checks.map((c14) => c14.name.length));
5527
+ const maxNameLen = Math.max(...checks.map((c15) => c15.name.length));
5394
5528
  let allOk = true;
5395
5529
  for (const check of checks) {
5396
5530
  const isOptional = check.optional ?? false;
@@ -5404,10 +5538,10 @@ function printResults(checks) {
5404
5538
  }
5405
5539
  async function autoFix(checks, agent) {
5406
5540
  const { spawn: spawn9 } = await import("child_process");
5407
- const ghInstalled = checks.find((c14) => c14.name === "GitHub CLI (gh)").ok;
5408
- const ghAuthed = checks.find((c14) => c14.name === "GitHub CLI auth").ok;
5409
- const mrAuthed = checks.find((c14) => c14.name === "Mr. Manager CLI auth").ok;
5410
- const claudeCheck = checks.find((c14) => c14.name === "Claude Code (claude)");
5541
+ const ghInstalled = checks.find((c15) => c15.name === "GitHub CLI (gh)").ok;
5542
+ const ghAuthed = checks.find((c15) => c15.name === "GitHub CLI auth").ok;
5543
+ const mrAuthed = checks.find((c15) => c15.name === "Mr. Manager CLI auth").ok;
5544
+ const claudeCheck = checks.find((c15) => c15.name === "Claude Code (claude)");
5411
5545
  if (claudeCheck && !claudeCheck.ok && agent === "claude") {
5412
5546
  console.log(paint5("cyan", " Installing Claude Code..."));
5413
5547
  console.log(paint5("dim", " Running: curl -fsSL https://claude.ai/install.sh | bash"));
@@ -5435,7 +5569,7 @@ async function autoFix(checks, agent) {
5435
5569
  console.log("");
5436
5570
  }
5437
5571
  }
5438
- var setupCommand = new Command16("setup").description("Check that all dependencies for mr watch are installed and configured").option("--fix", "Attempt to auto-fix issues where possible", false).option("--agent <agent>", "AI agent to check: claude, codex, or antigravity (default: claude)", "claude").action(async (opts) => {
5572
+ var setupCommand = new Command19("setup").description("Check that all dependencies for mr watch are installed and configured").option("--fix", "Attempt to auto-fix issues where possible", false).option("--agent <agent>", "AI agent to check: claude, codex, or antigravity (default: claude)", "claude").action(async (opts) => {
5439
5573
  const agent = opts.agent === "codex" ? "codex" : opts.agent === "antigravity" ? "antigravity" : "claude";
5440
5574
  const banner = [
5441
5575
  ``,
@@ -5470,7 +5604,7 @@ var setupCommand = new Command16("setup").description("Check that all dependenci
5470
5604
  console.log("");
5471
5605
  return;
5472
5606
  }
5473
- const fixes = checks.filter((c14) => !c14.ok && c14.fix && !c14.optional);
5607
+ const fixes = checks.filter((c15) => !c15.ok && c15.fix && !c15.optional);
5474
5608
  if (fixes.length > 0) {
5475
5609
  console.log(paint5("yellow", " To fix:"));
5476
5610
  for (const fix of fixes) {
@@ -5485,8 +5619,8 @@ var setupCommand = new Command16("setup").description("Check that all dependenci
5485
5619
  });
5486
5620
 
5487
5621
  // cli/commands/update.ts
5488
- import { Command as Command17 } from "commander";
5489
- var updateCommand = new Command17("update").description("Post a status update to a task, or attach a resource").argument("<task-id>", "Task ID").argument("[message-or-title]", "Status update message, or resource title when using --resource").argument("[content]", "Resource content (only used with --resource)").option("--source <source>", "Update source: agent, system, or user", "agent").option("--resource <type>", "Create a task resource (e.g. test-plan, note, plan, research)").action(async (taskId, messageOrTitle, content, opts) => {
5622
+ import { Command as Command20 } from "commander";
5623
+ var updateCommand = new Command20("update").description("Post a status update to a task, or attach a resource").argument("<task-id>", "Task ID").argument("[message-or-title]", "Status update message, or resource title when using --resource").argument("[content]", "Resource content (only used with --resource)").option("--source <source>", "Update source: agent, system, or user", "agent").option("--resource <type>", "Create a task resource (e.g. test-plan, note, plan, research)").action(async (taskId, messageOrTitle, content, opts) => {
5490
5624
  if (opts.resource) {
5491
5625
  if (!messageOrTitle || !content) {
5492
5626
  console.error(`Usage: mr update <task-id> --resource <type> "<title>" '<content>'`);
@@ -5512,11 +5646,11 @@ var updateCommand = new Command17("update").description("Post a status update to
5512
5646
  });
5513
5647
 
5514
5648
  // cli/commands/screenshot.ts
5515
- import { Command as Command18 } from "commander";
5649
+ import { Command as Command21 } from "commander";
5516
5650
  import { readFileSync as readFileSync6, existsSync as existsSync8, unlinkSync as unlinkSync2 } from "fs";
5517
5651
  import { join as join7 } from "path";
5518
5652
  import { tmpdir } from "os";
5519
- var screenshotCommand = new Command18("screenshot").description(
5653
+ var screenshotCommand = new Command21("screenshot").description(
5520
5654
  "Take or attach a screenshot to a task update (agents use this to show their work)"
5521
5655
  ).argument("<task-id>", "Task ID").argument("[file]", "Path to an image file (if omitted, uses headless browser to screenshot the app)").option("-m, --message <message>", "Optional message to include with the screenshot").option("-u, --url <url>", "Custom URL to screenshot (defaults to the task's project page)").action(async (taskId, file, opts) => {
5522
5656
  let filePath = file;
@@ -5607,10 +5741,10 @@ var screenshotCommand = new Command18("screenshot").description(
5607
5741
  });
5608
5742
 
5609
5743
  // cli/commands/resume.ts
5610
- import { Command as Command19 } from "commander";
5744
+ import { Command as Command22 } from "commander";
5611
5745
  import { spawn as spawn5 } from "child_process";
5612
5746
  import { resolve as resolve3 } from "path";
5613
- var c6 = {
5747
+ var c7 = {
5614
5748
  reset: "\x1B[0m",
5615
5749
  bold: "\x1B[1m",
5616
5750
  dim: "\x1B[2m",
@@ -5622,9 +5756,9 @@ var c6 = {
5622
5756
  gray: "\x1B[90m"
5623
5757
  };
5624
5758
  function paint6(color, text) {
5625
- return `${c6[color]}${text}${c6.reset}`;
5759
+ return `${c7[color]}${text}${c7.reset}`;
5626
5760
  }
5627
- var resumeCommand = new Command19("resume").description("Resume an interactive Claude session for a task (non-headless)").argument("<task-id>", "Task ID whose Claude session to resume").option("--dir <directory>", "Override the working directory for the session").action(async (taskId, opts) => {
5761
+ var resumeCommand = new Command22("resume").description("Resume an interactive Claude session for a task (non-headless)").argument("<task-id>", "Task ID whose Claude session to resume").option("--dir <directory>", "Override the working directory for the session").action(async (taskId, opts) => {
5628
5762
  const task = await api.get(`/api/tasks/${taskId}`);
5629
5763
  if (!task.claudeSessionId) {
5630
5764
  console.error(
@@ -5693,7 +5827,7 @@ var resumeCommand = new Command19("resume").description("Resume an interactive C
5693
5827
  });
5694
5828
 
5695
5829
  // cli/commands/browse.ts
5696
- import { Command as Command20 } from "commander";
5830
+ import { Command as Command23 } from "commander";
5697
5831
  import { execSync as execSync4, spawn as spawn6 } from "child_process";
5698
5832
  import { existsSync as existsSync9, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
5699
5833
  import { createHash } from "crypto";
@@ -5808,7 +5942,7 @@ async function ensureDevServer(options = {}) {
5808
5942
  }
5809
5943
  throw new Error(`Dev server failed to start within 60s. Command: ${devCmd} in ${projectCwd}`);
5810
5944
  }
5811
- var browseCommand = new Command20("browse").description("Control a headless browser for QA and testing").argument("[command]", "Browse command (goto, click, fill, screenshot, etc.)").argument("[args...]", "Command arguments").option(
5945
+ var browseCommand = new Command23("browse").description("Control a headless browser for QA and testing").argument("[command]", "Browse command (goto, click, fill, screenshot, etc.)").argument("[args...]", "Command arguments").option(
5812
5946
  "--task-id <id>",
5813
5947
  "Attach output to a task update (for screenshot and recording-stop commands)"
5814
5948
  ).option("--dev", "Auto-start local dev server before browsing").option("--dev-cwd <path>", "Working directory for the dev server (defaults to mr-manager root)").option("--dev-cmd <command>", "Dev server command to run (auto-detected from package.json if omitted)").option("--dev-port-flag <flag>", "CLI flag name used to set port (e.g. --port). Omit to use PORT env var.").allowUnknownOption(true).action(
@@ -5951,10 +6085,10 @@ var browseCommand = new Command20("browse").description("Control a headless brow
5951
6085
  );
5952
6086
 
5953
6087
  // cli/commands/set-path.ts
5954
- import { Command as Command21 } from "commander";
6088
+ import { Command as Command24 } from "commander";
5955
6089
  import { resolve as resolve5 } from "path";
5956
6090
  import { existsSync as existsSync10 } from "fs";
5957
- var setPathCommand = new Command21("set-path").description("Set or update the local repo path for a project").argument("<project-id>", "Project ID").argument("<path>", "Absolute or relative path to the local repo").action(async (projectId, pathArg) => {
6091
+ var setPathCommand = new Command24("set-path").description("Set or update the local repo path for a project").argument("<project-id>", "Project ID").argument("<path>", "Absolute or relative path to the local repo").action(async (projectId, pathArg) => {
5958
6092
  const absolutePath = resolve5(pathArg);
5959
6093
  if (!existsSync10(absolutePath)) {
5960
6094
  console.error(`Error: Path does not exist: ${absolutePath}`);
@@ -5972,9 +6106,9 @@ var setPathCommand = new Command21("set-path").description("Set or update the lo
5972
6106
  });
5973
6107
 
5974
6108
  // cli/commands/test.ts
5975
- import { Command as Command22 } from "commander";
6109
+ import { Command as Command25 } from "commander";
5976
6110
  import { readFileSync as readFileSync8, existsSync as existsSync11 } from "fs";
5977
- var testCommand = new Command22("test").description("Run automated browser test for a task's MR/PR").argument("<task-id>", "Task ID to test").option("--plan <file>", "Path to a custom test plan JSON file").option("--no-recording", "Disable proof recording for this run").action(async (taskId, opts) => {
6111
+ var testCommand = new Command25("test").description("Run automated browser test for a task's MR/PR").argument("<task-id>", "Task ID to test").option("--plan <file>", "Path to a custom test plan JSON file").option("--no-recording", "Disable proof recording for this run").action(async (taskId, opts) => {
5978
6112
  const config = loadConfig();
5979
6113
  console.log("[test] Fetching task...");
5980
6114
  let task;
@@ -6136,11 +6270,11 @@ var testCommand = new Command22("test").description("Run automated browser test
6136
6270
  });
6137
6271
 
6138
6272
  // cli/commands/features.ts
6139
- import { Command as Command23 } from "commander";
6273
+ import { Command as Command26 } from "commander";
6140
6274
  import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, existsSync as existsSync12 } from "fs";
6141
6275
  import { resolve as resolve6, sep as sep2 } from "path";
6142
6276
  var FEATURES_FILE3 = ".mr-features.md";
6143
- var c7 = {
6277
+ var c8 = {
6144
6278
  reset: "\x1B[0m",
6145
6279
  bold: "\x1B[1m",
6146
6280
  dim: "\x1B[2m",
@@ -6151,7 +6285,7 @@ var c7 = {
6151
6285
  gray: "\x1B[90m"
6152
6286
  };
6153
6287
  function paint7(color, text) {
6154
- return `${c7[color]}${text}${c7.reset}`;
6288
+ return `${c8[color]}${text}${c8.reset}`;
6155
6289
  }
6156
6290
  function resolveProjectRoot2() {
6157
6291
  const cwd = process.cwd();
@@ -6170,7 +6304,7 @@ function readFeatures2() {
6170
6304
  if (!existsSync12(path)) return null;
6171
6305
  return readFileSync9(path, "utf-8");
6172
6306
  }
6173
- var featuresCommand = new Command23("features").description("View or update the project features & goals document (.mr-features.md)").option("--update <content>", "Replace the features document with the given content").option("--file <path>", "Read content from a file and use it to update the features document").option("--path", "Print the path to the features file").action(async (opts) => {
6307
+ var featuresCommand = new Command26("features").description("View or update the project features & goals document (.mr-features.md)").option("--update <content>", "Replace the features document with the given content").option("--file <path>", "Read content from a file and use it to update the features document").option("--path", "Print the path to the features file").action(async (opts) => {
6174
6308
  if (opts.path) {
6175
6309
  console.log(getFeaturesPath());
6176
6310
  return;
@@ -6198,11 +6332,11 @@ var featuresCommand = new Command23("features").description("View or update the
6198
6332
  });
6199
6333
 
6200
6334
  // cli/commands/no-mr.ts
6201
- import { Command as Command24 } from "commander";
6335
+ import { Command as Command27 } from "commander";
6202
6336
  import { writeFileSync as writeFileSync6 } from "fs";
6203
6337
  import { resolve as resolve7 } from "path";
6204
6338
  var NO_MR_FILE = ".mr-no-mr";
6205
- var noMrCommand = new Command24("no-mr").description("Signal that a task does not require a merge/pull request and describe what was done instead").argument("<task-id>", "Task ID").argument("<description>", "Description of what was done instead of creating an MR/PR").action(async (taskId, description) => {
6339
+ var noMrCommand = new Command27("no-mr").description("Signal that a task does not require a merge/pull request and describe what was done instead").argument("<task-id>", "Task ID").argument("<description>", "Description of what was done instead of creating an MR/PR").action(async (taskId, description) => {
6206
6340
  const filePath = resolve7(process.cwd(), NO_MR_FILE);
6207
6341
  writeFileSync6(filePath, description, "utf-8");
6208
6342
  await api.post(`/api/tasks/${taskId}/updates`, {
@@ -6214,12 +6348,12 @@ var noMrCommand = new Command24("no-mr").description("Signal that a task does no
6214
6348
  });
6215
6349
 
6216
6350
  // cli/commands/review.ts
6217
- import { Command as Command26 } from "commander";
6351
+ import { Command as Command29 } from "commander";
6218
6352
  import { execSync as execSync6 } from "child_process";
6219
6353
  import { existsSync as existsSync14, statSync as statSync2 } from "fs";
6220
6354
 
6221
6355
  // cli/commands/review-apply.ts
6222
- import { Command as Command25 } from "commander";
6356
+ import { Command as Command28 } from "commander";
6223
6357
  import { execSync as execSync5 } from "child_process";
6224
6358
  import { existsSync as existsSync13 } from "fs";
6225
6359
 
@@ -6309,7 +6443,7 @@ async function runAgentInteractive(prompt2, opts) {
6309
6443
  }
6310
6444
 
6311
6445
  // cli/commands/review-apply.ts
6312
- var c8 = {
6446
+ var c9 = {
6313
6447
  reset: "\x1B[0m",
6314
6448
  dim: "\x1B[2m",
6315
6449
  cyan: "\x1B[36m",
@@ -6321,7 +6455,7 @@ var c8 = {
6321
6455
  magenta: "\x1B[35m"
6322
6456
  };
6323
6457
  function paint8(color, text) {
6324
- return `${c8[color]}${text}${c8.reset}`;
6458
+ return `${c9[color]}${text}${c9.reset}`;
6325
6459
  }
6326
6460
  function timestamp2() {
6327
6461
  return paint8("gray", (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false }));
@@ -6338,7 +6472,7 @@ function logOk(msg) {
6338
6472
  function logErr(msg) {
6339
6473
  console.error(`${timestamp2()} ${tag()} ${paint8("red", "\u2717")} ${msg}`);
6340
6474
  }
6341
- var reviewApplyCommand = new Command25("apply").description("Apply review comments and findings using the Claude agent").argument("<id>", "Code review ID (the one shown in the Reviews UI)").option("--no-push", "Skip pushing the fix commit to the remote").option("--no-commit", "Apply changes but don't commit (for dry-run review)").option("--in-place", "Apply edits directly in the linked checkout instead of an isolated worktree (legacy, unsafe)").action(async (id, opts) => {
6475
+ var reviewApplyCommand = new Command28("apply").description("Apply review comments and findings using the Claude agent").argument("<id>", "Code review ID (the one shown in the Reviews UI)").option("--no-push", "Skip pushing the fix commit to the remote").option("--no-commit", "Apply changes but don't commit (for dry-run review)").option("--in-place", "Apply edits directly in the linked checkout instead of an isolated worktree (legacy, unsafe)").action(async (id, opts) => {
6342
6476
  const config = loadConfig();
6343
6477
  if (!config.apiKey) {
6344
6478
  logErr('Not authenticated. Run "mr login" first.');
@@ -6358,7 +6492,7 @@ var reviewApplyCommand = new Command25("apply").description("Apply review commen
6358
6492
  logErr("Review has no comments or findings to act on.");
6359
6493
  process.exit(1);
6360
6494
  }
6361
- const actionableComments = comments.filter((c14) => !excluded.has(c14.file));
6495
+ const actionableComments = comments.filter((c15) => !excluded.has(c15.file));
6362
6496
  const dismissedCount = findings.filter((f) => f.status === "dismissed").length;
6363
6497
  const actionableFindings = findings.filter(
6364
6498
  (f) => !excluded.has(f.file) && f.status !== "dismissed"
@@ -6396,7 +6530,7 @@ var reviewApplyCommand = new Command25("apply").description("Apply review commen
6396
6530
  }
6397
6531
  const touchedFiles = Array.from(
6398
6532
  new Set([
6399
- ...actionableComments.map((c14) => c14.file),
6533
+ ...actionableComments.map((c15) => c15.file),
6400
6534
  ...actionableFindings.map((f) => f.file)
6401
6535
  ].filter(Boolean))
6402
6536
  );
@@ -6536,9 +6670,9 @@ function buildApplyPrompt(args) {
6536
6670
  }
6537
6671
  if (args.comments.length > 0) {
6538
6672
  lines.push("USER COMMENTS:");
6539
- for (const c14 of args.comments) {
6540
- const where = c14.line ? `${c14.file}:${c14.line}` : c14.file;
6541
- lines.push(`- [${where}] ${c14.body}`);
6673
+ for (const c15 of args.comments) {
6674
+ const where = c15.line ? `${c15.file}:${c15.line}` : c15.file;
6675
+ lines.push(`- [${where}] ${c15.body}`);
6542
6676
  }
6543
6677
  lines.push("");
6544
6678
  }
@@ -6792,6 +6926,37 @@ function buildDimensionPrompt(args) {
6792
6926
  lines.push(JSON_CONTRACT, "", "Here is the diff to review:", "", "```diff", args.diff, "```");
6793
6927
  return lines.join("\n");
6794
6928
  }
6929
+ function buildLightPrompt(args) {
6930
+ const allowedTypes = [
6931
+ ...new Set(REVIEW_DIMENSIONS.flatMap((d) => d.allowedTypes))
6932
+ ];
6933
+ const lines = [];
6934
+ lines.push(
6935
+ `You are a senior code reviewer doing a quick but careful pass.`,
6936
+ `Review the git diff for branch "${args.branch}" compared to "${args.baseBranch}".`,
6937
+ "",
6938
+ "Cover all of these concerns in a single pass and report the issues that matter most:",
6939
+ "- Security (injection, auth gaps, leaked secrets, unsafe input handling)",
6940
+ "- Correctness (logic bugs, null/undefined, broken contracts, bad async)",
6941
+ "- Performance (N+1 queries, hot-loop work, missing memoization)",
6942
+ "- Style & maintainability (naming, dead code, duplication) \u2014 keep these low severity",
6943
+ "",
6944
+ "Prioritize real, high-impact problems over nitpicks. This is a fast pass, so favor",
6945
+ "the issues you are confident about over exhaustive coverage.",
6946
+ "",
6947
+ `Emit findings whose "type" is one of: ${allowedTypes.join(", ")}.`,
6948
+ ""
6949
+ );
6950
+ if (args.canReadFiles) {
6951
+ lines.push(
6952
+ "You are running inside a checkout of this repository and MAY open changed files",
6953
+ "and their neighbors to confirm a finding before reporting it.",
6954
+ ""
6955
+ );
6956
+ }
6957
+ lines.push(JSON_CONTRACT, "", "Here is the diff to review:", "", "```diff", args.diff, "```");
6958
+ return lines.join("\n");
6959
+ }
6795
6960
  function buildVerificationPrompt(args) {
6796
6961
  const compact = args.findings.map((f) => ({
6797
6962
  id: f.id,
@@ -6832,6 +6997,41 @@ function buildVerificationPrompt(args) {
6832
6997
  return lines.join("\n");
6833
6998
  }
6834
6999
 
7000
+ // lib/review/depth.ts
7001
+ var REVIEW_DEPTHS = {
7002
+ light: {
7003
+ key: "light",
7004
+ label: "Light",
7005
+ description: "One agent, quick single pass",
7006
+ fanOut: false,
7007
+ verify: false,
7008
+ multiAgent: false
7009
+ },
7010
+ regular: {
7011
+ key: "regular",
7012
+ label: "Regular",
7013
+ description: "Team review across security, correctness, performance & style",
7014
+ fanOut: true,
7015
+ verify: true,
7016
+ multiAgent: false
7017
+ },
7018
+ deep: {
7019
+ key: "deep",
7020
+ label: "Deep",
7021
+ description: "Multiple agents (claude, codex, gemini) for deep analysis",
7022
+ fanOut: true,
7023
+ verify: true,
7024
+ multiAgent: true
7025
+ }
7026
+ };
7027
+ var DEFAULT_REVIEW_DEPTH = "regular";
7028
+ function normalizeReviewDepth(value) {
7029
+ return value === "light" || value === "regular" || value === "deep" ? value : DEFAULT_REVIEW_DEPTH;
7030
+ }
7031
+ function getReviewDepthConfig(value) {
7032
+ return REVIEW_DEPTHS[normalizeReviewDepth(value)];
7033
+ }
7034
+
6835
7035
  // lib/review/orchestrate.ts
6836
7036
  function splitDiffByFile(diff) {
6837
7037
  const sections = diff.split(/(?=^diff --git )/m).filter((s) => s.trim());
@@ -6852,7 +7052,10 @@ async function pool(items, limit) {
6852
7052
  await Promise.all(workers);
6853
7053
  return results;
6854
7054
  }
6855
- function buildJobs(opts) {
7055
+ function buildJobs(opts, fanOut) {
7056
+ if (!fanOut) {
7057
+ return [{ dimension: null, diff: opts.diff }];
7058
+ }
6856
7059
  const files = splitDiffByFile(opts.diff);
6857
7060
  const shardThreshold = opts.shardThreshold ?? 12;
6858
7061
  if (files.length >= shardThreshold) {
@@ -6881,40 +7084,63 @@ async function orchestrateReview(opts) {
6881
7084
  });
6882
7085
  const concurrency = opts.concurrency ?? 4;
6883
7086
  const canReadFiles = Boolean(opts.cwd);
6884
- const runOpts = { cwd: opts.cwd, chain: opts.chain };
6885
- const jobs = buildJobs(opts);
6886
- log4(`Fanning out ${jobs.length} review subagent(s) across ${REVIEW_DIMENSIONS.length} dimensions`);
7087
+ const depthConfig = getReviewDepthConfig(opts.depth);
7088
+ const jobs = buildJobs(opts, depthConfig.fanOut);
7089
+ const reviewers = depthConfig.multiAgent ? opts.chain : [opts.chain[0]];
7090
+ if (depthConfig.multiAgent) {
7091
+ log4(`Deep review across ${reviewers.length} agent(s): ${reviewers.join(", ")}`);
7092
+ }
7093
+ log4(
7094
+ depthConfig.fanOut ? `Fanning out ${jobs.length} review subagent(s) across ${REVIEW_DIMENSIONS.length} dimensions \xD7 ${reviewers.length} agent(s)` : `Running a light single-pass review with ${reviewers[0]}`
7095
+ );
7096
+ const tasks = jobs.flatMap(
7097
+ (job) => reviewers.map((agent) => ({ job, agent }))
7098
+ );
6887
7099
  const summaries = [];
6888
7100
  const collected = [];
6889
7101
  const jobResults = await pool(
6890
- jobs.map((job) => async () => {
6891
- const prompt2 = buildDimensionPrompt({
7102
+ tasks.map(({ job, agent }) => async () => {
7103
+ const prompt2 = job.dimension ? buildDimensionPrompt({
6892
7104
  dimension: job.dimension,
6893
7105
  branch: opts.branch,
6894
7106
  baseBranch: opts.baseBranch,
6895
7107
  diff: job.diff,
6896
7108
  canReadFiles,
6897
7109
  fileScope: job.fileScope
7110
+ }) : buildLightPrompt({
7111
+ branch: opts.branch,
7112
+ baseBranch: opts.baseBranch,
7113
+ diff: job.diff,
7114
+ canReadFiles
6898
7115
  });
7116
+ const runOpts = {
7117
+ cwd: opts.cwd,
7118
+ chain: depthConfig.multiAgent ? [agent] : opts.chain
7119
+ };
6899
7120
  try {
6900
- const { output } = await runAgentCaptured(prompt2, runOpts);
7121
+ const { output, agent: usedAgent } = await runAgentCaptured(prompt2, runOpts);
6901
7122
  const parsed = parseReviewOutput(output);
6902
- return { job, parsed };
7123
+ return { job, parsed, agent: usedAgent };
6903
7124
  } catch (err) {
6904
- log4(` ${job.dimension.key} subagent failed: ${err.message}`);
6905
- return { job, parsed: { summary: "", findings: [], parseFailed: true } };
7125
+ const label = job.dimension?.key ?? "light";
7126
+ log4(` ${label} subagent (${agent}) failed: ${err.message}`);
7127
+ return { job, parsed: { summary: "", findings: [], parseFailed: true }, agent };
6906
7128
  }
6907
7129
  }),
6908
7130
  concurrency
6909
7131
  );
6910
7132
  const dimensionsRun = /* @__PURE__ */ new Set();
6911
- for (const { job, parsed } of jobResults) {
6912
- if (parsed.summary) summaries.push(`${job.dimension.title}: ${parsed.summary}`);
7133
+ const agentsRun = /* @__PURE__ */ new Set();
7134
+ for (const { job, parsed, agent } of jobResults) {
7135
+ const label = job.dimension?.title ?? "Review";
7136
+ if (parsed.summary) summaries.push(`${label}: ${parsed.summary}`);
6913
7137
  for (const f of parsed.findings) {
6914
- dimensionsRun.add(job.dimension.key);
7138
+ agentsRun.add(agent);
7139
+ const fallbackType = job.dimension?.allowedTypes[0] ?? "bug";
7140
+ if (job.dimension) dimensionsRun.add(job.dimension.key);
6915
7141
  collected.push({
6916
7142
  id: f.id || "f",
6917
- type: f.type || job.dimension.allowedTypes[0],
7143
+ type: f.type || fallbackType,
6918
7144
  severity: f.severity || "medium",
6919
7145
  title: f.title || "Untitled finding",
6920
7146
  description: f.description || "",
@@ -6923,7 +7149,7 @@ async function orchestrateReview(opts) {
6923
7149
  endLine: typeof f.endLine === "number" ? f.endLine : void 0,
6924
7150
  suggestion: f.suggestion,
6925
7151
  status: "new",
6926
- dimension: job.dimension.key,
7152
+ dimension: job.dimension?.key ?? f.type ?? "general",
6927
7153
  confidence: typeof f.confidence === "number" ? f.confidence : void 0
6928
7154
  });
6929
7155
  }
@@ -6931,13 +7157,15 @@ async function orchestrateReview(opts) {
6931
7157
  const rawCount = collected.length;
6932
7158
  let findings = mergeFindings(collected);
6933
7159
  log4(`Merged ${rawCount} raw findings into ${findings.length} after dedup`);
6934
- if (opts.verify && findings.length > 0) {
6935
- findings = await verifyFindings(findings, opts, runOpts, log4);
7160
+ if (depthConfig.verify && findings.length > 0) {
7161
+ const verifyOpts = { cwd: opts.cwd, chain: opts.chain };
7162
+ findings = await verifyFindings(findings, opts, verifyOpts, log4);
6936
7163
  }
6937
7164
  return {
6938
7165
  summary: summaries.join(" "),
6939
7166
  findings,
6940
7167
  dimensionsRun: [...dimensionsRun],
7168
+ agentsRun: [...agentsRun],
6941
7169
  rawCount
6942
7170
  };
6943
7171
  }
@@ -6979,7 +7207,7 @@ async function verifyFindings(findings, opts, runOpts, log4) {
6979
7207
  }
6980
7208
 
6981
7209
  // cli/commands/review.ts
6982
- var c9 = {
7210
+ var c10 = {
6983
7211
  reset: "\x1B[0m",
6984
7212
  bold: "\x1B[1m",
6985
7213
  dim: "\x1B[2m",
@@ -6992,7 +7220,7 @@ var c9 = {
6992
7220
  blue: "\x1B[34m"
6993
7221
  };
6994
7222
  function paint9(color, text) {
6995
- return `${c9[color]}${text}${c9.reset}`;
7223
+ return `${c10[color]}${text}${c10.reset}`;
6996
7224
  }
6997
7225
  function timestamp3() {
6998
7226
  return paint9("gray", (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false }));
@@ -7009,7 +7237,7 @@ function logOk2(msg) {
7009
7237
  function logErr2(msg) {
7010
7238
  console.error(`${timestamp3()} ${tag2()} ${paint9("red", "\u2717")} ${msg}`);
7011
7239
  }
7012
- var reviewCommand = new Command26("review").description("Run an automated code review on a branch").option("--project <id>", "Project ID (defaults to linked project)").option("--report <id>", "Use an existing review report ID (created by UI trigger)").option("--branch <name>", "Branch to review (defaults to current branch)").option("--base <name>", "Base branch to diff against (defaults to main)").option("--pr-url <url>", "Pull/merge request URL; when set, diff is fetched via gh/glab and no local checkout is needed").option("--pr-number <n>", "Pull/merge request number (used with --pr-url)").addCommand(reviewApplyCommand).action(async (opts) => {
7240
+ var reviewCommand = new Command29("review").description("Run an automated code review on a branch").option("--project <id>", "Project ID (defaults to linked project)").option("--report <id>", "Use an existing review report ID (created by UI trigger)").option("--branch <name>", "Branch to review (defaults to current branch)").option("--base <name>", "Base branch to diff against (defaults to main)").option("--depth <level>", "Review depth: light | regular | deep", "regular").option("--pr-url <url>", "Pull/merge request URL; when set, diff is fetched via gh/glab and no local checkout is needed").option("--pr-number <n>", "Pull/merge request number (used with --pr-url)").addCommand(reviewApplyCommand).action(async (opts) => {
7013
7241
  const config = loadConfig();
7014
7242
  if (!config.apiKey) {
7015
7243
  logErr2('Not authenticated. Run "mr login" first.');
@@ -7038,6 +7266,8 @@ var reviewCommand = new Command26("review").description("Run an automated code r
7038
7266
  process.exit(1);
7039
7267
  }
7040
7268
  const baseBranch = opts.base || "main";
7269
+ const depth = normalizeReviewDepth(opts.depth);
7270
+ const depthConfig = getReviewDepthConfig(depth);
7041
7271
  const prUrl = opts.prUrl;
7042
7272
  const prNumberRaw = opts.prNumber;
7043
7273
  const prNumber = prNumberRaw ? Number(prNumberRaw) : void 0;
@@ -7157,7 +7387,8 @@ var reviewCommand = new Command26("review").description("Run an automated code r
7157
7387
  const report = await api.post("/api/reviews", {
7158
7388
  projectId,
7159
7389
  branch,
7160
- baseBranch
7390
+ baseBranch,
7391
+ depth
7161
7392
  });
7162
7393
  reportId = report.id;
7163
7394
  log2(`Created review report ${paint9("yellow", reportId.slice(0, 8))}`);
@@ -7185,6 +7416,7 @@ var reviewCommand = new Command26("review").description("Run an automated code r
7185
7416
  process.exit(1);
7186
7417
  }
7187
7418
  log2(`Agent chain: ${paint9("cyan", chain.join(" \u2192 "))}`);
7419
+ log2(`Review depth: ${paint9("magenta", depthConfig.label)} ${paint9("dim", `(${depthConfig.description})`)}`);
7188
7420
  const MAX_DIFF_CHARS = 4e5;
7189
7421
  const diffCharsTotal = diff.length;
7190
7422
  let reviewDiff = diff;
@@ -7195,15 +7427,15 @@ var reviewCommand = new Command26("review").description("Run an automated code r
7195
7427
  log2(paint9("yellow", `Diff truncated to ${MAX_DIFF_CHARS.toLocaleString()} of ${diffCharsTotal.toLocaleString()} chars`));
7196
7428
  }
7197
7429
  try {
7198
- log2("Running fan-out code review...");
7430
+ log2(`Running ${depthConfig.label.toLowerCase()} code review...`);
7199
7431
  const orchestrated = await orchestrateReview({
7200
7432
  branch,
7201
7433
  baseBranch,
7202
7434
  diff: reviewDiff,
7203
7435
  chain,
7436
+ depth,
7204
7437
  cwd: reviewCwd,
7205
7438
  concurrency: 4,
7206
- verify: true,
7207
7439
  log: (m) => log2(m)
7208
7440
  });
7209
7441
  const result = { summary: orchestrated.summary, findings: orchestrated.findings };
@@ -7316,7 +7548,7 @@ function formatDuration(ms) {
7316
7548
  }
7317
7549
 
7318
7550
  // cli/commands/scan.ts
7319
- import { Command as Command27 } from "commander";
7551
+ import { Command as Command30 } from "commander";
7320
7552
 
7321
7553
  // lib/scanner/index.ts
7322
7554
  import { spawn as spawn8 } from "child_process";
@@ -7782,10 +8014,10 @@ ${codebaseAnalysis.routes.map((r) => `- ${r}`).join("\n")}
7782
8014
  ${codebaseAnalysis.prismaModels.map((m) => `- ${m}`).join("\n")}
7783
8015
 
7784
8016
  **Components:**
7785
- ${codebaseAnalysis.components.slice(0, 15).map((c14) => `- ${c14}`).join("\n")}
8017
+ ${codebaseAnalysis.components.slice(0, 15).map((c15) => `- ${c15}`).join("\n")}
7786
8018
 
7787
8019
  **Recent Git Commits:**
7788
- ${codebaseAnalysis.recentCommits.slice(0, 8).map((c14) => `- ${c14}`).join("\n")}
8020
+ ${codebaseAnalysis.recentCommits.slice(0, 8).map((c15) => `- ${c15}`).join("\n")}
7789
8021
 
7790
8022
  **Completed Tasks:**
7791
8023
  ${context.completedTasks.slice(0, 10).map((t) => `- ${t.title}`).join("\n") || "None"}
@@ -8058,7 +8290,7 @@ function parseSynthesisOutput(output) {
8058
8290
  }
8059
8291
 
8060
8292
  // cli/commands/scan.ts
8061
- var c10 = {
8293
+ var c11 = {
8062
8294
  reset: "\x1B[0m",
8063
8295
  bold: "\x1B[1m",
8064
8296
  dim: "\x1B[2m",
@@ -8070,7 +8302,7 @@ var c10 = {
8070
8302
  gray: "\x1B[90m"
8071
8303
  };
8072
8304
  function paint10(color, text) {
8073
- return `${c10[color]}${text}${c10.reset}`;
8305
+ return `${c11[color]}${text}${c11.reset}`;
8074
8306
  }
8075
8307
  function timestamp4() {
8076
8308
  return paint10("gray", (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false }));
@@ -8087,7 +8319,7 @@ function logOk3(msg) {
8087
8319
  function logErr3(msg) {
8088
8320
  console.error(`${timestamp4()} ${scanTag()} ${paint10("red", "\u2717")} ${msg}`);
8089
8321
  }
8090
- var scanCommand = new Command27("scan").description("Run a product scan on the current project \u2014 analyzes codebase, crawls the app, and surfaces findings").option("--project <id>", "Project ID (defaults to linked project)").option("--report <id>", "Use an existing scan report ID (created by UI trigger)").option("--prompt <prompt>", "Custom scan direction/prompt to focus the scan on").option("--no-crawl", "Skip live crawl (codebase analysis only)").action(async (opts) => {
8322
+ var scanCommand = new Command30("scan").description("Run a product scan on the current project \u2014 analyzes codebase, crawls the app, and surfaces findings").option("--project <id>", "Project ID (defaults to linked project)").option("--report <id>", "Use an existing scan report ID (created by UI trigger)").option("--prompt <prompt>", "Custom scan direction/prompt to focus the scan on").option("--no-crawl", "Skip live crawl (codebase analysis only)").action(async (opts) => {
8091
8323
  const config = loadConfig();
8092
8324
  if (!config.apiKey) {
8093
8325
  logErr3('Not authenticated. Run "mr login" first.');
@@ -8252,7 +8484,7 @@ var scanCommand = new Command27("scan").description("Run a product scan on the c
8252
8484
  });
8253
8485
 
8254
8486
  // cli/commands/doctor.ts
8255
- import { Command as Command28 } from "commander";
8487
+ import { Command as Command31 } from "commander";
8256
8488
  import { existsSync as existsSync17 } from "fs";
8257
8489
  import { homedir as homedir2 } from "os";
8258
8490
  import { join as join11 } from "path";
@@ -8300,7 +8532,7 @@ async function checkProjectLink() {
8300
8532
  optional: true
8301
8533
  };
8302
8534
  }
8303
- var doctorCommand = new Command28("doctor").description("Diagnose Mr. Manager CLI installation and environment").action(async () => {
8535
+ var doctorCommand = new Command31("doctor").description("Diagnose Mr. Manager CLI installation and environment").action(async () => {
8304
8536
  const banner = [
8305
8537
  ``,
8306
8538
  paint5("cyan", ` MR DOCTOR`),
@@ -8331,7 +8563,7 @@ var doctorCommand = new Command28("doctor").description("Diagnose Mr. Manager CL
8331
8563
  console.log("");
8332
8564
  return;
8333
8565
  }
8334
- const fixes = checks.filter((c14) => !c14.ok && c14.fix && !c14.optional);
8566
+ const fixes = checks.filter((c15) => !c15.ok && c15.fix && !c15.optional);
8335
8567
  if (fixes.length > 0) {
8336
8568
  console.log(paint5("yellow", " To fix:"));
8337
8569
  for (const fix of fixes) {
@@ -8343,14 +8575,14 @@ var doctorCommand = new Command28("doctor").description("Diagnose Mr. Manager CL
8343
8575
  });
8344
8576
 
8345
8577
  // cli/commands/prompt-audit.ts
8346
- import { Command as Command29 } from "commander";
8578
+ import { Command as Command32 } from "commander";
8347
8579
  import { resolve as resolve8 } from "path";
8348
8580
  import { existsSync as existsSync18, readFileSync as readFileSync12 } from "fs";
8349
8581
  function auditLine(label, tokens) {
8350
8582
  const bar = "\u2588".repeat(Math.min(60, Math.round(tokens / 200)));
8351
8583
  return ` ${label.padEnd(30)} ${formatTokenCount(tokens).padStart(8)} ${bar}`;
8352
8584
  }
8353
- var promptAuditCommand = new Command29("prompt-audit").description("Dry-run prompt construction and report estimated token counts by job type").option("--task <id>", "Audit prompts for a specific task ID").option("--all", "Audit all supported job types with representative data", false).option("--json", "Output as JSON instead of plain text", false).action(async (opts) => {
8585
+ var promptAuditCommand = new Command32("prompt-audit").description("Dry-run prompt construction and report estimated token counts by job type").option("--task <id>", "Audit prompts for a specific task ID").option("--all", "Audit all supported job types with representative data", false).option("--json", "Output as JSON instead of plain text", false).action(async (opts) => {
8354
8586
  const results = [];
8355
8587
  if (opts.task) {
8356
8588
  try {
@@ -8410,7 +8642,7 @@ ${task.notes}` : "";
8410
8642
  }
8411
8643
  }
8412
8644
  sections.push({ name: "static-instructions (system)", tokens: estimateTokens(
8413
- "status-updates + screenshots + test-plan + no-mr + features-workflow"
8645
+ "status-updates + screenshots + no-mr + features-workflow"
8414
8646
  ) });
8415
8647
  const totalTokens = sections.reduce((sum, s) => sum + s.tokens, 0);
8416
8648
  const promptTokens = sections.filter((s) => !s.name.includes("system")).reduce((sum, s) => sum + s.tokens, 0);
@@ -8559,9 +8791,9 @@ ${r.jobType} [${r.identifier}]`);
8559
8791
  });
8560
8792
 
8561
8793
  // cli/commands/skill.ts
8562
- import { Command as Command30 } from "commander";
8563
- import { createInterface as createInterface3 } from "readline/promises";
8564
- var c11 = {
8794
+ import { Command as Command33 } from "commander";
8795
+ import { createInterface as createInterface4 } from "readline/promises";
8796
+ var c12 = {
8565
8797
  reset: "\x1B[0m",
8566
8798
  bold: "\x1B[1m",
8567
8799
  dim: "\x1B[2m",
@@ -8594,7 +8826,7 @@ function formatSize(bytes) {
8594
8826
  if (bytes < 1024) return `${bytes}b`;
8595
8827
  return `${(bytes / 1024).toFixed(1)}kb`;
8596
8828
  }
8597
- var skillCommand = new Command30("skill").description("Manage skills \u2014 reusable playbooks for AI agents");
8829
+ var skillCommand = new Command33("skill").description("Manage skills \u2014 reusable playbooks for AI agents");
8598
8830
  skillCommand.command("list").alias("ls").description("List all skills").option("--category <category>", "Filter by category").action(async (opts) => {
8599
8831
  const params = new URLSearchParams();
8600
8832
  if (opts.category) params.set("category", opts.category);
@@ -8602,17 +8834,17 @@ skillCommand.command("list").alias("ls").description("List all skills").option("
8602
8834
  `/api/skills${params.toString() ? `?${params}` : ""}`
8603
8835
  );
8604
8836
  if (skills.length === 0) {
8605
- console.log(`${c11.dim}No skills found.${c11.reset}`);
8837
+ console.log(`${c12.dim}No skills found.${c12.reset}`);
8606
8838
  return;
8607
8839
  }
8608
8840
  for (const skill of skills) {
8609
- const cat = skill.category ? ` ${c11.dim}[${skill.category}]${c11.reset}` : "";
8610
- const scope = skill.projectId ? ` ${c11.dim}(project)${c11.reset}` : ` ${c11.dim}(global)${c11.reset}`;
8611
- console.log(` ${c11.cyan}${skill.name}${c11.reset}${cat}${scope}`);
8841
+ const cat = skill.category ? ` ${c12.dim}[${skill.category}]${c12.reset}` : "";
8842
+ const scope = skill.projectId ? ` ${c12.dim}(project)${c12.reset}` : ` ${c12.dim}(global)${c12.reset}`;
8843
+ console.log(` ${c12.cyan}${skill.name}${c12.reset}${cat}${scope}`);
8612
8844
  if (skill.description) {
8613
- console.log(` ${c11.dim}${skill.description}${c11.reset}`);
8845
+ console.log(` ${c12.dim}${skill.description}${c12.reset}`);
8614
8846
  }
8615
- console.log(` ${c11.dim}id: ${skill.id}${c11.reset}`);
8847
+ console.log(` ${c12.dim}id: ${skill.id}${c12.reset}`);
8616
8848
  }
8617
8849
  });
8618
8850
  skillCommand.command("create").description("Create a new skill from a markdown file or inline content").argument("<name>", "Skill name").option("-d, --description <desc>", "Short description").option("-c, --category <cat>", "Category (e.g. Deployment, Testing)").option("-f, --file <path>", "Read content from a markdown file").option("--content <text>", "Inline markdown content").option("-p, --project", "Scope to the linked project").action(async (name, opts) => {
@@ -8648,7 +8880,7 @@ skillCommand.command("create").description("Create a new skill from a markdown f
8648
8880
  projectId
8649
8881
  });
8650
8882
  console.log(
8651
- `${c11.green}Created skill:${c11.reset} ${c11.bold}${skill.name}${c11.reset} ${c11.dim}(${skill.id})${c11.reset}`
8883
+ `${c12.green}Created skill:${c12.reset} ${c12.bold}${skill.name}${c12.reset} ${c12.dim}(${skill.id})${c12.reset}`
8652
8884
  );
8653
8885
  });
8654
8886
  skillCommand.command("update").description(
@@ -8709,14 +8941,14 @@ skillCommand.command("update").description(
8709
8941
  const beforeContent = existing.content ?? "";
8710
8942
  const afterContent = typeof patch.content === "string" ? patch.content : beforeContent;
8711
8943
  const contentChanged = typeof patch.content === "string" && patch.content !== beforeContent;
8712
- const sizeDiff = typeof patch.content === "string" ? ` ${c11.dim}(${formatSize(Buffer.byteLength(beforeContent, "utf-8"))} -> ${formatSize(Buffer.byteLength(afterContent, "utf-8"))})${c11.reset}` : "";
8944
+ const sizeDiff = typeof patch.content === "string" ? ` ${c12.dim}(${formatSize(Buffer.byteLength(beforeContent, "utf-8"))} -> ${formatSize(Buffer.byteLength(afterContent, "utf-8"))})${c12.reset}` : "";
8713
8945
  const priorRevisions = existing.revisions?.length ?? 0;
8714
8946
  const revisionsAfter = priorRevisions + (contentChanged ? 1 : 0);
8715
- const revisionNote = contentChanged ? ` ${c11.dim}kept ${revisionsAfter} prior revision${revisionsAfter === 1 ? "" : "s"}${c11.reset}` : "";
8947
+ const revisionNote = contentChanged ? ` ${c12.dim}kept ${revisionsAfter} prior revision${revisionsAfter === 1 ? "" : "s"}${c12.reset}` : "";
8716
8948
  console.log(
8717
- `${c11.green}Updated skill:${c11.reset} ${c11.bold}${updated.name}${c11.reset}${sizeDiff}${revisionNote}`
8949
+ `${c12.green}Updated skill:${c12.reset} ${c12.bold}${updated.name}${c12.reset}${sizeDiff}${revisionNote}`
8718
8950
  );
8719
- console.log(` ${c11.dim}id: ${updated.id}${c11.reset}`);
8951
+ console.log(` ${c12.dim}id: ${updated.id}${c12.reset}`);
8720
8952
  });
8721
8953
  skillCommand.command("delete").alias("rm").description("Delete a skill").argument("<idOrName>", "Skill id or name").option("--yes", "Skip confirmation prompt").action(async (idOrName, opts) => {
8722
8954
  let skill;
@@ -8727,9 +8959,9 @@ skillCommand.command("delete").alias("rm").description("Delete a skill").argumen
8727
8959
  process.exit(1);
8728
8960
  }
8729
8961
  if (!opts.yes) {
8730
- const rl = createInterface3({ input: process.stdin, output: process.stdout });
8962
+ const rl = createInterface4({ input: process.stdin, output: process.stdout });
8731
8963
  const answer = (await rl.question(
8732
- `Delete skill ${c11.bold}${skill.name}${c11.reset} ${c11.dim}(${skill.id})${c11.reset}? [y/N] `
8964
+ `Delete skill ${c12.bold}${skill.name}${c12.reset} ${c12.dim}(${skill.id})${c12.reset}? [y/N] `
8733
8965
  )).trim().toLowerCase();
8734
8966
  rl.close();
8735
8967
  if (answer !== "y" && answer !== "yes") {
@@ -8739,7 +8971,7 @@ skillCommand.command("delete").alias("rm").description("Delete a skill").argumen
8739
8971
  }
8740
8972
  await api.del(`/api/skills/${skill.id}`);
8741
8973
  console.log(
8742
- `${c11.yellow}Deleted skill:${c11.reset} ${c11.bold}${skill.name}${c11.reset} ${c11.dim}(${skill.id})${c11.reset}`
8974
+ `${c12.yellow}Deleted skill:${c12.reset} ${c12.bold}${skill.name}${c12.reset} ${c12.dim}(${skill.id})${c12.reset}`
8743
8975
  );
8744
8976
  });
8745
8977
  skillCommand.command("generate").alias("gen").description("Generate a new skill using AI from a text prompt").argument("<prompt>", "Describe the skill to generate").option("-p, --project", "Scope to the linked project").action(async (prompt2, opts) => {
@@ -8753,22 +8985,22 @@ skillCommand.command("generate").alias("gen").description("Generate a new skill
8753
8985
  process.exit(1);
8754
8986
  }
8755
8987
  }
8756
- console.log(`${c11.dim}Generating skill...${c11.reset}`);
8988
+ console.log(`${c12.dim}Generating skill...${c12.reset}`);
8757
8989
  try {
8758
8990
  const skill = await api.post("/api/skills/generate", {
8759
8991
  prompt: prompt2,
8760
8992
  projectId
8761
8993
  });
8762
8994
  console.log(
8763
- `${c11.green}Generated skill:${c11.reset} ${c11.bold}${skill.name}${c11.reset}`
8995
+ `${c12.green}Generated skill:${c12.reset} ${c12.bold}${skill.name}${c12.reset}`
8764
8996
  );
8765
8997
  if (skill.description) {
8766
- console.log(` ${c11.dim}${skill.description}${c11.reset}`);
8998
+ console.log(` ${c12.dim}${skill.description}${c12.reset}`);
8767
8999
  }
8768
9000
  if (skill.category) {
8769
- console.log(` ${c11.dim}Category: ${skill.category}${c11.reset}`);
9001
+ console.log(` ${c12.dim}Category: ${skill.category}${c12.reset}`);
8770
9002
  }
8771
- console.log(` ${c11.dim}id: ${skill.id}${c11.reset}`);
9003
+ console.log(` ${c12.dim}id: ${skill.id}${c12.reset}`);
8772
9004
  } catch (err) {
8773
9005
  console.error(`Failed to generate skill: ${err.message}`);
8774
9006
  process.exit(1);
@@ -8776,8 +9008,8 @@ skillCommand.command("generate").alias("gen").description("Generate a new skill
8776
9008
  });
8777
9009
 
8778
9010
  // cli/commands/resource.ts
8779
- import { Command as Command31 } from "commander";
8780
- var c12 = {
9011
+ import { Command as Command34 } from "commander";
9012
+ var c13 = {
8781
9013
  reset: "\x1B[0m",
8782
9014
  bold: "\x1B[1m",
8783
9015
  dim: "\x1B[2m",
@@ -8787,16 +9019,16 @@ var c12 = {
8787
9019
  magenta: "\x1B[35m"
8788
9020
  };
8789
9021
  var TYPE_COLORS = {
8790
- plan: c12.cyan,
8791
- research: c12.magenta,
8792
- "test-plan": c12.yellow,
8793
- note: c12.green
9022
+ plan: c13.cyan,
9023
+ research: c13.magenta,
9024
+ "test-plan": c13.yellow,
9025
+ note: c13.green
8794
9026
  };
8795
9027
  function typeLabel(type) {
8796
- const color = TYPE_COLORS[type] ?? c12.dim;
8797
- return `${color}${type}${c12.reset}`;
9028
+ const color = TYPE_COLORS[type] ?? c13.dim;
9029
+ return `${color}${type}${c13.reset}`;
8798
9030
  }
8799
- var resourceCommand = new Command31("resource").description("Manage resources \u2014 documents, plans, research, and notes");
9031
+ var resourceCommand = new Command34("resource").description("Manage resources \u2014 documents, plans, research, and notes");
8800
9032
  resourceCommand.command("list").alias("ls").description("List resources for the linked project (or all)").option("--all", "List all resources across projects").action(async (opts) => {
8801
9033
  const params = new URLSearchParams();
8802
9034
  if (opts.all) {
@@ -8809,13 +9041,13 @@ resourceCommand.command("list").alias("ls").description("List resources for the
8809
9041
  `/api/resources${params.toString() ? `?${params}` : ""}`
8810
9042
  );
8811
9043
  if (resources.length === 0) {
8812
- console.log(`${c12.dim}No resources found.${c12.reset}`);
9044
+ console.log(`${c13.dim}No resources found.${c13.reset}`);
8813
9045
  return;
8814
9046
  }
8815
9047
  for (const r of resources) {
8816
- const project = r.projectName ? ` ${c12.dim}[${r.projectName}]${c12.reset}` : "";
8817
- console.log(` ${typeLabel(r.type)} ${c12.bold}${r.title}${c12.reset}${project}`);
8818
- console.log(` ${c12.dim}id: ${r.id}${c12.reset}`);
9048
+ const project = r.projectName ? ` ${c13.dim}[${r.projectName}]${c13.reset}` : "";
9049
+ console.log(` ${typeLabel(r.type)} ${c13.bold}${r.title}${c13.reset}${project}`);
9050
+ console.log(` ${c13.dim}id: ${r.id}${c13.reset}`);
8819
9051
  }
8820
9052
  });
8821
9053
  resourceCommand.command("create").description("Create a new resource from a file or inline content").argument("<title>", "Resource title").option("-t, --type <type>", "Resource type (note, plan, research, test-plan)", "note").option("-f, --file <path>", "Read content from a file").option("--content <text>", "Inline content").option("--task <taskId>", "Attach to an existing task instead of creating a standalone resource").option("-p, --project", "Scope to the linked project").action(async (title, opts) => {
@@ -8840,9 +9072,9 @@ resourceCommand.command("create").description("Create a new resource from a file
8840
9072
  content: content.trim()
8841
9073
  });
8842
9074
  console.log(
8843
- `${c12.green}Created resource:${c12.reset} ${c12.bold}${title}${c12.reset} ${c12.dim}(${resource.id})${c12.reset}`
9075
+ `${c13.green}Created resource:${c13.reset} ${c13.bold}${title}${c13.reset} ${c13.dim}(${resource.id})${c13.reset}`
8844
9076
  );
8845
- console.log(` ${c12.dim}Attached to task ${opts.task}${c12.reset}`);
9077
+ console.log(` ${c13.dim}Attached to task ${opts.task}${c13.reset}`);
8846
9078
  return;
8847
9079
  }
8848
9080
  let projectId;
@@ -8862,7 +9094,7 @@ resourceCommand.command("create").description("Create a new resource from a file
8862
9094
  projectId
8863
9095
  });
8864
9096
  console.log(
8865
- `${c12.green}Created resource:${c12.reset} ${c12.bold}${title}${c12.reset} ${c12.dim}(${result.resource.id})${c12.reset}`
9097
+ `${c13.green}Created resource:${c13.reset} ${c13.bold}${title}${c13.reset} ${c13.dim}(${result.resource.id})${c13.reset}`
8866
9098
  );
8867
9099
  });
8868
9100
  resourceCommand.command("generate").alias("gen").description("Generate a resource using AI from a text prompt").argument("<prompt>", "Describe the resource to generate").option("-t, --type <type>", "Resource type (plan or research)", "research").option("-p, --project", "Scope to the linked project").action(async (prompt2, opts) => {
@@ -8881,30 +9113,30 @@ resourceCommand.command("generate").alias("gen").description("Generate a resourc
8881
9113
  process.exit(1);
8882
9114
  }
8883
9115
  }
8884
- console.log(`${c12.dim}Generating ${type}...${c12.reset}`);
9116
+ console.log(`${c13.dim}Generating ${type}...${c13.reset}`);
8885
9117
  const result = await api.post("/api/resources", {
8886
9118
  type,
8887
9119
  prompt: prompt2,
8888
9120
  projectId
8889
9121
  });
8890
9122
  console.log(
8891
- `${c12.green}Queued:${c12.reset} ${c12.bold}${result.task.title}${c12.reset}`
9123
+ `${c13.green}Queued:${c13.reset} ${c13.bold}${result.task.title}${c13.reset}`
8892
9124
  );
8893
- console.log(` ${c12.dim}task: ${result.task.id}${c12.reset}`);
9125
+ console.log(` ${c13.dim}task: ${result.task.id}${c13.reset}`);
8894
9126
  });
8895
9127
 
8896
9128
  // cli/commands/tests.ts
8897
- import { Command as Command32 } from "commander";
8898
- var c13 = {
9129
+ import { Command as Command35 } from "commander";
9130
+ var c14 = {
8899
9131
  reset: "\x1B[0m",
8900
9132
  dim: "\x1B[2m",
8901
9133
  yellow: "\x1B[33m"
8902
9134
  };
8903
- var testsCommand = new Command32("tests").description("List MR Test scenarios for the linked project").action(async () => {
9135
+ var testsCommand = new Command35("tests").description("List MR Test scenarios for the linked project").action(async () => {
8904
9136
  const projectId = getLinkedProjectId();
8905
9137
  if (!projectId) {
8906
9138
  console.error(
8907
- `${c13.yellow}No project linked to this directory.${c13.reset} Run "mr link <project-id>" first.`
9139
+ `${c14.yellow}No project linked to this directory.${c14.reset} Run "mr link <project-id>" first.`
8908
9140
  );
8909
9141
  process.exit(1);
8910
9142
  }
@@ -8917,13 +9149,13 @@ var testsCommand = new Command32("tests").description("List MR Test scenarios fo
8917
9149
  process.exit(1);
8918
9150
  }
8919
9151
  if (scenarios.length === 0) {
8920
- console.log(`${c13.dim}No test scenarios found for this project.${c13.reset}`);
9152
+ console.log(`${c14.dim}No test scenarios found for this project.${c14.reset}`);
8921
9153
  return;
8922
9154
  }
8923
9155
  for (const scenario of scenarios) {
8924
9156
  console.log(`### ${scenario.name}`);
8925
9157
  if (scenario.description) {
8926
- console.log(`${c13.dim}${scenario.description}${c13.reset}`);
9158
+ console.log(`${c14.dim}${scenario.description}${c14.reset}`);
8927
9159
  console.log();
8928
9160
  }
8929
9161
  console.log(scenario.content);
@@ -8932,9 +9164,9 @@ var testsCommand = new Command32("tests").description("List MR Test scenarios fo
8932
9164
  });
8933
9165
 
8934
9166
  // cli/commands/walkthrough.ts
8935
- import { Command as Command33 } from "commander";
9167
+ import { Command as Command36 } from "commander";
8936
9168
  var SKILL_NAME = "Generate Walkthrough Video";
8937
- var walkthroughCommand = new Command33("walkthrough").description("Attach the Generate Walkthrough Video skill to a task and queue it").argument("<task-id>", "Task ID to generate a walkthrough for").option("--prod", "Allow recording against production (requires explicit confirmation)").action(async (taskId, opts) => {
9169
+ var walkthroughCommand = new Command36("walkthrough").description("Attach the Generate Walkthrough Video skill to a task and queue it").argument("<task-id>", "Task ID to generate a walkthrough for").option("--prod", "Allow recording against production (requires explicit confirmation)").action(async (taskId, opts) => {
8938
9170
  const skills = await api.get("/api/skills");
8939
9171
  const skill = skills.find((s) => s.name === SKILL_NAME);
8940
9172
  if (!skill) {
@@ -8967,7 +9199,7 @@ var userArgs = process.argv.slice(2);
8967
9199
  var bypassCommands = /* @__PURE__ */ new Set(["login", "init", "auth", "help", "--help", "-h", "--version", "-V", "doctor", "setup"]);
8968
9200
  var shouldBypass = userArgs.length > 0 && bypassCommands.has(userArgs[0]);
8969
9201
  if (isFirstRun && !shouldBypass) {
8970
- const c14 = {
9202
+ const c15 = {
8971
9203
  reset: "\x1B[0m",
8972
9204
  bold: "\x1B[1m",
8973
9205
  dim: "\x1B[2m",
@@ -8977,28 +9209,28 @@ if (isFirstRun && !shouldBypass) {
8977
9209
  magenta: "\x1B[35m"
8978
9210
  };
8979
9211
  console.log("");
8980
- console.log(`${c14.cyan} \u2554\u2566\u2557\u2566\u2550\u2557 \u2554\u2566\u2557\u2554\u2550\u2557\u2554\u2557\u2554\u2554\u2550\u2557\u2554\u2550\u2557\u2554\u2550\u2557\u2566\u2550\u2557${c14.reset}`);
8981
- console.log(`${c14.magenta} \u2551\u2551\u2551\u2560\u2566\u255D \u2551\u2551\u2551\u2560\u2550\u2563\u2551\u2551\u2551\u2560\u2550\u2563\u2551 \u2566\u2551\u2563 \u2560\u2566\u255D${c14.reset}`);
8982
- console.log(`${c14.cyan} \u2569 \u2569\u2569\u255A\u2550 \u2569 \u2569\u2569 \u2569\u255D\u255A\u255D\u2569 \u2569\u255A\u2550\u255D\u255A\u2550\u255D\u2569\u255A\u2550${c14.reset}`);
8983
- console.log(`${c14.dim} \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c14.reset}`);
9212
+ console.log(`${c15.cyan} \u2554\u2566\u2557\u2566\u2550\u2557 \u2554\u2566\u2557\u2554\u2550\u2557\u2554\u2557\u2554\u2554\u2550\u2557\u2554\u2550\u2557\u2554\u2550\u2557\u2566\u2550\u2557${c15.reset}`);
9213
+ console.log(`${c15.magenta} \u2551\u2551\u2551\u2560\u2566\u255D \u2551\u2551\u2551\u2560\u2550\u2563\u2551\u2551\u2551\u2560\u2550\u2563\u2551 \u2566\u2551\u2563 \u2560\u2566\u255D${c15.reset}`);
9214
+ console.log(`${c15.cyan} \u2569 \u2569\u2569\u255A\u2550 \u2569 \u2569\u2569 \u2569\u255D\u255A\u255D\u2569 \u2569\u255A\u2550\u255D\u255A\u2550\u255D\u2569\u255A\u2550${c15.reset}`);
9215
+ console.log(`${c15.dim} \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${c15.reset}`);
8984
9216
  console.log("");
8985
- console.log(`${c14.bold} Welcome to Mr. Manager!${c14.reset}`);
8986
- console.log(`${c14.dim} Let's get you set up in a few quick steps.${c14.reset}`);
9217
+ console.log(`${c15.bold} Welcome to Mr. Manager!${c15.reset}`);
9218
+ console.log(`${c15.dim} Let's get you set up in a few quick steps.${c15.reset}`);
8987
9219
  console.log("");
8988
- console.log(` ${c14.yellow}Step 1:${c14.reset} Authenticate via Google OAuth`);
8989
- console.log(` ${c14.dim}Run:${c14.reset} ${c14.cyan}mr login${c14.reset}`);
9220
+ console.log(` ${c15.yellow}Step 1:${c15.reset} Authenticate via Google OAuth`);
9221
+ console.log(` ${c15.dim}Run:${c15.reset} ${c15.cyan}mr login${c15.reset}`);
8990
9222
  console.log("");
8991
- console.log(` ${c14.yellow}Step 2:${c14.reset} Verify your environment`);
8992
- console.log(` ${c14.dim}Run:${c14.reset} ${c14.cyan}mr setup${c14.reset}`);
9223
+ console.log(` ${c15.yellow}Step 2:${c15.reset} Verify your environment`);
9224
+ console.log(` ${c15.dim}Run:${c15.reset} ${c15.cyan}mr setup${c15.reset}`);
8993
9225
  console.log("");
8994
- console.log(` ${c14.yellow}Step 3:${c14.reset} Link a repo and start watching`);
8995
- console.log(` ${c14.dim}Run:${c14.reset} ${c14.cyan}mr link${c14.reset} ${c14.dim}&&${c14.reset} ${c14.cyan}mr watch${c14.reset}`);
9226
+ console.log(` ${c15.yellow}Step 3:${c15.reset} Link a repo and start watching`);
9227
+ console.log(` ${c15.dim}Run:${c15.reset} ${c15.cyan}mr link${c15.reset} ${c15.dim}&&${c15.reset} ${c15.cyan}mr watch${c15.reset}`);
8996
9228
  console.log("");
8997
- console.log(`${c14.dim} Or run ${c14.reset}${c14.cyan}mr login${c14.reset}${c14.dim} to get started now.${c14.reset}`);
9229
+ console.log(`${c15.dim} Or run ${c15.reset}${c15.cyan}mr login${c15.reset}${c15.dim} to get started now.${c15.reset}`);
8998
9230
  console.log("");
8999
9231
  process.exit(0);
9000
9232
  }
9001
- var program = new Command34();
9233
+ var program = new Command37();
9002
9234
  program.name("mr").description("Mr. Manager - Task and project management CLI").version(CLI_VERSION);
9003
9235
  program.addCommand(initCommand);
9004
9236
  program.addCommand(authCommand);
@@ -9015,6 +9247,9 @@ program.addCommand(delegateCommand);
9015
9247
  program.addCommand(undelegateCommand);
9016
9248
  program.addCommand(createCommand);
9017
9249
  program.addCommand(completeCommand);
9250
+ program.addCommand(showCommand);
9251
+ program.addCommand(editCommand);
9252
+ program.addCommand(deleteCommand);
9018
9253
  program.addCommand(subtaskCompleteCommand);
9019
9254
  program.addCommand(subtaskAddCommand);
9020
9255
  program.addCommand(prototypeCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dunnewold-labs/mr-manager",
3
- "version": "0.4.55",
3
+ "version": "0.4.56",
4
4
  "description": "Mr. Manager - Task and project management CLI",
5
5
  "bin": {
6
6
  "mr": "./dist/index.mjs"