@dunnewold-labs/mr-manager 0.4.20 → 0.4.21

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 +199 -43
  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 Command28 } from "commander";
4
+ import { Command as Command29 } 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.20",
188
+ version: "0.4.21",
189
189
  description: "Mr. Manager - Task and project management CLI",
190
190
  bin: {
191
191
  mr: "./dist/index.mjs"
@@ -1341,6 +1341,19 @@ Rules:
1341
1341
  - The "context" field should be a single sentence.
1342
1342
  - Use sequential IDs: q1, q2, q3, etc.
1343
1343
  - Place the JSON block at the very end of the "Open Questions" section.`;
1344
+ var SYSTEM_SECTION_MR_TESTS = `## MR Tests \u2014 Feature Testing Scenarios
1345
+
1346
+ Before writing your test plan, run:
1347
+ mr tests
1348
+
1349
+ This lists all human-authored test scenarios for this project. Each scenario describes how to navigate to a specific feature, what interactions to perform, and what to verify.
1350
+
1351
+ If a scenario name matches the feature you're testing (by name or keyword):
1352
+ 1. Use its interaction steps as the basis for your test plan.
1353
+ 2. Adapt specific assertions to the task's requirements.
1354
+ 3. Note in your test plan summary which scenario you used.
1355
+
1356
+ If no matching scenario exists, infer interactions from the codebase as normal.`;
1344
1357
  var SYSTEM_SECTIONS = {
1345
1358
  "status-updates": SYSTEM_SECTION_STATUS_UPDATES,
1346
1359
  "screenshots": SYSTEM_SECTION_SCREENSHOTS,
@@ -1348,12 +1361,13 @@ var SYSTEM_SECTIONS = {
1348
1361
  "no-mr": SYSTEM_SECTION_NO_MR,
1349
1362
  "features-workflow": SYSTEM_SECTION_FEATURES_WORKFLOW,
1350
1363
  "prd-format": SYSTEM_SECTION_PRD_FORMAT,
1351
- "prd-open-questions": SYSTEM_SECTION_PRD_OPEN_QUESTIONS
1364
+ "prd-open-questions": SYSTEM_SECTION_PRD_OPEN_QUESTIONS,
1365
+ "mr-tests": SYSTEM_SECTION_MR_TESTS
1352
1366
  };
1353
1367
  function composeSystemPrompt(sections) {
1354
1368
  return sections.map((s) => SYSTEM_SECTIONS[s]).join("\n\n");
1355
1369
  }
1356
- var EXECUTION_SYSTEM_SECTIONS = ["status-updates", "screenshots", "test-plan", "no-mr", "features-workflow"];
1370
+ var EXECUTION_SYSTEM_SECTIONS = ["status-updates", "screenshots", "test-plan", "mr-tests", "no-mr", "features-workflow"];
1357
1371
  var PRD_SYSTEM_SECTIONS = ["prd-format", "prd-open-questions"];
1358
1372
  var c = {
1359
1373
  reset: "\x1B[0m",
@@ -2166,6 +2180,7 @@ ${initPrompt}`] : [],
2166
2180
  ].join("\n");
2167
2181
  }
2168
2182
  function buildPrototypePrompt(proto, repoDir) {
2183
+ const prototypeType = proto.prototypeType ?? "web_app";
2169
2184
  const variantSteps = [];
2170
2185
  for (let i = 1; i <= proto.variantCount; i++) {
2171
2186
  const filename = `prototype-${i}.html`;
@@ -2178,14 +2193,87 @@ function buildPrototypePrompt(proto, repoDir) {
2178
2193
  );
2179
2194
  }
2180
2195
  const variantList = Array.from({ length: proto.variantCount }, (_, i) => `prototype-${i + 1}.html`);
2196
+ const typeConfig = {
2197
+ web_app: {
2198
+ role: "You are a UI designer and frontend engineer. Your job is to generate high-quality, visually distinct web app prototype variants based on the user's design request.",
2199
+ guidelines: [
2200
+ `- **Layout**: Grid, list, card, single-page, multi-section`,
2201
+ `- **Style**: Minimal, bold, playful, corporate, retro, futuristic`,
2202
+ `- **Color scheme**: Light, dark, colorful, monochrome`,
2203
+ `- **Interaction model**: Click-heavy, scroll-based, hover effects, animated`,
2204
+ `- **Information density**: Sparse, balanced, dense`,
2205
+ `- **Navigation**: Sidebar, top nav, bottom nav, hamburger, tabs`
2206
+ ],
2207
+ rules: [
2208
+ `- Each file must be a complete, functional page \u2014 pure HTML/CSS/JS, no external libraries (Tailwind CDN is acceptable).`
2209
+ ]
2210
+ },
2211
+ mobile_app: {
2212
+ role: "You are a mobile UI designer and frontend engineer. Your job is to generate high-quality, visually distinct mobile app prototype variants based on the user's design request.",
2213
+ guidelines: [
2214
+ `- **Viewport**: Use a mobile viewport (375px wide max, 812px tall). Center the phone frame on a neutral background.`,
2215
+ `- **Layout**: Bottom tabs, stack navigation, cards, lists, full-screen views`,
2216
+ `- **Style**: iOS-inspired, Material Design, custom/brand-driven, minimal`,
2217
+ `- **Color scheme**: Light mode, dark mode, brand-colored`,
2218
+ `- **Touch patterns**: Large tap targets (44px+), swipe gestures indicated, thumb-friendly navigation`,
2219
+ `- **Typography**: Mobile-scale fonts (14-18px body), clear hierarchy`,
2220
+ `- **Navigation**: Bottom tab bar, top navigation bar, hamburger drawer, floating action button`
2221
+ ],
2222
+ rules: [
2223
+ `- Render the app as a phone-sized frame (375\xD7812px) centered on a light gray page background.`,
2224
+ `- Use a \`<meta name="viewport" content="width=375">\` tag.`,
2225
+ `- Each file must be a complete, functional HTML page \u2014 pure HTML/CSS/JS, no external libraries (Tailwind CDN is acceptable).`
2226
+ ]
2227
+ },
2228
+ desktop_app: {
2229
+ role: "You are a desktop UI designer and frontend engineer. Your job is to generate high-quality, visually distinct desktop application prototype variants based on the user's design request.",
2230
+ guidelines: [
2231
+ `- **Viewport**: Full-width desktop layout (1280px+). Use the full browser window.`,
2232
+ `- **Layout**: Multi-panel, sidebar + main content, menubar, toolbar, status bar`,
2233
+ `- **Style**: Native OS-inspired (macOS, Windows), Electron-style, productivity tool, pro/creative app`,
2234
+ `- **Color scheme**: Light, dark, system-default`,
2235
+ `- **Interaction**: Dense information layouts, keyboard shortcuts shown, right-click context menus, drag handles`,
2236
+ `- **Navigation**: Left sidebar tree, top tabs, ribbon toolbar, split panes`
2237
+ ],
2238
+ rules: [
2239
+ `- Design for 1280px+ wide layouts. Use the full browser viewport width.`,
2240
+ `- Each file must be a complete, functional HTML page \u2014 pure HTML/CSS/JS, no external libraries (Tailwind CDN is acceptable).`
2241
+ ]
2242
+ },
2243
+ logo: {
2244
+ role: "You are a graphic designer specializing in logo and brand identity. Your job is to generate high-quality, visually distinct logo variants based on the user's brand brief.",
2245
+ guidelines: [
2246
+ `- **Style**: Wordmark, lettermark, icon + wordmark, abstract symbol, emblem/badge`,
2247
+ `- **Visual language**: Minimal/geometric, organic/hand-drawn, bold/impactful, elegant/luxury, playful/friendly`,
2248
+ `- **Color scheme**: Monochrome, duotone, full-color (max 3 colors), gradient`,
2249
+ `- **Typography**: Serif, sans-serif, display/decorative, script`,
2250
+ `- **Symbolism**: Use shapes, negative space, and iconography that reflect the brand concept`
2251
+ ],
2252
+ rules: [
2253
+ `- Each file is an HTML page that displays the logo centered on a white background with a dark mode toggle.`,
2254
+ `- The logo itself MUST be created as inline SVG \u2014 no raster images, no external assets.`,
2255
+ `- Show the logo at three sizes: large (400px wide), medium (200px), small (80px) stacked vertically.`,
2256
+ `- Include a dark background preview section below the logo to test contrast.`,
2257
+ `- The SVG must be clean and production-ready \u2014 no lorem ipsum, placeholder paths, or broken shapes.`
2258
+ ]
2259
+ }
2260
+ };
2261
+ const config = typeConfig[prototypeType] ?? typeConfig.web_app;
2262
+ const typeLabel = {
2263
+ web_app: "Web App",
2264
+ mobile_app: "Mobile App",
2265
+ desktop_app: "Desktop App",
2266
+ logo: "Logo"
2267
+ };
2181
2268
  return [
2182
- `You are a UI designer and frontend engineer. Your job is to generate ${proto.variantCount} high-quality, visually distinct HTML prototype variants based on the user's design request.`,
2269
+ `${config.role}`,
2183
2270
  ``,
2184
2271
  `Working directory: ${repoDir}`,
2185
2272
  ``,
2186
2273
  `## Prototype Request`,
2187
2274
  `Title: ${proto.title}`,
2188
2275
  `ID: ${proto.id}`,
2276
+ `Type: ${typeLabel[prototypeType] ?? prototypeType}`,
2189
2277
  ``,
2190
2278
  `## Design Prompt`,
2191
2279
  `${proto.prompt}`,
@@ -2196,17 +2284,12 @@ function buildPrototypePrompt(proto, repoDir) {
2196
2284
  ``,
2197
2285
  `Each file must be completely self-contained (inline all CSS and JS \u2014 no external dependencies). Tailwind CDN is acceptable.`,
2198
2286
  ``,
2199
- `## Prototype Variation Guidelines`,
2287
+ `## Variation Guidelines`,
2200
2288
  ``,
2201
- `When generating multiple prototypes, vary these aspects:`,
2202
- `- **Layout**: Grid, list, card, single-page, multi-section`,
2203
- `- **Style**: Minimal, bold, playful, corporate, retro, futuristic`,
2204
- `- **Color scheme**: Light, dark, colorful, monochrome`,
2205
- `- **Interaction model**: Click-heavy, scroll-based, hover effects, animated`,
2206
- `- **Information density**: Sparse, balanced, dense`,
2207
- `- **Navigation**: Sidebar, top nav, bottom nav, hamburger, tabs`,
2289
+ `When generating multiple variants, vary these aspects:`,
2290
+ ...config.guidelines,
2208
2291
  ``,
2209
- `Prototypes should demonstrate different interpretations, not just color swaps. Vary from very similar to wildly different approaches.`,
2292
+ `Variants should demonstrate different interpretations, not just color swaps. Vary from very similar to wildly different approaches.`,
2210
2293
  ``,
2211
2294
  ...variantSteps,
2212
2295
  `### Final verification`,
@@ -2216,7 +2299,7 @@ function buildPrototypePrompt(proto, repoDir) {
2216
2299
  `- You MUST produce exactly ${proto.variantCount} files: ${variantList.join(", ")}`,
2217
2300
  `- Generate them ONE AT A TIME \u2014 design each variant, write the file, then move to the next.`,
2218
2301
  `- Each variant must look visually DISTINCT from the others.`,
2219
- `- Each file must be a complete, functional page \u2014 pure HTML/CSS/JS, no external libraries (Tailwind CDN is acceptable).`,
2302
+ ...config.rules,
2220
2303
  `- Do NOT upload or POST the files anywhere. The watch handler will upload them automatically after you exit.`,
2221
2304
  `- Do NOT exit until ALL ${proto.variantCount} files have been written and verified.`
2222
2305
  ].join("\n");
@@ -2251,14 +2334,28 @@ function buildRefinementPrompt(proto, parentFiles, repoDir) {
2251
2334
  existingVariantLines.push(``);
2252
2335
  }
2253
2336
  const existingVariants = existingVariantLines.join("\n");
2337
+ const prototypeType = proto.prototypeType ?? "web_app";
2338
+ const typeRoleMap = {
2339
+ web_app: "You are a UI designer and frontend engineer. Your job is to REFINE an existing web app prototype based on user feedback.",
2340
+ mobile_app: "You are a mobile UI designer and frontend engineer. Your job is to REFINE an existing mobile app prototype based on user feedback.",
2341
+ desktop_app: "You are a desktop UI designer and frontend engineer. Your job is to REFINE an existing desktop app prototype based on user feedback.",
2342
+ logo: "You are a graphic designer specializing in logo and brand identity. Your job is to REFINE an existing logo prototype based on user feedback."
2343
+ };
2344
+ const typeLabel = {
2345
+ web_app: "Web App",
2346
+ mobile_app: "Mobile App",
2347
+ desktop_app: "Desktop App",
2348
+ logo: "Logo"
2349
+ };
2254
2350
  return [
2255
- `You are a UI designer and frontend engineer. Your job is to REFINE an existing prototype based on user feedback.`,
2351
+ `${typeRoleMap[prototypeType] ?? typeRoleMap.web_app}`,
2256
2352
  ``,
2257
2353
  `Working directory: ${repoDir}`,
2258
2354
  ``,
2259
2355
  `## Prototype Request`,
2260
2356
  `Title: ${proto.title}`,
2261
2357
  `ID: ${proto.id}`,
2358
+ `Type: ${typeLabel[prototypeType] ?? prototypeType}`,
2262
2359
  ``,
2263
2360
  `## Original Design Prompt`,
2264
2361
  `${proto.prompt}`,
@@ -2400,7 +2497,10 @@ ${systemPrompt}` : prompt2;
2400
2497
  if (mode === "plan") {
2401
2498
  return { bin: "claude", args: [...sessionArgs, ...nameArgs, ...systemArgs, ...turnsArgs, "--permission-mode", "plan", "-p", prompt2] };
2402
2499
  }
2403
- return { bin: "claude", args: [...sessionArgs, ...nameArgs, ...systemArgs, ...turnsArgs, "-p", "--dangerously-skip-permissions", prompt2] };
2500
+ const cfg = loadConfig();
2501
+ const permissionMode = cfg.claudePermissionMode ?? "auto";
2502
+ const permissionArgs = permissionMode === "dangerously-skip-permissions" ? ["--dangerously-skip-permissions"] : ["--permission-mode", "auto", "--enable-auto-mode"];
2503
+ return { bin: "claude", args: [...sessionArgs, ...nameArgs, ...systemArgs, ...turnsArgs, ...permissionArgs, "-p", prompt2] };
2404
2504
  }
2405
2505
  function commandExists(cmd) {
2406
2506
  return new Promise((resolve8) => {
@@ -4260,28 +4360,45 @@ var prototypeCommand = new Command13("prototype").description("Manage prototypes
4260
4360
  return;
4261
4361
  }
4262
4362
  console.log();
4363
+ const typeLabels = {
4364
+ web_app: "web",
4365
+ mobile_app: "mobile",
4366
+ desktop_app: "desktop",
4367
+ logo: "logo"
4368
+ };
4263
4369
  for (const p of prototypes) {
4264
4370
  const date = new Date(p.createdAt).toLocaleDateString();
4371
+ const typeLabel = typeLabels[p.prototypeType] ?? p.prototypeType ?? "web";
4265
4372
  console.log(
4266
- ` ${paint4("bold", p.title)} ${statusBadge(p.status)} ${paint4("gray", p.id.slice(0, 8))} ${paint4("dim", date)}`
4373
+ ` ${paint4("bold", p.title)} ${statusBadge(p.status)} ${paint4("blue", `[${typeLabel}]`)} ${paint4("gray", p.id.slice(0, 8))} ${paint4("dim", date)}`
4267
4374
  );
4268
4375
  console.log(` ${paint4("dim", p.prompt.slice(0, 80) + (p.prompt.length > 80 ? "\u2026" : ""))}`);
4269
4376
  console.log();
4270
4377
  }
4271
4378
  })
4272
4379
  ).addCommand(
4273
- new Command13("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").action(async (title, opts) => {
4380
+ new Command13("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").action(async (title, opts) => {
4274
4381
  const projectId = opts.project ?? getLinkedProjectId();
4275
4382
  const variantCount = Math.max(1, Math.min(50, parseInt(opts.variants, 10) || 5));
4383
+ const validTypes = ["web_app", "mobile_app", "desktop_app", "logo"];
4384
+ const prototypeType = validTypes.includes(opts.type) ? opts.type : "web_app";
4276
4385
  const prototype = await api.post("/api/prototypes", {
4277
4386
  title,
4278
4387
  prompt: opts.prompt,
4388
+ prototypeType,
4279
4389
  variantCount,
4280
4390
  projectId: projectId ?? null
4281
4391
  });
4392
+ const typeLabels = {
4393
+ web_app: "Web App",
4394
+ mobile_app: "Mobile App",
4395
+ desktop_app: "Desktop App",
4396
+ logo: "Logo"
4397
+ };
4282
4398
  console.log();
4283
4399
  console.log(` ${paint4("green", "\u2713")} Created prototype: ${paint4("bold", prototype.title)}`);
4284
4400
  console.log(` ${paint4("gray", "ID:")} ${prototype.id}`);
4401
+ console.log(` ${paint4("gray", "Type:")} ${typeLabels[prototype.prototypeType] ?? prototype.prototypeType}`);
4285
4402
  if (!prototype.projectId) {
4286
4403
  console.log(` ${paint4("gray", "Project:")} none (will generate in the active watch directory)`);
4287
4404
  }
@@ -4569,7 +4686,7 @@ async function checkApiConnectivity() {
4569
4686
  }
4570
4687
  }
4571
4688
  function printResults(checks) {
4572
- const maxNameLen = Math.max(...checks.map((c11) => c11.name.length));
4689
+ const maxNameLen = Math.max(...checks.map((c12) => c12.name.length));
4573
4690
  let allOk = true;
4574
4691
  for (const check of checks) {
4575
4692
  const isOptional = check.optional ?? false;
@@ -4583,10 +4700,10 @@ function printResults(checks) {
4583
4700
  }
4584
4701
  async function autoFix(checks, agent) {
4585
4702
  const { spawn: spawn8 } = await import("child_process");
4586
- const ghInstalled = checks.find((c11) => c11.name === "GitHub CLI (gh)").ok;
4587
- const ghAuthed = checks.find((c11) => c11.name === "GitHub CLI auth").ok;
4588
- const mrAuthed = checks.find((c11) => c11.name === "Mr. Manager CLI auth").ok;
4589
- const claudeCheck = checks.find((c11) => c11.name === "Claude Code (claude)");
4703
+ const ghInstalled = checks.find((c12) => c12.name === "GitHub CLI (gh)").ok;
4704
+ const ghAuthed = checks.find((c12) => c12.name === "GitHub CLI auth").ok;
4705
+ const mrAuthed = checks.find((c12) => c12.name === "Mr. Manager CLI auth").ok;
4706
+ const claudeCheck = checks.find((c12) => c12.name === "Claude Code (claude)");
4590
4707
  if (claudeCheck && !claudeCheck.ok && agent === "claude") {
4591
4708
  console.log(paint5("cyan", " Installing Claude Code..."));
4592
4709
  console.log(paint5("dim", " Running: curl -fsSL https://claude.ai/install.sh | bash"));
@@ -4649,7 +4766,7 @@ var setupCommand = new Command14("setup").description("Check that all dependenci
4649
4766
  console.log("");
4650
4767
  return;
4651
4768
  }
4652
- const fixes = checks.filter((c11) => !c11.ok && c11.fix && !c11.optional);
4769
+ const fixes = checks.filter((c12) => !c12.ok && c12.fix && !c12.optional);
4653
4770
  if (fixes.length > 0) {
4654
4771
  console.log(paint5("yellow", " To fix:"));
4655
4772
  for (const fix of fixes) {
@@ -5787,10 +5904,10 @@ ${codebaseAnalysis.routes.map((r) => `- ${r}`).join("\n")}
5787
5904
  ${codebaseAnalysis.prismaModels.map((m) => `- ${m}`).join("\n")}
5788
5905
 
5789
5906
  **Components:**
5790
- ${codebaseAnalysis.components.slice(0, 15).map((c11) => `- ${c11}`).join("\n")}
5907
+ ${codebaseAnalysis.components.slice(0, 15).map((c12) => `- ${c12}`).join("\n")}
5791
5908
 
5792
5909
  **Recent Git Commits:**
5793
- ${codebaseAnalysis.recentCommits.slice(0, 8).map((c11) => `- ${c11}`).join("\n")}
5910
+ ${codebaseAnalysis.recentCommits.slice(0, 8).map((c12) => `- ${c12}`).join("\n")}
5794
5911
 
5795
5912
  **Completed Tasks:**
5796
5913
  ${context.completedTasks.slice(0, 10).map((t) => `- ${t.title}`).join("\n") || "None"}
@@ -6437,7 +6554,7 @@ var doctorCommand = new Command25("doctor").description("Diagnose Mr. Manager CL
6437
6554
  console.log("");
6438
6555
  return;
6439
6556
  }
6440
- const fixes = checks.filter((c11) => !c11.ok && c11.fix && !c11.optional);
6557
+ const fixes = checks.filter((c12) => !c12.ok && c12.fix && !c12.optional);
6441
6558
  if (fixes.length > 0) {
6442
6559
  console.log(paint5("yellow", " To fix:"));
6443
6560
  for (const fix of fixes) {
@@ -6768,6 +6885,44 @@ skillCommand.command("generate").alias("gen").description("Generate a new skill
6768
6885
  }
6769
6886
  });
6770
6887
 
6888
+ // cli/commands/tests.ts
6889
+ import { Command as Command28 } from "commander";
6890
+ var c11 = {
6891
+ reset: "\x1B[0m",
6892
+ dim: "\x1B[2m",
6893
+ yellow: "\x1B[33m"
6894
+ };
6895
+ var testsCommand = new Command28("tests").description("List MR Test scenarios for the linked project").action(async () => {
6896
+ const projectId = getLinkedProjectId();
6897
+ if (!projectId) {
6898
+ console.error(
6899
+ `${c11.yellow}No project linked to this directory.${c11.reset} Run "mr link <project-id>" first.`
6900
+ );
6901
+ process.exit(1);
6902
+ }
6903
+ const params = new URLSearchParams({ category: "test", projectId });
6904
+ let scenarios;
6905
+ try {
6906
+ scenarios = await api.get(`/api/skills?${params}`);
6907
+ } catch (err) {
6908
+ console.error(`Failed to fetch test scenarios: ${err.message}`);
6909
+ process.exit(1);
6910
+ }
6911
+ if (scenarios.length === 0) {
6912
+ console.log(`${c11.dim}No test scenarios found for this project.${c11.reset}`);
6913
+ return;
6914
+ }
6915
+ for (const scenario of scenarios) {
6916
+ console.log(`### ${scenario.name}`);
6917
+ if (scenario.description) {
6918
+ console.log(`${c11.dim}${scenario.description}${c11.reset}`);
6919
+ console.log();
6920
+ }
6921
+ console.log(scenario.content);
6922
+ console.log();
6923
+ }
6924
+ });
6925
+
6771
6926
  // cli/index.ts
6772
6927
  var configPath = join12(homedir3(), ".mr-manager", "config.json");
6773
6928
  var isFirstRun = !existsSync17(configPath);
@@ -6775,7 +6930,7 @@ var userArgs = process.argv.slice(2);
6775
6930
  var bypassCommands = /* @__PURE__ */ new Set(["login", "init", "auth", "help", "--help", "-h", "--version", "-V", "doctor", "setup"]);
6776
6931
  var shouldBypass = userArgs.length > 0 && bypassCommands.has(userArgs[0]);
6777
6932
  if (isFirstRun && !shouldBypass) {
6778
- const c11 = {
6933
+ const c12 = {
6779
6934
  reset: "\x1B[0m",
6780
6935
  bold: "\x1B[1m",
6781
6936
  dim: "\x1B[2m",
@@ -6785,28 +6940,28 @@ if (isFirstRun && !shouldBypass) {
6785
6940
  magenta: "\x1B[35m"
6786
6941
  };
6787
6942
  console.log("");
6788
- 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}`);
6789
- 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}`);
6790
- 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}`);
6791
- 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}`);
6943
+ 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}`);
6944
+ 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}`);
6945
+ 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}`);
6946
+ 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}`);
6792
6947
  console.log("");
6793
- console.log(`${c11.bold} Welcome to Mr. Manager!${c11.reset}`);
6794
- console.log(`${c11.dim} Let's get you set up in a few quick steps.${c11.reset}`);
6948
+ console.log(`${c12.bold} Welcome to Mr. Manager!${c12.reset}`);
6949
+ console.log(`${c12.dim} Let's get you set up in a few quick steps.${c12.reset}`);
6795
6950
  console.log("");
6796
- console.log(` ${c11.yellow}Step 1:${c11.reset} Authenticate via Google OAuth`);
6797
- console.log(` ${c11.dim}Run:${c11.reset} ${c11.cyan}mr login${c11.reset}`);
6951
+ console.log(` ${c12.yellow}Step 1:${c12.reset} Authenticate via Google OAuth`);
6952
+ console.log(` ${c12.dim}Run:${c12.reset} ${c12.cyan}mr login${c12.reset}`);
6798
6953
  console.log("");
6799
- console.log(` ${c11.yellow}Step 2:${c11.reset} Verify your environment`);
6800
- console.log(` ${c11.dim}Run:${c11.reset} ${c11.cyan}mr setup${c11.reset}`);
6954
+ console.log(` ${c12.yellow}Step 2:${c12.reset} Verify your environment`);
6955
+ console.log(` ${c12.dim}Run:${c12.reset} ${c12.cyan}mr setup${c12.reset}`);
6801
6956
  console.log("");
6802
- console.log(` ${c11.yellow}Step 3:${c11.reset} Link a repo and start watching`);
6803
- console.log(` ${c11.dim}Run:${c11.reset} ${c11.cyan}mr link${c11.reset} ${c11.dim}&&${c11.reset} ${c11.cyan}mr watch${c11.reset}`);
6957
+ console.log(` ${c12.yellow}Step 3:${c12.reset} Link a repo and start watching`);
6958
+ console.log(` ${c12.dim}Run:${c12.reset} ${c12.cyan}mr link${c12.reset} ${c12.dim}&&${c12.reset} ${c12.cyan}mr watch${c12.reset}`);
6804
6959
  console.log("");
6805
- console.log(`${c11.dim} Or run ${c11.reset}${c11.cyan}mr login${c11.reset}${c11.dim} to get started now.${c11.reset}`);
6960
+ console.log(`${c12.dim} Or run ${c12.reset}${c12.cyan}mr login${c12.reset}${c12.dim} to get started now.${c12.reset}`);
6806
6961
  console.log("");
6807
6962
  process.exit(0);
6808
6963
  }
6809
- var program = new Command28();
6964
+ var program = new Command29();
6810
6965
  program.name("mr").description("Mr. Manager - Task and project management CLI").version(CLI_VERSION);
6811
6966
  program.addCommand(initCommand);
6812
6967
  program.addCommand(authCommand);
@@ -6838,4 +6993,5 @@ program.addCommand(ideaCommand);
6838
6993
  program.addCommand(doctorCommand);
6839
6994
  program.addCommand(promptAuditCommand);
6840
6995
  program.addCommand(skillCommand);
6996
+ program.addCommand(testsCommand);
6841
6997
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dunnewold-labs/mr-manager",
3
- "version": "0.4.20",
3
+ "version": "0.4.21",
4
4
  "description": "Mr. Manager - Task and project management CLI",
5
5
  "bin": {
6
6
  "mr": "./dist/index.mjs"