@dunnewold-labs/mr-manager 0.4.27 → 0.4.29

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 +150 -496
  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 Command29 } from "commander";
4
+ import { Command as Command28 } from "commander";
5
5
  import { existsSync as existsSync17 } 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.27",
188
+ version: "0.4.29",
189
189
  description: "Mr. Manager - Task and project management CLI",
190
190
  bin: {
191
191
  mr: "./dist/index.mjs"
@@ -1162,6 +1162,19 @@ function taskLikelyDoesNotNeedCodeChanges(task) {
1162
1162
  return NON_CODE_TASK_KEYWORDS.some((keyword) => haystack.includes(keyword)) || NON_CODE_TASK_PATTERNS.some((pattern) => pattern.test(haystack));
1163
1163
  }
1164
1164
 
1165
+ // lib/task-branch.ts
1166
+ function isPrOrMrUrl(input) {
1167
+ try {
1168
+ const url = new URL(input.trim());
1169
+ const path = url.pathname;
1170
+ if (url.hostname.includes("github") && /\/pull\/\d+/.test(path)) return true;
1171
+ if (url.hostname.includes("gitlab") && /\/merge_requests\/\d+/.test(path)) return true;
1172
+ } catch {
1173
+ return false;
1174
+ }
1175
+ return false;
1176
+ }
1177
+
1165
1178
  // cli/browse-runner.ts
1166
1179
  import { execSync as execSync3, spawn as spawn3 } from "child_process";
1167
1180
  import { existsSync as existsSync6 } from "fs";
@@ -1354,6 +1367,18 @@ If a scenario name matches the feature you're testing (by name or keyword):
1354
1367
  3. Note in your test plan summary which scenario you used.
1355
1368
 
1356
1369
  If no matching scenario exists, infer interactions from the codebase as normal.`;
1370
+ var SYSTEM_SECTION_QUIET_MODE = `## Quiet Mode \u2014 CRITICAL
1371
+
1372
+ You are running in **quiet mode**. This means:
1373
+
1374
+ 1. **DO NOT** write any explanatory text, conversation, commentary, or summaries outside of tool calls.
1375
+ 2. **DO NOT** describe what you are about to do or what you just did in prose.
1376
+ 3. **ONLY** output text when using \`mr update\` for status updates (keep these to 1 short sentence each).
1377
+ 4. All your work must happen through tool calls (Read, Edit, Write, Bash, etc.) \u2014 not through conversational output.
1378
+ 5. When you would normally explain your reasoning or next steps, simply proceed silently with the tool calls.
1379
+ 6. After completing work, exit immediately without a summary.
1380
+
1381
+ This mode exists to minimize output token usage. Every word of conversational text you generate costs tokens. Tool calls and file writes are the only acceptable output.`;
1357
1382
  var SYSTEM_SECTIONS = {
1358
1383
  "status-updates": SYSTEM_SECTION_STATUS_UPDATES,
1359
1384
  "screenshots": SYSTEM_SECTION_SCREENSHOTS,
@@ -1362,7 +1387,8 @@ var SYSTEM_SECTIONS = {
1362
1387
  "features-workflow": SYSTEM_SECTION_FEATURES_WORKFLOW,
1363
1388
  "prd-format": SYSTEM_SECTION_PRD_FORMAT,
1364
1389
  "prd-open-questions": SYSTEM_SECTION_PRD_OPEN_QUESTIONS,
1365
- "mr-tests": SYSTEM_SECTION_MR_TESTS
1390
+ "mr-tests": SYSTEM_SECTION_MR_TESTS,
1391
+ "quiet-mode": SYSTEM_SECTION_QUIET_MODE
1366
1392
  };
1367
1393
  function composeSystemPrompt(sections) {
1368
1394
  return sections.map((s) => SYSTEM_SECTIONS[s]).join("\n\n");
@@ -1469,6 +1495,15 @@ function taskBranchName(task) {
1469
1495
  }
1470
1496
  return `${ownerPrefix(task)}/${slugify(task.title)}`;
1471
1497
  }
1498
+ function resolveBranchFromPrUrl(prUrl, repoDir, vcs) {
1499
+ const cmd = vcs === "gitlab" ? `glab mr view "${prUrl}" --output json 2>/dev/null | jq -r '.source_branch // empty'` : `gh pr view "${prUrl}" --json headRefName -q .headRefName 2>/dev/null`;
1500
+ return new Promise((resolve9) => {
1501
+ exec(cmd, { cwd: repoDir }, (err, stdout) => {
1502
+ const branch = stdout?.trim();
1503
+ resolve9(branch || null);
1504
+ });
1505
+ });
1506
+ }
1472
1507
  function formatElapsed(ms) {
1473
1508
  const totalMinutes = Math.max(1, Math.floor(ms / 6e4));
1474
1509
  const hours = Math.floor(totalMinutes / 60);
@@ -2106,9 +2141,6 @@ function protoTag(sid) {
2106
2141
  function repoTag(sid) {
2107
2142
  return paint("cyan", `[repo:${sid}]`);
2108
2143
  }
2109
- function ideaTag(sid) {
2110
- return paint("magenta", `[idea:${sid}]`);
2111
- }
2112
2144
  function buildRepoCreationPrompt(project, rootDir, vcs = "github") {
2113
2145
  const apiBase = process.env.MR_API_BASE ?? "http://localhost:3000";
2114
2146
  const apiKey = process.env.MR_API_KEY ?? "";
@@ -2387,83 +2419,6 @@ function buildRefinementPrompt(proto, parentFiles, repoDir) {
2387
2419
  `- Do NOT exit until ALL ${proto.variantCount} files have been written and verified.`
2388
2420
  ].join("\n");
2389
2421
  }
2390
- function buildIdeaPrompt(idea, repoDir) {
2391
- const feedbackSection = idea.feedback ? [
2392
- `## Previous Feedback`,
2393
- ``,
2394
- `The user provided this feedback on a previous generation:`,
2395
- `${idea.feedback}`,
2396
- ``,
2397
- `Please incorporate this feedback into your new generation.`,
2398
- ``
2399
- ] : [];
2400
- const existingPlanSection = idea.plan && idea.feedback ? [
2401
- `## Previous Plan`,
2402
- ``,
2403
- `Here is the plan from the previous iteration:`,
2404
- `\`\`\`markdown`,
2405
- idea.plan,
2406
- `\`\`\``,
2407
- ``
2408
- ] : [];
2409
- return [
2410
- `You are a product strategist and UI designer. Your job is to take a rough idea and generate two outputs:`,
2411
- `1. An implementation plan (saved as \`idea-plan.md\`)`,
2412
- `2. A visual prototype (saved as \`idea-prototype.html\`)`,
2413
- ``,
2414
- `Working directory: ${repoDir}`,
2415
- ``,
2416
- `## Idea`,
2417
- `Title: ${idea.title}`,
2418
- `ID: ${idea.id}`,
2419
- ...idea.description ? [``, `Description: ${idea.description}`] : [],
2420
- ``,
2421
- ...feedbackSection,
2422
- ...existingPlanSection,
2423
- `## Instructions`,
2424
- ``,
2425
- `### Step 1: Generate the Plan`,
2426
- ``,
2427
- `Write a comprehensive implementation plan to \`${repoDir}/idea-plan.md\` covering:`,
2428
- `- **Problem statement**: What problem does this idea solve?`,
2429
- `- **Proposed solution**: High-level approach`,
2430
- `- **Key features**: Bulleted list of features/capabilities`,
2431
- `- **Technical approach**: How it could be built (components, data model, integrations)`,
2432
- `- **Implementation phases**: Phased rollout plan with milestones`,
2433
- `- **Open questions**: Things that need clarification`,
2434
- ``,
2435
- `### Step 2: Generate Follow-up Tasks`,
2436
- ``,
2437
- `Write a JSON file to \`${repoDir}/idea-tasks.json\` containing an array of follow-up tasks that will need to be done after the project repo is created. These are setup and implementation tasks the user will need to complete. Examples: "Add environment variables (.env)", "Set up CI/CD pipeline", "Configure database", "Add authentication", etc.`,
2438
- ``,
2439
- `Format: a JSON array of objects with "title" (short task name) and optional "notes" (additional context):`,
2440
- `\`\`\`json`,
2441
- `[`,
2442
- ` { "title": "Add environment variables (.env)", "notes": "Create .env file with required API keys and database URL" },`,
2443
- ` { "title": "Set up CI/CD pipeline" }`,
2444
- `]`,
2445
- `\`\`\``,
2446
- ``,
2447
- `Generate 3-8 tasks that are specific to this idea. Focus on actionable setup and implementation steps.`,
2448
- ``,
2449
- `### Step 3: Generate the Prototype`,
2450
- ``,
2451
- `Write a self-contained HTML prototype to \`${repoDir}/idea-prototype.html\` that visually demonstrates the idea.`,
2452
- `- Must be completely self-contained (inline CSS/JS, Tailwind CDN is acceptable)`,
2453
- `- Should be interactive where possible (click handlers, animations, sample data)`,
2454
- `- Should look polished and professional \u2014 this will be shown to stakeholders`,
2455
- `- Include realistic sample data that demonstrates the feature`,
2456
- ``,
2457
- `### Step 4: Verify`,
2458
- ``,
2459
- `List the files in ${repoDir} and confirm \`idea-plan.md\`, \`idea-tasks.json\`, and \`idea-prototype.html\` all exist.`,
2460
- ``,
2461
- `IMPORTANT RULES:`,
2462
- `- Write EXACTLY three files: idea-plan.md, idea-tasks.json, and idea-prototype.html`,
2463
- `- Do NOT upload or POST the files anywhere \u2014 the watch handler will upload them automatically`,
2464
- `- Do NOT exit until both files have been written and verified`
2465
- ].join("\n");
2466
- }
2467
2422
  function buildAgentArgs(agent, prompt2, mode, sessionId, name, resumeSession = false, systemPrompt, maxTurns, claudeModel) {
2468
2423
  if (agent === "codex") {
2469
2424
  const args = [];
@@ -2571,7 +2526,7 @@ function askYesNo(question) {
2571
2526
  });
2572
2527
  });
2573
2528
  }
2574
- function spawnAgent(agent, repoDir, prompt2, prefix, onActivity, sessionId, name, resumeSession = false, onSpawnError, systemPrompt, maxTurns, claudeModel) {
2529
+ function spawnAgent(agent, repoDir, prompt2, prefix, onActivity, sessionId, name, resumeSession = false, onSpawnError, systemPrompt, maxTurns, claudeModel, onOutputBytes) {
2575
2530
  const jobLabel = name ?? "unknown";
2576
2531
  console.log(`${timestamp()} ${prefix} ${paint("dim", tokenLogLine("agent", jobLabel, prompt2, systemPrompt))}`);
2577
2532
  const { bin, args } = buildAgentArgs(agent, prompt2, "execute", sessionId, name, resumeSession, systemPrompt, maxTurns, claudeModel);
@@ -2590,12 +2545,14 @@ function spawnAgent(agent, repoDir, prompt2, prefix, onActivity, sessionId, name
2590
2545
  }
2591
2546
  child.stdout?.on("data", (data) => {
2592
2547
  onActivity?.();
2548
+ onOutputBytes?.(data.length);
2593
2549
  for (const line of data.toString().split("\n")) {
2594
2550
  if (line) console.log(`${timestamp()} ${prefix} ${paint("dim", line)}`);
2595
2551
  }
2596
2552
  });
2597
2553
  child.stderr?.on("data", (data) => {
2598
2554
  onActivity?.();
2555
+ onOutputBytes?.(data.length);
2599
2556
  for (const line of data.toString().split("\n")) {
2600
2557
  if (line) logError(prefix, paint("dim", line));
2601
2558
  }
@@ -2704,7 +2661,7 @@ var watchCommand = new Command8("watch").description(
2704
2661
  logWarn(watchTag(), `Network unavailable \u2014 pausing active tasks until connectivity returns (${reason})`);
2705
2662
  }
2706
2663
  for (const taskId of active.keys()) {
2707
- const nonTaskPrefixes = ["proto-", "repo-", "scan-", "idea-", "test-"];
2664
+ const nonTaskPrefixes = ["proto-", "repo-", "scan-", "test-"];
2708
2665
  if (nonTaskPrefixes.some((prefix) => taskId.startsWith(prefix))) continue;
2709
2666
  pauseTaskForNetwork(taskId, reason);
2710
2667
  }
@@ -2751,10 +2708,17 @@ var watchCommand = new Command8("watch").description(
2751
2708
  const sid = shortId(task.id);
2752
2709
  const slug = slugify(task.title);
2753
2710
  const owner = ownerPrefix(task);
2754
- const branchName = taskBranchName(task);
2711
+ let branchName = taskBranchName(task);
2755
2712
  const legacyBranchName = `mr/${sid}/${slug}`;
2756
2713
  const prefix = taskTag(sid);
2757
2714
  const vcs = detectVcs(repoDir)?.provider ?? "github";
2715
+ if (!task.attachedBranch?.trim() && task.attachedBranchLink && isPrOrMrUrl(task.attachedBranchLink)) {
2716
+ const resolved = await resolveBranchFromPrUrl(task.attachedBranchLink, repoDir, vcs);
2717
+ if (resolved) {
2718
+ branchName = resolved;
2719
+ logInfo(prefix, `Resolved branch ${paint("cyan", resolved)} from attached ${vcs === "gitlab" ? "MR" : "PR"}`);
2720
+ }
2721
+ }
2758
2722
  logDispatch(prefix, `"${paint("bold", task.title)}" ${paint("gray", repoDir)} ${paint("dim", `[${vcs}]`)}`);
2759
2723
  await postTaskUpdate(task.id, `Agent dispatched \u2014 starting work on "${task.title}"`, "system");
2760
2724
  let subtasks = [];
@@ -2829,7 +2793,8 @@ var watchCommand = new Command8("watch").description(
2829
2793
  cleanupRepoDir: cleanupWorktreePath ? repoDir : void 0,
2830
2794
  cleanupWorktreePath,
2831
2795
  startedAt: Date.now(),
2832
- lastActivityAt: Date.now()
2796
+ lastActivityAt: Date.now(),
2797
+ outputBytes: 0
2833
2798
  };
2834
2799
  const touchActivity = () => {
2835
2800
  activeEntry.lastActivityAt = Date.now();
@@ -2858,7 +2823,8 @@ var watchCommand = new Command8("watch").description(
2858
2823
  const shouldResumeClaudeSession = attemptAgent === "claude" && !!task.claudeSessionId && !resumeAlreadyRetried && (hasFeedback || pausedForNetwork?.resumeSession === true);
2859
2824
  const sessionId = attemptAgent === "claude" ? shouldResumeClaudeSession ? task.claudeSessionId : randomUUID() : void 0;
2860
2825
  const effectiveClaudeModel = attemptAgent === "claude" ? taskClaudeModel : void 0;
2861
- const executionSystemPrompt = composeSystemPrompt(EXECUTION_SYSTEM_SECTIONS);
2826
+ const systemSections = ["quiet-mode", ...EXECUTION_SYSTEM_SECTIONS];
2827
+ const executionSystemPrompt = composeSystemPrompt(systemSections);
2862
2828
  const child = spawnAgent(
2863
2829
  attemptAgent,
2864
2830
  executionDir,
@@ -2873,7 +2839,10 @@ var watchCommand = new Command8("watch").description(
2873
2839
  },
2874
2840
  executionSystemPrompt,
2875
2841
  void 0,
2876
- effectiveClaudeModel
2842
+ effectiveClaudeModel,
2843
+ (bytes) => {
2844
+ activeEntry.outputBytes += bytes;
2845
+ }
2877
2846
  );
2878
2847
  activeEntry.process = child;
2879
2848
  activeEntry.currentAgent = attemptAgent;
@@ -2903,31 +2872,48 @@ var watchCommand = new Command8("watch").description(
2903
2872
  logWarn(prefix, `${attemptAgent} paused after network loss (${failureDetail})`);
2904
2873
  return;
2905
2874
  }
2906
- if (shouldResumeClaudeSession && !resumeAlreadyRetried) {
2907
- resumeAlreadyRetried = true;
2908
- logWarn(prefix, `Claude session resume failed (${failureDetail}) \u2014 retrying with fresh session`);
2909
- await postTaskUpdate(
2910
- task.id,
2911
- `Claude session resume failed \u2014 retrying with fresh session`,
2912
- "system"
2913
- );
2914
- await launchAttempt("claude");
2915
- return;
2875
+ try {
2876
+ const currentTask = await api.get(`/api/tasks/${task.id}`);
2877
+ if (currentTask.status === "completed" || currentTask.status === "review" || currentTask.status === "error") {
2878
+ logWarn(prefix, `Task already in "${currentTask.status}" state after agent exit \u2014 skipping retry`);
2879
+ activeEntry.terminatedForError = true;
2880
+ }
2881
+ } catch {
2882
+ logWarn(prefix, `Could not verify task status \u2014 skipping retry to avoid stale re-dispatch`);
2883
+ activeEntry.terminatedForError = true;
2916
2884
  }
2917
- const nextAgent = attemptOrder[attemptIndex + 1];
2918
- if (nextAgent) {
2919
- logWarn(prefix, `${attemptAgent} failed (${failureDetail}) \u2014 retrying with ${nextAgent}`);
2920
- await postTaskUpdate(
2921
- task.id,
2922
- `${attemptAgent} failed (${failureDetail}) \u2014 retrying with ${nextAgent}`,
2923
- "system"
2924
- );
2925
- attemptIndex += 1;
2926
- await launchAttempt(nextAgent);
2927
- return;
2885
+ if (!activeEntry.terminatedForError) {
2886
+ if (shouldResumeClaudeSession && !resumeAlreadyRetried) {
2887
+ resumeAlreadyRetried = true;
2888
+ logWarn(prefix, `Claude session resume failed (${failureDetail}) \u2014 retrying with fresh session`);
2889
+ await postTaskUpdate(
2890
+ task.id,
2891
+ `Claude session resume failed \u2014 retrying with fresh session`,
2892
+ "system"
2893
+ );
2894
+ await launchAttempt("claude");
2895
+ return;
2896
+ }
2897
+ const nextAgent = attemptOrder[attemptIndex + 1];
2898
+ if (nextAgent) {
2899
+ logWarn(prefix, `${attemptAgent} failed (${failureDetail}) \u2014 retrying with ${nextAgent}`);
2900
+ await postTaskUpdate(
2901
+ task.id,
2902
+ `${attemptAgent} failed (${failureDetail}) \u2014 retrying with ${nextAgent}`,
2903
+ "system"
2904
+ );
2905
+ attemptIndex += 1;
2906
+ await launchAttempt(nextAgent);
2907
+ return;
2908
+ }
2928
2909
  }
2929
2910
  }
2930
2911
  finishing.add(task.id);
2912
+ const elapsedMs = Date.now() - activeEntry.startedAt;
2913
+ const outputTokenEstimate = Math.ceil(activeEntry.outputBytes / 4);
2914
+ console.log(
2915
+ `${timestamp()} ${prefix} ${paint("dim", `[output] output=~${formatTokenCount(outputTokenEstimate)} elapsed=${Math.round(elapsedMs / 1e3)}s exit=${code}`)}`
2916
+ );
2931
2917
  try {
2932
2918
  if (code === 0) {
2933
2919
  try {
@@ -3266,7 +3252,7 @@ var watchCommand = new Command8("watch").description(
3266
3252
  active.delete(key);
3267
3253
  }
3268
3254
  const failedAttempt = code !== 0 || spawnFailureReason !== null;
3269
- if (failedAttempt) {
3255
+ if (failedAttempt && !activeEntry.terminatedForError) {
3270
3256
  const nextAgent = attemptOrder[attemptIndex + 1];
3271
3257
  if (nextAgent) {
3272
3258
  const failureDetail = spawnFailureReason ?? `exit code ${code}`;
@@ -3376,7 +3362,7 @@ var watchCommand = new Command8("watch").description(
3376
3362
  active.delete(key);
3377
3363
  }
3378
3364
  const failedAttempt = code !== 0 || spawnFailureReason !== null;
3379
- if (failedAttempt) {
3365
+ if (failedAttempt && !activeEntry.terminatedForError) {
3380
3366
  const nextAgent = attemptOrder[attemptIndex + 1];
3381
3367
  if (nextAgent) {
3382
3368
  const failureDetail = spawnFailureReason ?? `exit code ${code}`;
@@ -3413,158 +3399,6 @@ var watchCommand = new Command8("watch").description(
3413
3399
  };
3414
3400
  await launchAttempt(attemptOrder[attemptIndex]);
3415
3401
  }
3416
- async function dispatchIdeaJob(idea, repoDir) {
3417
- const sid = shortId(idea.id);
3418
- const prefix = ideaTag(sid);
3419
- logDispatch(prefix, `"${paint("bold", idea.title)}"${idea.feedback ? paint("cyan", " (iteration)") : ""} ${paint("gray", repoDir)}`);
3420
- for (const f of ["idea-plan.md", "idea-tasks.json", "idea-prototype.html"]) {
3421
- try {
3422
- unlinkSync(resolve2(repoDir, f));
3423
- } catch {
3424
- }
3425
- }
3426
- const prompt2 = buildIdeaPrompt(idea, repoDir);
3427
- const key = `idea-${idea.id}`;
3428
- const attemptOrder = await resolveAgentChain(agent);
3429
- if (attemptOrder.length === 0) {
3430
- logError(prefix, `No available agents found for fallback chain starting at ${agent}`);
3431
- queued.delete(key);
3432
- try {
3433
- await api.patch(`/api/ideas/${idea.id}`, { status: "draft" });
3434
- } catch {
3435
- }
3436
- return;
3437
- }
3438
- const activeEntry = {
3439
- process: void 0,
3440
- title: idea.title,
3441
- repoDir,
3442
- startedAt: Date.now(),
3443
- lastActivityAt: Date.now()
3444
- };
3445
- let attemptIndex = 0;
3446
- const launchAttempt = async (attemptAgent) => {
3447
- let spawnFailureReason = null;
3448
- const child = spawnAgent(
3449
- attemptAgent,
3450
- repoDir,
3451
- prompt2,
3452
- prefix,
3453
- void 0,
3454
- void 0,
3455
- idea.title,
3456
- false,
3457
- (err) => {
3458
- spawnFailureReason = err.message;
3459
- }
3460
- );
3461
- activeEntry.process = child;
3462
- activeEntry.currentAgent = attemptAgent;
3463
- active.set(key, activeEntry);
3464
- child.on("exit", async (code) => {
3465
- if (active.get(key)?.process === child) {
3466
- active.delete(key);
3467
- }
3468
- const failedAttempt = code !== 0 || spawnFailureReason !== null;
3469
- if (failedAttempt) {
3470
- const nextAgent = attemptOrder[attemptIndex + 1];
3471
- if (nextAgent) {
3472
- const failureDetail = spawnFailureReason ?? `exit code ${code}`;
3473
- logWarn(prefix, `${attemptAgent} failed (${failureDetail}) \u2014 retrying idea generation with ${nextAgent}`);
3474
- attemptIndex += 1;
3475
- await launchAttempt(nextAgent);
3476
- return;
3477
- }
3478
- }
3479
- finishing.add(key);
3480
- try {
3481
- if (code === 0) {
3482
- try {
3483
- let plan;
3484
- let protoHtml;
3485
- let followUpTasks;
3486
- const planPath = resolve2(repoDir, "idea-plan.md");
3487
- const tasksPath = resolve2(repoDir, "idea-tasks.json");
3488
- const protoPath = resolve2(repoDir, "idea-prototype.html");
3489
- try {
3490
- plan = readFileSync5(planPath, "utf-8");
3491
- } catch {
3492
- }
3493
- try {
3494
- protoHtml = readFileSync5(protoPath, "utf-8");
3495
- } catch {
3496
- }
3497
- try {
3498
- const tasksRaw = readFileSync5(tasksPath, "utf-8");
3499
- const parsed = JSON.parse(tasksRaw);
3500
- if (Array.isArray(parsed)) {
3501
- followUpTasks = parsed.filter((t) => t && typeof t === "object" && "title" in t);
3502
- }
3503
- } catch {
3504
- }
3505
- if (!plan && !protoHtml) {
3506
- logError(prefix, `No output files found in ${repoDir}`);
3507
- await api.patch(`/api/ideas/${idea.id}`, { status: "draft" });
3508
- return;
3509
- }
3510
- const updateData = { status: "generated" };
3511
- if (plan) updateData.plan = plan;
3512
- if (followUpTasks) updateData.followUpTasks = followUpTasks;
3513
- if (protoHtml) {
3514
- try {
3515
- const proto = await api.post("/api/prototypes", {
3516
- title: `${idea.title} \u2014 Idea Prototype`,
3517
- prompt: idea.description || idea.title,
3518
- variantCount: 1,
3519
- projectId: idea.projectId ?? null
3520
- });
3521
- await api.patch(`/api/prototypes/${proto.id}`, {
3522
- status: "completed",
3523
- files: [{ name: "idea-prototype.html", content: protoHtml }]
3524
- });
3525
- updateData.generatedPrototypeId = proto.id;
3526
- logSuccess(prefix, `Prototype created: ${paint("gray", proto.id.slice(0, 8))}`);
3527
- } catch (err) {
3528
- logError(prefix, `Failed to create prototype: ${err.message}`);
3529
- }
3530
- }
3531
- await api.patch(`/api/ideas/${idea.id}`, updateData);
3532
- logSuccess(prefix, `"${paint("bold", idea.title)}" generation complete`);
3533
- try {
3534
- unlinkSync(planPath);
3535
- } catch {
3536
- }
3537
- try {
3538
- unlinkSync(tasksPath);
3539
- } catch {
3540
- }
3541
- try {
3542
- unlinkSync(protoPath);
3543
- } catch {
3544
- }
3545
- } catch (err) {
3546
- logError(prefix, `Failed to upload idea output: ${err.message}`);
3547
- try {
3548
- await api.patch(`/api/ideas/${idea.id}`, { status: "draft" });
3549
- } catch {
3550
- }
3551
- }
3552
- } else {
3553
- const failureDetail = spawnFailureReason ?? `exit code ${code}`;
3554
- logError(prefix, `"${paint("bold", idea.title)}" generation failed via ${attemptAgent} (${failureDetail})`);
3555
- try {
3556
- await api.patch(`/api/ideas/${idea.id}`, { status: "draft" });
3557
- } catch {
3558
- }
3559
- }
3560
- } finally {
3561
- queued.delete(key);
3562
- finishing.delete(key);
3563
- }
3564
- });
3565
- };
3566
- await launchAttempt(attemptOrder[attemptIndex]);
3567
- }
3568
3402
  function dispatchScan(scan, prefix, key) {
3569
3403
  logDispatch(prefix, `Running scan for project ${paint("cyan", scan.projectId.slice(0, 8))}`);
3570
3404
  const scanProc = spawn4(process.execPath, [process.argv[1], "scan", "--project", scan.projectId, "--report", scan.id], {
@@ -3701,6 +3535,7 @@ ${divider}`);
3701
3535
  const running = active.get(task.id);
3702
3536
  if (running) {
3703
3537
  logWarn(prefix, `Task exceeded hang timeout after ${formatElapsed(Date.now() - running.startedAt)}, terminating agent\u2026`);
3538
+ running.terminatedForError = true;
3704
3539
  running.process.kill("SIGTERM");
3705
3540
  active.delete(task.id);
3706
3541
  }
@@ -3757,7 +3592,7 @@ ${divider}`);
3757
3592
  queued.delete(taskId);
3758
3593
  }
3759
3594
  }
3760
- const nonTaskPrefixes = ["proto-", "repo-", "scan-", "idea-", "test-"];
3595
+ const nonTaskPrefixes = ["proto-", "repo-", "scan-", "test-"];
3761
3596
  for (const taskId of failed.keys()) {
3762
3597
  if (nonTaskPrefixes.some((p) => taskId.startsWith(p))) continue;
3763
3598
  if (!activeTaskIds.has(taskId)) failed.delete(taskId);
@@ -3826,6 +3661,7 @@ ${divider}`);
3826
3661
  for (const [key, entry] of active) {
3827
3662
  if (key.startsWith("proto-") && !inProgressProtoKeys.has(key)) {
3828
3663
  logWarn(watchTag(), `Prototype ${paint("yellow", key)} no longer in_progress, terminating\u2026`);
3664
+ entry.terminatedForError = true;
3829
3665
  entry.process.kill("SIGTERM");
3830
3666
  active.delete(key);
3831
3667
  queued.delete(key);
@@ -4039,59 +3875,6 @@ ${divider}`);
4039
3875
  }
4040
3876
  dispatchRepoCreation(project, rootDir);
4041
3877
  }
4042
- let generatingIdeas = [];
4043
- try {
4044
- generatingIdeas = await api.get("/api/ideas?status=generating");
4045
- } catch (err) {
4046
- logError(watchTag(), `Failed to fetch generating ideas: ${err.message}`);
4047
- }
4048
- const inProgressIdeaKeys = new Set(generatingIdeas.map((i) => `idea-${i.id}`));
4049
- for (const [key, entry] of active) {
4050
- if (key.startsWith("idea-") && !inProgressIdeaKeys.has(key)) {
4051
- logWarn(watchTag(), `Idea ${paint("yellow", key)} no longer generating, terminating\u2026`);
4052
- entry.process.kill("SIGTERM");
4053
- active.delete(key);
4054
- queued.delete(key);
4055
- }
4056
- }
4057
- for (const key of failed.keys()) {
4058
- if (key.startsWith("idea-") && !inProgressIdeaKeys.has(key)) failed.delete(key);
4059
- }
4060
- for (const key of queued) {
4061
- if (key.startsWith("idea-") && !inProgressIdeaKeys.has(key) && !finishing.has(key)) queued.delete(key);
4062
- }
4063
- const activeIdeaCount = [...active.keys()].filter((k) => k.startsWith("idea-")).length;
4064
- let ideaSlots = Math.max(0, 1 - activeIdeaCount);
4065
- for (const idea of generatingIdeas) {
4066
- if (ideaSlots <= 0) break;
4067
- const key = `idea-${idea.id}`;
4068
- if (queued.has(key)) continue;
4069
- if (finishing.has(key)) continue;
4070
- if (failed.has(key)) continue;
4071
- const sid = shortId(idea.id);
4072
- const prefix = ideaTag(sid);
4073
- let repoDir;
4074
- if (idea.projectId) {
4075
- const dir = findDirectoryForProject(config, idea.projectId, rootDir);
4076
- if (!dir) {
4077
- logWarn(prefix, `"${idea.title}": no linked directory found \u2014 skipping`);
4078
- continue;
4079
- }
4080
- repoDir = dir;
4081
- } else {
4082
- repoDir = rootDir;
4083
- }
4084
- queued.add(key);
4085
- ideaSlots--;
4086
- if (dryRun) {
4087
- logInfo(
4088
- watchTag(),
4089
- `${paint("yellow", "[dry-run]")} would dispatch idea "${paint("bold", idea.title)}" in ${paint("cyan", repoDir)}`
4090
- );
4091
- continue;
4092
- }
4093
- dispatchIdeaJob(idea, repoDir);
4094
- }
4095
3878
  let pendingScans = [];
4096
3879
  try {
4097
3880
  pendingScans = await api.get("/api/scans?status=pending&limit=5");
@@ -4716,7 +4499,7 @@ async function checkApiConnectivity() {
4716
4499
  }
4717
4500
  }
4718
4501
  function printResults(checks) {
4719
- const maxNameLen = Math.max(...checks.map((c12) => c12.name.length));
4502
+ const maxNameLen = Math.max(...checks.map((c11) => c11.name.length));
4720
4503
  let allOk = true;
4721
4504
  for (const check of checks) {
4722
4505
  const isOptional = check.optional ?? false;
@@ -4730,10 +4513,10 @@ function printResults(checks) {
4730
4513
  }
4731
4514
  async function autoFix(checks, agent) {
4732
4515
  const { spawn: spawn8 } = await import("child_process");
4733
- const ghInstalled = checks.find((c12) => c12.name === "GitHub CLI (gh)").ok;
4734
- const ghAuthed = checks.find((c12) => c12.name === "GitHub CLI auth").ok;
4735
- const mrAuthed = checks.find((c12) => c12.name === "Mr. Manager CLI auth").ok;
4736
- const claudeCheck = checks.find((c12) => c12.name === "Claude Code (claude)");
4516
+ const ghInstalled = checks.find((c11) => c11.name === "GitHub CLI (gh)").ok;
4517
+ const ghAuthed = checks.find((c11) => c11.name === "GitHub CLI auth").ok;
4518
+ const mrAuthed = checks.find((c11) => c11.name === "Mr. Manager CLI auth").ok;
4519
+ const claudeCheck = checks.find((c11) => c11.name === "Claude Code (claude)");
4737
4520
  if (claudeCheck && !claudeCheck.ok && agent === "claude") {
4738
4521
  console.log(paint5("cyan", " Installing Claude Code..."));
4739
4522
  console.log(paint5("dim", " Running: curl -fsSL https://claude.ai/install.sh | bash"));
@@ -4796,7 +4579,7 @@ var setupCommand = new Command14("setup").description("Check that all dependenci
4796
4579
  console.log("");
4797
4580
  return;
4798
4581
  }
4799
- const fixes = checks.filter((c12) => !c12.ok && c12.fix && !c12.optional);
4582
+ const fixes = checks.filter((c11) => !c11.ok && c11.fix && !c11.optional);
4800
4583
  if (fixes.length > 0) {
4801
4584
  console.log(paint5("yellow", " To fix:"));
4802
4585
  for (const fix of fixes) {
@@ -5989,10 +5772,10 @@ ${codebaseAnalysis.routes.map((r) => `- ${r}`).join("\n")}
5989
5772
  ${codebaseAnalysis.prismaModels.map((m) => `- ${m}`).join("\n")}
5990
5773
 
5991
5774
  **Components:**
5992
- ${codebaseAnalysis.components.slice(0, 15).map((c12) => `- ${c12}`).join("\n")}
5775
+ ${codebaseAnalysis.components.slice(0, 15).map((c11) => `- ${c11}`).join("\n")}
5993
5776
 
5994
5777
  **Recent Git Commits:**
5995
- ${codebaseAnalysis.recentCommits.slice(0, 8).map((c12) => `- ${c12}`).join("\n")}
5778
+ ${codebaseAnalysis.recentCommits.slice(0, 8).map((c11) => `- ${c11}`).join("\n")}
5996
5779
 
5997
5780
  **Completed Tasks:**
5998
5781
  ${context.completedTasks.slice(0, 10).map((t) => `- ${t.title}`).join("\n") || "None"}
@@ -6439,128 +6222,8 @@ var scanCommand = new Command23("scan").description("Run a product scan on the c
6439
6222
  }
6440
6223
  });
6441
6224
 
6442
- // cli/commands/idea.ts
6443
- import { Command as Command24 } from "commander";
6444
- var c9 = {
6445
- reset: "\x1B[0m",
6446
- bold: "\x1B[1m",
6447
- dim: "\x1B[2m",
6448
- cyan: "\x1B[36m",
6449
- green: "\x1B[32m",
6450
- yellow: "\x1B[33m",
6451
- red: "\x1B[31m",
6452
- blue: "\x1B[34m",
6453
- gray: "\x1B[90m",
6454
- magenta: "\x1B[35m"
6455
- };
6456
- function paint9(color, text) {
6457
- return `${c9[color]}${text}${c9.reset}`;
6458
- }
6459
- function statusBadge2(status) {
6460
- switch (status) {
6461
- case "draft":
6462
- return paint9("gray", "\u25CB draft");
6463
- case "generating":
6464
- return paint9("cyan", "\u27F3 generating");
6465
- case "generated":
6466
- return paint9("green", "\u2713 generated");
6467
- case "promoted":
6468
- return paint9("magenta", "\u2191 promoted");
6469
- case "archived":
6470
- return paint9("dim", "\u2298 archived");
6471
- default:
6472
- return paint9("gray", status);
6473
- }
6474
- }
6475
- var ideaCommand = new Command24("idea").description("Manage ideas \u2014 brainstorm, generate prototypes & plans").addCommand(
6476
- new Command24("list").description("List ideas for the linked project").option("--all", "Show ideas for all projects").option("--status <status>", "Filter by status").action(async (opts) => {
6477
- const params = new URLSearchParams();
6478
- if (!opts.all) {
6479
- const projectId = getLinkedProjectId();
6480
- if (projectId) {
6481
- params.set("projectId", projectId);
6482
- }
6483
- }
6484
- if (opts.status) params.set("status", opts.status);
6485
- const ideas = await api.get(`/api/ideas?${params.toString()}`);
6486
- if (ideas.length === 0) {
6487
- console.log(paint9("gray", "No ideas found."));
6488
- return;
6489
- }
6490
- console.log();
6491
- for (const idea of ideas) {
6492
- const date = new Date(idea.createdAt).toLocaleDateString();
6493
- console.log(
6494
- ` ${paint9("bold", idea.title)} ${statusBadge2(idea.status)} ${paint9("gray", idea.id.slice(0, 8))} ${paint9("dim", date)}`
6495
- );
6496
- if (idea.description) {
6497
- console.log(` ${paint9("dim", idea.description.slice(0, 80) + (idea.description.length > 80 ? "\u2026" : ""))}`);
6498
- }
6499
- console.log();
6500
- }
6501
- })
6502
- ).addCommand(
6503
- new Command24("create").description("Create a new idea").argument("<title>", "Title of the idea").option("--description <desc>", "Description of the idea").option("--project <projectId>", "Project ID (defaults to linked project)").option("--generate", "Immediately start generating plan & prototype").action(async (title, opts) => {
6504
- const projectId = opts.project ?? getLinkedProjectId() ?? null;
6505
- const idea = await api.post("/api/ideas", {
6506
- title,
6507
- description: opts.description,
6508
- projectId
6509
- });
6510
- console.log();
6511
- console.log(` ${paint9("green", "\u2713")} Created idea: ${paint9("bold", idea.title)}`);
6512
- console.log(` ${paint9("gray", "ID:")} ${idea.id}`);
6513
- if (opts.generate) {
6514
- await api.post(`/api/ideas/${idea.id}/generate`);
6515
- console.log(` ${paint9("cyan", "\u27F3")} Generation will begin automatically via the watch agent.`);
6516
- }
6517
- console.log();
6518
- })
6519
- ).addCommand(
6520
- new Command24("generate").description("Start generating plan & prototype for an idea").argument("<id>", "Idea ID").action(async (id) => {
6521
- const idea = await api.post(`/api/ideas/${id}/generate`);
6522
- console.log();
6523
- console.log(` ${paint9("cyan", "\u27F3")} Generating: ${paint9("bold", idea.title)}`);
6524
- console.log(` ${paint9("gray", "The watch agent will pick this up shortly.")}`);
6525
- console.log();
6526
- })
6527
- ).addCommand(
6528
- new Command24("feedback").description("Send feedback to iterate on an idea's generated content").argument("<id>", "Idea ID").argument("<feedback>", "Feedback text").action(async (id, feedback) => {
6529
- const idea = await api.post(`/api/ideas/${id}/feedback`, { feedback });
6530
- console.log();
6531
- console.log(` ${paint9("cyan", "\u27F3")} Feedback sent for: ${paint9("bold", idea.title)}`);
6532
- console.log(` ${paint9("gray", "The watch agent will re-generate with your feedback.")}`);
6533
- console.log();
6534
- })
6535
- ).addCommand(
6536
- new Command24("promote").description("Promote an idea to a task").argument("<id>", "Idea ID").action(async (id) => {
6537
- const result = await api.post(`/api/ideas/${id}/promote`);
6538
- console.log();
6539
- console.log(` ${paint9("green", "\u2713")} Promoted idea to task: ${paint9("bold", result.task.title)}`);
6540
- console.log(` ${paint9("gray", "Task ID:")} ${result.task.id}`);
6541
- console.log();
6542
- })
6543
- ).addCommand(
6544
- new Command24("spin-up").description("Spin up a new project with a GitHub repo from an idea").argument("<id>", "Idea ID").option("--name <name>", "Custom project name (defaults to idea title)").action(async (id, opts) => {
6545
- const body = {};
6546
- if (opts.name) body.name = opts.name;
6547
- const result = await api.post(`/api/ideas/${id}/spin-up`, body);
6548
- console.log();
6549
- console.log(` ${paint9("green", "\u2713")} Spinning up project: ${paint9("bold", result.project.name)}`);
6550
- console.log(` ${paint9("gray", "Project ID:")} ${result.project.id}`);
6551
- if (result.tasks && result.tasks.length > 0) {
6552
- console.log(` ${paint9("green", "\u2713")} Created ${result.tasks.length} follow-up task(s):`);
6553
- for (const task of result.tasks) {
6554
- console.log(` ${paint9("gray", "\u2022")} ${task.title}`);
6555
- }
6556
- }
6557
- console.log(` ${paint9("cyan", "\u27F3")} Repo creation is queued \u2014 the watch daemon will pick it up.`);
6558
- console.log();
6559
- })
6560
- );
6561
-
6562
6225
  // cli/commands/doctor.ts
6563
- import { Command as Command25 } from "commander";
6226
+ import { Command as Command24 } from "commander";
6564
6227
  import { existsSync as existsSync15 } from "fs";
6565
6228
  import { homedir as homedir2 } from "os";
6566
6229
  import { join as join11 } from "path";
@@ -6608,7 +6271,7 @@ async function checkProjectLink() {
6608
6271
  optional: true
6609
6272
  };
6610
6273
  }
6611
- var doctorCommand = new Command25("doctor").description("Diagnose Mr. Manager CLI installation and environment").action(async () => {
6274
+ var doctorCommand = new Command24("doctor").description("Diagnose Mr. Manager CLI installation and environment").action(async () => {
6612
6275
  const banner = [
6613
6276
  ``,
6614
6277
  paint5("cyan", ` MR DOCTOR`),
@@ -6639,7 +6302,7 @@ var doctorCommand = new Command25("doctor").description("Diagnose Mr. Manager CL
6639
6302
  console.log("");
6640
6303
  return;
6641
6304
  }
6642
- const fixes = checks.filter((c12) => !c12.ok && c12.fix && !c12.optional);
6305
+ const fixes = checks.filter((c11) => !c11.ok && c11.fix && !c11.optional);
6643
6306
  if (fixes.length > 0) {
6644
6307
  console.log(paint5("yellow", " To fix:"));
6645
6308
  for (const fix of fixes) {
@@ -6651,14 +6314,14 @@ var doctorCommand = new Command25("doctor").description("Diagnose Mr. Manager CL
6651
6314
  });
6652
6315
 
6653
6316
  // cli/commands/prompt-audit.ts
6654
- import { Command as Command26 } from "commander";
6317
+ import { Command as Command25 } from "commander";
6655
6318
  import { resolve as resolve8 } from "path";
6656
6319
  import { existsSync as existsSync16, readFileSync as readFileSync12 } from "fs";
6657
6320
  function auditLine(label, tokens) {
6658
6321
  const bar = "\u2588".repeat(Math.min(60, Math.round(tokens / 200)));
6659
6322
  return ` ${label.padEnd(30)} ${formatTokenCount(tokens).padStart(8)} ${bar}`;
6660
6323
  }
6661
- var promptAuditCommand = new Command26("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) => {
6324
+ var promptAuditCommand = new Command25("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) => {
6662
6325
  const results = [];
6663
6326
  if (opts.task) {
6664
6327
  try {
@@ -6818,14 +6481,6 @@ ${task.notes}` : "";
6818
6481
  { name: "instructions", tokens: 500 }
6819
6482
  ]
6820
6483
  },
6821
- {
6822
- jobType: "idea",
6823
- description: "Idea generation prompt",
6824
- sections: [
6825
- { name: "core-prompt", tokens: 500 },
6826
- { name: "idea-desc", tokens: 200 }
6827
- ]
6828
- },
6829
6484
  {
6830
6485
  jobType: "repo-creation",
6831
6486
  description: "Repository creation prompt",
@@ -6871,8 +6526,8 @@ ${r.jobType} [${r.identifier}]`);
6871
6526
  });
6872
6527
 
6873
6528
  // cli/commands/skill.ts
6874
- import { Command as Command27 } from "commander";
6875
- var c10 = {
6529
+ import { Command as Command26 } from "commander";
6530
+ var c9 = {
6876
6531
  reset: "\x1B[0m",
6877
6532
  bold: "\x1B[1m",
6878
6533
  dim: "\x1B[2m",
@@ -6880,7 +6535,7 @@ var c10 = {
6880
6535
  green: "\x1B[32m",
6881
6536
  yellow: "\x1B[33m"
6882
6537
  };
6883
- var skillCommand = new Command27("skill").description("Manage skills \u2014 reusable playbooks for AI agents");
6538
+ var skillCommand = new Command26("skill").description("Manage skills \u2014 reusable playbooks for AI agents");
6884
6539
  skillCommand.command("list").alias("ls").description("List all skills").option("--category <category>", "Filter by category").action(async (opts) => {
6885
6540
  const params = new URLSearchParams();
6886
6541
  if (opts.category) params.set("category", opts.category);
@@ -6888,17 +6543,17 @@ skillCommand.command("list").alias("ls").description("List all skills").option("
6888
6543
  `/api/skills${params.toString() ? `?${params}` : ""}`
6889
6544
  );
6890
6545
  if (skills.length === 0) {
6891
- console.log(`${c10.dim}No skills found.${c10.reset}`);
6546
+ console.log(`${c9.dim}No skills found.${c9.reset}`);
6892
6547
  return;
6893
6548
  }
6894
6549
  for (const skill of skills) {
6895
- const cat = skill.category ? ` ${c10.dim}[${skill.category}]${c10.reset}` : "";
6896
- const scope = skill.projectId ? ` ${c10.dim}(project)${c10.reset}` : ` ${c10.dim}(global)${c10.reset}`;
6897
- console.log(` ${c10.cyan}${skill.name}${c10.reset}${cat}${scope}`);
6550
+ const cat = skill.category ? ` ${c9.dim}[${skill.category}]${c9.reset}` : "";
6551
+ const scope = skill.projectId ? ` ${c9.dim}(project)${c9.reset}` : ` ${c9.dim}(global)${c9.reset}`;
6552
+ console.log(` ${c9.cyan}${skill.name}${c9.reset}${cat}${scope}`);
6898
6553
  if (skill.description) {
6899
- console.log(` ${c10.dim}${skill.description}${c10.reset}`);
6554
+ console.log(` ${c9.dim}${skill.description}${c9.reset}`);
6900
6555
  }
6901
- console.log(` ${c10.dim}id: ${skill.id}${c10.reset}`);
6556
+ console.log(` ${c9.dim}id: ${skill.id}${c9.reset}`);
6902
6557
  }
6903
6558
  });
6904
6559
  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) => {
@@ -6934,7 +6589,7 @@ skillCommand.command("create").description("Create a new skill from a markdown f
6934
6589
  projectId
6935
6590
  });
6936
6591
  console.log(
6937
- `${c10.green}Created skill:${c10.reset} ${c10.bold}${skill.name}${c10.reset} ${c10.dim}(${skill.id})${c10.reset}`
6592
+ `${c9.green}Created skill:${c9.reset} ${c9.bold}${skill.name}${c9.reset} ${c9.dim}(${skill.id})${c9.reset}`
6938
6593
  );
6939
6594
  });
6940
6595
  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) => {
@@ -6948,22 +6603,22 @@ skillCommand.command("generate").alias("gen").description("Generate a new skill
6948
6603
  process.exit(1);
6949
6604
  }
6950
6605
  }
6951
- console.log(`${c10.dim}Generating skill...${c10.reset}`);
6606
+ console.log(`${c9.dim}Generating skill...${c9.reset}`);
6952
6607
  try {
6953
6608
  const skill = await api.post("/api/skills/generate", {
6954
6609
  prompt: prompt2,
6955
6610
  projectId
6956
6611
  });
6957
6612
  console.log(
6958
- `${c10.green}Generated skill:${c10.reset} ${c10.bold}${skill.name}${c10.reset}`
6613
+ `${c9.green}Generated skill:${c9.reset} ${c9.bold}${skill.name}${c9.reset}`
6959
6614
  );
6960
6615
  if (skill.description) {
6961
- console.log(` ${c10.dim}${skill.description}${c10.reset}`);
6616
+ console.log(` ${c9.dim}${skill.description}${c9.reset}`);
6962
6617
  }
6963
6618
  if (skill.category) {
6964
- console.log(` ${c10.dim}Category: ${skill.category}${c10.reset}`);
6619
+ console.log(` ${c9.dim}Category: ${skill.category}${c9.reset}`);
6965
6620
  }
6966
- console.log(` ${c10.dim}id: ${skill.id}${c10.reset}`);
6621
+ console.log(` ${c9.dim}id: ${skill.id}${c9.reset}`);
6967
6622
  } catch (err) {
6968
6623
  console.error(`Failed to generate skill: ${err.message}`);
6969
6624
  process.exit(1);
@@ -6971,17 +6626,17 @@ skillCommand.command("generate").alias("gen").description("Generate a new skill
6971
6626
  });
6972
6627
 
6973
6628
  // cli/commands/tests.ts
6974
- import { Command as Command28 } from "commander";
6975
- var c11 = {
6629
+ import { Command as Command27 } from "commander";
6630
+ var c10 = {
6976
6631
  reset: "\x1B[0m",
6977
6632
  dim: "\x1B[2m",
6978
6633
  yellow: "\x1B[33m"
6979
6634
  };
6980
- var testsCommand = new Command28("tests").description("List MR Test scenarios for the linked project").action(async () => {
6635
+ var testsCommand = new Command27("tests").description("List MR Test scenarios for the linked project").action(async () => {
6981
6636
  const projectId = getLinkedProjectId();
6982
6637
  if (!projectId) {
6983
6638
  console.error(
6984
- `${c11.yellow}No project linked to this directory.${c11.reset} Run "mr link <project-id>" first.`
6639
+ `${c10.yellow}No project linked to this directory.${c10.reset} Run "mr link <project-id>" first.`
6985
6640
  );
6986
6641
  process.exit(1);
6987
6642
  }
@@ -6994,13 +6649,13 @@ var testsCommand = new Command28("tests").description("List MR Test scenarios fo
6994
6649
  process.exit(1);
6995
6650
  }
6996
6651
  if (scenarios.length === 0) {
6997
- console.log(`${c11.dim}No test scenarios found for this project.${c11.reset}`);
6652
+ console.log(`${c10.dim}No test scenarios found for this project.${c10.reset}`);
6998
6653
  return;
6999
6654
  }
7000
6655
  for (const scenario of scenarios) {
7001
6656
  console.log(`### ${scenario.name}`);
7002
6657
  if (scenario.description) {
7003
- console.log(`${c11.dim}${scenario.description}${c11.reset}`);
6658
+ console.log(`${c10.dim}${scenario.description}${c10.reset}`);
7004
6659
  console.log();
7005
6660
  }
7006
6661
  console.log(scenario.content);
@@ -7015,7 +6670,7 @@ var userArgs = process.argv.slice(2);
7015
6670
  var bypassCommands = /* @__PURE__ */ new Set(["login", "init", "auth", "help", "--help", "-h", "--version", "-V", "doctor", "setup"]);
7016
6671
  var shouldBypass = userArgs.length > 0 && bypassCommands.has(userArgs[0]);
7017
6672
  if (isFirstRun && !shouldBypass) {
7018
- const c12 = {
6673
+ const c11 = {
7019
6674
  reset: "\x1B[0m",
7020
6675
  bold: "\x1B[1m",
7021
6676
  dim: "\x1B[2m",
@@ -7025,28 +6680,28 @@ if (isFirstRun && !shouldBypass) {
7025
6680
  magenta: "\x1B[35m"
7026
6681
  };
7027
6682
  console.log("");
7028
- console.log(`${c12.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${c12.reset}`);
7029
- console.log(`${c12.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${c12.reset}`);
7030
- console.log(`${c12.cyan} \u2569 \u2569\u2569\u255A\u2550 \u2569 \u2569\u2569 \u2569\u255D\u255A\u255D\u2569 \u2569\u255A\u2550\u255D\u255A\u2550\u255D\u2569\u255A\u2550${c12.reset}`);
7031
- console.log(`${c12.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${c12.reset}`);
6683
+ console.log(`${c11.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${c11.reset}`);
6684
+ console.log(`${c11.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${c11.reset}`);
6685
+ console.log(`${c11.cyan} \u2569 \u2569\u2569\u255A\u2550 \u2569 \u2569\u2569 \u2569\u255D\u255A\u255D\u2569 \u2569\u255A\u2550\u255D\u255A\u2550\u255D\u2569\u255A\u2550${c11.reset}`);
6686
+ console.log(`${c11.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${c11.reset}`);
7032
6687
  console.log("");
7033
- console.log(`${c12.bold} Welcome to Mr. Manager!${c12.reset}`);
7034
- console.log(`${c12.dim} Let's get you set up in a few quick steps.${c12.reset}`);
6688
+ console.log(`${c11.bold} Welcome to Mr. Manager!${c11.reset}`);
6689
+ console.log(`${c11.dim} Let's get you set up in a few quick steps.${c11.reset}`);
7035
6690
  console.log("");
7036
- console.log(` ${c12.yellow}Step 1:${c12.reset} Authenticate via Google OAuth`);
7037
- console.log(` ${c12.dim}Run:${c12.reset} ${c12.cyan}mr login${c12.reset}`);
6691
+ console.log(` ${c11.yellow}Step 1:${c11.reset} Authenticate via Google OAuth`);
6692
+ console.log(` ${c11.dim}Run:${c11.reset} ${c11.cyan}mr login${c11.reset}`);
7038
6693
  console.log("");
7039
- console.log(` ${c12.yellow}Step 2:${c12.reset} Verify your environment`);
7040
- console.log(` ${c12.dim}Run:${c12.reset} ${c12.cyan}mr setup${c12.reset}`);
6694
+ console.log(` ${c11.yellow}Step 2:${c11.reset} Verify your environment`);
6695
+ console.log(` ${c11.dim}Run:${c11.reset} ${c11.cyan}mr setup${c11.reset}`);
7041
6696
  console.log("");
7042
- console.log(` ${c12.yellow}Step 3:${c12.reset} Link a repo and start watching`);
7043
- console.log(` ${c12.dim}Run:${c12.reset} ${c12.cyan}mr link${c12.reset} ${c12.dim}&&${c12.reset} ${c12.cyan}mr watch${c12.reset}`);
6697
+ console.log(` ${c11.yellow}Step 3:${c11.reset} Link a repo and start watching`);
6698
+ console.log(` ${c11.dim}Run:${c11.reset} ${c11.cyan}mr link${c11.reset} ${c11.dim}&&${c11.reset} ${c11.cyan}mr watch${c11.reset}`);
7044
6699
  console.log("");
7045
- console.log(`${c12.dim} Or run ${c12.reset}${c12.cyan}mr login${c12.reset}${c12.dim} to get started now.${c12.reset}`);
6700
+ console.log(`${c11.dim} Or run ${c11.reset}${c11.cyan}mr login${c11.reset}${c11.dim} to get started now.${c11.reset}`);
7046
6701
  console.log("");
7047
6702
  process.exit(0);
7048
6703
  }
7049
- var program = new Command29();
6704
+ var program = new Command28();
7050
6705
  program.name("mr").description("Mr. Manager - Task and project management CLI").version(CLI_VERSION);
7051
6706
  program.addCommand(initCommand);
7052
6707
  program.addCommand(authCommand);
@@ -7074,7 +6729,6 @@ program.addCommand(testCommand);
7074
6729
  program.addCommand(featuresCommand);
7075
6730
  program.addCommand(noMrCommand);
7076
6731
  program.addCommand(scanCommand);
7077
- program.addCommand(ideaCommand);
7078
6732
  program.addCommand(doctorCommand);
7079
6733
  program.addCommand(promptAuditCommand);
7080
6734
  program.addCommand(skillCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dunnewold-labs/mr-manager",
3
- "version": "0.4.27",
3
+ "version": "0.4.29",
4
4
  "description": "Mr. Manager - Task and project management CLI",
5
5
  "bin": {
6
6
  "mr": "./dist/index.mjs"