@dunnewold-labs/mr-manager 0.4.53 → 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 +543 -175
  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.53",
188
+ version: "0.4.56",
189
189
  description: "Mr. Manager - Task and project management CLI",
190
190
  bin: {
191
191
  mr: "./dist/index.mjs"
@@ -1151,6 +1151,118 @@ function getAvailableAgentFallbackChain(agent, availability) {
1151
1151
  return getAgentFallbackChain(agent).filter((candidate) => availability[candidate] !== false);
1152
1152
  }
1153
1153
 
1154
+ // lib/permissions.ts
1155
+ var DEFAULT_HEADLESS_MODE = "bypass";
1156
+ var ENV_VAR = "MR_HEADLESS_PERMISSION_MODE";
1157
+ var DESTRUCTIVE_BASH_DENY = [
1158
+ // Privilege escalation.
1159
+ "Bash(sudo:*)",
1160
+ "Bash(su:*)",
1161
+ // Recursive deletes of broad / out-of-repo roots.
1162
+ "Bash(rm -rf /:*)",
1163
+ "Bash(rm -rf /*:*)",
1164
+ "Bash(rm -fr /:*)",
1165
+ "Bash(rm -rf ~:*)",
1166
+ "Bash(rm -rf ~/:*)",
1167
+ "Bash(rm -rf $HOME:*)",
1168
+ "Bash(rm -rf ..:*)",
1169
+ // Filesystem / device destruction.
1170
+ "Bash(mkfs:*)",
1171
+ "Bash(dd:*)",
1172
+ // Mass permission/ownership changes from root.
1173
+ "Bash(chmod -R 777 /:*)",
1174
+ "Bash(chown -R:*)",
1175
+ // Force-push (history rewrite / remote clobber).
1176
+ "Bash(git push --force:*)",
1177
+ "Bash(git push -f:*)",
1178
+ "Bash(git push origin --force:*)",
1179
+ "Bash(git push origin -f:*)",
1180
+ // Remote pipe-to-shell (curl|sh / wget|bash).
1181
+ "Bash(curl:* | sh)",
1182
+ "Bash(curl:* | bash)",
1183
+ "Bash(wget:* | sh)",
1184
+ "Bash(wget:* | bash)"
1185
+ ];
1186
+ var OUT_OF_REPO_WRITE_DENY = [
1187
+ "Write(/etc/**)",
1188
+ "Edit(/etc/**)",
1189
+ "Write(//usr/**)",
1190
+ "Edit(//usr/**)",
1191
+ "Write(~/.ssh/**)",
1192
+ "Edit(~/.ssh/**)",
1193
+ "Write(~/.aws/**)",
1194
+ "Edit(~/.aws/**)"
1195
+ ];
1196
+ var READ_ONLY_EXTRA_DENY = ["Edit", "Write", "MultiEdit", "NotebookEdit"];
1197
+ function resolveHeadlessMode(config) {
1198
+ const fromEnv = process.env[ENV_VAR]?.trim().toLowerCase();
1199
+ if (fromEnv === "auto" || fromEnv === "bypass") return fromEnv;
1200
+ const fromConfig = config?.headlessPermissionMode?.trim().toLowerCase();
1201
+ if (fromConfig === "auto" || fromConfig === "bypass") return fromConfig;
1202
+ if (config?.claudePermissionMode != null && config.headlessPermissionMode == null) {
1203
+ return "bypass";
1204
+ }
1205
+ return DEFAULT_HEADLESS_MODE;
1206
+ }
1207
+ function claudeDenyList(runKind) {
1208
+ const base = [...DESTRUCTIVE_BASH_DENY, ...OUT_OF_REPO_WRITE_DENY];
1209
+ if (runKind === "review" || runKind === "scan") {
1210
+ return [...base, ...READ_ONLY_EXTRA_DENY];
1211
+ }
1212
+ return base;
1213
+ }
1214
+ function resolvePermissionArgs(agent, runKind, mode) {
1215
+ if (runKind === "plan") {
1216
+ if (agent === "claude") {
1217
+ return { args: ["--permission-mode", "plan"], effectiveMode: "plan", mappedToBypassForLackOfSandbox: false };
1218
+ }
1219
+ return resolvePermissionArgs(agent, "execute", mode);
1220
+ }
1221
+ if (mode === "bypass") {
1222
+ return { args: bypassArgs(agent, runKind), effectiveMode: "bypass", mappedToBypassForLackOfSandbox: false };
1223
+ }
1224
+ switch (agent) {
1225
+ case "claude": {
1226
+ const deny = claudeDenyList(runKind);
1227
+ return {
1228
+ args: ["--permission-mode", "acceptEdits", "--disallowedTools", deny.join(",")],
1229
+ effectiveMode: "auto",
1230
+ mappedToBypassForLackOfSandbox: false
1231
+ };
1232
+ }
1233
+ case "codex": {
1234
+ return { args: ["-s", "workspace-write"], effectiveMode: "auto", mappedToBypassForLackOfSandbox: false };
1235
+ }
1236
+ case "antigravity":
1237
+ return { args: ["--dangerously-skip-permissions"], effectiveMode: "bypass", mappedToBypassForLackOfSandbox: true };
1238
+ default:
1239
+ return { args: bypassArgs(agent, runKind), effectiveMode: "bypass", mappedToBypassForLackOfSandbox: true };
1240
+ }
1241
+ }
1242
+ function bypassArgs(agent, _runKind) {
1243
+ switch (agent) {
1244
+ case "codex":
1245
+ return ["-s", "danger-full-access"];
1246
+ case "antigravity":
1247
+ case "claude":
1248
+ default:
1249
+ return ["--dangerously-skip-permissions"];
1250
+ }
1251
+ }
1252
+ function describePermissionMode(res) {
1253
+ if (res.mappedToBypassForLackOfSandbox) {
1254
+ return "bypass (no scoped sandbox for this agent \u2014 full access)";
1255
+ }
1256
+ switch (res.effectiveMode) {
1257
+ case "auto":
1258
+ return "auto (scoped: acceptEdits + destructive-command deny-list)";
1259
+ case "plan":
1260
+ return "plan (read-only)";
1261
+ case "bypass":
1262
+ return "bypass (--dangerously-skip-permissions \u2014 full access)";
1263
+ }
1264
+ }
1265
+
1154
1266
  // lib/task-workflow.ts
1155
1267
  function normalizeWhitespace(value) {
1156
1268
  return value.replace(/\s+/g, " ").trim();
@@ -1303,6 +1415,22 @@ function tokenLogLine(jobType, identifier, prompt2, systemPrompt) {
1303
1415
  return parts[0];
1304
1416
  }
1305
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
+
1306
1434
  // cli/commands/watch.ts
1307
1435
  var FEATURES_FILE2 = ".mr-features.md";
1308
1436
  var SYSTEM_SECTION_STATUS_UPDATES = `## Status Updates
@@ -1449,7 +1577,6 @@ var SYSTEM_SECTIONS = {
1449
1577
  function composeSystemPrompt(sections) {
1450
1578
  return sections.map((s) => SYSTEM_SECTIONS[s]).join("\n\n");
1451
1579
  }
1452
- var EXECUTION_SYSTEM_SECTIONS = ["status-updates", "screenshots", "test-plan", "mr-tests", "no-mr", "features-workflow"];
1453
1580
  var PRD_SYSTEM_SECTIONS = ["prd-format", "prd-open-questions"];
1454
1581
  var c = {
1455
1582
  reset: "\x1B[0m",
@@ -2851,41 +2978,46 @@ function buildRefinementPrompt(proto, parentFiles, repoDir, options = {}) {
2851
2978
  ].join("\n");
2852
2979
  }
2853
2980
  function buildAgentArgs(agent, prompt2, mode, sessionId, name, resumeSession = false, systemPrompt, maxTurns, claudeModel) {
2981
+ const headlessMode = resolveHeadlessMode(loadConfig());
2982
+ const runKind = mode === "plan" ? "plan" : "execute";
2854
2983
  if (agent === "codex") {
2984
+ const permission2 = resolvePermissionArgs("codex", runKind, headlessMode);
2855
2985
  const args = [];
2856
2986
  if (mode === "execute") {
2857
2987
  args.push("-a", "never");
2858
2988
  }
2859
2989
  args.push("exec");
2860
2990
  if (mode === "execute") {
2861
- args.push("-s", "danger-full-access");
2991
+ args.push(...permission2.args);
2862
2992
  }
2863
2993
  const fullPrompt = systemPrompt ? `${prompt2}
2864
2994
 
2865
2995
  ${systemPrompt}` : prompt2;
2866
2996
  args.push(fullPrompt);
2867
- return { bin: "codex", args };
2997
+ return { bin: "codex", args, permission: permission2 };
2868
2998
  }
2869
2999
  if (agent === "antigravity") {
3000
+ const permission2 = resolvePermissionArgs("antigravity", runKind, headlessMode);
2870
3001
  const fullPrompt = systemPrompt ? `${prompt2}
2871
3002
 
2872
3003
  ${systemPrompt}` : prompt2;
2873
3004
  const args = ["-p", fullPrompt];
2874
3005
  if (mode === "execute") {
2875
- args.push("--dangerously-skip-permissions");
3006
+ args.push(...permission2.args);
2876
3007
  }
2877
- return { bin: AGENT_BINARIES.antigravity, args };
3008
+ return { bin: AGENT_BINARIES.antigravity, args, permission: permission2 };
2878
3009
  }
3010
+ const permission = resolvePermissionArgs("claude", runKind, headlessMode);
2879
3011
  const sessionArgs = sessionId ? resumeSession ? ["--resume", sessionId] : ["--session-id", sessionId] : [];
2880
3012
  const nameArgs = name ? ["--name", name] : [];
2881
3013
  const systemArgs = systemPrompt ? ["--append-system-prompt", systemPrompt] : [];
2882
3014
  const turnsArgs = maxTurns ? ["--max-turns", String(maxTurns)] : [];
2883
3015
  const modelArgs = claudeModel ? ["--model", claudeModel] : [];
2884
- if (mode === "plan") {
2885
- return { bin: "claude", args: [...sessionArgs, ...nameArgs, ...systemArgs, ...turnsArgs, ...modelArgs, "--permission-mode", "plan", "-p", prompt2] };
2886
- }
2887
- const permissionArgs = ["--dangerously-skip-permissions"];
2888
- return { bin: "claude", args: [...sessionArgs, ...nameArgs, ...systemArgs, ...turnsArgs, ...modelArgs, ...permissionArgs, "-p", prompt2] };
3016
+ return {
3017
+ bin: "claude",
3018
+ args: [...sessionArgs, ...nameArgs, ...systemArgs, ...turnsArgs, ...modelArgs, ...permission.args, "-p", prompt2],
3019
+ permission
3020
+ };
2889
3021
  }
2890
3022
  var AGENT_BINARIES = {
2891
3023
  claude: "claude",
@@ -2968,7 +3100,13 @@ function askYesNo(question) {
2968
3100
  function spawnAgent(agent, repoDir, prompt2, prefix, onActivity, sessionId, name, resumeSession = false, onSpawnError, systemPrompt, maxTurns, claudeModel, onOutputBytes) {
2969
3101
  const jobLabel = name ?? "unknown";
2970
3102
  console.log(`${timestamp()} ${prefix} ${paint("dim", tokenLogLine("agent", jobLabel, prompt2, systemPrompt))}`);
2971
- const { bin, args } = buildAgentArgs(agent, prompt2, "execute", sessionId, name, resumeSession, systemPrompt, maxTurns, claudeModel);
3103
+ const { bin, args, permission } = buildAgentArgs(agent, prompt2, "execute", sessionId, name, resumeSession, systemPrompt, maxTurns, claudeModel);
3104
+ const permLine = `${timestamp()} ${prefix} ${paint("dim", `permission: ${describePermissionMode(permission)}`)}`;
3105
+ if (permission.mappedToBypassForLackOfSandbox) {
3106
+ logWarn(prefix, `permission: ${describePermissionMode(permission)}`);
3107
+ } else {
3108
+ console.log(permLine);
3109
+ }
2972
3110
  const child = spawn4(bin, args, { cwd: repoDir, stdio: ["ignore", "pipe", "pipe"] });
2973
3111
  child.on("error", (err) => {
2974
3112
  logError(prefix, `Failed to spawn ${agent}: ${err.message}`);
@@ -3000,13 +3138,14 @@ function spawnAgent(agent, repoDir, prompt2, prefix, onActivity, sessionId, name
3000
3138
  }
3001
3139
  var watchCommand = new Command9("watch").description(
3002
3140
  "Watch for in-progress tasks and autonomously dispatch an AI coding agent to work on them"
3003
- ).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) => {
3004
3142
  const intervalMs = parseInt(opts.interval, 10) * 1e3;
3005
3143
  const dryRun = opts.dryRun;
3006
3144
  const planApproval = opts.planApproval;
3007
3145
  const rootDir = opts.root ? resolve2(opts.root) : process.cwd();
3008
3146
  const agent = opts.agent === "codex" ? "codex" : opts.agent === "antigravity" ? "antigravity" : "claude";
3009
3147
  const scanAt = opts.scanAt;
3148
+ const includeTestPlan = opts.testPlan;
3010
3149
  const taskStallTimeoutMs = getTaskStallTimeoutMs();
3011
3150
  const hungTaskTimeoutMinutes = Math.max(5, parseInt(process.env.MR_WATCH_HUNG_TASK_TIMEOUT_MINUTES ?? "60", 10) || 60);
3012
3151
  const hungTaskTimeoutMs = hungTaskTimeoutMinutes * 6e4;
@@ -3028,6 +3167,7 @@ var watchCommand = new Command9("watch").description(
3028
3167
  ...planApproval ? [paint("yellow", "plan-approval")] : [],
3029
3168
  ...dryRun ? [paint("yellow", "dry-run")] : [],
3030
3169
  ...scanAt ? [`scan-at=${paint("cyan", scanAt)}`] : [],
3170
+ ...includeTestPlan ? [paint("yellow", "test-plan")] : [],
3031
3171
  `hung-timeout=${paint("cyan", `${hungTaskTimeoutMinutes}m`)}`
3032
3172
  ].join(" ");
3033
3173
  const banner = [
@@ -3262,7 +3402,7 @@ var watchCommand = new Command9("watch").description(
3262
3402
  const shouldResumeClaudeSession = attemptAgent === "claude" && !!task.claudeSessionId && !resumeAlreadyRetried && (hasFeedback || pausedForNetwork?.resumeSession === true);
3263
3403
  const sessionId = attemptAgent === "claude" ? shouldResumeClaudeSession ? task.claudeSessionId : randomUUID() : void 0;
3264
3404
  const effectiveClaudeModel = attemptAgent === "claude" ? taskClaudeModel : void 0;
3265
- const systemSections = ["quiet-mode", ...EXECUTION_SYSTEM_SECTIONS];
3405
+ const systemSections = getExecutionSystemSections(includeTestPlan);
3266
3406
  const executionSystemPrompt = composeSystemPrompt(systemSections);
3267
3407
  const child = spawnAgent(
3268
3408
  attemptAgent,
@@ -4020,6 +4160,7 @@ var watchCommand = new Command9("watch").description(
4020
4160
  function dispatchCodeReview(review, prefix, key) {
4021
4161
  logDispatch(prefix, `Running code review on branch ${paint("cyan", review.branch)}`);
4022
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);
4023
4164
  if (review.branchUrl) reviewArgs.push("--pr-url", review.branchUrl);
4024
4165
  if (review.prNumber != null) reviewArgs.push("--pr-number", String(review.prNumber));
4025
4166
  const reviewProc = spawn4(process.execPath, reviewArgs, {
@@ -4857,9 +4998,125 @@ var completeCommand = new Command12("complete").description("Mark a task as comp
4857
4998
  printTaskBanner2(paint3("green", "complete \u2713"), task.title, task.id);
4858
4999
  });
4859
5000
 
4860
- // cli/commands/subtask-complete.ts
5001
+ // cli/commands/show.ts
4861
5002
  import { Command as Command13 } from "commander";
4862
- 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) => {
4863
5120
  const subtask = await api.patch(
4864
5121
  `/api/tasks/${taskId}/subtasks/${subtaskId}`,
4865
5122
  { completed: true }
@@ -4868,8 +5125,8 @@ var subtaskCompleteCommand = new Command13("subtask-complete").description("Mark
4868
5125
  });
4869
5126
 
4870
5127
  // cli/commands/subtask-add.ts
4871
- import { Command as Command14 } from "commander";
4872
- 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) => {
4873
5130
  const title = titleParts.join(" ").trim();
4874
5131
  if (!title) {
4875
5132
  console.error("Subtask title is required.");
@@ -4882,8 +5139,8 @@ var subtaskAddCommand = new Command14("subtask-add").description("Add a subtask
4882
5139
  });
4883
5140
 
4884
5141
  // cli/commands/prototype.ts
4885
- import { Command as Command15 } from "commander";
4886
- var c4 = {
5142
+ import { Command as Command18 } from "commander";
5143
+ var c5 = {
4887
5144
  reset: "\x1B[0m",
4888
5145
  bold: "\x1B[1m",
4889
5146
  dim: "\x1B[2m",
@@ -4895,7 +5152,7 @@ var c4 = {
4895
5152
  gray: "\x1B[90m"
4896
5153
  };
4897
5154
  function paint4(color, text) {
4898
- return `${c4[color]}${text}${c4.reset}`;
5155
+ return `${c5[color]}${text}${c5.reset}`;
4899
5156
  }
4900
5157
  function statusBadge(status) {
4901
5158
  switch (status) {
@@ -4911,8 +5168,8 @@ function statusBadge(status) {
4911
5168
  return paint4("gray", status);
4912
5169
  }
4913
5170
  }
4914
- var prototypeCommand = new Command15("prototype").description("Manage prototypes").addCommand(
4915
- 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) => {
4916
5173
  const params = new URLSearchParams();
4917
5174
  if (!opts.all) {
4918
5175
  const projectId = getLinkedProjectId();
@@ -4946,7 +5203,7 @@ var prototypeCommand = new Command15("prototype").description("Manage prototypes
4946
5203
  }
4947
5204
  })
4948
5205
  ).addCommand(
4949
- 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) => {
4950
5207
  const projectId = opts.project ?? getLinkedProjectId();
4951
5208
  const variantCount = Math.max(1, Math.min(50, parseInt(opts.variants, 10) || 5));
4952
5209
  const validTypes = ["web_app", "mobile_app", "desktop_app", "logo"];
@@ -4987,7 +5244,7 @@ var prototypeCommand = new Command15("prototype").description("Manage prototypes
4987
5244
  console.log();
4988
5245
  })
4989
5246
  ).addCommand(
4990
- 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) => {
4991
5248
  const prototype = await api.patch(`/api/prototypes/${id}`, {
4992
5249
  status: "in_progress"
4993
5250
  });
@@ -4997,7 +5254,7 @@ var prototypeCommand = new Command15("prototype").description("Manage prototypes
4997
5254
  console.log();
4998
5255
  })
4999
5256
  ).addCommand(
5000
- 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) => {
5001
5258
  const prototype = await api.patch(`/api/prototypes/${id}`, {
5002
5259
  status: "in_progress",
5003
5260
  files: null
@@ -5009,9 +5266,9 @@ var prototypeCommand = new Command15("prototype").description("Manage prototypes
5009
5266
  );
5010
5267
 
5011
5268
  // cli/commands/setup.ts
5012
- import { Command as Command16 } from "commander";
5269
+ import { Command as Command19 } from "commander";
5013
5270
  import { exec as exec2 } from "child_process";
5014
- var c5 = {
5271
+ var c6 = {
5015
5272
  reset: "\x1B[0m",
5016
5273
  bold: "\x1B[1m",
5017
5274
  dim: "\x1B[2m",
@@ -5023,7 +5280,7 @@ var c5 = {
5023
5280
  gray: "\x1B[90m"
5024
5281
  };
5025
5282
  function paint5(color, text) {
5026
- return `${c5[color]}${text}${c5.reset}`;
5283
+ return `${c6[color]}${text}${c6.reset}`;
5027
5284
  }
5028
5285
  function commandExists2(cmd) {
5029
5286
  return new Promise((resolve9) => {
@@ -5267,7 +5524,7 @@ async function checkApiConnectivity() {
5267
5524
  }
5268
5525
  }
5269
5526
  function printResults(checks) {
5270
- const maxNameLen = Math.max(...checks.map((c14) => c14.name.length));
5527
+ const maxNameLen = Math.max(...checks.map((c15) => c15.name.length));
5271
5528
  let allOk = true;
5272
5529
  for (const check of checks) {
5273
5530
  const isOptional = check.optional ?? false;
@@ -5281,10 +5538,10 @@ function printResults(checks) {
5281
5538
  }
5282
5539
  async function autoFix(checks, agent) {
5283
5540
  const { spawn: spawn9 } = await import("child_process");
5284
- const ghInstalled = checks.find((c14) => c14.name === "GitHub CLI (gh)").ok;
5285
- const ghAuthed = checks.find((c14) => c14.name === "GitHub CLI auth").ok;
5286
- const mrAuthed = checks.find((c14) => c14.name === "Mr. Manager CLI auth").ok;
5287
- 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)");
5288
5545
  if (claudeCheck && !claudeCheck.ok && agent === "claude") {
5289
5546
  console.log(paint5("cyan", " Installing Claude Code..."));
5290
5547
  console.log(paint5("dim", " Running: curl -fsSL https://claude.ai/install.sh | bash"));
@@ -5312,7 +5569,7 @@ async function autoFix(checks, agent) {
5312
5569
  console.log("");
5313
5570
  }
5314
5571
  }
5315
- 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) => {
5316
5573
  const agent = opts.agent === "codex" ? "codex" : opts.agent === "antigravity" ? "antigravity" : "claude";
5317
5574
  const banner = [
5318
5575
  ``,
@@ -5347,7 +5604,7 @@ var setupCommand = new Command16("setup").description("Check that all dependenci
5347
5604
  console.log("");
5348
5605
  return;
5349
5606
  }
5350
- const fixes = checks.filter((c14) => !c14.ok && c14.fix && !c14.optional);
5607
+ const fixes = checks.filter((c15) => !c15.ok && c15.fix && !c15.optional);
5351
5608
  if (fixes.length > 0) {
5352
5609
  console.log(paint5("yellow", " To fix:"));
5353
5610
  for (const fix of fixes) {
@@ -5362,8 +5619,8 @@ var setupCommand = new Command16("setup").description("Check that all dependenci
5362
5619
  });
5363
5620
 
5364
5621
  // cli/commands/update.ts
5365
- import { Command as Command17 } from "commander";
5366
- 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) => {
5367
5624
  if (opts.resource) {
5368
5625
  if (!messageOrTitle || !content) {
5369
5626
  console.error(`Usage: mr update <task-id> --resource <type> "<title>" '<content>'`);
@@ -5389,11 +5646,11 @@ var updateCommand = new Command17("update").description("Post a status update to
5389
5646
  });
5390
5647
 
5391
5648
  // cli/commands/screenshot.ts
5392
- import { Command as Command18 } from "commander";
5649
+ import { Command as Command21 } from "commander";
5393
5650
  import { readFileSync as readFileSync6, existsSync as existsSync8, unlinkSync as unlinkSync2 } from "fs";
5394
5651
  import { join as join7 } from "path";
5395
5652
  import { tmpdir } from "os";
5396
- var screenshotCommand = new Command18("screenshot").description(
5653
+ var screenshotCommand = new Command21("screenshot").description(
5397
5654
  "Take or attach a screenshot to a task update (agents use this to show their work)"
5398
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) => {
5399
5656
  let filePath = file;
@@ -5484,10 +5741,10 @@ var screenshotCommand = new Command18("screenshot").description(
5484
5741
  });
5485
5742
 
5486
5743
  // cli/commands/resume.ts
5487
- import { Command as Command19 } from "commander";
5744
+ import { Command as Command22 } from "commander";
5488
5745
  import { spawn as spawn5 } from "child_process";
5489
5746
  import { resolve as resolve3 } from "path";
5490
- var c6 = {
5747
+ var c7 = {
5491
5748
  reset: "\x1B[0m",
5492
5749
  bold: "\x1B[1m",
5493
5750
  dim: "\x1B[2m",
@@ -5499,9 +5756,9 @@ var c6 = {
5499
5756
  gray: "\x1B[90m"
5500
5757
  };
5501
5758
  function paint6(color, text) {
5502
- return `${c6[color]}${text}${c6.reset}`;
5759
+ return `${c7[color]}${text}${c7.reset}`;
5503
5760
  }
5504
- 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) => {
5505
5762
  const task = await api.get(`/api/tasks/${taskId}`);
5506
5763
  if (!task.claudeSessionId) {
5507
5764
  console.error(
@@ -5570,7 +5827,7 @@ var resumeCommand = new Command19("resume").description("Resume an interactive C
5570
5827
  });
5571
5828
 
5572
5829
  // cli/commands/browse.ts
5573
- import { Command as Command20 } from "commander";
5830
+ import { Command as Command23 } from "commander";
5574
5831
  import { execSync as execSync4, spawn as spawn6 } from "child_process";
5575
5832
  import { existsSync as existsSync9, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
5576
5833
  import { createHash } from "crypto";
@@ -5685,7 +5942,7 @@ async function ensureDevServer(options = {}) {
5685
5942
  }
5686
5943
  throw new Error(`Dev server failed to start within 60s. Command: ${devCmd} in ${projectCwd}`);
5687
5944
  }
5688
- 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(
5689
5946
  "--task-id <id>",
5690
5947
  "Attach output to a task update (for screenshot and recording-stop commands)"
5691
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(
@@ -5828,10 +6085,10 @@ var browseCommand = new Command20("browse").description("Control a headless brow
5828
6085
  );
5829
6086
 
5830
6087
  // cli/commands/set-path.ts
5831
- import { Command as Command21 } from "commander";
6088
+ import { Command as Command24 } from "commander";
5832
6089
  import { resolve as resolve5 } from "path";
5833
6090
  import { existsSync as existsSync10 } from "fs";
5834
- 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) => {
5835
6092
  const absolutePath = resolve5(pathArg);
5836
6093
  if (!existsSync10(absolutePath)) {
5837
6094
  console.error(`Error: Path does not exist: ${absolutePath}`);
@@ -5849,9 +6106,9 @@ var setPathCommand = new Command21("set-path").description("Set or update the lo
5849
6106
  });
5850
6107
 
5851
6108
  // cli/commands/test.ts
5852
- import { Command as Command22 } from "commander";
6109
+ import { Command as Command25 } from "commander";
5853
6110
  import { readFileSync as readFileSync8, existsSync as existsSync11 } from "fs";
5854
- 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) => {
5855
6112
  const config = loadConfig();
5856
6113
  console.log("[test] Fetching task...");
5857
6114
  let task;
@@ -6013,11 +6270,11 @@ var testCommand = new Command22("test").description("Run automated browser test
6013
6270
  });
6014
6271
 
6015
6272
  // cli/commands/features.ts
6016
- import { Command as Command23 } from "commander";
6273
+ import { Command as Command26 } from "commander";
6017
6274
  import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, existsSync as existsSync12 } from "fs";
6018
6275
  import { resolve as resolve6, sep as sep2 } from "path";
6019
6276
  var FEATURES_FILE3 = ".mr-features.md";
6020
- var c7 = {
6277
+ var c8 = {
6021
6278
  reset: "\x1B[0m",
6022
6279
  bold: "\x1B[1m",
6023
6280
  dim: "\x1B[2m",
@@ -6028,7 +6285,7 @@ var c7 = {
6028
6285
  gray: "\x1B[90m"
6029
6286
  };
6030
6287
  function paint7(color, text) {
6031
- return `${c7[color]}${text}${c7.reset}`;
6288
+ return `${c8[color]}${text}${c8.reset}`;
6032
6289
  }
6033
6290
  function resolveProjectRoot2() {
6034
6291
  const cwd = process.cwd();
@@ -6047,7 +6304,7 @@ function readFeatures2() {
6047
6304
  if (!existsSync12(path)) return null;
6048
6305
  return readFileSync9(path, "utf-8");
6049
6306
  }
6050
- 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) => {
6051
6308
  if (opts.path) {
6052
6309
  console.log(getFeaturesPath());
6053
6310
  return;
@@ -6075,11 +6332,11 @@ var featuresCommand = new Command23("features").description("View or update the
6075
6332
  });
6076
6333
 
6077
6334
  // cli/commands/no-mr.ts
6078
- import { Command as Command24 } from "commander";
6335
+ import { Command as Command27 } from "commander";
6079
6336
  import { writeFileSync as writeFileSync6 } from "fs";
6080
6337
  import { resolve as resolve7 } from "path";
6081
6338
  var NO_MR_FILE = ".mr-no-mr";
6082
- 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) => {
6083
6340
  const filePath = resolve7(process.cwd(), NO_MR_FILE);
6084
6341
  writeFileSync6(filePath, description, "utf-8");
6085
6342
  await api.post(`/api/tasks/${taskId}/updates`, {
@@ -6091,12 +6348,12 @@ var noMrCommand = new Command24("no-mr").description("Signal that a task does no
6091
6348
  });
6092
6349
 
6093
6350
  // cli/commands/review.ts
6094
- import { Command as Command26 } from "commander";
6351
+ import { Command as Command29 } from "commander";
6095
6352
  import { execSync as execSync6 } from "child_process";
6096
6353
  import { existsSync as existsSync14, statSync as statSync2 } from "fs";
6097
6354
 
6098
6355
  // cli/commands/review-apply.ts
6099
- import { Command as Command25 } from "commander";
6356
+ import { Command as Command28 } from "commander";
6100
6357
  import { execSync as execSync5 } from "child_process";
6101
6358
  import { existsSync as existsSync13 } from "fs";
6102
6359
 
@@ -6119,18 +6376,26 @@ async function resolveReviewAgentChain(preferred2 = "claude") {
6119
6376
  }
6120
6377
  return getAvailableAgentFallbackChain(preferred2, availability);
6121
6378
  }
6122
- function buildArgs(agent, prompt2) {
6379
+ function buildArgs(agent, prompt2, runKind) {
6380
+ const mode = resolveHeadlessMode(loadConfig());
6381
+ const permission = resolvePermissionArgs(agent, runKind, mode);
6123
6382
  if (agent === "codex") {
6124
- return ["-a", "never", "exec", "-s", "danger-full-access", prompt2];
6383
+ return ["-a", "never", "exec", ...permission.args, prompt2];
6125
6384
  }
6126
6385
  if (agent === "antigravity") {
6127
- return ["-p", prompt2, "--dangerously-skip-permissions"];
6386
+ return ["-p", prompt2, ...permission.args];
6128
6387
  }
6129
- return ["-p", "--dangerously-skip-permissions", prompt2];
6388
+ return ["-p", ...permission.args, prompt2];
6389
+ }
6390
+ function logPermission(agent, runKind) {
6391
+ const permission = resolvePermissionArgs(agent, runKind, resolveHeadlessMode(loadConfig()));
6392
+ const label = permission.mappedToBypassForLackOfSandbox ? "warning" : "info";
6393
+ console.error(`[review:${label}] ${agent} ${runKind} permission: ${describePermissionMode(permission)}`);
6130
6394
  }
6131
6395
  function runOnce(agent, prompt2, opts) {
6132
6396
  return new Promise((resolve9) => {
6133
- const child = spawn7(AGENT_BINARIES2[agent], buildArgs(agent, prompt2), {
6397
+ logPermission(agent, opts.runKind);
6398
+ const child = spawn7(AGENT_BINARIES2[agent], buildArgs(agent, prompt2, opts.runKind), {
6134
6399
  cwd: opts.cwd,
6135
6400
  stdio: opts.capture ? ["ignore", "pipe", "pipe"] : ["ignore", "inherit", "inherit"]
6136
6401
  });
@@ -6156,7 +6421,7 @@ async function runAgentCaptured(prompt2, opts) {
6156
6421
  }
6157
6422
  let lastError = "";
6158
6423
  for (const agent of opts.chain) {
6159
- const result = await runOnce(agent, prompt2, { cwd: opts.cwd, capture: true });
6424
+ const result = await runOnce(agent, prompt2, { cwd: opts.cwd, capture: true, runKind: "review" });
6160
6425
  if (result.ok && result.output) {
6161
6426
  return { output: result.output, agent };
6162
6427
  }
@@ -6170,7 +6435,7 @@ async function runAgentInteractive(prompt2, opts) {
6170
6435
  }
6171
6436
  let lastError = "";
6172
6437
  for (const agent of opts.chain) {
6173
- const result = await runOnce(agent, prompt2, { cwd: opts.cwd, capture: false });
6438
+ const result = await runOnce(agent, prompt2, { cwd: opts.cwd, capture: false, runKind: "execute" });
6174
6439
  if (result.ok) return { agent };
6175
6440
  lastError = result.spawnError ? `${agent} could not be spawned` : `${agent} exited non-zero`;
6176
6441
  }
@@ -6178,7 +6443,7 @@ async function runAgentInteractive(prompt2, opts) {
6178
6443
  }
6179
6444
 
6180
6445
  // cli/commands/review-apply.ts
6181
- var c8 = {
6446
+ var c9 = {
6182
6447
  reset: "\x1B[0m",
6183
6448
  dim: "\x1B[2m",
6184
6449
  cyan: "\x1B[36m",
@@ -6190,7 +6455,7 @@ var c8 = {
6190
6455
  magenta: "\x1B[35m"
6191
6456
  };
6192
6457
  function paint8(color, text) {
6193
- return `${c8[color]}${text}${c8.reset}`;
6458
+ return `${c9[color]}${text}${c9.reset}`;
6194
6459
  }
6195
6460
  function timestamp2() {
6196
6461
  return paint8("gray", (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false }));
@@ -6207,7 +6472,7 @@ function logOk(msg) {
6207
6472
  function logErr(msg) {
6208
6473
  console.error(`${timestamp2()} ${tag()} ${paint8("red", "\u2717")} ${msg}`);
6209
6474
  }
6210
- 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) => {
6211
6476
  const config = loadConfig();
6212
6477
  if (!config.apiKey) {
6213
6478
  logErr('Not authenticated. Run "mr login" first.');
@@ -6227,7 +6492,7 @@ var reviewApplyCommand = new Command25("apply").description("Apply review commen
6227
6492
  logErr("Review has no comments or findings to act on.");
6228
6493
  process.exit(1);
6229
6494
  }
6230
- const actionableComments = comments.filter((c14) => !excluded.has(c14.file));
6495
+ const actionableComments = comments.filter((c15) => !excluded.has(c15.file));
6231
6496
  const dismissedCount = findings.filter((f) => f.status === "dismissed").length;
6232
6497
  const actionableFindings = findings.filter(
6233
6498
  (f) => !excluded.has(f.file) && f.status !== "dismissed"
@@ -6265,7 +6530,7 @@ var reviewApplyCommand = new Command25("apply").description("Apply review commen
6265
6530
  }
6266
6531
  const touchedFiles = Array.from(
6267
6532
  new Set([
6268
- ...actionableComments.map((c14) => c14.file),
6533
+ ...actionableComments.map((c15) => c15.file),
6269
6534
  ...actionableFindings.map((f) => f.file)
6270
6535
  ].filter(Boolean))
6271
6536
  );
@@ -6405,9 +6670,9 @@ function buildApplyPrompt(args) {
6405
6670
  }
6406
6671
  if (args.comments.length > 0) {
6407
6672
  lines.push("USER COMMENTS:");
6408
- for (const c14 of args.comments) {
6409
- const where = c14.line ? `${c14.file}:${c14.line}` : c14.file;
6410
- 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}`);
6411
6676
  }
6412
6677
  lines.push("");
6413
6678
  }
@@ -6661,6 +6926,37 @@ function buildDimensionPrompt(args) {
6661
6926
  lines.push(JSON_CONTRACT, "", "Here is the diff to review:", "", "```diff", args.diff, "```");
6662
6927
  return lines.join("\n");
6663
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
+ }
6664
6960
  function buildVerificationPrompt(args) {
6665
6961
  const compact = args.findings.map((f) => ({
6666
6962
  id: f.id,
@@ -6701,6 +6997,41 @@ function buildVerificationPrompt(args) {
6701
6997
  return lines.join("\n");
6702
6998
  }
6703
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
+
6704
7035
  // lib/review/orchestrate.ts
6705
7036
  function splitDiffByFile(diff) {
6706
7037
  const sections = diff.split(/(?=^diff --git )/m).filter((s) => s.trim());
@@ -6721,7 +7052,10 @@ async function pool(items, limit) {
6721
7052
  await Promise.all(workers);
6722
7053
  return results;
6723
7054
  }
6724
- function buildJobs(opts) {
7055
+ function buildJobs(opts, fanOut) {
7056
+ if (!fanOut) {
7057
+ return [{ dimension: null, diff: opts.diff }];
7058
+ }
6725
7059
  const files = splitDiffByFile(opts.diff);
6726
7060
  const shardThreshold = opts.shardThreshold ?? 12;
6727
7061
  if (files.length >= shardThreshold) {
@@ -6750,40 +7084,63 @@ async function orchestrateReview(opts) {
6750
7084
  });
6751
7085
  const concurrency = opts.concurrency ?? 4;
6752
7086
  const canReadFiles = Boolean(opts.cwd);
6753
- const runOpts = { cwd: opts.cwd, chain: opts.chain };
6754
- const jobs = buildJobs(opts);
6755
- 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
+ );
6756
7099
  const summaries = [];
6757
7100
  const collected = [];
6758
7101
  const jobResults = await pool(
6759
- jobs.map((job) => async () => {
6760
- const prompt2 = buildDimensionPrompt({
7102
+ tasks.map(({ job, agent }) => async () => {
7103
+ const prompt2 = job.dimension ? buildDimensionPrompt({
6761
7104
  dimension: job.dimension,
6762
7105
  branch: opts.branch,
6763
7106
  baseBranch: opts.baseBranch,
6764
7107
  diff: job.diff,
6765
7108
  canReadFiles,
6766
7109
  fileScope: job.fileScope
7110
+ }) : buildLightPrompt({
7111
+ branch: opts.branch,
7112
+ baseBranch: opts.baseBranch,
7113
+ diff: job.diff,
7114
+ canReadFiles
6767
7115
  });
7116
+ const runOpts = {
7117
+ cwd: opts.cwd,
7118
+ chain: depthConfig.multiAgent ? [agent] : opts.chain
7119
+ };
6768
7120
  try {
6769
- const { output } = await runAgentCaptured(prompt2, runOpts);
7121
+ const { output, agent: usedAgent } = await runAgentCaptured(prompt2, runOpts);
6770
7122
  const parsed = parseReviewOutput(output);
6771
- return { job, parsed };
7123
+ return { job, parsed, agent: usedAgent };
6772
7124
  } catch (err) {
6773
- log4(` ${job.dimension.key} subagent failed: ${err.message}`);
6774
- 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 };
6775
7128
  }
6776
7129
  }),
6777
7130
  concurrency
6778
7131
  );
6779
7132
  const dimensionsRun = /* @__PURE__ */ new Set();
6780
- for (const { job, parsed } of jobResults) {
6781
- 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}`);
6782
7137
  for (const f of parsed.findings) {
6783
- 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);
6784
7141
  collected.push({
6785
7142
  id: f.id || "f",
6786
- type: f.type || job.dimension.allowedTypes[0],
7143
+ type: f.type || fallbackType,
6787
7144
  severity: f.severity || "medium",
6788
7145
  title: f.title || "Untitled finding",
6789
7146
  description: f.description || "",
@@ -6792,7 +7149,7 @@ async function orchestrateReview(opts) {
6792
7149
  endLine: typeof f.endLine === "number" ? f.endLine : void 0,
6793
7150
  suggestion: f.suggestion,
6794
7151
  status: "new",
6795
- dimension: job.dimension.key,
7152
+ dimension: job.dimension?.key ?? f.type ?? "general",
6796
7153
  confidence: typeof f.confidence === "number" ? f.confidence : void 0
6797
7154
  });
6798
7155
  }
@@ -6800,13 +7157,15 @@ async function orchestrateReview(opts) {
6800
7157
  const rawCount = collected.length;
6801
7158
  let findings = mergeFindings(collected);
6802
7159
  log4(`Merged ${rawCount} raw findings into ${findings.length} after dedup`);
6803
- if (opts.verify && findings.length > 0) {
6804
- 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);
6805
7163
  }
6806
7164
  return {
6807
7165
  summary: summaries.join(" "),
6808
7166
  findings,
6809
7167
  dimensionsRun: [...dimensionsRun],
7168
+ agentsRun: [...agentsRun],
6810
7169
  rawCount
6811
7170
  };
6812
7171
  }
@@ -6848,7 +7207,7 @@ async function verifyFindings(findings, opts, runOpts, log4) {
6848
7207
  }
6849
7208
 
6850
7209
  // cli/commands/review.ts
6851
- var c9 = {
7210
+ var c10 = {
6852
7211
  reset: "\x1B[0m",
6853
7212
  bold: "\x1B[1m",
6854
7213
  dim: "\x1B[2m",
@@ -6861,7 +7220,7 @@ var c9 = {
6861
7220
  blue: "\x1B[34m"
6862
7221
  };
6863
7222
  function paint9(color, text) {
6864
- return `${c9[color]}${text}${c9.reset}`;
7223
+ return `${c10[color]}${text}${c10.reset}`;
6865
7224
  }
6866
7225
  function timestamp3() {
6867
7226
  return paint9("gray", (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false }));
@@ -6878,7 +7237,7 @@ function logOk2(msg) {
6878
7237
  function logErr2(msg) {
6879
7238
  console.error(`${timestamp3()} ${tag2()} ${paint9("red", "\u2717")} ${msg}`);
6880
7239
  }
6881
- 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) => {
6882
7241
  const config = loadConfig();
6883
7242
  if (!config.apiKey) {
6884
7243
  logErr2('Not authenticated. Run "mr login" first.');
@@ -6907,6 +7266,8 @@ var reviewCommand = new Command26("review").description("Run an automated code r
6907
7266
  process.exit(1);
6908
7267
  }
6909
7268
  const baseBranch = opts.base || "main";
7269
+ const depth = normalizeReviewDepth(opts.depth);
7270
+ const depthConfig = getReviewDepthConfig(depth);
6910
7271
  const prUrl = opts.prUrl;
6911
7272
  const prNumberRaw = opts.prNumber;
6912
7273
  const prNumber = prNumberRaw ? Number(prNumberRaw) : void 0;
@@ -7026,7 +7387,8 @@ var reviewCommand = new Command26("review").description("Run an automated code r
7026
7387
  const report = await api.post("/api/reviews", {
7027
7388
  projectId,
7028
7389
  branch,
7029
- baseBranch
7390
+ baseBranch,
7391
+ depth
7030
7392
  });
7031
7393
  reportId = report.id;
7032
7394
  log2(`Created review report ${paint9("yellow", reportId.slice(0, 8))}`);
@@ -7054,6 +7416,7 @@ var reviewCommand = new Command26("review").description("Run an automated code r
7054
7416
  process.exit(1);
7055
7417
  }
7056
7418
  log2(`Agent chain: ${paint9("cyan", chain.join(" \u2192 "))}`);
7419
+ log2(`Review depth: ${paint9("magenta", depthConfig.label)} ${paint9("dim", `(${depthConfig.description})`)}`);
7057
7420
  const MAX_DIFF_CHARS = 4e5;
7058
7421
  const diffCharsTotal = diff.length;
7059
7422
  let reviewDiff = diff;
@@ -7064,15 +7427,15 @@ var reviewCommand = new Command26("review").description("Run an automated code r
7064
7427
  log2(paint9("yellow", `Diff truncated to ${MAX_DIFF_CHARS.toLocaleString()} of ${diffCharsTotal.toLocaleString()} chars`));
7065
7428
  }
7066
7429
  try {
7067
- log2("Running fan-out code review...");
7430
+ log2(`Running ${depthConfig.label.toLowerCase()} code review...`);
7068
7431
  const orchestrated = await orchestrateReview({
7069
7432
  branch,
7070
7433
  baseBranch,
7071
7434
  diff: reviewDiff,
7072
7435
  chain,
7436
+ depth,
7073
7437
  cwd: reviewCwd,
7074
7438
  concurrency: 4,
7075
- verify: true,
7076
7439
  log: (m) => log2(m)
7077
7440
  });
7078
7441
  const result = { summary: orchestrated.summary, findings: orchestrated.findings };
@@ -7185,7 +7548,7 @@ function formatDuration(ms) {
7185
7548
  }
7186
7549
 
7187
7550
  // cli/commands/scan.ts
7188
- import { Command as Command27 } from "commander";
7551
+ import { Command as Command30 } from "commander";
7189
7552
 
7190
7553
  // lib/scanner/index.ts
7191
7554
  import { spawn as spawn8 } from "child_process";
@@ -7651,10 +8014,10 @@ ${codebaseAnalysis.routes.map((r) => `- ${r}`).join("\n")}
7651
8014
  ${codebaseAnalysis.prismaModels.map((m) => `- ${m}`).join("\n")}
7652
8015
 
7653
8016
  **Components:**
7654
- ${codebaseAnalysis.components.slice(0, 15).map((c14) => `- ${c14}`).join("\n")}
8017
+ ${codebaseAnalysis.components.slice(0, 15).map((c15) => `- ${c15}`).join("\n")}
7655
8018
 
7656
8019
  **Recent Git Commits:**
7657
- ${codebaseAnalysis.recentCommits.slice(0, 8).map((c14) => `- ${c14}`).join("\n")}
8020
+ ${codebaseAnalysis.recentCommits.slice(0, 8).map((c15) => `- ${c15}`).join("\n")}
7658
8021
 
7659
8022
  **Completed Tasks:**
7660
8023
  ${context.completedTasks.slice(0, 10).map((t) => `- ${t.title}`).join("\n") || "None"}
@@ -7869,7 +8232,9 @@ async function fetchScanContext(opts) {
7869
8232
  }
7870
8233
  function runClaude(prompt2) {
7871
8234
  return new Promise((resolve9, reject) => {
7872
- const child = spawn8("claude", ["-p", "--dangerously-skip-permissions", prompt2], {
8235
+ const permission = resolvePermissionArgs("claude", "scan", resolveHeadlessMode(loadConfig()));
8236
+ console.error(`[scanner] permission: ${describePermissionMode(permission)}`);
8237
+ const child = spawn8("claude", ["-p", ...permission.args, prompt2], {
7873
8238
  stdio: ["ignore", "pipe", "pipe"]
7874
8239
  });
7875
8240
  let output = "";
@@ -7925,7 +8290,7 @@ function parseSynthesisOutput(output) {
7925
8290
  }
7926
8291
 
7927
8292
  // cli/commands/scan.ts
7928
- var c10 = {
8293
+ var c11 = {
7929
8294
  reset: "\x1B[0m",
7930
8295
  bold: "\x1B[1m",
7931
8296
  dim: "\x1B[2m",
@@ -7937,7 +8302,7 @@ var c10 = {
7937
8302
  gray: "\x1B[90m"
7938
8303
  };
7939
8304
  function paint10(color, text) {
7940
- return `${c10[color]}${text}${c10.reset}`;
8305
+ return `${c11[color]}${text}${c11.reset}`;
7941
8306
  }
7942
8307
  function timestamp4() {
7943
8308
  return paint10("gray", (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false }));
@@ -7954,7 +8319,7 @@ function logOk3(msg) {
7954
8319
  function logErr3(msg) {
7955
8320
  console.error(`${timestamp4()} ${scanTag()} ${paint10("red", "\u2717")} ${msg}`);
7956
8321
  }
7957
- 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) => {
7958
8323
  const config = loadConfig();
7959
8324
  if (!config.apiKey) {
7960
8325
  logErr3('Not authenticated. Run "mr login" first.');
@@ -8119,7 +8484,7 @@ var scanCommand = new Command27("scan").description("Run a product scan on the c
8119
8484
  });
8120
8485
 
8121
8486
  // cli/commands/doctor.ts
8122
- import { Command as Command28 } from "commander";
8487
+ import { Command as Command31 } from "commander";
8123
8488
  import { existsSync as existsSync17 } from "fs";
8124
8489
  import { homedir as homedir2 } from "os";
8125
8490
  import { join as join11 } from "path";
@@ -8167,7 +8532,7 @@ async function checkProjectLink() {
8167
8532
  optional: true
8168
8533
  };
8169
8534
  }
8170
- 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 () => {
8171
8536
  const banner = [
8172
8537
  ``,
8173
8538
  paint5("cyan", ` MR DOCTOR`),
@@ -8198,7 +8563,7 @@ var doctorCommand = new Command28("doctor").description("Diagnose Mr. Manager CL
8198
8563
  console.log("");
8199
8564
  return;
8200
8565
  }
8201
- const fixes = checks.filter((c14) => !c14.ok && c14.fix && !c14.optional);
8566
+ const fixes = checks.filter((c15) => !c15.ok && c15.fix && !c15.optional);
8202
8567
  if (fixes.length > 0) {
8203
8568
  console.log(paint5("yellow", " To fix:"));
8204
8569
  for (const fix of fixes) {
@@ -8210,14 +8575,14 @@ var doctorCommand = new Command28("doctor").description("Diagnose Mr. Manager CL
8210
8575
  });
8211
8576
 
8212
8577
  // cli/commands/prompt-audit.ts
8213
- import { Command as Command29 } from "commander";
8578
+ import { Command as Command32 } from "commander";
8214
8579
  import { resolve as resolve8 } from "path";
8215
8580
  import { existsSync as existsSync18, readFileSync as readFileSync12 } from "fs";
8216
8581
  function auditLine(label, tokens) {
8217
8582
  const bar = "\u2588".repeat(Math.min(60, Math.round(tokens / 200)));
8218
8583
  return ` ${label.padEnd(30)} ${formatTokenCount(tokens).padStart(8)} ${bar}`;
8219
8584
  }
8220
- 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) => {
8221
8586
  const results = [];
8222
8587
  if (opts.task) {
8223
8588
  try {
@@ -8277,7 +8642,7 @@ ${task.notes}` : "";
8277
8642
  }
8278
8643
  }
8279
8644
  sections.push({ name: "static-instructions (system)", tokens: estimateTokens(
8280
- "status-updates + screenshots + test-plan + no-mr + features-workflow"
8645
+ "status-updates + screenshots + no-mr + features-workflow"
8281
8646
  ) });
8282
8647
  const totalTokens = sections.reduce((sum, s) => sum + s.tokens, 0);
8283
8648
  const promptTokens = sections.filter((s) => !s.name.includes("system")).reduce((sum, s) => sum + s.tokens, 0);
@@ -8426,9 +8791,9 @@ ${r.jobType} [${r.identifier}]`);
8426
8791
  });
8427
8792
 
8428
8793
  // cli/commands/skill.ts
8429
- import { Command as Command30 } from "commander";
8430
- import { createInterface as createInterface3 } from "readline/promises";
8431
- var c11 = {
8794
+ import { Command as Command33 } from "commander";
8795
+ import { createInterface as createInterface4 } from "readline/promises";
8796
+ var c12 = {
8432
8797
  reset: "\x1B[0m",
8433
8798
  bold: "\x1B[1m",
8434
8799
  dim: "\x1B[2m",
@@ -8461,7 +8826,7 @@ function formatSize(bytes) {
8461
8826
  if (bytes < 1024) return `${bytes}b`;
8462
8827
  return `${(bytes / 1024).toFixed(1)}kb`;
8463
8828
  }
8464
- 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");
8465
8830
  skillCommand.command("list").alias("ls").description("List all skills").option("--category <category>", "Filter by category").action(async (opts) => {
8466
8831
  const params = new URLSearchParams();
8467
8832
  if (opts.category) params.set("category", opts.category);
@@ -8469,17 +8834,17 @@ skillCommand.command("list").alias("ls").description("List all skills").option("
8469
8834
  `/api/skills${params.toString() ? `?${params}` : ""}`
8470
8835
  );
8471
8836
  if (skills.length === 0) {
8472
- console.log(`${c11.dim}No skills found.${c11.reset}`);
8837
+ console.log(`${c12.dim}No skills found.${c12.reset}`);
8473
8838
  return;
8474
8839
  }
8475
8840
  for (const skill of skills) {
8476
- const cat = skill.category ? ` ${c11.dim}[${skill.category}]${c11.reset}` : "";
8477
- const scope = skill.projectId ? ` ${c11.dim}(project)${c11.reset}` : ` ${c11.dim}(global)${c11.reset}`;
8478
- 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}`);
8479
8844
  if (skill.description) {
8480
- console.log(` ${c11.dim}${skill.description}${c11.reset}`);
8845
+ console.log(` ${c12.dim}${skill.description}${c12.reset}`);
8481
8846
  }
8482
- console.log(` ${c11.dim}id: ${skill.id}${c11.reset}`);
8847
+ console.log(` ${c12.dim}id: ${skill.id}${c12.reset}`);
8483
8848
  }
8484
8849
  });
8485
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) => {
@@ -8515,7 +8880,7 @@ skillCommand.command("create").description("Create a new skill from a markdown f
8515
8880
  projectId
8516
8881
  });
8517
8882
  console.log(
8518
- `${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}`
8519
8884
  );
8520
8885
  });
8521
8886
  skillCommand.command("update").description(
@@ -8576,14 +8941,14 @@ skillCommand.command("update").description(
8576
8941
  const beforeContent = existing.content ?? "";
8577
8942
  const afterContent = typeof patch.content === "string" ? patch.content : beforeContent;
8578
8943
  const contentChanged = typeof patch.content === "string" && patch.content !== beforeContent;
8579
- 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}` : "";
8580
8945
  const priorRevisions = existing.revisions?.length ?? 0;
8581
8946
  const revisionsAfter = priorRevisions + (contentChanged ? 1 : 0);
8582
- 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}` : "";
8583
8948
  console.log(
8584
- `${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}`
8585
8950
  );
8586
- console.log(` ${c11.dim}id: ${updated.id}${c11.reset}`);
8951
+ console.log(` ${c12.dim}id: ${updated.id}${c12.reset}`);
8587
8952
  });
8588
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) => {
8589
8954
  let skill;
@@ -8594,9 +8959,9 @@ skillCommand.command("delete").alias("rm").description("Delete a skill").argumen
8594
8959
  process.exit(1);
8595
8960
  }
8596
8961
  if (!opts.yes) {
8597
- const rl = createInterface3({ input: process.stdin, output: process.stdout });
8962
+ const rl = createInterface4({ input: process.stdin, output: process.stdout });
8598
8963
  const answer = (await rl.question(
8599
- `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] `
8600
8965
  )).trim().toLowerCase();
8601
8966
  rl.close();
8602
8967
  if (answer !== "y" && answer !== "yes") {
@@ -8606,7 +8971,7 @@ skillCommand.command("delete").alias("rm").description("Delete a skill").argumen
8606
8971
  }
8607
8972
  await api.del(`/api/skills/${skill.id}`);
8608
8973
  console.log(
8609
- `${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}`
8610
8975
  );
8611
8976
  });
8612
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) => {
@@ -8620,22 +8985,22 @@ skillCommand.command("generate").alias("gen").description("Generate a new skill
8620
8985
  process.exit(1);
8621
8986
  }
8622
8987
  }
8623
- console.log(`${c11.dim}Generating skill...${c11.reset}`);
8988
+ console.log(`${c12.dim}Generating skill...${c12.reset}`);
8624
8989
  try {
8625
8990
  const skill = await api.post("/api/skills/generate", {
8626
8991
  prompt: prompt2,
8627
8992
  projectId
8628
8993
  });
8629
8994
  console.log(
8630
- `${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}`
8631
8996
  );
8632
8997
  if (skill.description) {
8633
- console.log(` ${c11.dim}${skill.description}${c11.reset}`);
8998
+ console.log(` ${c12.dim}${skill.description}${c12.reset}`);
8634
8999
  }
8635
9000
  if (skill.category) {
8636
- console.log(` ${c11.dim}Category: ${skill.category}${c11.reset}`);
9001
+ console.log(` ${c12.dim}Category: ${skill.category}${c12.reset}`);
8637
9002
  }
8638
- console.log(` ${c11.dim}id: ${skill.id}${c11.reset}`);
9003
+ console.log(` ${c12.dim}id: ${skill.id}${c12.reset}`);
8639
9004
  } catch (err) {
8640
9005
  console.error(`Failed to generate skill: ${err.message}`);
8641
9006
  process.exit(1);
@@ -8643,8 +9008,8 @@ skillCommand.command("generate").alias("gen").description("Generate a new skill
8643
9008
  });
8644
9009
 
8645
9010
  // cli/commands/resource.ts
8646
- import { Command as Command31 } from "commander";
8647
- var c12 = {
9011
+ import { Command as Command34 } from "commander";
9012
+ var c13 = {
8648
9013
  reset: "\x1B[0m",
8649
9014
  bold: "\x1B[1m",
8650
9015
  dim: "\x1B[2m",
@@ -8654,16 +9019,16 @@ var c12 = {
8654
9019
  magenta: "\x1B[35m"
8655
9020
  };
8656
9021
  var TYPE_COLORS = {
8657
- plan: c12.cyan,
8658
- research: c12.magenta,
8659
- "test-plan": c12.yellow,
8660
- note: c12.green
9022
+ plan: c13.cyan,
9023
+ research: c13.magenta,
9024
+ "test-plan": c13.yellow,
9025
+ note: c13.green
8661
9026
  };
8662
9027
  function typeLabel(type) {
8663
- const color = TYPE_COLORS[type] ?? c12.dim;
8664
- return `${color}${type}${c12.reset}`;
9028
+ const color = TYPE_COLORS[type] ?? c13.dim;
9029
+ return `${color}${type}${c13.reset}`;
8665
9030
  }
8666
- 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");
8667
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) => {
8668
9033
  const params = new URLSearchParams();
8669
9034
  if (opts.all) {
@@ -8676,13 +9041,13 @@ resourceCommand.command("list").alias("ls").description("List resources for the
8676
9041
  `/api/resources${params.toString() ? `?${params}` : ""}`
8677
9042
  );
8678
9043
  if (resources.length === 0) {
8679
- console.log(`${c12.dim}No resources found.${c12.reset}`);
9044
+ console.log(`${c13.dim}No resources found.${c13.reset}`);
8680
9045
  return;
8681
9046
  }
8682
9047
  for (const r of resources) {
8683
- const project = r.projectName ? ` ${c12.dim}[${r.projectName}]${c12.reset}` : "";
8684
- console.log(` ${typeLabel(r.type)} ${c12.bold}${r.title}${c12.reset}${project}`);
8685
- 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}`);
8686
9051
  }
8687
9052
  });
8688
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) => {
@@ -8707,9 +9072,9 @@ resourceCommand.command("create").description("Create a new resource from a file
8707
9072
  content: content.trim()
8708
9073
  });
8709
9074
  console.log(
8710
- `${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}`
8711
9076
  );
8712
- console.log(` ${c12.dim}Attached to task ${opts.task}${c12.reset}`);
9077
+ console.log(` ${c13.dim}Attached to task ${opts.task}${c13.reset}`);
8713
9078
  return;
8714
9079
  }
8715
9080
  let projectId;
@@ -8729,7 +9094,7 @@ resourceCommand.command("create").description("Create a new resource from a file
8729
9094
  projectId
8730
9095
  });
8731
9096
  console.log(
8732
- `${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}`
8733
9098
  );
8734
9099
  });
8735
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) => {
@@ -8748,30 +9113,30 @@ resourceCommand.command("generate").alias("gen").description("Generate a resourc
8748
9113
  process.exit(1);
8749
9114
  }
8750
9115
  }
8751
- console.log(`${c12.dim}Generating ${type}...${c12.reset}`);
9116
+ console.log(`${c13.dim}Generating ${type}...${c13.reset}`);
8752
9117
  const result = await api.post("/api/resources", {
8753
9118
  type,
8754
9119
  prompt: prompt2,
8755
9120
  projectId
8756
9121
  });
8757
9122
  console.log(
8758
- `${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}`
8759
9124
  );
8760
- console.log(` ${c12.dim}task: ${result.task.id}${c12.reset}`);
9125
+ console.log(` ${c13.dim}task: ${result.task.id}${c13.reset}`);
8761
9126
  });
8762
9127
 
8763
9128
  // cli/commands/tests.ts
8764
- import { Command as Command32 } from "commander";
8765
- var c13 = {
9129
+ import { Command as Command35 } from "commander";
9130
+ var c14 = {
8766
9131
  reset: "\x1B[0m",
8767
9132
  dim: "\x1B[2m",
8768
9133
  yellow: "\x1B[33m"
8769
9134
  };
8770
- 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 () => {
8771
9136
  const projectId = getLinkedProjectId();
8772
9137
  if (!projectId) {
8773
9138
  console.error(
8774
- `${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.`
8775
9140
  );
8776
9141
  process.exit(1);
8777
9142
  }
@@ -8784,13 +9149,13 @@ var testsCommand = new Command32("tests").description("List MR Test scenarios fo
8784
9149
  process.exit(1);
8785
9150
  }
8786
9151
  if (scenarios.length === 0) {
8787
- 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}`);
8788
9153
  return;
8789
9154
  }
8790
9155
  for (const scenario of scenarios) {
8791
9156
  console.log(`### ${scenario.name}`);
8792
9157
  if (scenario.description) {
8793
- console.log(`${c13.dim}${scenario.description}${c13.reset}`);
9158
+ console.log(`${c14.dim}${scenario.description}${c14.reset}`);
8794
9159
  console.log();
8795
9160
  }
8796
9161
  console.log(scenario.content);
@@ -8799,9 +9164,9 @@ var testsCommand = new Command32("tests").description("List MR Test scenarios fo
8799
9164
  });
8800
9165
 
8801
9166
  // cli/commands/walkthrough.ts
8802
- import { Command as Command33 } from "commander";
9167
+ import { Command as Command36 } from "commander";
8803
9168
  var SKILL_NAME = "Generate Walkthrough Video";
8804
- 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) => {
8805
9170
  const skills = await api.get("/api/skills");
8806
9171
  const skill = skills.find((s) => s.name === SKILL_NAME);
8807
9172
  if (!skill) {
@@ -8834,7 +9199,7 @@ var userArgs = process.argv.slice(2);
8834
9199
  var bypassCommands = /* @__PURE__ */ new Set(["login", "init", "auth", "help", "--help", "-h", "--version", "-V", "doctor", "setup"]);
8835
9200
  var shouldBypass = userArgs.length > 0 && bypassCommands.has(userArgs[0]);
8836
9201
  if (isFirstRun && !shouldBypass) {
8837
- const c14 = {
9202
+ const c15 = {
8838
9203
  reset: "\x1B[0m",
8839
9204
  bold: "\x1B[1m",
8840
9205
  dim: "\x1B[2m",
@@ -8844,28 +9209,28 @@ if (isFirstRun && !shouldBypass) {
8844
9209
  magenta: "\x1B[35m"
8845
9210
  };
8846
9211
  console.log("");
8847
- 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}`);
8848
- 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}`);
8849
- 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}`);
8850
- 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}`);
8851
9216
  console.log("");
8852
- console.log(`${c14.bold} Welcome to Mr. Manager!${c14.reset}`);
8853
- 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}`);
8854
9219
  console.log("");
8855
- console.log(` ${c14.yellow}Step 1:${c14.reset} Authenticate via Google OAuth`);
8856
- 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}`);
8857
9222
  console.log("");
8858
- console.log(` ${c14.yellow}Step 2:${c14.reset} Verify your environment`);
8859
- 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}`);
8860
9225
  console.log("");
8861
- console.log(` ${c14.yellow}Step 3:${c14.reset} Link a repo and start watching`);
8862
- 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}`);
8863
9228
  console.log("");
8864
- 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}`);
8865
9230
  console.log("");
8866
9231
  process.exit(0);
8867
9232
  }
8868
- var program = new Command34();
9233
+ var program = new Command37();
8869
9234
  program.name("mr").description("Mr. Manager - Task and project management CLI").version(CLI_VERSION);
8870
9235
  program.addCommand(initCommand);
8871
9236
  program.addCommand(authCommand);
@@ -8882,6 +9247,9 @@ program.addCommand(delegateCommand);
8882
9247
  program.addCommand(undelegateCommand);
8883
9248
  program.addCommand(createCommand);
8884
9249
  program.addCommand(completeCommand);
9250
+ program.addCommand(showCommand);
9251
+ program.addCommand(editCommand);
9252
+ program.addCommand(deleteCommand);
8885
9253
  program.addCommand(subtaskCompleteCommand);
8886
9254
  program.addCommand(subtaskAddCommand);
8887
9255
  program.addCommand(prototypeCommand);